「数据可视化库王者」D3.js 极速上手到Vue应用

论坛 期权论坛 期权     
高级前端进阶   2019-7-27 15:01   2696   0
戳蓝字「高级前端进阶」关注我们哦!
[h1]前言[/h1]
  1. D3
复制代码
近年来一直是
  1. JavaScript
复制代码
最重要的数据可视化库之一,在创建者
  1. MikeBostock
复制代码
的维护下,前景依然无量,至少现在没有能打的:
    1. D3
    复制代码
    与众多其他库的区别在于无限定制的能力(直接操作
    1. SVG
    复制代码
    )。
  • 它的底层
    1. API
    复制代码
    提供对原生
    1. SVG
    复制代码
    元素的直接控制,但它也带来了高学习曲线的成本。
  • 我们将把
    1. D3
    复制代码
    1. Vue
    复制代码
    结合在一起 - 使用
    1. Vue
    复制代码
    的动态数据绑定,清晰的语法和模块化结构,可以充分发挥
    1. D3
    复制代码
    的最佳性能。
    根据广泛定义,D3可拆分为以下几种分库:


  • 绝大部分的
    1. D3
    复制代码
    课程或书籍,都会着重讲解在其
    1. DOM
    复制代码
    操作功能上,但这明显与近几年来的web框架理念相违背。
  • 用于数据可视化的
    1. D3
    复制代码
    ,其核心在于使用绘图指令装饰数据,从源数据创建新的可绘制数据,生成
    1. SVG
    复制代码
    路径以及从数据和方法在
    1. DOM
    复制代码
    中创建数据可视化元素(如轴)的功能。

  • 有许多用于管理DOM的工具,所有这些工具都可以在
    1. D3
    复制代码
    中集成数据可视化功能。这也是
    1. D3
    复制代码
    能与
    1. Vue
    复制代码
    无缝结合的原因之一。
于此,我们不需要从
  1. D3 DOM
复制代码
操作功能开始学起,直接通过实例来入门
  1. D3
复制代码

[h1]D3.js 渐进入门[/h1]以下实例的模版均为以下形式:
    1. [/code]
    2. [*][code]   
    复制代码
    1.         
    复制代码
    1.         Learn D3.js
    复制代码
    1.    
    复制代码
    1.    
    复制代码
    1.         
    复制代码
    1.         First heading
    复制代码

    1.         
    复制代码
    1.         
    复制代码
    1.    
    复制代码
    1. [/code]
    2. [/list][h2]1. 选择和操作[/h2][img]https://201907.oss-cn-shanghai.aliyuncs.com/wc/1811847-262563bf3aa8c8bf2c71b50213cfe7b8[/img]
    3. 你需要学习的第一件事是如何使用D3.js选择和操作DOM元素。该库在操作DOM方面实际上非常强大,因此理论上可以将其用作 [code]jQuery
    复制代码
    的替代品。以下代码请逐行添加运行。
      1. // index.js
      复制代码
      1. d3.select();
      复制代码
      1. d3.selectAll();
      复制代码

      1. d3.select('h1').style('color', 'red')
      复制代码
      1. .attr('class', 'heading')
      复制代码
      1. .text('Updated h1 tag');
      复制代码

      1. d3.select('body').append('p').text('First Paragraph');
      复制代码
      1. d3.select('body').append('p').text('Second Paragraph');
      复制代码
      1. d3.select('body').append('p').text('Third Paragraph');
      复制代码

      1. d3.selectAll('p').style('')
      复制代码
    [h2]2.数据加载和绑定[/h2]
    当你要创建可视化时,了解如何加载数据以及将其绑定到DOM非常重要。所以在这个实例中,你将学到这两点。
      1. let dataset = [1, 2, 3, 4, 5];
      复制代码

      1. d3.select('body')
      复制代码
      1.     .selectAll('p')
      复制代码
      1.     .data(dataset)
      复制代码
      1.     .enter()
      复制代码
      1.     .append('p') // appends paragraph for each data element
      复制代码
      1.     .text('D3 is awesome!!');
      复制代码
      1.     //.text(function(d) { return d; });
      复制代码
    [h2]3.创建一个简单的柱状图[/h2]
    首先需要添加一个
    1. svg
    复制代码
    标签
      1. Bar Chart using D3.js
      复制代码

      1. [/code]
      2. [/list]然后在 [code]index.js
      复制代码
      中添加(已添加关键注释):
        1. // 数据集
        复制代码
        1. let dataset = [80, 100, 56, 120, 180, 30, 40, 120, 160];
        复制代码
        1. // 定义svg图形宽高,以及柱状图间距
        复制代码
        1. let svgWidth = 500, svgHeight = 300, barPadding = 5;
        复制代码
        1. // 通过图形计算每个柱状宽度
        复制代码
        1. let barWidth = (svgWidth / dataset.length);
        复制代码

        1. // 绘制图形
        复制代码
        1. let svg = d3.select('svg')
        复制代码
        1.     .attr("width", svgWidth)
        复制代码
        1.     .attr("height", svgHeight);
        复制代码

        1. // rect,长方形
        复制代码
        1. // 文档:http://www.w3school.com.cn/svg/svg_rect.asp
        复制代码

        1. let barChart = svg.selectAll("rect")
        复制代码
        1.     .data(dataset) //绑定数组
        复制代码
        1.     .enter() // 指定选择集的enter部分
        复制代码
        1.     .append("rect") // 添加足够数量的矩形
        复制代码
        1.     .attr("y", d => svgHeight - d ) // d为数据集每一项的值, 取y坐标
        复制代码
        1.     .attr("height", d => d) // 设定高度
        复制代码
        1.     .attr("width", barWidth - barPadding) // 设定宽度
        复制代码
        1.     .attr("transform", (d, i) =>  {
        复制代码
        1.         let translate = [barWidth * i, 0];
        复制代码
        1.         return "translate("+ translate +")";
        复制代码
        1.     }); // 实际是计算每一项值的x坐标
        复制代码
      [h2]4. 在图形上方显示数值[/h2]

      这时就需要在上述代码中创建
      1. svg
      复制代码
      1. text
      复制代码
      文本
        1. let text = svg.selectAll("text")
        复制代码
        1.     .data(dataset)
        复制代码
        1.     .enter()
        复制代码
        1.     .append("text")
        复制代码
        1.     .text(d => d)
        复制代码
        1.     .attr("y", (d, i) => svgHeight - d - 2)
        复制代码
        1.     .attr("x", (d, i) =>  barWidth * i)
        复制代码
        1.     .attr("fill", "#A64C38");
        复制代码
      过程比较简单,就是返回文本,计算x/y坐标,并填充颜色。
      [h2]5.
      1. scales
      复制代码
      : 比例尺函数[/h2]
      1. D3
      复制代码
      中有个重要的概念就是比例尺。比例尺就是把一组输入域映射到输出域的函数。映射就是两个数据集之间元素相互对应的关系。比如输入是1,输出是100,输入是5,输出是10000,那么这其中的映射关系就是你所定义的比例尺。
      1. D3
      复制代码
      中有各种比例尺函数,有连续性的,有非连续性的,在本例子中,你将学到
      1. d3.scaleLinear()
      复制代码
      ,线性比例尺。
      [h3]5.1
      1. d3.scaleLinear()
      复制代码
      ,线性比例尺[/h3]使用
      1. d3.scaleLinear()
      复制代码
      创造一个线性比例尺,其中:
        1. domain()
        复制代码
        是输入域
        1. range()
        复制代码
        是输出域
      • 相当于将
        1. domain
        复制代码
        中的数据集映射到
        1. range
        复制代码
        的数据集中。
        1. let scale = d3.scaleLinear().domain([1,5]).range([0,100])
        复制代码
      映射关系:


      值得注意的是,上述代码只是定义了一个映射规则,映射的输入值并不局限于
      1. domain()
      复制代码
      中的输入域。
        1. scale(1) // 输出:0
        复制代码
        1. scale(4) // 输出:75
        复制代码
        1. scale(5) // 输出:100
        复制代码
        1. scale(-1) // 输出:-50
        复制代码
        1. scale(10) // 输出:225
        复制代码
      于是我们来改造
      1. 3~4
      复制代码
      的例子:
        1. let dataset = [1,2,3,4,5];
        复制代码

        1. let svgWidth = 500, svgHeight = 300, barPadding = 5;
        复制代码
        1. let barWidth = (svgWidth / dataset.length);
        复制代码


        1. let svg = d3.select('svg')
        复制代码
        1.     .attr("width", svgWidth)
        复制代码
        1.     .attr("height", svgHeight);
        复制代码

        1. let yScale = d3.scaleLinear()
        复制代码
        1.     .domain([0, d3.max(dataset)])
        复制代码
        1.     .range([0, svgHeight]);
        复制代码

        1. let barChart = svg.selectAll("rect")
        复制代码
        1.     .data(dataset)
        复制代码
        1.     .enter()
        复制代码
        1.     .append("rect")
        复制代码
        1.     .attr("y", d => svgHeight - yScale(d))
        复制代码
        1.     .attr("height", d => yScale(d))
        复制代码
        1.     .attr("width", barWidth - barPadding)
        复制代码
        1.     .attr("transform", (d, i) => {
        复制代码
        1.         let translate = [barWidth * i, 0];
        复制代码
        1.         return "translate("+ translate +")";
        复制代码
        1.     });
        复制代码
      然后就会得到以下图形:


      [h2]6.
      1. Axes
      复制代码
      :轴[/h2]

      轴是任何图表的组成部分,本例子中将会用到上面讲到的比例尺函数。
        1. let data= [80, 100, 56, 120, 180, 30, 40, 120, 160];
        复制代码

        1. let svgWidth = 500, svgHeight = 300;
        复制代码

        1. let svg = d3.select('svg')
        复制代码
        1.     .attr("width", svgWidth)
        复制代码
        1.     .attr("height", svgHeight);
        复制代码

        1. // 首先是拿最大值构建x轴坐标
        复制代码
        1. let xScale = d3.scaleLinear()
        复制代码
        1.     .domain([0, d3.max(data)])
        复制代码
        1.     .range([0, svgWidth]);
        复制代码

        1. // 接下来是反转值,用作y轴坐标。
        复制代码
        1. let yScale = d3.scaleLinear()
        复制代码
        1.     .domain([0, d3.max(data)])
        复制代码
        1.     .range([svgHeight, 0]);
        复制代码

        1. // 横轴的API使用
        复制代码
        1. let x_axis = d3.axisBottom()
        复制代码
        1.     .scale(xScale);
        复制代码

        1. // 纵轴的API使用
        复制代码
        1. let y_axis = d3.axisLeft()
        复制代码
        1.     .scale(yScale);
        复制代码

        1. // 在svg中提供了如g元素这样的将多个元素组织在一起的元素。
        复制代码
        1. // 由g元素编组在一起的可以设置相同的颜色,可以进行坐标变换等,类似于Vue中的
        复制代码

        1. svg.append("g")
        复制代码
        1.     .attr("transform", "translate(50, 10)")
        复制代码
        1.     .call(y_axis);
        复制代码

        1. let xAxisTranslate = svgHeight - 20;
        复制代码

        1. svg.append("g")
        复制代码
        1.     .attr("transform", "translate(50, " + xAxisTranslate  +")")
        复制代码
        1.     .call(x_axis);
        复制代码
      [h2]7. 创建简易的
      1. SVG
      复制代码
      元素[/h2]
      在这里面,你会创建
      1. [/code], [code]
      复制代码
      1. [/code]元素
      2. [list=1][*][code]let svgWidth = 600, svgHeight = 500;
      复制代码
      1. let svg = d3.select("svg")
      复制代码
      1.     .attr("width", svgWidth)
      复制代码
      1.     .attr("height", svgHeight)
      复制代码
      1.     .attr("class", "svg-container")
      复制代码

      1. let line = svg.append("line")
      复制代码
      1.     .attr("x1", 100)
      复制代码
      1.     .attr("x2", 500)
      复制代码
      1.     .attr("y1", 50)
      复制代码
      1.     .attr("y2", 50)
      复制代码
      1.     .attr("stroke", "red");
      复制代码

      1. let rect = svg.append("rect")
      复制代码
      1.     .attr("x", 100)
      复制代码
      1.     .attr("y", 100)
      复制代码
      1.     .attr("width", 200)
      复制代码
      1.     .attr("height", 100)
      复制代码
      1.     .attr("fill", "#9B95FF");
      复制代码

      1. let circle = svg.append("circle")
      复制代码
      1.     .attr("cx", 200)
      复制代码
      1.     .attr("cy", 300)
      复制代码
      1.     .attr("r", 80)
      复制代码
      1.     .attr("fill", "#7CE8D5");
      复制代码
    [h2]8. 创建饼图[/h2]

      1. let data = [
      复制代码
      1.     {"platform": "Android", "percentage": 40.11},
      复制代码
      1.     {"platform": "Windows", "percentage": 36.69},
      复制代码
      1.     {"platform": "iOS", "percentage": 13.06}
      复制代码
      1. ];
      复制代码

      1. let svgWidth = 500, svgHeight = 300, radius =  Math.min(svgWidth, svgHeight) / 2;
      复制代码
      1. let svg = d3.select('svg')
      复制代码
      1.     .attr("width", svgWidth)
      复制代码
      1.     .attr("height", svgHeight);
      复制代码

      1. //Create group element to hold pie chart
      复制代码
      1. let g = svg.append("g")
      复制代码
      1.     .attr("transform", "translate(" + radius + "," + radius + ")") ;
      复制代码

      1. // d3.scaleOrdinal() 序数比例尺
      复制代码
      1. // schemeCategory10, 颜色比例尺
      复制代码
      1. // D3提供了一些颜色比例尺,10就是10种颜色,20就是20种:
      复制代码
      1. let color = d3.scaleOrdinal(d3.schemeCategory10);
      复制代码

      1. let pie = d3.pie().value(d => d.percentage);
      复制代码

      1. let path = d3.arc()
      复制代码
      1.     .outerRadius(radius)
      复制代码
      1.     .innerRadius(0);
      复制代码

      1. let arc = g.selectAll("arc")
      复制代码
      1.     .data(pie(data))
      复制代码
      1.     .enter()
      复制代码
      1.     .append("g");
      复制代码

      1. arc.append("path")
      复制代码
      1.     .attr("d", path)
      复制代码
      1.     .attr("fill", d => color(d.data.percentage));
      复制代码

      1. let label = d3.arc()
      复制代码
      1.     .outerRadius(radius)
      复制代码
      1.     .innerRadius(0);
      复制代码

      1. arc.append("text")
      复制代码
      1.     .attr("transform",  d => `translate(${label.centroid(d)})`)
      复制代码
      1.     .attr("text-anchor", "middle")
      复制代码
      1.     .text(d => `${d.data.platform}:${d.data.percentage}%`);
      复制代码
    [h2]9. 创建折线图[/h2]

    最后,你将学习如何创建折线图以显示近四个月的比特币价格。要获取数据,你将使用外部API。这个项目还将你在整个课程中学到的很多概念结合在一起,所以这是一个很好的可视化课程结束。
      1. // 外部API,注意日期记得补零
      复制代码
      1. const api = 'https://api.coindesk.com/v1/bpi/historical/close.json?start=2019-03-31&end=2019-07-01';
      复制代码

      1. /**
      复制代码
      1. * dom内容加载完毕时,从API中加载数据
      复制代码
      1. */
      复制代码
      1. document.addEventListener("DOMContentLoaded", function(event) {
      复制代码
      1. fetch(api)
      复制代码
      1.     .then(response => response.json())
      复制代码
      1.     .then(data => {
      复制代码
      1.         let parsedData = parseData(data);
      复制代码
      1.         drawChart(parsedData);
      复制代码
      1.     })
      复制代码
      1.     .catch(err =>  console.log(err))
      复制代码
      1. });
      复制代码

      1. /**
      复制代码
      1. * 将数据解析为键值对
      复制代码
      1. */
      复制代码
      1. parseData = data =>{
      复制代码
      1.     let arr = [];
      复制代码
      1.     for (let i in data.bpi) {
      复制代码
      1.         arr.push({
      复制代码
      1.             date: new Date(i), //date
      复制代码
      1.             value: +data.bpi[i] //convert string to number
      复制代码
      1.         });
      复制代码
      1.     }
      复制代码
      1.     return arr;
      复制代码
      1. }
      复制代码

      1. /**
      复制代码
      1. * 创建图表
      复制代码
      1. */
      复制代码
      1. drawChart  = data => {
      复制代码
      1. let svgWidth = 600, svgHeight = 400;
      复制代码
      1. let margin = { top: 20, right: 20, bottom: 30, left: 50 };
      复制代码
      1. let width = svgWidth - margin.left - margin.right;
      复制代码
      1. let height = svgHeight - margin.top - margin.bottom;
      复制代码

      1. let svg = d3.select('svg')
      复制代码
      1.     .attr("width", svgWidth)
      复制代码
      1.     .attr("height", svgHeight);
      复制代码

      1. let g = svg.append("g")
      复制代码
      1.     .attr("transform", "translate(" + margin.left + "," + margin.top + ")");
      复制代码

      1. let x = d3.scaleTime()
      复制代码
      1.     .rangeRound([0, width]);
      复制代码

      1. let y = d3.scaleLinear()
      复制代码
      1.     .rangeRound([height, 0]);
      复制代码

      1. let line = d3.line()
      复制代码
      1.     .x(d=> x(d.date))
      复制代码
      1.     .y(d=> y(d.value))
      复制代码
      1.     x.domain(d3.extent(data, function(d) { return d.date }));
      复制代码
      1.     y.domain(d3.extent(data, function(d) { return d.value }));
      复制代码

      1. g.append("g")
      复制代码
      1.     .attr("transform", "translate(0," + height + ")")
      复制代码
      1.     .call(d3.axisBottom(x))
      复制代码
      1.     .select(".domain")
      复制代码
      1.     .remove();
      复制代码

      1. g.append("g")
      复制代码
      1.     .call(d3.axisLeft(y))
      复制代码
      1.     .append("text")
      复制代码
      1.     .attr("fill", "#000")
      复制代码
      1.     .attr("transform", "rotate(-90)")
      复制代码
      1.     .attr("y", 6)
      复制代码
      1.     .attr("dy", "0.71em")
      复制代码
      1.     .attr("text-anchor", "end")
      复制代码
      1.     .text("Price ($)");
      复制代码

      1. g.append("path")
      复制代码
      1.     .datum(data)
      复制代码
      1.     .attr("fill", "none")
      复制代码
      1.     .attr("stroke", "steelblue")
      复制代码
      1.     .attr("stroke-linejoin", "round")
      复制代码
      1.     .attr("stroke-linecap", "round")
      复制代码
      1.     .attr("stroke-width", 1.5)
      复制代码
      1.     .attr("d", line);
      复制代码
      1. }
      复制代码
    以上原实例均来自:Learn D3 for free。scrimba是一个非常神奇的网站。它是使用交互式编码截屏工具构建的。


    所有的操作都是:
    暂停截屏视频 → 编辑代码 → 运行它!→ 查看更改
    非常值得安利一波。接下来进入第二部分:
    1. Vue
    复制代码
    中使用
    1. D3.js
    复制代码
    的正确姿势
    [h1]2.
    1. Vue
    复制代码
    中使用
    1. D3.js
    复制代码
    的正确姿势[/h1]我们将使用
    1. D3
    复制代码
    1. Vue
    复制代码
    构建一个基本的柱状图组件。网上有一堆例子,但我们将专注于写
    1. Vue
    复制代码
    ,而不是滥用D3。
    [h2]1. 安装依赖[/h2]首先,我们需要为项目安装依赖项。我们可以简单地安装和使用
    1. D3
    复制代码
    整库:
      1. npm i d3
      复制代码
    但我在前面讲到,实际上
    1. D3
    复制代码
    是几个分库的集合,考虑到项目的优化,我们只安装所需的模块。


    使用
    1. VueCli
    复制代码
    初始化项目即可。
    [h2]2. 创建柱状图[/h2]

    [h2]3. 柱状图模块导入[/h2]

    [h2]4. 创建
    1. svg
    复制代码
    元素[/h2]

    1. Vue
    复制代码
    数据响应的特性,我们不需要用到
    1. D3
    复制代码
    操作
    1. DOM
    复制代码
    的那套链式创建。
    [h2]5. 数据与窗口大小响应[/h2]
    1. mounted
    复制代码
    钩子中,我们将为窗口调整大小事件添加一个监听器,它将触发绘制动画,并将
    1. [/code]大小设置为新窗口的比例。我们不会立即渲染,而是等待 [code]300
    复制代码
    毫秒,以确保完全调整窗口大小。
    以下是完整的
    1. BarChart.vue
    复制代码
    ,请配合注释食用:
      1. [/code]
      2. [*][code]  
      复制代码
      1.     {{ title }}
      复制代码
      1.    
      复制代码
      1.       
      复制代码
      1.         
      复制代码
      1.       
      复制代码
      1.    
      复制代码
      1.   
      复制代码
      1. [/code]
      2. [*]
      3. [*][code]
      复制代码
      1. import { scaleLinear, scaleBand } from "d3-scale";
      复制代码
      1. import { max, min } from "d3-array";
      复制代码
      1. import { selectAll } from "d3-selection";
      复制代码
      1. import { transition } from "d3-transition";
      复制代码

      1. export default {
      复制代码
      1.   name: "BarChart",
      复制代码
      1.   props: {
      复制代码
      1.     title: String,
      复制代码
      1.     xKey: String,
      复制代码
      1.     yKey: String,
      复制代码
      1.     data: Array
      复制代码
      1.   },
      复制代码
      1.   mounted() {
      复制代码
      1.     this.svgWidth = document.getElementById("container").offsetWidth * 0.75;
      复制代码
      1.     this.AddResizeListener();
      复制代码
      1.     this.AnimateLoad();
      复制代码
      1.   },
      复制代码
      1.   data: () => ({
      复制代码
      1.     svgWidth: 0,
      复制代码
      1.     redrawToggle: true
      复制代码
      1.   }),
      复制代码
      1.   methods: {
      复制代码
      1.     // 绘制柱形
      复制代码
      1.     AnimateLoad() {
      复制代码
      1.       selectAll("rect")
      复制代码
      1.         .data(this.data)
      复制代码
      1.         .transition()
      复制代码
      1.         .delay((d, i) => {
      复制代码
      1.           return i * 150;
      复制代码
      1.         })
      复制代码
      1.         .duration(1000)
      复制代码
      1.         .attr("y", d => {
      复制代码
      1.           return this.yScale(d[this.yKey]);
      复制代码
      1.         })
      复制代码
      1.         .attr("height", d => {
      复制代码
      1.           return this.svgHeight - this.yScale(d[this.yKey]);
      复制代码
      1.         });
      复制代码
      1.     },
      复制代码
      1.     // 调整窗口大小后300毫秒重新绘制图表
      复制代码
      1.     // 即响应式绘制
      复制代码
      1.     AddResizeListener() {
      复制代码
      1.       window.addEventListener("resize", () => {
      复制代码
      1.         this.$data.redrawToggle = false;
      复制代码
      1.         setTimeout(() => {
      复制代码
      1.           this.$data.redrawToggle = true;
      复制代码
      1.           this.$data.svgWidth =
      复制代码
      1.             document.getElementById("container").offsetWidth * 0.75;
      复制代码
      1.           this.AnimateLoad();
      复制代码
      1.         }, 300);
      复制代码
      1.       });
      复制代码
      1.     }
      复制代码
      1.   },
      复制代码
      1.   computed: {
      复制代码
      1.     dataMax() {
      复制代码
      1.       return max(this.data, d => {
      复制代码
      1.         return d[this.yKey];
      复制代码
      1.       });
      复制代码
      1.     },
      复制代码
      1.     dataMin() {
      复制代码
      1.       return min(this.data, d => {
      复制代码
      1.         return d[this.yKey];
      复制代码
      1.       });
      复制代码
      1.     },
      复制代码
      1.     xScale() {
      复制代码
      1.       return scaleBand()
      复制代码
      1.         .rangeRound([0, this.svgWidth])
      复制代码
      1.         .padding(0.1)
      复制代码
      1.         .domain(
      复制代码
      1.           this.data.map(d => {
      复制代码
      1.             return d[this.xKey];
      复制代码
      1.           })
      复制代码
      1.         );
      复制代码
      1.     },
      复制代码
      1.     // 通过线性比例尺自动生成
      复制代码
      1.     yScale() {
      复制代码
      1.       return scaleLinear()
      复制代码
      1.         .rangeRound([this.svgHeight, 0])
      复制代码
      1.         .domain([this.dataMin > 0 ? 0 : this.dataMin, this.dataMax]);
      复制代码
      1.     },
      复制代码
      1.     svgHeight() {
      复制代码
      1.       return this.svgWidth / 1.61803398875; // 黄金比例
      复制代码
      1.     }
      复制代码
      1.   }
      复制代码
      1. };
      复制代码
      1. [/code]
      2. [*]
      3. [*][code]
      复制代码
      1. .bar-positive {
      复制代码
      1.   fill: steelblue;
      复制代码
      1.   transition: r 0.2s ease-in-out;
      复制代码
      1. }
      复制代码

      1. .bar-positive:hover {
      复制代码
      1.   fill: brown;
      复制代码
      1. }
      复制代码

      1. .svg-container {
      复制代码
      1.   display: inline-block;
      复制代码
      1.   position: relative;
      复制代码
      1.   width: 100%;
      复制代码
      1.   padding-bottom: 1%;
      复制代码
      1.   vertical-align: top;
      复制代码
      1.   overflow: hidden;
      复制代码
      1. }
      复制代码
      1. [/code]
      2. [/list]我们将从父组件 [code]App.vue
      复制代码
      获取数据:
        1. [/code]
        2. [*][code]  
        复制代码
        1.    
        复制代码
        1.   
        复制代码
        1. [/code]
        2. [*]
        3. [*][code]
        复制代码
        1. import BarChart from "./components/BarChart.vue";
        复制代码

        1. export default {
        复制代码
        1.   name: "App",
        复制代码
        1.   components: {
        复制代码
        1.     BarChart
        复制代码
        1.   },
        复制代码
        1.   data: () => ({
        复制代码
        1.     barChartData: [
        复制代码
        1.       {
        复制代码
        1.         name: "张三",
        复制代码
        1.         amount: 25
        复制代码
        1.       },
        复制代码
        1.       {
        复制代码
        1.         name: "李四",
        复制代码
        1.         amount: 40
        复制代码
        1.       },
        复制代码
        1.       {
        复制代码
        1.         name: "老王",
        复制代码
        1.         amount: 15
        复制代码
        1.       },
        复制代码
        1.       {
        复制代码
        1.         name: "老赖",
        复制代码
        1.         amount: 9
        复制代码
        1.       }
        复制代码
        1.     ]
        复制代码
        1.   })
        复制代码
        1. };
        复制代码
        1. [/code]
        2. [*]
        3. [*][code]
        复制代码
        1. #app {
        复制代码
        1.   font-family: "Open Sans", Helvetica, Arial, sans-serif;
        复制代码
        1.   -webkit-font-smoothing: antialiased;
        复制代码
        1.   -moz-osx-font-smoothing: grayscale;
        复制代码
        1.   text-align: center;
        复制代码
        1.   color: #282f36;
        复制代码
        1.   margin-top: 30px;
        复制代码
        1. }
        复制代码
        1. [/code]
        2. [/list]这时候 [code]yarn run serve
        复制代码
        后将会看到:


        好像还缺点显示数值,考虑到该图高度是根据比例尺生成,我们调整下y坐标:
          1. yScale() {
          复制代码
          1.   return scaleLinear()
          复制代码
          1.     .rangeRound([this.svgHeight, 0])
          复制代码
          1.     .domain([this.dataMin > 0 ? 0 : this.dataMin + 2, this.dataMax + 2]);
          复制代码
          1. },
          复制代码
        1. AnimateLoad()
        复制代码
        末尾添加:
          1. selectAll("text")
          复制代码
          1.   .data(this.data)
          复制代码
          1.   .enter()
          复制代码
        最后在
        1. [/code]元素中添加:
        2. [list=1][*][code]{{ item[xKey]}} {{ item[yKey]}}
        复制代码
        1. [/code]
        2. [/list][img]https://201907.oss-cn-shanghai.aliyuncs.com/wc/1811847-baa48749a6e55bcad1d9a8afb1f76471[/img]
        3. [h1]3. 参考文章[/h1]   
        4. [img]https://201907.oss-cn-shanghai.aliyuncs.com/wc/1811847-124bd4848857866e677e58f3399f6f91[/img]
        5. [list][*]D3 is not a Data Visualization Library
        6. [*]D3中常用的比例尺
        7. [*]D3 vs G2 vs Echarts
        8. [*]Dynamic Data Visualizations With Vue.js and D3
        9. [/list][h1]4. 总结[/h1]该库几乎凭 [code]MikeBostock
        复制代码
        一人之力完成,且在学术界、专业团队中享有极大声誉。


          1. D3
          复制代码
          更接近底层,与
          1. g2
          复制代码
          1. echarts
          复制代码
          不同,
          1. d3
          复制代码
          能直接操作
          1. svg
          复制代码
          ,所以拥有极大的自由度,几乎可以实现任何 2d 的设计需求。
        • 正如其名
          1. DataDrivenDocuments
          复制代码
          ,其本质是将数据与
          1. DOM
          复制代码
          绑定,并将数据映射至
          1. DOM
          复制代码
          属性上。
          1. D3
          复制代码
          长于可视化,而不止于可视化,还提供了
          1. 数据处理
          复制代码
          1. 数据分析
          复制代码
          1. DOM
          复制代码
          操作等诸多功能。
        • 如果有想深耕数据可视化方面的前端,
          1. D3
          复制代码
          不得不学。


        掌握
        1. D3
        复制代码
        后,限制作品水平的只会是想象力而不再是技术。
        源码地址:点这里
        [h1]作者掘金文章总集[/h1]需要转载到公众号的喊我加下白名单就行了。
        • 「真全栈之路」Web前端开发的后端指南
        • 「Vue实践」5分钟撸一个Vue CLI 插件
        • 「Vue实践」武装你的前端项目
        • 「中高级前端面试」JavaScript手写代码无敌秘籍
        • 「从源码中学习」面试官都不知道的Vue题目答案
        • 「从源码中学习」Vue源码中的JS骚操作
        • 「从源码中学习」彻底理解Vue选项Props
        • 「Vue实践」项目升级vue-cli3的正确姿势
        • 为何你始终理解不了JavaScript作用域链?

        [h2] 看完三件事[/h2]如果你觉得这篇内容对你挺有启发,我想邀请你帮我三个小忙:
        • 点个「在看」,让更多的人也能看到这篇内容(喜欢不点在看,都是耍流氓 -_-)
        • 关注我的 GitHub:github.com/yygmind,让我们成为长期关系
        • 关注公众号「高级前端进阶」,每周重点攻克一个前端面试重难点,公众号后台回复「面试题」 送你高级前端面试题。

分享到 :
0 人收藏
您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

积分:20
帖子:4
精华:0
期权论坛 期权论坛
发布
内容

下载期权论坛手机APP