美文网首页
Js+SVG 柱状图 & D3+SVG 柱状图

Js+SVG 柱状图 & D3+SVG 柱状图

作者: bei6 | 来源:发表于2019-11-25 23:59 被阅读0次

    Js+SVG 柱状图

    <!DOCTYPE html>
    <html lang="en">
    
    <head>
      <meta charset="UTF-8" />
      <meta name="viewport" content="width=device-width, initial-scale=1.0" />
      <meta http-equiv="X-UA-Compatible" content="ie=edge" />
      <title>Document</title>
      <style>
        svg,
        .container {
          box-sizing: border-box;
          padding: 8px;
          border-radius: 3px;
          border: 1px solid #ddd;
        }
    
        svg {
          background-color: #f1f1f1;
        }
    
        .container {
          background-color: #fff;
        }
      </style>
    </head>
    
    <body>
      <div class="container"></div>
      <script>
        onload = function () {
          let width = '100%',
            height = 256,
            barHeight = 16;
    
          let dataset = new Array(15);
          for (let i = 0; i < dataset.length; i++) {
            (dataset[i] = Number.parseInt(Math.random() * 1000, 10));
          }
    
          let body = document.querySelector('.container');
    
          let svg = document.createElementNS('http://www.w3.org/2000/svg', 'svg');
          svg.setAttribute('width', width);
          svg.setAttribute('height', height);
    
          dataset.forEach((v, idx) => {
            let r = document.createElementNS('http://www.w3.org/2000/svg', 'rect');
            r.setAttribute('y', barHeight * idx);
            r.setAttribute('width', v);
            r.setAttribute('height', barHeight - 4);
            r.setAttribute('fill', '#369');
            r.setAttribute('ry', '2px');
            r.setAttribute('fill-opacity', 0.85);
            svg.appendChild(r);
    
            let t = document.createElementNS('http://www.w3.org/2000/svg', 'text');
            t.setAttribute('x', v + 4);
            t.setAttribute('y', (idx + 1) * barHeight - 6);
            t.setAttribute('font-size', '0.75em');
            t.textContent = v;
            svg.appendChild(t);
          });
    
          body.appendChild(svg);
        };
      </script>
    </body>
    
    </html>
    

    D3+SVG 柱状图

    <!DOCTYPE html>
    <html lang="en">
    
    <head>
      <meta charset="UTF-8">
      <meta name="viewport" content="width=device-width, initial-scale=1.0">
      <meta http-equiv="X-UA-Compatible" content="ie=edge">
      <title>Document</title>
    </head>
    
    <body>
      <style>
        svg,
        .container {
          box-sizing: border-box;
          padding: 8px;
          border-radius: 3px;
          border: 1px solid #ddd;
        }
    
        svg {
          background-color: #f1f1f1;
        }
    
        .container {
          background-color: #fff;
        }
      </style>
      <div class="container"></div>
      <script src="../../source/d3.js"></script>
    
      <script>
        let width = '100%',
          height = 256,
          barHeight = 16;
    
        let dataset = new Array(15);
        for (let i = 0; i < dataset.length; i++) {
          (dataset[i] = Number.parseInt(Math.random() * 1000, 10));
        }
    
        let svg = d3.select('.container').append('svg');
        svg.attr('width', width)
          .attr('height', height);
    
        let rectes = svg.selectAll('rect')
          .data(dataset)
          .enter()
          .append('rect');
    
        rectes
          .attr('y', (item, idx) => idx * barHeight)
          .attr('width', item => item)
          .attr('height', barHeight - 4)
          .attr('ry', '2px')
          .attr('fill-opacity', 0.85)
          .attr('fill', '#369')
    
        let title = svg.selectAll('text')
          .data(dataset)
          .enter()
          .append('text');
    
        title.attr('x', item => item + 4)
          .attr('y', (_, idx) => (idx + 1) * barHeight - 6)
          .attr('font-size', '0.75em')
          .text(item => item)
      </script>
    </body>
    
    </html>
    

    Js vs D3

    效果预览

    两个段代码实现的效果是相同的.

    总的来说, 通过比较上述代码, 可以看的出来:

    1. 创建 SVG 元素

    Js 创建一个 SVG 元素相对复杂, 需要指定 namespaceURI, 通常这个值等于 http://www.w3.org/2000/svg(也可以点击网址查看更多信息), 写作 document.createElementNS('http://www.w3.org/2000/svg', 'svg');

    虽说看起来挺长的, 不过总的来说也并不是那么复杂就是了. 另外, 关于 namespaceURI, vscode 的提示信息内可以复制到, 其他编辑器并未测试.


    vscode namespaceURI 提示

    D3 创建一个 SVG 元素就很简单了, Selection.append('svg');.

    1. 编程方式

    Js 是普通的逐行编写.

    D3 看起来更加倾向于链式.

    1. 批量生成元素

    Js 需要书写遍历函数, 在循环体内编写创建 SVG 元素的代码.

    D3 不需要我们自己来写遍历函数, 采用了 .data(dataset).enter().append(元素名) 的方式自动补全元素.

    1. 补齐元素(本例并不明显)

    这个所谓的补齐元素的概念, 其出发点可能是为了性能优化吧, 具体来讲就是:

    当文档中已经存在了 N 个 rect 元素(就拿 rect 元素举例), 然后由于某种原因, 原本对应这 N 个 rect 元素的数组发生了改变, 变成了 M 个.

    此时如果不考虑那么多, 直接移除所有的 rect 在重新遍历一遍显然也不是不行! 不过总感觉如此大量的删/插元素并不是什么好的选择.

    可能是因此, D3 才提出了补齐/删齐元素的说法, 以求尽量少的删/插元素吧.

    总之此时:

    Js 可能需要计算了, 比如现有 N 个元素, M 个数据; 需要划分 3 中情况来分别进行编写.

    D3 提供了一段通用的代码

    // Update 情形2
    var p = d3.select("body")
        .selectAll("p")
        .data([4, 8, 15, 16, 23, 42])
        .text(function(d) { return d; });
    
    // Enter 情形1
    p.enter().append("p")
        .text(function(d) { return d; });
    
    // Exit 情形3
        p.exit().remove();
    

    结语

    就制作一个简单的条形图而言, 还没有特别强烈的感到使用 D3 能够带来莫大的好处.

    相关文章

      网友评论

          本文标题:Js+SVG 柱状图 & D3+SVG 柱状图

          本文链接:https://www.haomeiwen.com/subject/ermswctx.html