为 GIF 图像创建多边形轮廓
我正在使用 imagefilledpolygon
在 GIF 图像 (PHP) 上绘制箭头,并且我想将箭头轮廓设置为黑色。我首先为箭头创建一个三角形,然后在三角形的底部画一条粗线以获得箭头效果。
我认为的一个解决方案是创建两个三角形箭头,第一个是黑色的并且比第一个稍大(以创建轮廓效果),但我不确定如何进行数学计算。
任何帮助都会很棒!
创建箭头(头和尾)的代码:
function arrow($img, $x1, $y1, $x2, $y2, $alength, $awidth, $color) {
$distance = sqrt(pow($x1 - $x2, 2) + pow($y1 - $y2, 2));
$dx = $x2 + ($x1 - $x2) * $alength / $distance;
$dy = $y2 + ($y1 - $y2) * $alength / $distance;
$k = $awidth / $alength;
$x2o = $x2 - $dx;
$y2o = $dy - $y2;
$x3 = $y2o * $k + $dx;
$y3 = $x2o * $k + $dy;
$x4 = $dx - $y2o * $k;
$y4 = $dy - $x2o * $k;
imagelinethick($img, $x1, $y1, $dx, $dy, $color,3);
return imagefilledpolygon($img, array($x2, $y2, $x3, $y3, $x4, $y4), 3, $color);
}
为箭头线调用此函数(仅供参考):
function imagelinethick($image, $x1, $y1, $x2, $y2, $color, $thick = 1)
{
/* this way it works well only for orthogonal lines
imagesetthickness($image, $thick);
return imageline($image, $x1, $y1, $x2, $y2, $color);
*/
if ($thick == 1) {
return imageline($image, $x1, $y1, $x2, $y2, $color);
}
$t = $thick / 2 - 0.5;
if ($x1 == $x2 || $y1 == $y2) {
return imagefilledrectangle($image, round(min($x1, $x2) - $t), round(min($y1, $y2) - $t), round(max($x1, $x2) + $t), round(max($y1, $y2) + $t), $color);
}
$k = ($y2 - $y1) / ($x2 - $x1); //y = kx + q
$a = $t / sqrt(1 + pow($k, 2));
$points = array(
round($x1 - (1+$k)*$a), round($y1 + (1-$k)*$a),
round($x1 - (1-$k)*$a), round($y1 - (1+$k)*$a),
round($x2 + (1+$k)*$a), round($y2 - (1-$k)*$a),
round($x2 + (1-$k)*$a), round($y2 + (1+$k)*$a),
);
imagefilledpolygon($image, $points, 4, $color);
return imagepolygon($image, $points, 4, $color);
}
I'm using imagefilledpolygon
to draw an arrow on a GIF image (PHP) and I'd like to make the arrowhead outlined in black. I first create a triangle for the arrow and then draw a thick line at the base of the triangle for the arrow effect.
One solution I think is to create two triangle arrows, the first one being black and slightly larger than the first (to create an outline effect) but I'm not sure how to go about the math of that.
Any help would be great!
Code to create the arrow (head and tail):
function arrow($img, $x1, $y1, $x2, $y2, $alength, $awidth, $color) {
$distance = sqrt(pow($x1 - $x2, 2) + pow($y1 - $y2, 2));
$dx = $x2 + ($x1 - $x2) * $alength / $distance;
$dy = $y2 + ($y1 - $y2) * $alength / $distance;
$k = $awidth / $alength;
$x2o = $x2 - $dx;
$y2o = $dy - $y2;
$x3 = $y2o * $k + $dx;
$y3 = $x2o * $k + $dy;
$x4 = $dx - $y2o * $k;
$y4 = $dy - $x2o * $k;
imagelinethick($img, $x1, $y1, $dx, $dy, $color,3);
return imagefilledpolygon($img, array($x2, $y2, $x3, $y3, $x4, $y4), 3, $color);
}
This function is called for the line of the arrow (just for your reference):
function imagelinethick($image, $x1, $y1, $x2, $y2, $color, $thick = 1)
{
/* this way it works well only for orthogonal lines
imagesetthickness($image, $thick);
return imageline($image, $x1, $y1, $x2, $y2, $color);
*/
if ($thick == 1) {
return imageline($image, $x1, $y1, $x2, $y2, $color);
}
$t = $thick / 2 - 0.5;
if ($x1 == $x2 || $y1 == $y2) {
return imagefilledrectangle($image, round(min($x1, $x2) - $t), round(min($y1, $y2) - $t), round(max($x1, $x2) + $t), round(max($y1, $y2) + $t), $color);
}
$k = ($y2 - $y1) / ($x2 - $x1); //y = kx + q
$a = $t / sqrt(1 + pow($k, 2));
$points = array(
round($x1 - (1+$k)*$a), round($y1 + (1-$k)*$a),
round($x1 - (1-$k)*$a), round($y1 - (1+$k)*$a),
round($x2 + (1+$k)*$a), round($y2 - (1-$k)*$a),
round($x2 + (1-$k)*$a), round($y2 + (1+$k)*$a),
);
imagefilledpolygon($image, $points, 4, $color);
return imagepolygon($image, $points, 4, $color);
}
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(1)
绘制稍大一点的箭头会有问题,因为它不会在每个点都变大相同的量。您可以用轮廓颜色绘制箭头 8 次,8 个方向各偏移 1 个像素,然后在其顶部绘制最终形状。
Drawing a slightly larger arrow is going to be problematic, because it won't be the same amount larger at every point. You can draw the arrow in outline color 8 times, offset by 1 pixel for each of 8 directions, then draw the final shape on top of it.