D3.js SVG绘图实践:波浪动画

效果图

D3.js SVG绘图实践:波浪动画_第1张图片

TALK IS CHEAP

源码就50多行,比较好看懂。


<html>
  <head>
    <meta charset="utf-8">
    <title>svg动画title>
    <script src="https://d3js.org/d3.v4.min.js">script>
  head>
  <body>
    <svg id="svg-area" width="500" height="200">
      <path fill="rgba(33, 150, 243, 0.4)">path>
      <path fill="rgba(33, 150, 243, 0.6)">path>
    svg>
    <script>
      //波浪动画
      var svg_height = 200,
        svg_width = 500,
        wave_data = [[],[]],
        area = d3.area().y0(svg_height).curve(d3.curveBasis),   //curve会进行平滑处理
        svg_paths = [];
      var max = 100;  //控制速度
      for (var i=0; ivar r = i / max * 2;
        wave_data[0].push(r);           //波浪一
        wave_data[1].push(r + 1);   //波浪二(+1代表偏移π)
      }
      var d = svg_width/(wave_data[0].length-1);
      svg_paths.push(d3.select('#svg-area path:first-child'));
      svg_paths.push(d3.select('#svg-area path:last-child'));
      function area_generator(data) {
        var wave_height = 0.15;     //波浪高度
        var area_data = data.map( function(y,i) {
          return [i * d, svg_height*(1 - (wave_height*Math.sin(y*Math.PI) + 2)/3)]; //+2将范围[-1,1]转成[1,3]
        } );
        return function() {
          return area(area_data);
        };
      }
      function renderWave() {
        svg_paths.forEach(function(svg_path,i){
          svg_path.attr('d', area_generator(wave_data[i]));
          wave_data[i] = getNextData(wave_data[i]);
        });
        requestAnimationFrame(renderWave);
      }
      function getNextData(data) {
        var r = data.slice(1);
        r.push(data[0]);
        return r;
      }
      requestAnimationFrame(renderWave);
    script>
  body>
html>

补充

这估计是我写得最简短的博客之一了,看到这里的同学估计是我的代码没写好,没有简单易懂,下面补充一下实现的思路和涉及到的一些知识点吧。

实现思路

因为之前画过趋势图(D3.js SVG绘图实践:趋势缩略图),所以看到波浪动画,第一想法就是,这不是两个带透明度重叠的区域嘛,让区域动起来就好。

画区域已经在上一篇博客中解决了,这次只不过加了平滑处理:

    area = d3.area().y0(svg_height).curve(d3.curveBasis)    //curve会进行平滑处理

重点是怎么动起来:

  • 方案一:用transform实现平移(一般思路,从左到右,然后移到与开始视觉一样时瞬间移回原点)
  • 方案二:区域不动,区域上边界按照波浪的规律动,重绘区域(实现比较复杂)
  • 方案三:将区域数据平移,重绘区域
function getNextData(data) {
    var r = data.slice(1);
    r.push(data[0]);
    return r;
}

一些知识点:

  • requestAnimationFrame
  • d3.js
  • d3.js区域曲线平滑

总结

实现上没很大的难度,但一开始因为用了Math.sin,波浪起伏的幅度较大,看着不像波浪在上下动,而是在从右往左移动,一开始都想尝试之前的方案二了,后来去看了波浪的效果,发现主要问题出在波浪本来就不是正弦图形那样的,于是改成了0.15 * Math.sin,效果就好多了。

最近在计划手上的React项目重构的事,也在看各类库的源码,希望能有更多的东西和大家分享,共勉。

你可能感兴趣的:(前端)