zoukankan      html  css  js  c++  java
  • d3.js 入门指南

      说到数据可视化,我们会行到很多优秀的框架,像echarts、highcharts,这些框架很优雅,健壮,能满足我们对可视化的大部分需求,但是缺点也很明显,就是这些框架几乎是不可定制化的,当遇到特殊的需求,那就太难了。这个时候,聪明的小伙伴会转而学习一些基础的,定制化程度更高的框架,而其中最杰出的就是D3.js,由于我是专为北京地铁定制化软件,经常会用到数据可视化,废话不多说先上北京地铁路网,因为今天是入门教程,但是我不想讲svg基础知识,只讲一点基础内容饼图,大佬请绕行。

    1.绘制饼图的预备知识

    1. 1.比例尺的使用
    2. 2.饼图布局的使用
    3. 3.弧生成器的使用

    1.比例尺的使用

      d3中有很多种比例尺,其中有四种经常使用,分别是scaleLinear线性比例尺,scaleOrdinal序数比例尺,scaleBand序数段比例尺,scaleTime时间比例尺。今天我们只介绍序数比例尺。

    const colorList = ["#ffa39e", "#eaff8f", "#87e8de", "#ffd591", "#91d5ff", "#ffadd2", "#ffe58f"];
    const color = d3.scaleOrdinal()
            .domain(colorList.map((d,i) => i))
            .range(colorList)

    使用序数比例尺将索引和颜色对应,如color(1) --> "#eaff8f"

    2.饼图布局的使用

    d3中同样有很多种布局,布局并没有绘制的作用,他只是将原始数据转换成绘制图形所需要的数据的方法。饼图布局就是将数据转换成绘制饼图所需要的数据,如startAngle,endAngle,index,data等数据。

    let pie = d3.pie().sort(null).value(d => d.number);

      sort方法是先将传入方法的数据做排序处理,默认降序,null参数,即保留原数据局顺序。
      value方法是选择布局要处理的数据,即按照传入对象的number属性值排序。既然布局是一个方法,那么试用起来非常简单

    var pieData = pie(dataset);

      这里pieData就是我们需要的数据

    3.弧生成器的使用

      d3中大部分图形都是通过path绘制的,弧生成器,就是将数据绘制出path的d属性。

    let arc = d3.arc().innerRadius(100).outerRadius(200);

      innerRadius为绘制弧的内径,outerRadius为绘制弧的内径,使用方式如下

    arc({startAngle: 0, endAngle: 2})

      因为我们的布局就是将数据处理成startAngle,endAngle这种形式,那么画出饼图就变得非常简单

    selection.data(pieData)
         .enter()
         .append('path')
         .attr('d', (d) => arc(d))

      这就生成了一个饼图。

    2.完整的画一个饼图

    1.分组

      想做好一个d3的项目,分析必不可少,好的分组能代码更简洁优雅。饼图大致分四个部分

    1. 弧形部分
    2. 虚线部分
    3. 文字部分
    4. 中心详情部分
    group.append('g').attr('class', 'pies');
    group.append('g').attr('class', 'lines');
    group.append('g').attr('class', 'texts');
    const centersT = group.append('g').append('text').attr('x', 0).attr('y', 0).attr('text-anchor', 'middle').attr('dy', '-1.6em').attr('font-size', 30).attr('fill', 'none').attr('stroke', '#888').text('');
    const centersC = group.append('g').append('text').attr('x', 0).attr('y', 0).attr('text-anchor', 'middle').attr('dy', '0em').attr('font-size', 30).attr('fill', 'none').attr('stroke', '#888').text('');
    const centersB = group.append('g').append('text').attr('x', 0).attr('y', 0).attr('text-anchor', 'middle').attr('dy', '1.6em').attr('font-size', 30).attr('fill', 'none').attr('stroke', '#888').text('');

      这里中心详情部分我为了简单就没有分组。只把三大块分了组。

    2.生成数据方法

    const initData = () => {
      dataset = dataset.map( d => {
        return {
          name: d.name,
          number: Math.floor(Math.random() * 1000 + 100)
        }
      })
    }

    3.使用merge()方法将数据更新。

      merge()方法可以把update和enter部分的操作合一,更加方便数据更新。

    let pathUpdate = group.select('.pies').selectAll('path.pie').data(pieData)
    let pathEnter = pathUpdate.enter().append('path');
    pathEnter.merge(pathUpdate)
         .attr('fill', (d,i) => color(i))
         .attr('class', 'pie')
         .attrTween('d', function (d) {
            return arc(d)
         })

    4.绘制折线

      因为每次数据的变化势必会影响折线的位置,这里要做一些计算

    let polylineUpdate = group.select('.lines').selectAll('polyline').data(pieData);
    let polylineEnter = polylineUpdate.enter().append('polyline');
    
    polylineEnter.merge(polylineUpdate)
             .attr('fill', 'none')
             .attr('stroke', '#333')
             .attr('stroke-dasharray', '5,5')
             .attr('points', d => {
              let direction = (d.startAngle + d.endAngle < Math.PI * 2 ? 1 : -1);
              return [arc.centroid(d), arc.centroid(d)[0] * 1.6, arc.centroid(d)[1] * 1.6, (innerRadius + outerRadius) * direction, arc.centroid(d)[1] * 1.6]
             })

      这里的arc.centroid(d)为当前扇形的中心坐标,arc.centroid(d)[0]为x坐标,arc.centroid(d)[1]为y坐标。

    (d.startAngle + d.endAngle < Math.PI * 2 ? 1 : -1);

      这段代码是判断扇形是属于左半面还是右半面。

    5.加入一些动画。

      transition(动画)能让图形更加优雅的变化。这里主要是学习一下attrTween,直接看文档我就不多说了。具体代码请移步至饼图

      后续将发布更多的教程。

    原创博客:转载请注明d3.js 入门指南

     

  • 相关阅读:
    JAVA中的注解小结
    终结任务
    共享资源访问
    基本线程机制
    HashSet、LinkedHashSet、TreeSet
    EnumMap
    LinkedHashMap及其源码分析
    集合迭代器快速失败行为及CopyOnWriteArrayList
    LinkedList
    比特币中的Base58 编码
  • 原文地址:https://www.cnblogs.com/vadim-web/p/11270850.html
Copyright © 2011-2022 走看看