html的svg路径,SVG Path路径在网页开发的作用

原标题:SVG Path路径在网页开发的作用

作者:会编程的银猪

www.yinchengli.com/2018/06/17/svg-path/

SVG是矢量图形表示,它的一个强大之处在于path标签可以表示任意的矢量形状,利用好这个path可以做出很多传统html/css做不出来的效果。下面举几个例子。

1. 做路径动画

这个我在《SVG导航下划线光标跟随效果》文后补充介绍了这个实现,最后的效果是这样的:

fc56e25f5524e976e9c012f0285579a7.gif

实现代码如下:

2383641c1df394b39e8a2395fed5f88c.png

利用animateMotion结合path做的动画,具体说明可见上文。

2. 实现不规则形状的点击

如下图所示,需要实现点到哪个洲就进入哪个洲的效果,例如点到非洲就进入非洲:

039750ca404e0e636950cc811179bbac.png

我们可以用div定一个框盖在非洲的上面,但是用div的话只能是规则的四方形,没办法实现点到非洲大陆的时候才进入,但是大陆的轮廓又是不规则的,所以用传统html是不能解决这个问题的。但是用SVG的path可以解决这个问题,方法1是监听path的点击事件即可,如下图所示:

b3a1501c595b6a718d89d7cbb23d89cb.png

因为这个轮廓可以跟UI要到,他们一般都是用AI/PS等矢量软件画出来的,让他们导一个SVG给你就好了。

方法2是可以调SVG的isPointInFill这个API判断点击的点是否在Path的fill区域里面,这个也可以实现,但是相对于方法1来说比较麻烦,因为还需要把鼠标的位置转换为svg视图的位置。

3. 沿着路径拖拽的交互

在第1点沿着路径的动画是自动的过程,有没有办法让用户自己拖拽过去呢,实现如下效果:

90be8ce6e18433bc23a6ee273611426a.gif

这种的场景有音量控制等需要有百分比控制的。可以先用一个SVG的在线工具画出一个这样的图形:

642621f748d4f4d031ad24ce98cdb227.png

就可以拿到SVG的代码:

这里比较关键的是path标签里的d属性,d是data的缩写,定义这个路径的形状,它里面可以用很多属性控制形状的变化,如下图所示:

86ef7269168f3708f499293b6840f544.png

为了实现这个交互,需要动态地改变circle的圆心位置(cx, cy)到路径上相应的地方。SVG没有直接提供相关的API,但是它提供了一个可以间接利用的API叫getPointAtLength,传递一个长度参数,如下代码所示:

letvolumnPath=document.querySelector('.volumn-path');

// 输出path在长度为100的位置的点坐标

console.log(volumnPath.getPointAtLength(100));

// 输出当前path的总长度

console.log(volumnPath.getTotalLength());

控制台输出:

08583620a385a3eb54004d3f6865f736.png

把circle的cx/cy改成上面的x/y坐标,圆圈就会跑到对应的位置去了:

11580a0189fe7649cf653a90d9be1441.png

这里的问题在于这个API传递的length参数是相对于曲线长度的,但是鼠标移动的位置是线性的,没办法直接知道当前鼠标在曲线上距离起始位置多少。

所以需要算一下,在这个场景里面我们可以取鼠标的x坐标在曲线上对应的位置就可以了,如下图示意:

872bf18927baf7ac2322309d1921fbef.png

到这里就有思路了,可以把这条路径上每隔一个像素长度就算一下它的坐标在哪里,然后存在一个数组里面。由于鼠标移动的时候x坐标是知道的,就可以查一下在这个数组里面相应x坐标的y坐标是多少,就能得到想要的圆心位置了。

所以先计算一下,保存到一个数组:

let$volumnController=document.querySelector('.volumn-controller'),

$volumnPath=$volumnController.querySelector('.volumn-path');

// 得到当前路径的总长度

letpathTotalLength=$volumnPath.getTotalLength()>>0;

letpoints=[];

// 起始位置为长度为0的位置

letstartX=Math.round($volumnPath.getPointAtLength(0).x);

// 每隔一个像素距离就保存一下路径上点的坐标

for(leti=0;i

letp=$volumnPath.getPointAtLength(i);

// 保存的坐标用四舍五入,可以平衡误差

points[Math.round(p.x)-startX]=Math.round(p.y);

}

这里用一个p0ints数组来保存,它的索引index就为x坐标,值为y坐标。在这个例子里面,总长度为451.5px,得到的points数组长度为388. 你可以隔0.5px长度就保存一个坐标,不过在这个例子里面1px就够了。

然后监听鼠标事件,得到x坐标,查询y坐标,动态地改变circle的圆心位置,如下代码所示:

let$dragButton=$volumnController.querySelector('.drag-button'),

// 得到起始位置相对当前视窗的位置,相当于jQuery.fn.offset

dragButtonPos=$dragButton.getBoundingClientRect();

functionmovePoint(event){

// 当前鼠标的位置减去圆心起始位置就得到移位偏差,12是半径值,这里先直接写死

letdiffX=event.clientX-Math.round(dragButtonPos.left+12);

// 需要做个边界判断

diffX<0&&(diffX=0);

diffX>=points.length&&(diffX=points.length-1);

// startX是在上面的代码得到的长度为0的位置

$dragButton.setAttribute('cx',diffX+startX);

// 使用points数组得到y坐标

$dragButton.setAttribute('cy',points[diffX]);

}

$dragButton.addEventListener('mousedown',function(event){

document.addEventListener('mousemove',movePoint);

});

document.addEventListener('mouseup',function(){

document.removeEventListener('mousemove',movePoint);

});

这个实现的代码也是比较简单,需要注意的地方是起始位置的选取,这里有两个坐标系,一个是相对页面的视窗的,它的原点(0, 0)坐标点是当前页面可视区域(client)的左上角,第二个坐标系是SVG的坐标系,它的原点(0, 0)位置是SVG画布的左上角,如下图所示:

4fb9461c5d4ee4eed0f3b86cb9fd13e3.png

鼠标的位置是相对于视图client的,所以需要得到圆圈在client的位置,可以通过原生的getBoundingClient获取,然后用鼠标的clientX减掉圆圈的clientX就得到正确的位移偏差diff了,这个diff值加上圆圏的在svg坐标的起始位置就能得到svg里的x坐标了,然后去查一下points数组就能得到y坐标,然后去设置circle的cx/cy值。

这个的实现已经算是十分简单的,大概30行代码。需要注意的是如果svg缩放了,那么坐标也要相应比例地改一下。所以最好是不要缩放,1:1显示就简单多了。

如果要显示具体的音量值呢?这个也好办,只需要在第一步保存点坐标的时候把在路径上的长度也保存下来就好了,最后效果如下:

cc7470803ae80d1c5420cedd0fed9f66.gif

一个完整的demo:svg-path-drag.html(https://www.yinchengli.com/html/demo/svg-path-drag.html)

如果路径比较复杂怎么办呢,一个x坐标可能会对应两个点,如下图所示:

456e244386cec6ef236e63eaea50db98.png

这个也是有办法的,计算的方法类似,也是需要把路径上所有每隔1px的点坐标都取出来,然后计算一下鼠标的位置距离哪个点的坐标最接近,然后就取那个点就好了。当然在判断哪个点最优时,算法需要优化,不能直接一个for循环,具体可见这个codepen。

4. 路径的变形动画

路径结合关键帧可以做出一些有趣的效果,如这个codepen的示例:

fa5edf8652233c83bb60933804db16d2.gif

它的实现是hover的时候改变path的d值,然后做d的transition动画,如下代码:

.svg-1:hover path{

d:path("M8,2 L2,8");

}

path{

transition:d0.5slinear;

}

这种变形过渡动画是有条件的,就是它的路径数据格式是要一致的,有多少个M/L/C属性都要保持一致,否则无法做变形动画。

5. 结合clip-path做遮罩效果

使用CSS通常只能用border-radius做一些圆角的遮罩,即用border-radius结合overflow: hidden实现,但是使用clip-path + svg的路径能够做出任意形状遮罩,如下做一个心形的:

3a329cd2977d6abd69798838d0cf6853.png

如下代码所示:

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
Vue是一种流行的JavaScript框架,它可以方便地创建可交互的用户界面。在Vue中,使用SVG路径动画可以实现各种有趣的效果。 首先,要在Vue项目中使用SVG路径动画,需要安装vue-svg路径动画扩展。可以通过运行`npm install vue-svg-path-animation`命令来安装。 一旦安装完成,就可以在Vue组件中使用SVG路径动画了。首先,需要在Vue组件中引入`vue-svg-path-animation`模块。然后,可以在组件的`data`选项中创建一个属性来存储SVG路径。这个属性可以在`<svg>`元素的`d`属性中使用。 接下来,可以使用Vue的生命周期钩子函数来触发SVG路径动画。例如,在`mounted`钩子函数中可以使用`setPath`方法来更新SVG路径属性,从而触发动画。可以在该钩子函数中设置一定的延迟,以便动画效果更加明显。 除了在`mounted`钩子函数中触发动画,还可以根据需要在其他钩子函数中实现动画效果。例如,在`created`钩子函数中初始化SVG路径属性,然后在`beforeDestroy`钩子函数中清除SVG路径属性,以停止动画。 在Vue组件中使用SVG路径动画可以为用户提供一种更加丰富和吸引人的交互体验。通过使用Vue的生命周期钩子函数和`vue-svg-path-animation`扩展,可以轻松地实现各种有趣的SVG路径动画效果。这不仅可以使用户界面更加生动,还可以提高用户对网站或应用程序的参与度和满意度。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值