马黑黑 发表于 2023-9-27 07:44

svg path路径之:Q T

<style>
.code { tab-size: 4; font: normal 14px/20px Consolas, Monaco, 'Andale Mono', 'Ubuntu Mono', monospace; background: #efefef; padding: 10px; white-space: pre-wrap; word-break: break-word; }
.rred { color: red; }
</style>

<p>之前,介绍过二次贝塞尔曲线,有兴趣的朋友请参阅 <a href="https://www.huachaowang.com/forum.php?mod=viewthread&amp;tid=69653&amp;highlight=%B6%FE%B4%CE%B1%B4%C8%FB%B6%FB%C7%FA%CF%DF">理解二次贝塞尔曲线</a>,这里再以不同的方式对之进行探讨。<br><br></p>
<p>我们先来理解什么是二次贝塞尔曲线。该曲线可以用一根钢丝来比喻:两端固定,在中间任意一点像拉弓箭一样拉扯,所形成的曲线就叫二次贝塞尔曲线。不过,发力点不一定在钢丝线上,请看下图,蓝色的曲线就是二次贝塞尔曲线,发力点(即控制点)在曲线之外:<br><br></p>
<p><img id="" alt="" src="https://638183.freep.cn/638183/t23/3/qt.png" /><br><br></p>
<p>二次贝塞尔曲线在svg path的d路径中使用Q(q)以点坐标描述路径,大写Q表示使用绝对位置(即使用svg坐标系),小写q表示使用相对位置(即相对于本指令的起点的位置,向右、向下为正,向左、向上为负)。<br><br></p>
<p>下面来看一个实例,先上代码:<br><br></p>
<pre class="code">
&lt;svg width="300" height="200" style="border: 1px solid gray"&gt;
        &lt;path id="path1" <span class="rred">d="M0 100 Q150 -90, 300 100"</span> fill="none" stroke="steelblue"&gt;&lt;/path&gt;
&lt;/svg&gt;
</pre>
<p>红色的就是路径数据,可依托前面的图片帮助理解。这里解释一下:d属性用于描述path路径,其值中,<span class="rred">M0 100</span> 表示将画笔移动到{0,100}处,它就是二次贝塞尔曲线的起点,<span class="rred">Q150 -90</span>是曲线的控制点坐标{x1,y1},<span class="rred">300 100</span>是曲线的终点{x,y}。运行效果如下:<br><br></p>
<svg width="300" height="200" style="border: 1px solid gray">
        <path id="path1" d="M0 100 Q150 -90, 300 100" fill="none" stroke="blue"></path>
</svg>
<p>
        <lable class="rred" for="ctrlX">控制点x1:</lable>
        <input id="ctrlX" type="range" min="0" max="300" value="150" oninput="x1.value=this.value" />
        <output id="x1" class="rred">150</output>
        <br>
        <lable class="rred" for="ctrlY">控制点y1:</lable>
        <input id="ctrlY" type="range" min="-100" max="300" value="-90" oninput="y1.value=this.value" />
        <output id="y1" class="rred">-90</output>
<br><br></p>
<p>上面二次贝塞尔曲线实例,可以尝试改变控制点x1、y1的值,体验控制点数值对曲线产生的影响。控制点做了一些限制,以避免曲线跑到svg视界之外。<br><br></p>

<p>以上是Q指令。T指令一般配合Q指令,是在Q指令基础上再画二次贝塞尔曲线,它以Q指令的终点做起点,并依据Q指令的控制点来测算自己的控制点,将曲线画到T指令指定的唯一坐标点即终点{x,y}。下面我们将上面实例改变一下,svg画布宽度加倍,然后用T指令续接一段T指令的曲线。先看代码:<br><br></p>
<pre class="code">
&lt;svg width="600" height="200" style="border: 1px solid gray"&gt;
        &lt;path id="path2" <span class="rred">d="M0 100 Q150 -90, 300 100 T600 100"</span> fill="none" stroke="steelblue"&gt;&lt;/path&gt;
        &lt;line x1="0" y1="100" x2="600" y2="100" fill="none" stroke="red" /&gt;
&lt;/svg&gt;
</pre>

<p>本示例,为了便于观察,使用line标签加了一根红线做参考线。效果如下:<br><br></p>

<svg width="600" height="200" style="border: 1px solid gray">
        <path id="path2" d="M0 100 Q150 -90, 300 100 T600 100" fill="none" stroke="steelblue"></path>
        <line x1="0" y1="100" x2="600" y2="100" fill="none" stroke="red" />
</svg>
<p>
        <lable class="rred" for="ctrlXx">控制点x1:</lable>
        <input id="ctrlXx" type="range" min="0" max="300" value="150" oninput="xt.value=this.value" />
        <output id="xt" class="rred">150</output>
        <br>
        <lable class="rred" for="ctrlYy">控制点y1:</lable>
        <input id="ctrlYy" type="range" min="-100" max="300" value="-90" oninput="yt.value=this.value" />
        <output id="yt" class="rred">-90</output>
<br><br></p>
<p>同样,可以改变控制点的坐标值令曲线发生变化,注意观察T指令如何测算自己支配的曲线段的控制点。<br><br></p>
<p>T指令还可以接下一个T指令。下一个T指令以上一个T指令的终点为起点,依据上一个T指令的控制点测算自己的控制点,平滑续上下一条二次贝塞尔曲线。T指令也可以单独使用,它以 Mx0 y0 为起点、以自己带的参数为终点,画出来的永远是直线。<br><br></p>

<script>

ctrlX.onchange = ctrlY.onchange = () => path1.setAttribute('d', `M0 100 Q${ctrlX.value} ${ctrlY.value}, 300 100`);
ctrlXx.onchange = ctrlYy.onchange = () => path2.setAttribute('d', `M0 100 Q${ctrlXx.value} ${ctrlYy.value}, 300 100 T600 100`);

</script>

红影 发表于 2023-9-27 10:26

这个真好,可以在线演示,对二次贝塞尔曲线可以更好地理解了{:4_199:}

红影 发表于 2023-9-27 10:28

两个在线调整的stroke="steelblue" 颜色设置一样的,但感受不同。感觉下面的比上面的浅呢{:4_173:}

马黑黑 发表于 2023-9-27 12:55

红影 发表于 2023-9-27 10:28
两个在线调整的stroke="steelblue" 颜色设置一样的,但感受不同。感觉下面的比上面的浅呢

红线影响了视觉效果

马黑黑 发表于 2023-9-27 12:55

红影 发表于 2023-9-27 10:26
这个真好,可以在线演示,对二次贝塞尔曲线可以更好地理解了

之前的那个帖子也有演示

红影 发表于 2023-9-27 14:34

马黑黑 发表于 2023-9-27 12:55
红线影响了视觉效果

色彩的相互影响真是挺神奇的事呢。

红影 发表于 2023-9-27 14:34

马黑黑 发表于 2023-9-27 12:55
之前的那个帖子也有演示

是的,来这里看更方便,省得回去翻了{:4_173:}

马黑黑 发表于 2023-9-27 18:24

红影 发表于 2023-9-27 14:34
是的,来这里看更方便,省得回去翻了

一楼有链接

马黑黑 发表于 2023-9-27 18:25

红影 发表于 2023-9-27 14:34
色彩的相互影响真是挺神奇的事呢。

那是自然

红影 发表于 2023-9-27 20:15

马黑黑 发表于 2023-9-27 18:24
一楼有链接

看到了,黑黑还把那个帖子找出来的,真仔细{:4_204:}

红影 发表于 2023-9-27 20:16

马黑黑 发表于 2023-9-27 18:25
那是自然

就这么跟它有点距离的红线都能影响到它。

马黑黑 发表于 2023-9-27 21:00

红影 发表于 2023-9-27 20:16
就这么跟它有点距离的红线都能影响到它。

颜色就是颜色

马黑黑 发表于 2023-9-27 21:00

红影 发表于 2023-9-27 20:15
看到了,黑黑还把那个帖子找出来的,真仔细

哪里的话,粗人一个,玩刀弄枪勉强,其他的不行

红影 发表于 2023-9-27 21:45

马黑黑 发表于 2023-9-27 21:00
颜色就是颜色

感觉越来越搞不懂它了{:4_173:}

红影 发表于 2023-9-27 21:46

马黑黑 发表于 2023-9-27 21:00
哪里的话,粗人一个,玩刀弄枪勉强,其他的不行

现代社会,舞刀弄枪已经不需要了啊,更需要玩代码的{:4_173:}

马黑黑 发表于 2023-9-27 22:14

红影 发表于 2023-9-27 21:46
现代社会,舞刀弄枪已经不需要了啊,更需要玩代码的

玩代码只是休闲

马黑黑 发表于 2023-9-27 22:15

红影 发表于 2023-9-27 21:45
感觉越来越搞不懂它了

其实呢,那个是蓝色的(我给的代码是钢蓝色而已),第二个才是钢蓝色。

红影 发表于 2023-9-28 21:28

马黑黑 发表于 2023-9-27 22:14
玩代码只是休闲

这也要有本事才能玩得了呢{:4_187:}

红影 发表于 2023-9-28 21:29

马黑黑 发表于 2023-9-27 22:15
其实呢,那个是蓝色的(我给的代码是钢蓝色而已),第二个才是钢蓝色。

哦,原来如此,还以为我眼睛出问题了呢{:4_170:}

马黑黑 发表于 2023-9-28 23:46

红影 发表于 2023-9-28 21:29
哦,原来如此,还以为我眼睛出问题了呢

没去看大夫吧{:4_189:}
页: [1] 2 3
查看完整版本: svg path路径之:Q T