我试图在贝塞尔曲线的中点放置一个箭头。在问题How properly shift arrow head on cubic bezier in SVG to its center中使用<animateMotion>
的解决方案仅在Firefox中有效,该解决方案移动箭头即箭头<path>
并将其冻结在贝塞尔曲线的中间。由于在我的情况下曲线的点经常变化,因此我不想使用marker-mid
,因为每次计算贝塞尔曲线的中点都比较昂贵。
<svg viewBox="0 0 500 500">
<g>
<path id="path1" d="M291.698 268.340 C321.698 268.340, 411.904 93.133 441.904 93.133"></path>
<path class="path_arrow" d="M0,0 L6,6 L0,12" transform="translate(-3,-6)">
<animateMotion dur="0s" rotate="auto" fill="freeze" keyTimes="0;1" keyPoints="0.5;0.5">
<mpath xlink:href="#path1"></mpath>
</animateMotion>
</path>
</g>
<g transform="translate(166.698,243.340)">
<circle r="5" class="p1"></circle>
</g>
<g transform="translate(441.904,68.133)" >
<circle r="5" class="p2"></circle>
</g>
</svg>
有什么方法可以使用CSS动画来避免使用<animateMotion>
吗?
编辑1:
此处的曲线端点是可拖动的,因此曲线的点倾向于频繁变化。动画是将箭头移动到曲线的中心,而不计算中点。
编辑2:
感谢Kaiido的评论,我添加了calcMode="linear"
,现在箭头已按预期放置在路径上。但是,当我通过拖动来重新定位端点时,箭头在Chrome中停留在其初始位置(如图所示),但预计它将沿着父路径移动。在Firefox中,它可以像以前一样正常工作。
答案 0 :(得分:2)
您可以使用CSS offset-path
,offset-distance
和offset-rotate
属性来实现相同的目的:
var startDate = moment().subtract(1, 'months').format('YYYY-MM-DD');
var endDate = moment().format('YYYY-MM-DD');
const data = {
labels: [startDate, endDate],
//rest of the code
}
#path1 {
fill: none;
stroke: black;
}
.path_arrow {
transform: translate( -3px, -6px );
offset-path: path("M220 104C220 144,400 180,400 224");
offset-rotate: auto;
offset-distance: 50%;
}
body { background: white; }
但是their browser support远低于the one of SMIL,所以我不推荐它。
请注意,我确实修复了the answer there缺失的<svg width="500" height="500" >
<path id="path1" d="M 220 104 C 220 144 400 180 400 224"
fill="none" stroke-width="2" stroke="black" />
<path class="path_arrow" d="M0,0 L0,12 L12,6 z" />
</svg>
属性,以使Blink浏览器满意。
如果您需要IE支持,则可以尝试使用似乎支持calcMode="linear"
和<animateMotion>
的{{3}},但要记住我并不是自己测试的。
Chrome确实确实需要显式调用才能更新rotate
。可以通过在每次更新后调用<mpath>
元素的this js implementation方法来实现:
<animationMotion>
document.querySelector('svg').onmousemove = function(e) {
const rect = this.getBoundingClientRect();
const x = e.clientX - rect.left;
const y = e.clientY - rect.top;
path1.setAttribute( 'd', `M ${x} ${y} C 220 144 400 180 400 224` );
// Chrome requires an explicit update
document.querySelector('animateMotion').beginElement();
}
答案 1 :(得分:0)
您必须在CSS内使用Webkit动画。我也建议https://codepen.io/collection/yivpx/。是用于SVG优化的开源项目。我还建议您在SVG中命名所有类,以便通过动画制作酷炫的CSS素材,例如:
animation: kaboom 5s ease alternate infinite;