Use d3.js in the Vue project

Before I wrote a Demo, I had to use D3 to achieve some effects, but I couldn't find a way to use D3.js in Vue in many forums. D3 on npm is relatively inhumane, and I didn't say how to use D3.js on webpack at all

Finally, I saw a foreign tycoon for a long time to see that his case successfully realized the use of D3 in Vue project

First installation

npm install d3 --save-dev

Just in case, then look at package.json

installation is complete

Before we start, let's render a Vue component that uses the normal D3 DOM operation to present a simple line graph:

<script>
import * as d3 from 'd3';
const data = [99, 71, 78, 25, 36, 92];
export default {
  name: 'non-vue-line-chart',
  template: '<div></div>',
  mounted() {
    const svg = d3.select(this.$el)
      .append('svg')
      .attr('width', 500)
      .attr('height', 270)
      .append('g')
      .attr('transform', 'translate(0, 10)');
    const x = d3.scaleLinear().range([0, 430]);
    const y = d3.scaleLinear().range([210, 0]);
    d3.axisLeft().scale(x);
    d3.axisTop().scale(y);
    x.domain(d3.extent(data, (d, i) => i));
    y.domain([0, d3.max(data, d => d)]);
    const createPath = d3.line()
      .x((d, i) => x(i))
      .y(d => y(d));
    svg.append('path').attr('d', createPath(data));
  },
};
</script>
<style lang="sass">
svg
  margin: 25px;
  path
    fill: none
    stroke: #76BF8A
    stroke-width: 3px
</style>

The code is easy to understand, but this is just a basic example. Because we don't use templates, more complex visualizations that require more operations and calculations can obscure the design and logic of components. Another warning of the above method is that we cannot use the properties of scopedCSS because D3 dynamically adds elements to the DOM.

It can be implemented in a strange but elegant way

<template>
  <svg width="500" height="270">
    <g style="transform: translate(0, 10px)">
      <path :d="line" />
    </g>
  </svg>
</template>
<script>
import * as d3 from 'd3';
export default {
  name: 'vue-line-chart',
  data() {
    return {
      data: [99, 71, 78, 25, 36, 92],
      line: '',
    };
  },
  mounted() {
    this.calculatePath();
  },
  methods: {
    getScales() {
      const x = d3.scaleTime().range([0, 430]);
      const y = d3.scaleLinear().range([210, 0]);
      d3.axisLeft().scale(x);
      d3.axisBottom().scale(y);
      x.domain(d3.extent(this.data, (d, i) => i));
      y.domain([0, d3.max(this.data, d => d)]);
      return { x, y };
    },
    calculatePath() {
      const scale = this.getScales();
      const path = d3.line()
        .x((d, i) => scale.x(i))
        .y(d => scale.y(d));
      this.line = path(this.data);
    },
  },
};
</script>
<style lang="sass" scoped>
svg
  margin: 25px;
path
  fill: none
  stroke: #76BF8A
  stroke-width: 3px
</style>

Cool, even if it doesn't expose any properties and the data is hard coded, it's a good way to separate the view from the logic and use Vue hooks, methods and data objects, just like the above figure

Tags: Javascript Vue npm sass Webpack

Posted on Fri, 27 Mar 2020 08:50:51 -0700 by scarabee