命令 | 名称 | 参数 |
M | moveto(移动到) | (x y)+ |
Z | closepath(关闭路径) | (none) |
L | lineto(画线到) | (x y)+ |
H | horizontal lineto(水平线到) | x+ |
V | vertical lineto (垂直线到) | y+ |
C | curveto(三次贝塞尔曲线到) | (x1 y1 x2 y2 x y)+ |
S | smooth curveto(光滑三次贝塞尔曲线到) | (x2 y2 x y)+ |
Q | quadratic Bézier curveto(二次贝塞尔曲线到) | (x1 y1 x y)+ |
T | smooth quadratic Bézier curveto(光滑二次贝塞尔曲线到) | (x y)+ |
A | elliptical arc (椭圆弧) | (rx ry x-axis-rotation large-arc-flag sweep-flag x y)+ |
R | Catmull-Rom curveto* (Catmull-Rom曲线) | x1 y1 (x y)+ |
贝塞尔曲线
在SVGpath
命令中我个人认为最精髓的部分是贝塞尔曲线,贝塞尔能画出各种令人愉悦的曲线。
贝塞尔曲线完全由其控制点决定其形状,n个控制点对应着n-1阶的贝塞尔曲线,并且可以通过递归的方式来绘制。我们先看下一次和二次贝塞尔曲线如何来绘制的:
一次曲线:
一条直线上,随着时间t的变化,红色线段的那个点的坐标公式应该如下:
二次贝塞尔曲线:
p0、p1、p2
是3个不共线的点,依次用线段连接,此时随意取线段p0p1
上的一个点p0'
, 如上图: 我们的p0'
点在p0p1
线段的0.26处(t=0.26),此刻p1p2
线段相同比列取p1'
点,此时p0'
和p1'
连接后形成线段p0'p1'
, 在按照如上比列进行取值p0''
, 这时候就确定了二次贝塞尔曲线的一个点。
通过一番巴拉巴拉牛逼的推导后,二次贝塞尔曲线公式为:
N次贝塞尔可以认为是如上取值方式的迭代过程,可以通过下图直观的感受到1~4次曲线随着时间t的变化过程,具体N次贝塞尔曲线的公式可以参考下方关于曲线的文章
SVG中的Q命令
回到我们的ToolTips
话题, 其中的圆角是可以通过二次贝塞尔曲线来实现,SVG中Q
命令就是来实现二次贝塞尔曲线的,SVG中Q
命令的示例图如下:
对应的指令,其中x1,y1就是我们上面提到的p1
点:
Q x1 y1, x y
二次贝塞尔曲线Q
示例如下:
<svg width="190px" height="160px" version="1.1" xmlns="http://www.w3.org/2000/svg"> <path d="M10 80 Q 95 10 180 80" stroke="black" fill="transparent"/> </svg>
通过设置起始点和调整控制点p1
我们能得到我们想要的圆角,如下图所示,小圆点为我们的p1
控制点
NO.6
样式设置
实现了上方的SVG后接下来的透明、背景渐变、阴影、边框的设置就都不成问题了。
背景透明
path { fill: rgba(0,0,0, .3); storke: #ffffff; storke-width: 1px }
阴影
svg { filter:drop-shadow(2px 4px 6px black) }
关于为何使用drop-shadow
来实现阴影,可以看下图使用了box-shadow
和drop-shadow
效果区别,
使用box-shadow
的时候我们的尖角部分没有阴影,气泡框部分是有阴影的,就会出现下图所示的情况,而使用drop-shadow
就能符合我们尖角和气泡框都有阴影的要求。
背景渐变
SVG不仅支持简单的填充,还支持线性渐变和径向渐变以及图形纹理等。为了让渐变能被重复使用,渐变内容需要定义在标签内部。
如下图是径向渐变的演示:
<svg width="120" height="240" version="1.1" xmlns="http://www.w3.org/2000/svg"> <defs> <linearGradient id="Gradient2" x1="0" x2="0" y1="0" y2="1"> <stop offset="0%" stop-color="red"/> <stop offset="50%" stop-color="black" stop-opacity="0"/> <stop offset="100%" stop-color="blue"/> </linearGradient> </defs> <rect x="10" y="120" rx="15" ry="15" width="100" height="100" fill="url(#Gradient2)"/> </svg>
将这个渐变作用到我们提示框后可以看到如下图的效果,终于不用辛辛苦苦的处理尖角的渐变衔接问题了。
更多
SVG同时也支持纹理叠加效果,具体感兴趣的可以自行去研究下。
NO.7
需求还没完
上面方案落地到项目中后,可能是我们不经意感动了设计师,最近的需求视觉稿中我们发现其中涉及到的Tooltips样式已经越发令人惊艳。简单列举如下两个样式:
第一版方案我们基于Demo工具演示我们已经产出了ToolTips的SDK, 我们使用的单个参数arrowHeight
传入来生成尖角。在应付上方两个样式是不可能的,尖角样式多变,如何来扩展性和易用性成为了一个问题,不可能多变的尖角样式都开发一个SDK。
NO.8
方案改进
要应付多变的气泡尖角一定要想办法把尖角抽离出原先的气泡外层路径,生成尖角路径后在整合到气泡上形成一个完整的闭合路径。
为了简单处理数值,我将原先的尖角(0,0)
坐标定义更换到下方图示点:
所以接下来尖角可以自由设计了,只要保证从(0,0)
出发最后回到(-arrowWidth,0)
就行了,如下是一个尖角的路径:(M 0 0 C -10 0 -8 5 -12 5 S -14 0 -24 0
)
通过设计不同的尖角路径我们就能组合成不同的气泡样式:
上方右侧的尖角气泡最终给出的路径字符串如下,其中Q -2 7 -9 10 Q -6 5 -7 0
这一段即为我们的尖角路径:
M 0 0
Q -2 7 -9 10 Q -6 5 -7 0
H -110
Q -116,0 -116,-6
V -56
Q -116,-62 -110,-62
H 101
Q 107,-62 107,-56
V -6
Q 107,0 101,0
H 0 z
从上方简短的路径能看出,我们的尖角路径是完整的整合在整个SVG气泡路径中的,所以就不会担心会出现CSS的 clip-path 方案的问题。
NO.9
可视化工具
方案看起来好像已经搞定了需求中的尖角样式,然而你可能会说这尖角路径是如何产生,难道需要通过强大的数学能力推导出来?如下三次贝塞尔曲线就已经不敢直视了,更何况四次、五次...
所以想配合的我们一定要产出可视化工具来实现这路径生成过程,得益于D3.js工具库操作SVG方面的强大功能,我们开发完的 生成工具地址 (https://market.m.taobao.com/app/fdilab/svg-tool-demo/pages/index/index.html) 如下:
对于熟悉SVG的path
命令的同学来说这个操作不难,如果不熟悉的推荐看下下方的参考文章,了解了曲线命令后就能画出圆滑的曲线。
10
总结
至此在ToolTips
这块基本已经满足了设计的需求,同时也沉淀了SVG路径生成工具。使用SVG来实现ToolTips
能覆盖 CSSclip-path
不能完美解决的几个场景。在此特别感谢大漠老师的指导。
11
参考文章
D3官网(https://d3js.org.cn/)
曲线篇: 贝塞尔曲线(https://zhuanlan.zhihu.com/p/136647181 )
Tooltips using SVG Path(https://medium.com/welldone-software/tooltips-using-svg-path-1bd69cc7becd )
SVG渐变(https://developer.mozilla.org/zh-CN/docs/Web/SVG/Tutorial/Gradients )
深度掌握SVG路径path的贝塞尔曲线指令(https://www.zhangxinxu.com/wordpress/2014/06/deep-understand-svg-path-bezier-curves-command/ )
css drop-shadow(https://www.zhangxinxu.com/wordpress/2016/05/css3-filter-drop-shadow-vs-box-shadow/ )
到此这篇关于使用SVG实现提示框功能的示例代码的文章就介绍到这了,更多相关svg 提示框内容请搜索脚本之家以前的文章或继续浏览下面的相关文章,希望大家以后多多支持脚本之家!
上一篇:Html5嵌入钉钉的实现示例