svg动画小分享

970 阅读2分钟

svg简介和基本学习

前端动效中svg的使用

分享1:路径颜色循环动画

newdemo1_1.gif

这里我们创建了3组动效,矩形,圆,自定义路径。 我们定义4种颜色,通过控制路径动画的俩常用属性stroke-dasharray和stroke-dashoffset来实现,初始化好虚线配置,动态调整虚线偏移完成一段颜色的动画

newdemo_2.gif

然后创建剩余颜色的图形,叠加到上面,调整偏移,完成初始的显示

截屏2021-12-21 下午6.13.30.png

接下来就是帧循环,随着时间来调整每段的偏移完成动画了。

需要注意的是:可以看到的是圆的首尾有很好的连续,矩形的没有连续,原因是矩形的我给每段虚线设置了固定长度,没有正好平铺满矩形周长,圆形的处理成了每段虚线是周长的1/8,这样,4组颜色能正好2次铺满周长

主要代码:

    // 创建svg的元素
    function makeSVG(tag, attrs) {
        var el = document.createElementNS('http://www.w3.org/2000/svg', tag);
        for (var k in attrs)
            el.setAttribute(k, attrs[k]);
        return el;
    }
    // 段的颜色
    var colors = [
        "#ff0000",
        "#00ff00",
        "#0000ff",
        "#ff00ff",
    ];
    // 圆半径
    var cir_radwid = 200;
    // 圆周长
    var cir_pm = 2 * Math.PI * cir_radwid;
    // colors共4段颜色,准备2次铺满
    var cir_line = cir_pm / (colors.length * 2);
    var cir_offset = cir_line * (colors.length - 1);
    // 圆所有路径的存储
    var circlearr = [];
    // 添加圆
    for (var i = 0; i < colors.length; i++) {
        // 每种颜色一个圆
        var one_circle = makeSVG("circle", {
            "cx": 250,
            "cy": 250,
            "r": cir_radwid,
            "fill": "none",
            "stroke-width": 10,
            "stroke": colors[i],
            //重要
            "stroke-dasharray": cir_line + " " + cir_offset,
            //重要
            "stroke-dashoffset": i * cir_offset,
            //连接点的处理
            "stroke-linecap": "round",//butt,square,round
            "id": "circle" + i
        })
        circlearr.push(one_circle);
    }
    // 上帧时间,用来计算时间
    var lastframe = Date.now();
    // 运动的速度
    var rect1_offset = 0;
    // requestAnimationFrame的id
    var updateid = 1;
    // 帧循环
    var loop = () => {
        var ntime = Date.now();
        // 帧间隔
        var passtime = ntime - lastframe;
        if (passtime > 30) {
            passtime = 30;
        }
        // 偏移增量
        rect1_offset += passtime * 100 / 1000;
        for (var i2 = 0; i2 < circlearr.length; i2++) {
            var i2circle = circlearr[i2];
            // 更新偏移实现动画
            i2circle.setAttribute("stroke-dashoffset", (rect1_offset + i2 * cir_offset));
        }
        updateid = requestAnimationFrame(loop);
    }
    loop();

分享2:常见的滚动显示的动画

demo2.gif

这个demo包含了3个效果,一个是路径线的动效,一个是图片的遮罩显示,一个是文字的按照路径移动显示。

路径线的动效

先分段绘制所有的线,分组添加到svg中

    // 宽度
    var svg_wid = document.body.clientWidth;
    // 高度
    var svg_hei = 3500;
    // 0->500的路径,第一段的所有路径
    var p1 = makeSVG("path", {
        "d": "M" + svg_wid / 2 + " 0," +
            "V" + 500,
    });
    // 500->1000的路径,第一段的所有路径
    var p2 = makeSVG("path", {
        "d": "M" + svg_wid / 2 + " " + 500
            + ",h" + svg_wid / 3
            + ",V" + 1000
            + ",h" + (-svg_wid / 3)
    });
    var p2_1 = makeSVG("path", {
        "d": "M" + svg_wid / 2 + " " + 500
            + ",h" + (-svg_wid / 3)
            + ",V" + 1000
            + ",h" + (svg_wid / 3)
    });
    .
    .
    .
    //滚动监听,调整每个path的stroke-dashoffset

路径绘制好后,添加滚动监听,根据滚动位置,来调整路径的虚线偏移完成路径动画

图片的遮罩

添加图片和遮罩,动态调整遮罩位置,完成图片的遮罩动画

    // 设置一个遮罩
    var mask = makeSVG("mask", {
        "id": "mask1"
    });
    // 遮罩的区域
    var rect = makeSVG("rect", {
        "x": svg_wid / 6,
        "y": 0,
        "width": svg_wid / 3 * 2,
        "height": 500,
        "fill": "#ffffff",
        "id":"mask_rect1",
    });
    mask.appendChild(rect);
    // 添加一个图片
    var p2_img = makeSVG("image", {
        "href": "../bannerimg.png",
        "x": svg_wid / 6,
        "y": 500,
        "height": 500,
        "width": svg_wid / 3 * 2,
        "mask": "url(#mask1)"
    })
    
    //滚动监听,调整mask中rect的y

文字的路径移动

使用svg文字的textPath标签设置显示路径,动态调整startOffset属性完成文字动画

    // 文字的显示路径
    var onecurve = makeSVG("path",{
        "id":"curvepath",
        "d":"M"+(100)+" "+1260+","
        +"Q"+(svg_wid/2)+" 2000, "+(svg_wid-300)+" 1450"
    })
    // 文本
    var p4_txt = makeSVG("text",{
        "x":svg_wid/2,
        "y":1650,
        "text-anchor":"middle",
        "font-size":88,
        "stroke-width":2
    });
    // 路径文本
    var p4_txtpath = makeSVG("textPath",{
        "href":"#curvepath",
        "startOffset":"100%"
    })
    p4_txtpath.innerHTML = "点个赞再走";
    p4_txt.appendChild(p4_txtpath);
    //滚动监听,调整p4_txtpath的startOffset

代码在:gitee.com/zjz1995/svg… test7和8中