在PHP中创建迷你折线图
注意:这篇文章发布已超过两年,因此其中包含的信息可能已过时。如果您发现了问题,请留下评论,我公司会尽力更正。
2023年9月17日 - 阅读时长16分钟
迷你折线图是一种尺寸很小的折线图,主要用于传达简单信息,通常是随时间变化的数值信息。它一般没有坐标轴或其他标签,常被添加到信息读数中,为数字补充说明,赋予更多背景信息。
迷你折线图高度通常在20 - 30像素左右,宽度可达150 - 200像素。当要展示5到15个数据项时,效果最佳,因为在这么小的图表中添加更多数据项,可能会让图表显得杂乱。
在本文中,我将介绍使用PHP生成迷你折线图的步骤。在Drupal开发中,这种迷你折线图也能为数据展示增添不少实用性,无论是Drupal模块开发还是Drupal升级,都可能会用到这样的图表展示数据变化趋势。
举个例子,您可能有一个数字列表,显示了几个月内某事物的数量统计。
仅仅列出数字当然没问题,但要是在数字旁边配上一个小的折线图,就能更清晰地呈现这些数字之间的关系。
添加这样一个小图表,能清晰显示数字的上升趋势,而且不需要很多数字就能看出趋势。
最终,我们的目标是编写一段通用代码,用于为应用程序的任何部分生成迷你折线图。实现这一目标,最好的办法是使用HTML图像标签调用一个PHP脚本,传递想要展示的数据,并以图像形式返回数据。
以下是一个使用现有数据在页面内生成上述迷你折线图的示例。
<img src="/sparkline.php?data=10,30,40,20,50,20,40,50,100"/>
由于PHP脚本返回的是图像数据,浏览器会将其作为图像显示。
一、接受用户输入
我们传递给脚本的数据采用逗号分隔的格式,所以需要处理传入的字符串,把数据提取到一个数组中。通过URL添加的参数,在PHP中可通过$_GET超全局变量自动获取。
我们要确保$_GET变量中有数据,并且在将数据处理成数组之前,数据包含多个数据点。通过is_numeric()检查传入的值,过滤掉数据中的所有非数字值,最后把符合条件的值添加到$data数组中。
// 处理传入的数据。
$data = [];
if (isset($_GET['data']) && str_contains($_GET['data'], ',')) {
foreach (explode(',', $_GET['data']) as $datum) {
if (is_numeric($datum)) {
// 忽略非数字的任何内容。
$data[] = $datum;
}
}
}
对于图表的宽度和高度,我们采用类似的处理方式。为图表设置默认大小为50x30像素,并允许将大小设置到最大300x300像素。将可选的传入值转换为整数,确保它们是整数,因为不能用浮点值来创建图像的宽度和高度。
// 定义宽度。
$width = 50;
if (isset($_GET['w']) && is_numeric($_GET['w']) && $_GET['w']
现在我们已经获取了迷你折线图的数据以及可选的自定义图表尺寸。
二、初始化迷你折线图图像
首先,我们要定义用于绘制迷你折线图的图像,这可以使用PHP的GD库生成一个图像资源。生成图像资源后,用一个白色矩形设置图像的背景。
这时,我们可以检查传递给脚本的$data,如果没有数据需要处理,就返回这个空白图表。为此,先返回一个图像头信息,让浏览器知道我们即将返回的数据类型,然后调用imagepng()函数输出图像。
// 创建图像。
$image = imagecreatetruecolor($width, $height);
// 设置背景颜色。
$backgroundColour = imagecolorallocate($image, 255, 255, 255);
imagefilledrectangle($image, 0, 0, $width, $height, $backgroundColour);
if (empty($data)) {
// 如果$data为空,则输出空白图像。
header('Content-Type: image/png');
imagepng($image);
exit();
}
在此处停止执行可以防止报告中出现任何错误或损坏的图像。
或者,如果我们有数据需要处理,那么可以定义图表中线条的颜色。
// 设置线条颜色。
$lineColour = imagecolorallocate($image, 0, 0, 255);
$baseLineColour = imagecolorallocate($image, 128, 128, 128);
在这种情况下,我们将蓝色定义为线条颜色,浅灰色定义为代表0的线条颜色,如果有负数,就会绘制这条线。
三、绘制线条
创建好图像资源和颜色后,就可以开始在图表中绘制线条了。这个过程的第一步是将图表的表观高度减1,这样任何值为0的数据项实际上会出现在图表的位置1处,防止包含一个或多个值为0的数据项的图表不被绘制在图表上。
// 现在我们已经定义了图像的高度,确保图表上的0实际上是1。
$height--;
为了计算图表的相对高度,我们还需要找出数据的最大值和最小值,这可以使用PHP的max()和min()函数来完成。
// 从数据中获取最大值。
$maxValue = max($data);
$minValue = min($data);
在为我们的数据绘制线条之前,如果图表同时包含负值和正值,我们需要在图表中绘制值为0的基线。这条线的高度是通过将数据的最小值和最大值映射到图表的总高度来计算的,这样就可以将这条线绘制在位置0处。
if ($minValue 0) {
// 这条线穿过0点,因此在0处绘制图表的基线。
$x1 = 0;
$x2 = $width;
$y1 = $height - round($height * ((0 - $minValue) / ($maxValue - $minValue)));
$y2 = $height - round($height * ((0 - $minValue) / ($maxValue - $minValue)));
imageline($image, $x1, $y1, $x2, $y2, $baseLineColour);
}
在PHP GD图像中绘制线条的顺序很重要,所以我们先绘制基线,这样就可以在这条线上方绘制其他线条。
最后,我们可以绘制图表的线条了。
// 计算图表中每个点之间的校正距离。
$barWidth = ($width) / (count($data) -1);
// 绘制图表的线条。
for ($i = 0; $i
最后要做的是创建一个头信息,让浏览器知道我们返回的数据类型,然后使用imagepng()函数输出图像。
// 输出图像。
header('Content-Type: image/png');
imagepng($image);
这样做会渲染图像并将其返回给浏览器。这里不需要退出脚本,因为这是最后一条指令,脚本会自动退出。
四、结论
这是一种非常有用的技术,可以为系统中的数据提供更多的背景信息。您甚至可以用它来扩展单个值,以显示该值随时间的趋势,这是一种更直观的展示数值的方式。在Drupal11的开发过程中,这种可视化数据的方式能更好地满足用户对数据展示的需求。
以下是一个使用这种技术来扩展数字列表中单个值的示例。
这个脚本还有一些可以改进的地方。例如,您可以允许用户为迷你折线图指定自己的颜色,因为目前这些颜色值是硬编码在脚本中的。您需要接受十六进制颜色值,并将其转换为imagecolorallocate()函数所需的格式。
这里的主要限制是,PHP不允许在imageline()函数中使用浮点值,这意味着我们需要对数值进行四舍五入后才能用于绘制线条。由于图表尺寸较小,并且采用了这种四舍五入的方式,线条中可能会出现小的精度误差,这可能会导致图表中偶尔出现小的像素间隙。
如果您需要这个迷你折线图脚本的完整代码,可以向我公司咨询获取。


