概要总结
1、path路径概念
2、path绘制三角形
3、path绘制二次贝塞尔曲线
4、二次贝塞尔曲线算法
一、path路径概念
1、d: 绘制路径的命令,d是draw的缩写,是绘制的意思。以下是d的常用命令:
(1)M:M命令是moveto的缩写,定义绘制图形的起点坐标。例如M 150 0,也可以写成M150 0,表示路径从屏幕坐标的x150,y0这个点开始绘制
(2)L:L命令是lineto的缩写,用来绘制一条直线,例如l 75 200,也可以写成l75 200,表示从上一个结束点到x75,y200这个点绘制一条直线。
2、命令字母大小写
命令的字母大小写表示的意义是不同的,大写字母表示绝对定位,小写字母表示相对定位。
绝对定位是相对于屏幕坐标原点的位置,相对定位是相对于上一个绘制点的位置。
二、path绘制三角形
<svg width="400" height="210" style="background: #eee">
<path d="M150 0 L75 200 L225 200"/>
</svg>
它的绘制流程,首先它把画笔移动到150,0的顶点位置,从这个位置画到75,200的左下角,然后再画到225,200右下角的位置,最后连接回起始的顶点位置。
三、path绘制二次贝塞尔曲线
1、概念
在path中绘制"二次贝塞尔曲线"使用Q命令,q是quardratic Bézier curve的缩写,用来绘制二次贝塞尔曲线。
2、绘制原理
需要定义控制点和终点的坐标,例如q 150 -300 300 0,表示控制点坐标是x 150, y -300,终点坐标是x 300, y0。
二次贝塞尔曲线的绘制示意图:
A为起点,B为控制点,C为终点,在AB、BC两条红色的线段上有一条绿色的切线,蓝色的为绘制的二次贝塞尔曲线。
3、绘制过程
(1)绘制起点、控制点和终点
<svg width="550" height="400" style="background: #eee">
<circle cx="100" cy="350" r="3"/>
<circle cx="250" cy="50" r="3"/>
<circle cx="400" cy="350" r="3"/>
</svg>
在SVG中,我们可以使用g标签把多个绘图元素包裹起来,在g标签上定义公共的属性。
<svg width="550" height="400" style="background: #eee">
<g fill="black">
<circle cx="100" cy="350" r="3"/>
<circle cx="250" cy="50" r="3"/>
<circle cx="400" cy="350" r="3"/>
</g>
</svg>
(2)绘制A、B、C三个点的文本
<svg width="550" height="400" style="background: #eee">
<g fill="black">
<circle cx="100" cy="350" r="3"/>
<circle cx="250" cy="50" r="3"/>
<circle cx="400" cy="350" r="3"/>
</g>
<g font-size="20" fill="black">
<text x="90" y="380">A(100, 350)</text>
<text x="250" y="40">B(250, 50)</text>
<text x="400" y="380">C(400, 350)</text>
</g>
</svg>
(3)绘制AB、BC两条连线
<path d="M 100 350 l 150 -300" stroke="red" stroke-width="3" fill="none"/> <path d="M 250 50 l 150 300" stroke="red" stroke-width="3" fill="none"/>
<svg width="550" height="400" style="background: #eee">
<path d="M 100 350 l 150 -300" stroke="red" stroke-width="3" fill="none"/>
<path d="M 250 50 l 150 300" stroke="red" stroke-width="3" fill="none"/>
<g fill="black">
<circle cx="100" cy="350" r="3"/>
<circle cx="250" cy="50" r="3"/>
<circle cx="400" cy="350" r="3"/>
</g>
<g font-size="20" fill="black">
<text x="90" y="380">A(100, 350)</text>
<text x="250" y="40">B(250, 50)</text>
<text x="400" y="380">C(400, 350)</text>
</g>
</svg>
(4)绘制绿色切线
<svg width="550" height="400" style="background: #eee">
<path d="M 100 350 l 150 -300" stroke="red" stroke-width="3" fill="none"/>
<path d="M 250 50 l 150 300" stroke="red" stroke-width="3" fill="none"/>
<path d="M 175 200 l 150 0" stroke="green" stroke-width="3" fill="none"/>
<g fill="black">
<circle cx="100" cy="350" r="3"/>
<circle cx="250" cy="50" r="3"/>
<circle cx="400" cy="350" r="3"/>
<circle cx="175" cy="200" r="3"/>
<circle cx="325" cy="200" r="3"/>
</g>
<g font-size="20" fill="black">
<text x="90" y="380">A(100, 350)</text>
<text x="250" y="40">B(250, 50)</text>
<text x="400" y="380">C(400, 350)</text>
<text x="50" y="200">D(175, 200)</text>
<text x="340" y="200">E(325, 200)</text>
</g>
</svg>
(5)绘制贝塞尔曲线
<svg width="550" height="400" style="background: #eee">
<path d="M 100 350 l 150 -300" stroke="red" stroke-width="3" fill="none"/>
<path d="M 250 50 l 150 300" stroke="red" stroke-width="3" fill="none"/>
<path d="M 175 200 l 150 0" stroke="green" stroke-width="3" fill="none"/>
<path d="M 100 350 q 150 -300 300 0" stroke="blue" stroke-width="5" fill="none"/>
<g fill="black">
<circle cx="100" cy="350" r="3"/>
<circle cx="250" cy="50" r="3"/>
<circle cx="400" cy="350" r="3"/>
<circle cx="175" cy="200" r="3"/>
<circle cx="325" cy="200" r="3"/>
<circle cx="250" cy="200" r="3"/>
</g>
<g font-size="20" fill="black">
<text x="90" y="380">A(100, 350)</text>
<text x="250" y="40">B(250, 50)</text>
<text x="400" y="380">C(400, 350)</text>
<text x="50" y="200">D(175, 200)</text>
<text x="340" y="200">E(325, 200)</text>
<text x="195" y="230">F(250, 200)</text>
</g>
</svg>
(6)清除所有点和辅助线
<svg width="450" height="400" style="background: #eee">
<path d="M 100 350 q 150 -300 300 0" stroke="blue" stroke-width="5" fill="none"/>
</svg>
(7)非常规三角形的贝塞尔曲线
<svg width="550" height="500" style="background: #eee">
<path d="M 100 250 l 200 -200" stroke="red" stroke-width="3" fill="none" />
<path d="M 300 50 l 100 350" stroke="red" stroke-width="3" fill="none" />
<path d="M 200 150 l 150 75" stroke="green" stroke-width="3" fill="none" />
<path d="M 100 250 q 200 -200 300 150" stroke="blue" stroke-width="5" fill="none"/>
<g fill="black">
<circle cx="100" cy="250" r="3"/>
<circle cx="300" cy="50" r="3"/>
<circle cx="400" cy="400" r="3"/>
<circle cx="200" cy="150" r="3"/>
<circle cx="350" cy="225" r="3"/>
<circle cx="275" cy="187.5" r="3"/>
</g>
<g font-size="20" fill="black">
<text x="90" y="275">A(100, 250)</text>
<text x="300" y="40">B(300, 50)</text>
<text x="400" y="425">C(400, 400)</text>
<text x="80" y="150">D(200, 150)</text>
<text x="360" y="230">E(350, 225)</text>
<text x="270" y="180">F(275, 187.5)</text>
</g>
</svg>
4、代码演示
四、二次贝塞尔曲线算法
贝塞尔曲线起点和终点对应的就是三角形的两个底角,而曲线的控制点就是顶角,目前未知。但曲线的最高点是已知的,它实际上就是三角形的中线的中点。
由图可知,曲线的起点是A,终点是C,最高点是F。而最高点F实际上是AB和CB的中点连线的中点。
一条贝塞尔曲线需要3个条件,分别是起点、终点和控制点,这个控制点可以理解为三角形的顶角B。已知A和C两个角的坐标,因此可以求出AC的中点G坐标为(250, 325)。最高点F是曲线的最高点也是已知的,根据三角形定理,BG是三角形BAC的中线,F是BG的中点,假设B点的x坐标为x,y坐标为y,可以根据以下公式:
(x + 250) / 2 = 275
(y + 325) / 2 = 187.5
因此B点的坐标为(300, 50)。现在起点、终点和控制点都已具备,那么可以通过path的q将这条贝塞尔曲线绘制出来。
五、代码链接