美文网首页
使用d3的心得

使用d3的心得

作者: HelenYin | 来源:发表于2017-02-17 20:11 被阅读0次

    两次在项目中用到d3都是做tree这种树状的流程图,所以就针对d3谈一下我个人的心得体会,然后再做一个简单例子展示一下图形,最后谈一谈在项目中踩到的坑。

    但是在讲d3之前需要了解一下数据驱动的思想和svg。

    1. 首先,说一下我理解的数据驱动的思想

    在进行数据可视化的时候,最重要的一点就是将数据和对应的DOM元素关联起来,然后将用户需要的数据展示在DOM元素上,d3提供了方法,能够方便的将数据和DOM进行绑定。
    那么数据驱动又是怎么回事呢?
    一开始,页面上除了一个图形的container元素用来包裹整个图形,是没有其他元素的。现在我们开始向后端请求数据,前端拿到数据之后,当然是一对杂乱无章的不知道什么东西,我们需要做的是将这堆数据在DOM元素上展示出来,但是我们并不知道需要多少DOM元素,这里d3向我们提供了一个方法 ,可以告诉d3我们需要什么元素,然后在container中选择该元素,然后就开始向这个元素上添加一点数据,方法是selection.data(),这里的selection暂时一个都没有,但是不用着急, 我们可以将从后端取到的数据绑定在这个空的selection上。 这里selection为空,但是我们的数据有很多,这怎么办呢?这里再使用selection.enter()方法,数据实际使用了占位符,d3这里知道多出了多少数据没有实际的DOM元素绑定(好可怜的数据们啊),最后使用append()方法,将多出的数据添加上DOM元素,将他们绑定在一起。数据们终于找到落脚之处,我也就放心了。到目前为止,我们终于可以将绑定好的数据用在DOM上,进行可视化的渲染。可以用数据的大小来改变div的宽度,可以根据数据的不同改变<rect>的颜色等等。当我们的数据改变的时候,图形会相应的改变,而不用我们再去重新计算dom的样式,这样我们可以将更多的精力放在数据操作上,而不是一直操作DOM。
    因为我们项目中使用了Vue.js,Vue的数据双向绑定也是数据驱动的思想,当数据变动的时候,页面上的数据自动改变,而不需要我们去手动操作DOM,如果使用过一些框架的开发者来说,理解这个概念更容易。

    2. SVG

    其实SVG本身很简单,但是为什么这里要说呢,因为说了,d3操作DOM很简单,所以,作图的时候用SVG比使用canvas方便多咯?但并不是说不能用canvas,可以看看官方的实例,还是有一些是使用canvas做的。
    这里想说一下SVG的<g>元素,它可以将多个元素组织在一起,由g元素编组在一起的svg元素可以设置相同的颜色,可以进行坐标变换。像这样:

     <svg width="100%" height="100%" version="1.1"
    xmlns="http://www.w3.org/2000/svg">
        <g fill="dodgerblue">
          <rect x="10" y="10" width="40" height="40" ry="10" />
          <rect x="80" y="80" width="40" height="40" ry="10" />
          <rect x="150" y="150" width="40" height="40" ry="10" />
      </g>
    </svg>
    

    上面所有的rect元素都是由dodgerblue颜色填充

    当然,要做图还要了解坐标和viewbox的概念,坐标的概念默认开发者都知道,viewbox可能需要查阅资料,这里延伸开说就太多了。

    3. 下面就实战作一个图

    我们在做数据可视化的时候,最常用和比较简单的就是柱状图,所以我们就从柱状图入手。做好之后的效果图是这样:


    QQ20170217-0.png

    首先,需要一个div作为container包裹住整个图形,div的id为chart
    这里我们先模拟一个后端传回来的数据:
    var data = [4, 8, 15, 16, 23, 42];
    下面这段代码是控制div的显示范围,因为数字可能很大,也可能很小,为了用户在视觉上看起来体验更好,d3能够将图形展示在设置的范围内

    var x = d3.scale.linear()
        .domain([0, d3.max(data)])
        .range([0, 420]);
    
    //现在进行数据绑定
    d3.select(“.chart")       //选择container
        .selectAll(“div")       //选择我们将要添加的DOM元素
        .data(data)             //将数据绑定在一个空的DOM元素上
        .enter()                   //数据形成占位符
        .append(“div”)        //将多出来的data数据添加上DOM
        .attr(‘class’, ‘item’)  //将每个div添加一个class
    //接下来我们就可以将数据进行可视化操作了
    d3.selectAll(‘.item’)                    //选择所有的item
        .style("width", function(d) {    //控制style的width,使div的width样式和数据相同
            return x(d) + "px";             //这样就能根据数据的不同呈现不同的效果
        })
        .text(function(d) { return d; });// 这里讲具体的数据显示出来
    

    以上代码就能展示出一个最简单的树状图

    4.项目中踩到的坑

    我们用了dagreD3这个插件来做流程图,遇到的一个问题就是,当两个节点之间有多条线的时候,d3只显示后面数据的那根线,看到的也就只有一根线了像这样:

    389A4BBC-3874-4FAE-8F36-3AC37CAC057F.png
    原本a1a3之间有两条线,但是合并成了一条。
    我在github上也发现有人跟我提出了同样的issue

    后来想到了一个办法,将所有线上的数据数据都做成节点,然后再将节点的样式做成一根线的样子,看起来就是一个流程线上的数据,就像这样:


    5D985328-2231-4BBA-A696-05C908175AEB.png

    我们只需要后端修改数据结构,前端只用稍稍修改一下样式,整个图形就会变成我们想要的样子。

    相关文章

      网友评论

          本文标题:使用d3的心得

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