阿里云地图流量动画效果的实现分析

预览

阿里云的:
preview1.gif

实验品:
preview2.gif

原理

阿里云的流量动画是先画出一条线,然后改变每个关键颜色的offset,实现类似抛投的效果;渐变的结构如下:

7451DFEF-A99C-4777-B035-FB1F501F5093.png

实现

这里只画出一条简单的直线作为例子,如果需要画出曲线,d3的geo相关的函数可以很方便的作出。

C1B9DB0B-3364-404F-BCAE-682BB2FD942D.png

代码如下:

(function () {

    var svg = d3.select("#container")
                .append("svg")
                .attr("width", 500)
                .attr("height", 200);
    var gradient = svg.append("defs")
                      .append("linearGradient")
                        .attr("id", "gradient")
                        .attr("x1", "0%")
                        .attr("x2", "100%");
    var stops = [];
    var stop;
    stop = gradient.append("stop").attr("stop-opacity", 1).attr("offset", "0%")
        .attr("stop-color", "rgba(255, 255, 255, 0)");
    stops.push(stop);

    // start stop
    stop = gradient.append("stop").attr("stop-opacity", 1).attr("offset", "0%")
        .attr("stop-color", "rgba(255, 255, 255, 0)");
    stops.push(stop);

    // start color
    stop = gradient.append("stop").attr("stop-opacity", 1).attr("offset", "0%")
        .attr("stop-color", "rgba(255, 255, 255, 0)");
    stops.push(stop);

    // end color
    stop = gradient.append("stop").attr("stop-opacity", 1).attr("offset", "100%")
        .attr("stop-color", "#009a61");
    stops.push(stop);

    // end stop
    stop = gradient.append("stop").attr("stop-opacity", 1).attr("offset", "100%")
        .attr("stop-color", "rgba(255, 255, 255, 0)");
    stops.push(stop);

    stop = gradient.append("stop").attr("stop-opacity", 1).attr("offset", "100%")
        .attr("stop-color", "rgba(255, 255, 255, 0)");
    stops.push(stop);


    var route = svg.append("line")
                    .attr("x1", 0)
                    .attr("y1", 100)
                    .attr("x2", 500)
                    .attr("y2", 200)
                    .style("stroke", "url(#gradient)")
                    .style("stroke-width", 4)
                    .style("stroke-linecap", "round")
                    .style("fill", "none");

    var myoffset = 0;
    setInterval(function () {
        myoffset += 1;
        stops.slice(1, 3).forEach(function (stop, i) {
            stop.attr("offset", (myoffset - 20) + "%");
        });
        stops.slice(3, 5).forEach(function (stop, i) {
            stop.attr("offset", myoffset + "%");
        });
        if (myoffset >= 100) {
            myoffset = 0;
        }
    }, 100);
})();

标签: none

添加新评论