需求背景
在某个项目中,需要自行画一条svg直线,然后svg还需要在起始点、终点和中点额外添加图标,这就研究了一下 marker 和 CSS运动路径
marker-start/-mid/-end
我们先看在主要的一些场景下,它们的可行性
直线
代码如下,预期结果,三点均有图标
// css
.line {
fill: none;
stroke: red;
stroke-width: 2px;
marker-start: url(#markerCircle);
marker-end: url(#markerCircle);
marker-mid: url(#markerCircle);
}
// marker svg定义
<svg width="0"
height="0"
style="position: absolute;">
<defs>
<marker id="markerCircle"
markerWidth="8"
markerHeight="8"
refX="4"
refY="4">
<circle cx="4"
cy="4"
r="2.5">
</marker>
</defs>
</svg>
// 直线 svg
<svg>
<line class="line" x1="10"
y1="10"
x2="130"
y2="10"></line>
</svg>
实际效果,起始、终点都ok,中间没有
结论:marker-mid在直线中不起作用
折线
// css 和 marker svg定义一样
// 折线 svg
<svg>
<polyline class="line" points="20,100 50,60 80,80 110,20 140,60 170,40 200,90">
</svg>
实际效果,起始、终点都ok,中间每个转折点都有
结论:marker-mid在折现的每个转折点生效
弧线
// 弧线 svg
<svg>
<path class="line"
d="M30 90 Q115 139 200 90"></path>
</svg>
实际效果,起始、终点都ok,中间没有
结论:marker-mid在弧线中不起作用
贝塞尔
// 贝塞尔 svg
<svg>
<path class="line"
d="M30 100 Q 80 30,100 100 T 200 80" />
</svg>
实际效果,起始、终点都ok,中间也有,但位置不是我想要的
再看另一个贝塞尔
<svg>
<path class="line"
d="M30 100 Q 80 30,100 100,130 65,200 80" />
</svg>
实际效果同上
结论:marker-mid在贝塞尔线中起部分作用
CSS运动路径
既然marker-mid不行,就又尝试了一下CSS运动路径
CSS运动路径是什么?
CSS运动路径全名是 CSS Motion Path;
用这个属性,我们可以控制元素按照特定的路径进行位置变换的动画, 并且,这个路径可以是非常复杂的一条路径。
由于是css动画,所以动画的性能也比较高,动画流畅,画面不卡, 在实现控制物体按照制定路径运动效果的时候,这个是首选。
主要属性有哪些
- offset-path:接收一个 SVG 路径(就是SVG中的Path),以此来确定运动路径
- offset-distance:控制当前元素基于 offset-path 运动的距离, 0%就是开始位置, 100%就是走到路径的终点
- offset-position:指定 offset-path 的初始位置
- offset-rotate:定义沿 offset-path 定位时元素的方向,说人话就是运动过程中元素的角度朝向
居中图标
// css
.circle {
width: 10px;
height: 10px;
border-radius: 50%;
background-color: black;
position: absolute;
offset-distance: 50%; /* 中间位置 */
offset-path: path("M10,10 L100,10");
}
// 小图标
<div class="circle"></div>
// 直线svg
<svg>
<path d="M10,10 L100,10" class="line" />
</svg>
实际效果