【SVG】SVG的夺命利器——path

博客说明

文章所涉及的资料来自互联网整理和个人总结,意在于个人学习和经验汇总,如有什么地方侵权,请联系本人删除,谢谢!

说明

昨天一发布,突然看到有朋友留言,希望看到更多的SVG的文章。突然有些感动,那么继续。(感动点比较低哈)

path元素的能力

path元素是SVG基本形状中最强大的一个,它不仅能创建其他基本形状,还能创建更多其他形状。

比如矩形(直角矩形或者圆角矩形)、圆形、椭圆、折线形、多边形等。

更重要的是能够绘制一些曲线,如贝塞尔曲线、二次曲线等。

path元素的形状是通过属性d来定义的,d属性通过“命令和坐标”的序列来控制整个path绘制的路径

path的坐标命令

先采用总分的形式吧。

  • M = moveto
  • L = lineto
  • H = horizontal lineto
  • V = vertical lineto
  • C = curveto
  • S = smooth curveto
  • Q = quadratic Bézier curve
  • T = smooth quadratic Bézier curveto
  • A = elliptical Arc
  • Z = closepath

然后一个个来介绍主要分为直线命令和曲线命令

直线命令

直线命令主要有以下几种:

  • M(moveto):需要两个参数(x轴和y轴坐标,移动到的点的x轴和y轴的坐标
  • L(lineto):需要两个参数(x轴和y轴坐标),它会在当前位置和最新的位置(L前面画笔所在的点)之间画一条线段。
  • H(horizontal lineto):一个参数,标明在x轴移动到的位置,绘制水平线
  • V(vertical lineto):一个参数,标明在y轴移动到的位置,绘制垂直线
  • Z( closepath):从当前点画一条直线到路径的起点

示例:

画一个正方形

<svg width="100px" height="100px" version="1.1" xmlns="http://www.w3.org/2000/svg">
<path d="M10 10 H 90 V 90 H 10 L 10 10"/>
</svg>

效果:

代码解析:

首先定义了一个100x100的画布(坐标系),用M命令在(10,10)创建起点,通过H命令在水平方向移动到x轴为90的位置,y轴不变,也就是移动到(90, 10),再通过V命令移动到y轴为90的位置,x轴不变,也就是坐标为(90,90)的位置,再通过H命令在水平方向移动到x轴为10的位置,y轴不变,此刻的位置为(10,90),最后使用L命令在起点(10,10)的位置与上次的点(10,90)画一条直线,那么四条边就画完了。

思考?

通过上面的参数和示例可以想到,其实最后的一步有几种办法可以实现

<svg width="100px" height="100px" version="1.1" xmlns="http://www.w3.org/2000/svg">
<!-- 利用Z命令 -->
<path d="M10 10 H 90 V 90 H 10 Z"/>
<!-- 利用V命令 -->
<path d="M10 10 H 90 V 90 H 10 V 10"/>
</svg>

实现的效果都是一样的,Z命令是直接从当前点画一条直线到起点,V利用本次示例中最后一步向垂直方向移动,所以它也能够做到。

以上所说的是绝对距离,当然还可以使用相对距离来画,使用小写字母

<svg width="100px" height="100px" version="1.1" xmlns="http://www.w3.org/2000/svg">
<path d="M10 10 h 80 v 80 h -80 Z" />
</svg>
曲线命令

C(curveto)三次贝塞尔曲线

三次贝塞尔曲线需要定义一个点和两个控制点,用C命令来创建。

(x,y)表示的是曲线的终点,(x1,y1)是起点的控制点,(x2,y2)是终点的控制点。控制点描述的是曲线起始点的斜率,曲线上各个点的斜率,是从起点斜率到终点斜率的渐变过程。

命令参数:

C x1 y1, x2 y2, x y
c dx1 dy1, dx2 dy2, dx dy

示例:

<svg width="200px" height="200px" version="1.1" xmlns="http://www.w3.org/2000/svg">
<path d="M10 10 C 20 20, 40 20, 50 10" stroke="black" fill="transparent"/>
</svg>

效果:

代码解释:

用M创建一个起点(10,10),C创建一个以(50,10)为终点,(20,20)为起点的控制点,(40,10)为终点的控制点。

给它加上辅助的点,看效果和代码

<svg width="200px" height="200px" version="1.1" xmlns="http://www.w3.org/2000/svg">
<path d="M130 110 C 120 140, 180 140, 170 110" stroke="black" fill="transparent"/>
<circle cx="130" cy="110" r="2" fill="red"/>
<circle cx="120" cy="140" r="2" fill="red"/>
<line x1="130" y1="110" x2="120" y2="140" style="stroke:rgb(255,0,0);stroke-width:2"/>
<circle cx="180" cy="140" r="2" fill="red"/>
<circle cx="170" cy="110" r="2" fill="red"/>
<line x1="180" y1="140" x2="170" y2="110" style="stroke:rgb(255,0,0);stroke-width:2"/>
</svg>

原理分析:结合下面的图看一下,曲线沿着起点到第一控制点的方向伸出,逐渐弯曲,然后沿着第二控制点到终点的方向结束。

S(smooth curveto)简写的三次贝塞尔曲线

S其实是创建一个特殊的三次贝塞尔曲线。它特殊的地方就是当一个点某一侧的控制点是它另一侧的控制点的对称也就是保持斜率不变。

(x,y)表示的是曲线的终点,(x2,y2)是既是终点的控制点也是起点的控制点。

命令参数:

S x2 y2, x y
s dx2 dy2, dx dy

示例:

先画一个三次贝塞尔曲线

<svg width="400px" height="200px" version="1.1" xmlns="http://www.w3.org/2000/svg">
<path d="M 10 50 C 40 20, 120 20, 150 50" stroke="black" fill="transparent"/>
</svg>

效果:

在三次贝塞尔曲线后面使用简写的三次贝塞尔曲线,使用S命令画一个简写的三次贝塞尔曲线。

<svg width="400px" height="200px" version="1.1" xmlns="http://www.w3.org/2000/svg">
<path d="M 10 50 C 40 20, 120 20, 150 50 S 260 80, 290 50" stroke="black" fill="transparent"/>
</svg>

效果:

相当于起始点使用上一个三次贝塞尔曲线终点的斜率,依照这个斜率画出了一个镜像的三次贝塞尔曲线。

将辅助点标示出来

<svg width="400px" height="200px" version="1.1" xmlns="http://www.w3.org/2000/svg">
<path d="M 10 50 C 40 20, 120 20, 150 50 S 260 80, 290 50" stroke="black" fill="transparent"/>
<circle cx="10" cy="50" r="2" fill="red"/>
<circle cx="40" cy="20" r="2" fill="red"/>
<line x1="10" y1="50" x2="40" y2="20" style="stroke:rgb(255,0,0);stroke-width:1"/> <circle cx="120" cy="20" r="2" fill="red"/>
<circle cx="150" cy="50" r="2" fill="red"/>
<line x1="120" y1="20" x2="150" y2="50" style="stroke:rgb(255,0,0);stroke-width:1"/> <circle cx="180" cy="80" r="2" fill="blue"/>
<circle cx="180" cy="80" r="2" fill="red"/>
<circle cx="260" cy="80" r="2" fill="red"/>
<line x1="150" y1="50" x2="180" y2="80" style="stroke:blue;stroke-width:1"/>
<line x1="290" y1="50" x2="260" y2="80" style="stroke:rgb(255,0,0);stroke-width:1"/>
</svg>

效果:

蓝色的线连接的那个点,其实就是向上一个“借”来的。

注意:如果S命令跟在一个C命令或者另一个S命令的后面,它的第一个控制点,就会被假设成前一个控制点的对称点。如果S命令单独使用,前面没有C命令或者另一个S命令,那么它的两个控制点就会被假设为同一个点。

Q(quadratic Bézier curve)二次贝塞尔曲线

二次贝塞尔曲线Q,只需要一个控制点,用来确定起点和终点的曲线斜率。因此它需要两组参数,控制点和终点坐标。

Q x1 y1, x y
q dx1 dy1, dx dy

示例:

<svg width="200px" height="200px" version="1.1" xmlns="http://www.w3.org/2000/svg">
<path d="M 10 80 Q 95 20 180 80" stroke="black" fill="transparent"/>
</svg>

效果:

它相比三次贝塞尔曲线,只有一个控制点,也就是一个点同时控制起点和终点,将辅助点标出来

<svg width="200px" height="200px" version="1.1" xmlns="http://www.w3.org/2000/svg">
<path d="M 10 80 Q 95 20 180 80" stroke="black" fill="transparent"/>
<circle cx="10" cy="80" r="2" fill="red"/>
<circle cx="95" cy="20" r="2" fill="red"/>
<circle cx="180" cy="80" r="2" fill="red"/>
<line x1="10" y1="80" x2="95" y2="20" style="stroke:rgb(255,0,0);stroke-width:1"/>
<line x1="95" y1="20" x2="180" y2="80" style="stroke:rgb(255,0,0);stroke-width:1"/>
</svg>

效果:

T(smooth quadratic Bézier curveto)简写的二次贝塞尔曲线

简写的二次贝塞尔曲线T,只需要一个终点。

T x y
t dx dy

示例:

<svg width="400px" height="200px" version="1.1" xmlns="http://www.w3.org/2000/svg">
<path d="M10 80 Q 50 10, 90 80 T 170 80" stroke="black" fill="transparent"/>
</svg>

效果:

加上辅助线和点

<svg width="400px" height="200px" version="1.1" xmlns="http://www.w3.org/2000/svg">
<path d="M10 80 Q 50 10, 90 80 T 170 80" stroke="black" fill="transparent"/> <circle cx="10" cy="80" r="2" fill="red"/>
<circle cx="50" cy="10" r="2" fill="red"/>
<line x1="10" y1="80" x2="50" y2="10" style="stroke:rgb(255,0,0);stroke-width:1"/> <circle cx="90" cy="80" r="2" fill="red"/>
<line x1="90" y1="80" x2="50" y2="10" style="stroke:rgb(255,0,0);stroke-width:1"/> <circle cx="170" cy="80" r="2" fill="blue"/>
<circle cx="130" cy="150" r="2" fill="blue"/>
<line x1="90" y1="80" x2="130" y2="150" style="stroke:rgb(0,0,255);stroke-width:1"/>
<line x1="130" y1="150" x2="170" y2="80" style="stroke:rgb(0,0,255);stroke-width:1"/>
</svg>

效果:

注意:T命令前面必须是一个Q命令,或者是另一个T命令,才能达到这种效果。如果T单独使用,那么控制点就会被认为和终点是同一个点,所以画出来的将是一条直线。

A(elliptical Arc)弧形

A命令用于画弧形。

A rx ry x-axis-rotation large-arc-flag sweep-flag x y
a rx ry x-axis-rotation large-arc-flag sweep-flag dx dy

参数说明

  • 弧形命令A前两个参数rx和ry分别是x轴半径和y轴半径。
  • 弧形命令A的第三个参数表示弧形的旋转情况。
  • large-arc-flag决定弧线是大于还是小于180度,0表示小角度弧,1表示大角度弧。
  • sweep-flag表示弧线的方向,0表示从起点到终点沿逆时针画弧,1表示从起点到终点沿顺时针画弧。
  • x:结束点x坐标。
  • y:结束点y坐标。

示例:

<svg width="400px" height="320px" version="1.1" xmlns="http://www.w3.org/2000/svg">
<path d="M10 315
L 110 215
A 30 50 0 0 1 162.55 162.45
L 172.55 152.45
A 30 50 -45 0 1 215.1 109.9
L 315 10" stroke="black" fill="red" stroke-width="2" fill-opacity="0.5"/>
</svg>

效果:

代码解析:

画布上有一条对角线,中间有两个椭圆弧被对角线切开(x radius = 30, y radius = 50)。

第一个椭圆弧的x-axis-rotation(x轴旋转角度)是0,所以弧形所在的椭圆是正置的(没有倾斜)。

在第二个椭圆弧中,x-axis-rotation设置为-45,所以这是一个旋转了45度的椭圆,并以短轴为分割线,形成了两个对称的弧形。

总结

学习了直线命令,特别是比较难理解的曲线命令。

绘制平滑曲线的命令有三个,其中两个用来绘制贝塞尔曲线,另外一个用来绘制弧形或者说是圆的一部分。

在path元素里,只存在两种贝塞尔曲线:三次贝塞尔曲线C,和二次贝塞尔曲线Q。

在这里还要注意简写的贝塞尔曲线使用的前提。最难的当然是弧形了。

当然看到这里,有朋友可能会有疑问,还有必要去学习这个复杂SVG的画法吗?对于这个问题,其实写这篇文章的目的不是让你手写SVG,而是理解SVG的画法,SVG大多数都是一些矢量图形工具来制作,但是细心的你没发现吗,上文的一些操作,不正是应和了我们使用AI等工具绘图的场景吗?

学习终是在脚下,累积也是如此。

感谢

万能的网络

路径-SVG|MDN

以及勤劳的自己,个人博客GitHub测试GitHub

公众号-归子莫,小程序-小归博客

【SVG】SVG的夺命利器——path的更多相关文章

  1. SVG & convert polygon/polyline to path

    SVG & convert polygon/polyline to path SVG Polygon/Polyline to Path Converter https://codepen.io ...

  2. svg学习(九)path

    <path> 标签用来定义路径. 下面的命令可用于路径数据: M = moveto L = lineto H = horizontal lineto V = vertical lineto ...

  3. 在svg中的line和path根据路径返回x,y

    由于path有自带的api可获得总长度,和某个长度返回的坐标. var total = d.path.getTotalLength();//返回总长度 var point = d.path.getPo ...

  4. div转svg svg转canvas svg生成图片及图片下载 分享

    链接来自:http://blog.csdn.net/u010081689/article/details/50728854

  5. 【js类库Raphaël】基于svg中的path画40%表示的环型图

     一.可供参考的文档资料. raphaeljs官网:http://raphaeljs.com/ w3c关于path的介绍:http://www.w3.org/TR/2003/REC-SVG11-200 ...

  6. SVG的path的使用

    SVG的path的使用: 参考:http://justcoding.iteye.com/blog/2226354 <%@ page language="java" conte ...

  7. SVG之Path

    一.Path概述 1.控制命令 SVG提供了一些基础图形元素标签如<circle>.<rect>.<ellipse>.<line>.<polyli ...

  8. SVG 可伸缩矢量图形 简介 Path路径

    w3school:http://www.w3school.com.cn/svg/svg_intro.asp  SVG 意为可缩放矢量图形(Scalable Vector Graphics). SVG ...

  9. svg path 动画效果

    http://www.zhangxinxu.com/wordpress/2014/04/animateion-line-drawing-svg-path-%E5%8A%A8%E7%94%BB-%E8% ...

随机推荐

  1. thinkphp5自带workerman应用

    1.在vendor/workerman/文件夹下建立server.php文件,内容如下: <?php use Workerman\Worker; require_once __DIR__ . ' ...

  2. Hutool时间和日期相关工具

    日期时间工具 获取当前时间(1) public class HDateAndTime { public static void main(String[] args) { //获取当前时间 Date ...

  3. 踩坑系列《六》Spring增加事务处理遇到异常解决办法

    当在对数据进行增删改操作时,需要用到事务的处理,所以在业务层中加入@Transactional注解,但是在执行业务操作的前面遇到异常,因此对异常进行抛出,但是数据又诡异地成功保存到数据库了. 解决方法 ...

  4. Ubuntu 20.04上安装MySQL教程,ubuntu安装mysql

    在Ubuntu 20.04上安装MySQL教程 先决条件 确保您以具有sudo特权的用户身份登录. 在Ubuntu上安装MySQL 在撰写本文时,Ubuntu存储库中可用的MySQL的最新版本是MyS ...

  5. java 从零开始手写 RPC (05) reflect 反射实现通用调用之服务端

    通用调用 java 从零开始手写 RPC (01) 基于 socket 实现 java 从零开始手写 RPC (02)-netty4 实现客户端和服务端 java 从零开始手写 RPC (03) 如何 ...

  6. Serverless 解惑——函数计算如何安装字体

    前言 首先介绍下在本文出现的几个比较重要的概念: 函数计算(Function Compute):函数计算是一个事件驱动的服务,通过函数计算,用户无需管理服务器等运行情况,只需编写代码并上传.函数计算准 ...

  7. 面试官:为什么需要Java内存模型?

    面试官:今天想跟你聊聊Java内存模型,这块你了解过吗? 候选者:嗯,我简单说下我的理解吧.那我就从为什么要有Java内存模型开始讲起吧 面试官:开始你的表演吧. 候选者:那我先说下背景吧 候选者:1 ...

  8. System.Drawing Linux Centos7 The type initializer for 'Gdip' threw an exception

    System.Drawing 在linux使用时提示异常 The type initializer for 'Gdip' threw an exception 解决方案: yum install au ...

  9. 洛谷4719 【模板】动态dp 学习笔记(ddp 动态dp)

    qwq大概是混乱的一个题. 首先,还是从一个比较基础的想法开始想起. 如果每次暴力修改的话,那么每次就可以暴力树形dp 令\(dp[x][0/1]\)表示\(x\)的子树中,是否选择\(x\)这个点的 ...

  10. RA-28000 账号被锁定的解决办法

    ORA-28000 账号被锁定的解决办法 错误场景:当使用sqlplus进行登录时报错:ORA-28000 账号被锁定.错误原因:由于oracle 11g 在默认在default概要文件中设置了密码最 ...