preface

D3 has been one of the most important data visualization libraries for JavaScript in recent years, and under the maintenance of its creator, Mike Bostock, the future is still promising, at least not for now:

  • D3What sets it apart from many other libraries is the ability to do unlimited customization (direct manipulationSVG).
  • Its underlyingAPIProvide access to nativeSVGElement, but it also comes with a high learning curve cost.
  • We will putD3andVueCombine together – useVueDynamic data binding, clear syntax and modular structure can be fully exploitedD3For optimum performance.

According to the broad definition, D3 can be broken down into the following sub-libraries:

  1. The vast majorityD3The course or the book, will focus on itsDOMOperationally, but this clearly goes against the philosophy of web frameworks in recent years.
  2. Used for data visualizationD3, its core is to use drawing instructions to decorate data, create new drawable data from source data, and generateSVGPaths as well from data and methods inDOMTo create data visualization elements, such as axes.

3. There are many tools for managing the DOM, all of which are available in theD3Data visualization function is integrated in This is alsoD3withVueOne of the reasons for the seamless combination.

At this point, we don’t need to start with THE D3 DOM manipulation functions, directly through the example to get started with D3.

1. Gradual introduction to D3.js

The templates for the following examples are of the following form:

<html> <head> <link rel="stylesheet" href="index.css"> <title>Learn D3.js</title> </head> <body> <! - or other tags - > < h1 > First heading < / h1 > < script SRC = "https://d3js.org/d3.v4.min.js" > < / script > < script SRC = "index. Js" > < / script >  </body> </html>Copy the code

1. Select and operate

The first thing you need to learn is how to use d3.js to select and manipulate DOM elements. The library is actually so powerful in manipulating the DOM that it could theoretically be used as an alternative to jQuery. Add and run the following code line by line.

// index.js
d3.select();
d3.selectAll();

d3.select('h1').style('color', 'red')
.attr('class', 'heading')
.text('Updated h1 tag');

d3.select('body').append('p').text('First Paragraph');
d3.select('body').append('p').text('Second Paragraph');
d3.select('body').append('p').text('Third Paragraph');

d3.selectAll('p').style('')
Copy the code

2. Load and bind data

When you’re creating visualizations, it’s important to know how to load the data and bind it to the DOM. So in this case, you’re going to learn those two things.

let dataset = [1, 2, 3, 4, 5]; d3.select('body') .selectAll('p') .data(dataset) .enter() .append('p') // appends paragraph for each data element .text('D3 is awesome!! '); //.text(function(d) { return d; });Copy the code

3. Create a simple bar chart

First, you need to add an SVG tag

<h1>Bar Chart using D3.js</h1>

<svg class="bar-chart"></svg>
Copy the code

Then add (with key comments added) in index.js:

Let dataset = [80, 100, 56, 120, 180, 30, 40, 120, 160]; let dataset = [80, 100, 56, 120, 180, 30, 40, 120, 160]; Let svgWidth = 500, svgHeight = 300, barPadding = 5; Let barWidth = (svgWidth/dataset.length); Let SVG = d3.select(' SVG ').attr("width", svgWidth).attr("height", svgHeight); // rect, rectangle // document: http://www.w3school.com.cn/svg/svg_rect.asp let barChart = SVG. SelectAll (" the rect "). The data (dataset) / / bind array. Enter () / / Append ("rect") // Add a sufficient number of rectangles. Attr ("y", d => svgHeight -d) // select the y coordinate.attr("height", Attr ("width", barwidth-barpadding-width); i) => { let translate = [barWidth * i, 0]; return "translate("+ translate +")"; }); // Calculate the x coordinate of each valueCopy the code

4. Display the value at the top of the graph

This is where you need to create it in the above codesvgthetextThe text

let text = svg.selectAll("text")
    .data(dataset)
    .enter()
    .append("text")
    .text(d => d)
    .attr("y", (d, i) => svgHeight - d - 2)
    .attr("x", (d, i) =>  barWidth * i)
    .attr("fill", "#A64C38");
Copy the code

The process is simple: return the text, calculate the x/y coordinates, and fill in the color.

5. scales: Scale function

An important concept in D3 is scale. A scale is a function that maps a set of input fields to an output field. A mapping is a relationship between the elements of two data sets. If the input is 1 and the output is 100, if the input is 5 and the output is 10,000, then the mapping between them is the scale that you define.

There are various scale functions in D3, some continuous, some discontinuous, and in this example, you will learn d3.scalelinear (), linear scale.

5.1 d3.scaleLinear(), linear scale

Use d3.scalelinear () to create a linear scale where:

  • domain()Is the input field
  • range()Is the output domain
  • Is equivalent todomainIs mapped torangeData set of.
Let scale = d3. ScaleLinear (.) domain ([1, 5)). The range ([0100])Copy the code

Mapping:

It is important to note that the above code only defines a mapping rule; the input values of the mapping are not limited to the input fields in domain().

Scale (1) // Output :0 scale(4) // Output :75 scale(5) // Output :100 scale(-1) // Output :-50 scale(10) // Output :225Copy the code

So let’s change the example of 3 ~ 4:

Let the dataset = [1, 2, 3, 4, 5]; let svgWidth = 500, svgHeight = 300, barPadding = 5; let barWidth = (svgWidth / dataset.length); let svg = d3.select('svg') .attr("width", svgWidth) .attr("height", svgHeight); let yScale = d3.scaleLinear() .domain([0, d3.max(dataset)]) .range([0, svgHeight]); let barChart = svg.selectAll("rect") .data(dataset) .enter() .append("rect") .attr("y", d => svgHeight - yScale(d)) .attr("height", d => yScale(d)) .attr("width", barWidth - barPadding) .attr("transform", (d, i) => { let translate = [barWidth * i, 0]; return "translate("+ translate +")"; });Copy the code

Then you get the following graph:

6. Axes: shaft

Axes are part of any graph, and the scale function mentioned above will be used in this example.

let data= [80, 100, 56, 120, 180, 30, 40, 120, 160]; let svgWidth = 500, svgHeight = 300; let svg = d3.select('svg') .attr("width", svgWidth) .attr("height", svgHeight); Let xScale = d3.scalelinear ().domain([0, d3.max(data)]).range([0, svgWidth]); let xScale = d3.scalelinear ().domain([0, d3.max(data)]).range([0, svgWidth]); // Next is the inverted value, which is used as the y coordinate. let yScale = d3.scaleLinear() .domain([0, d3.max(data)]) .range([svgHeight, 0]); // Let x_axis = d3.axisBottom().scale(xScale); // Let y_axis = d3.axisLeft().scale(yScale); // Elements such as g elements are provided in SVG to group multiple elements together. // G elements grouped together can be set to the same color, coordinate transformation, etc. Append ("g").attr("transform", "translate(50, 10)").call(y_axis); let xAxisTranslate = svgHeight - 20; svg.append("g") .attr("transform", "translate(50, " + xAxisTranslate +")") .call(x_axis);Copy the code

7. Easy to createSVGThe element

And in this, you’re going to create<rect>.<circle>and<line>The element

let svgWidth = 600, svgHeight = 500;
let svg = d3.select("svg")
    .attr("width", svgWidth)
    .attr("height", svgHeight)
    .attr("class", "svg-container")
    
let line = svg.append("line")
    .attr("x1", 100)
    .attr("x2", 500)
    .attr("y1", 50)
    .attr("y2", 50)
    .attr("stroke", "red");
    
let rect = svg.append("rect")
    .attr("x", 100)
    .attr("y", 100)
    .attr("width", 200)
    .attr("height", 100)
    .attr("fill", "#9B95FF");
    
let circle = svg.append("circle")
    .attr("cx", 200)
    .attr("cy", 300)
    .attr("r", 80)
    .attr("fill", "#7CE8D5");
Copy the code

8. Create a pie chart

Let data = [{" percentage": "Android", "percentage": 40.11}, {" percentage": "Windows", "percentage": 36.69}, {"platform": "percentage": 40.11}, {"platform": "Windows", "percentage": 36.69}, {"platform": "IOS", "percentage" : 13.06}]; let svgWidth = 500, svgHeight = 300, radius = Math.min(svgWidth, svgHeight) / 2; let svg = d3.select('svg') .attr("width", svgWidth) .attr("height", svgHeight); //Create group element to hold pie chart let g = svg.append("g") .attr("transform", "translate(" + radius + "," + radius + ")") ; // d3.scaleordinal () // schemeCategory10, color scale // d3 provides some color scale, 10 is 10 colors, 20 is 20:  let color = d3.scaleOrdinal(d3.schemeCategory10); let pie = d3.pie().value(d => d.percentage); let path = d3.arc() .outerRadius(radius) .innerRadius(0); let arc = g.selectAll("arc") .data(pie(data)) .enter() .append("g"); arc.append("path") .attr("d", path) .attr("fill", d => color(d.data.percentage)); let label = d3.arc() .outerRadius(radius) .innerRadius(0); arc.append("text") .attr("transform", d => `translate(${label.centroid(d)})`) .attr("text-anchor", "middle") .text(d => `${d.data.platform}:${d.data.percentage}%`);Copy the code

9. Create line charts

Finally, you’ll learn how to create a line chart showing the bitcoin price for the last four months. To get the data, you’ll use an external API. The project also pulls together a lot of the concepts you’ve learned throughout the course, so it’s a good visualization at the end of the course.

/ / external API, note the date remember zero padding const API = 'https://api.coindesk.com/v1/bpi/historical/close.json?start=2019-03-31&end=2019-07-01'; /** * When the dom content is loaded, Load data from the API * / document. The addEventListener (" DOMContentLoaded ", function(event) { fetch(api) .then(response => response.json()) .then(data => { let parsedData = parseData(data); drawChart(parsedData); }) .catch(err => console.log(err)) }); /** * parseData into key-value pairs */ parseData = data =>{let arr = []; for (let i in data.bpi) { arr.push({ date: new Date(i), //date value: +data.bpi[i] //convert string to number }); } return arr; } /** * create chart */ drawChart = data => {let svgWidth = 600, svgHeight = 400; let margin = { top: 20, right: 20, bottom: 30, left: 50 }; let width = svgWidth - margin.left - margin.right; let height = svgHeight - margin.top - margin.bottom; let svg = d3.select('svg') .attr("width", svgWidth) .attr("height", svgHeight); let g = svg.append("g") .attr("transform", "translate(" + margin.left + "," + margin.top + ")"); let x = d3.scaleTime() .rangeRound([0, width]); let y = d3.scaleLinear() .rangeRound([height, 0]); let line = d3.line() .x(d=> x(d.date)) .y(d=> y(d.value)) x.domain(d3.extent(data, function(d) { return d.date })); y.domain(d3.extent(data, function(d) { return d.value })); g.append("g") .attr("transform", "translate(0," + height + ")") .call(d3.axisBottom(x)) .select(".domain") .remove(); g.append("g") .call(d3.axisLeft(y)) .append("text") .attr("fill", "#000") .attr("transform", "rotate(-90)") .attr("y", 6). Attr (" dy ", "0.71 em"). The attr (" text - anchor ", "end"), text (" Price ($) "); g.append("path") .datum(data) .attr("fill", "none") .attr("stroke", "steelblue") .attr("stroke-linejoin", "Round"). Attr (" stroke - linecap ", "round"). The attr (" stroke - width ", 1.5). The attr (" d ", line); }Copy the code

The original examples above are from: Learn D3 for Free.

Scrimba is an amazing site. It is built using an interactive coding screenshot tool.

All operations are:

Pause the screenshot video → Edit the code → run it! → View changes

Well worth the amway wave. Let’s move on to part two: The correct pose for using d3.js in Vue

2. VueThe use ofD3.jsCorrect posture

We will use D3 and Vue to build a basic bar chart component. There are a bunch of examples online, but we’ll focus on writing Vue and not abusing D3.

1. Install the dependency

First, we need to install the dependencies for the project. We can simply install and use the D3 entire library:

npm i d3
Copy the code

But as I mentioned earlier, D3 is actually a collection of several separate libraries, and for project optimization, we only install the required modules.

Use the Vue Cli to initialize the project.

2. Create a bar chart

3. Bar chart module import

4. CreatesvgThe element

Due to the nature of Vue’s data response, we don’t need to use D3 to manipulate the DOM’s set of chain creation.

5. Data and window size response

mountedIn the hook, we’ll add a listener for the window resize event, which will trigger the drawing animation and will<svg>Size is set to the scale of the new window. Instead of rendering immediately, we wait300Milliseconds to ensure that the window is fully resized.

Here is the complete barchart.vue, please eat with the notes:

<template> <div id="container" class="svg-container" align="center"> <h1>{{ title }}</h1> <svg v-if="redrawToggle === true" :width="svgWidth" :height="svgHeight"> <g> <rect v-for="item in data" class="bar-positive" :key="item[xKey]" :x="xScale(item[xKey])" :y="yScale(0)" :width="xScale.bandwidth()" :height="0" ></rect> </g> </svg> </div> </template> <script> import { scaleLinear, scaleBand } from "d3-scale"; import { max, min } from "d3-array"; import { selectAll } from "d3-selection"; import { transition } from "d3-transition"; export default { name: "BarChart", props: { title: String, xKey: String, yKey: String, data: Array}, mounted() {this.svgWidth = document.getelementById ("container").offsetwidth * 0.75; this.AddResizeListener(); this.AnimateLoad(); }, data: () => ({ svgWidth: 0, redrawToggle: true }), methods: {// draw AnimateLoad() {selectAll("rect").data(this.data).transition().delay((d, I) => {return I * 150; }) .duration(1000) .attr("y", d => { return this.yScale(d[this.yKey]); }) .attr("height", d => { return this.svgHeight - this.yScale(d[this.yKey]); }); }, // redraw the chart 300 milliseconds after resizing the window // to draw the chart in response () => { this.$data.redrawToggle = false; setTimeout(() => { this.$data.redrawToggle = true; This.$data.svgWidth = document.getelementById ("container").offsetwidTh * 0.75; this.AnimateLoad(); }, 300); }); } }, computed: { dataMax() { return max(this.data, d => { return d[this.yKey]; }); }, dataMin() { return min(this.data, d => { return d[this.yKey]; }); }, xScale() { return scaleBand() .rangeRound([0, This.svgwidth]).padding(0.1).domain(this.data.map(d => {return d[this.xkey]; })); }, // generate yScale() {return scaleLinear().rangeround ([this.svgheight, 0]).domain([this.datamin > 0? 0: this.dataMin, this.dataMax]); }, svgHeight() {return this.svgwidth / 1.61803398875; // The golden ratio}}}; </script> <style scoped> .bar-positive { fill: steelblue; The transition: r 0.2 s ease - in-out; } .bar-positive:hover { fill: brown; } .svg-container { display: inline-block; position: relative; width: 100%; padding-bottom: 1%; vertical-align: top; overflow: hidden; } </style>Copy the code

We’ll get the data from the parent app.vue:

<template> <div id="app"> <BarChart title="Bar Chart" xKey="name" yKey="amount" :data="barChartData"/> </div> </template> <script> import BarChart from "./components/BarChart.vue"; Export default {name: "App", components: {BarChart}, data: () => ({barChartData: [{name: "App", components: {BarChart}, data: () => ({barChartData: [{name: "App", data: ())) 25}, {name: "bill," the amount: 40}, {name: "wang", amount: 15}, {name: "LaoLai", amount: 9}})}; </script> <style> #app { font-family: "Open Sans", Helvetica, Arial, sans-serif; -webkit-font-smoothing: antialiased; -moz-osx-font-smoothing: grayscale; text-align: center; color: #282f36; margin-top: 30px; } </style>Copy the code

After the Yarn Run serves, you will see:

Considering that the height of the graph is generated according to the scale, let’s adjust the y coordinate:

yScale() {
  return scaleLinear()
    .rangeRound([this.svgHeight, 0])
    .domain([this.dataMin > 0 ? 0 : this.dataMin + 2, this.dataMax + 2]);
},
Copy the code

At the end of AnimateLoad() add:

selectAll("text")
  .data(this.data)
  .enter()
Copy the code

Finally, in the

element add:

<text
  v-for="item in data"
  :key="item[xKey].amount"
  :x="xScale(item[xKey]) + 30"
  :y="yScale(item[yKey]) - 2"
  fill="red"
>{{ item[xKey]}} {{ item[yKey]}}
</text>
Copy the code

3. Refer to the article

  • The Hitchhiker’s Guide to d3.js

  • D3 is not a Data Visualization Library

  • The scale commonly used in D3

  • D3 vs G2 vs Echarts

  • Dynamic Data Visualizations With Vue.js and D3

4. To summarize

The library was built almost single-handedly by Mike Bostock and has a great reputation in the academic and professional community.

  • D3Closer to the bottom, withg2,echartsDifferent,d3Direct operationsvg, so it has a great degree of freedom and can realize almost any 2D design requirements.
  • As its name suggestsData Driven Documents, the essence of which is to combine data withDOMBind and map data toDOMOn the property.
  • D3Good at visualization, not just visualization, but also provideThe data processing,The data analysis,DOMOperation and many other functions.
  • If there’s a front end that wants to dig deeper into data visualization,D3Have to learn.

masterD3In the end, it is imagination, not technology, that will limit the level of the work.

Source address: click here

❤️ see three things

If you found this post inspiring, I’d like to invite you to do three small favors for me:

  1. Like, let more people can also see this content (collection does not like, is playing rogue – -)
  2. Pay attention to the public number “front-end dispeller”, irregularly share original knowledge.
  3. Check out other articles as well
  • Design Patterns you Inadvertently Use (part 1) – Creation patterns
  • “King of data visualization library” D3.js fast start to Vue application

] (juejin. Cn/post / 684490…).

  • “True ® Path to Full Stack” a back-end guide to Web front-end development
  • “Vue Practice” 5 minutes for a Vue CLI plug-in
  • “Vue practices” arm your front-end projects
  • “Advanced front end interview” JavaScript handwriting unbeatable secrets
  • “Learn from source code” answers to Vue questions that interviewers don’t know
  • “Learn from the source code” Vue source code in JS SAO operation
  • “Vue Practice” project to upgrade vue-CLI3 correct posture
  • Why do you never understand JavaScript scope chains?