为 GIF 图像创建多边形轮廓

发布于 2025-01-05 19:33:21 字数 1867 浏览 1 评论 0原文

我正在使用 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 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

心舞飞扬 2025-01-12 19:33:22

绘制稍大一点的箭头会有问题,因为它不会在每个点都变大相同的量。您可以用轮廓颜色绘制箭头 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.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文