[Vuejs]-How can I build a d3.js linechart in Vue.js?

2👍

Here is an example of Vue.js & D3.js linechart

const data = [40,45,47,59,54,53,62,69,76,85,94,111,129,144,154,157,161,155,164,174];

const buildChart = ref => {
    const svg = d3.select(ref);
  const xScale = 
    d3.scaleLinear()
    .domain([0, 50])
    .range([0, 300]);
                  
 const xAxis = 
        d3.axisBottom()
    .scale(xScale);

svg.append("g")
    .attr('transform', 'translate(50,210)')
  .call(xAxis);                 

const yScale = 
    d3.scaleLinear()
    .domain([200, 0])
    .range([0, 200]);
                  
 const yAxis = 
        d3.axisLeft()
    .scale(yScale);

svg.append("g")
    .attr('transform', 'translate(50,10)')
  .call(yAxis);         
    
const path = data.reduce((p, v, i) => {
 const x = 300 / data.length * i;
 const y = yScale(v);
 if (i === 0) return `M ${x},${y}`;
 return p + ` L ${x},${y}`;
}, null)

svg.append('g')
    .attr('transform', 'translate(50, 10)')
  .append('path')
  .attr('d', path)
  .style('fill', 'none')
  .style('stroke', 'red')
  .style('stroke-width', 2)
}


Vue.component('d3-component', {
  mounted() {
    buildChart(this.$refs.svg)
  },
  template: '<svg ref="svg" width="400" height="250"></svg>'
})

new Vue({ el: '#d3-component-demo' })
<script src="https://cdnjs.cloudflare.com/ajax/libs/vue/2.5.17/vue.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/d3/5.7.0/d3.min.js"></script>

<div id="d3-component-demo">
  <d3-component/>
</div>

1👍

  1. You can set negative values to X axis with domain:

    const xScale = d3.scaleLinear().domain([-50, 50])

  2. I (personally) prefer not to use viewbox. Instead, I pass the width and height attributes explicitly to SVG and use them in the chart calculations

  3. You can round by stroke-linejoin=’round’, but it does not work smoothly in every case

const data = [40,45,47,59,54,53,62,69,76,85,94,111,129,144,154,157,161,155,164,174];

const buildChart = ref => {
    const svg = d3.select(ref);
  const xScale = 
    d3.scaleLinear()
    .domain([-50, 50])
    .range([0, 300]);
                  
 const xAxis = 
        d3.axisBottom()
    .scale(xScale);

svg.append("g")
    .attr('transform', 'translate(50,210)')
  .call(xAxis);                 

const yScale = 
    d3.scaleLinear()
    .domain([200, 0])
    .range([0, 200]);
                  
 const yAxis = 
        d3.axisLeft()
    .scale(yScale);

svg.append("g")
    .attr('transform', 'translate(50,10)')
  .call(yAxis);         
    
const path = data.reduce((p, v, i) => {
 const x = 300 / data.length * i;
 const y = yScale(v);
 if (i === 0) return `M ${x},${y}`;
 return p + ` L ${x},${y}`;
}, null)

svg.append('g')
    .attr('transform', 'translate(50, 10)')
  .append('path')
  .attr('d', path)
  .attr('stroke-linejoin', 'round')
  .style('fill', 'none')
  .style('stroke', 'red')
  .style('stroke-width', 5)
}


Vue.component('d3-component', {
  mounted() {
    buildChart(this.$refs.svg)
  },
  template: '<svg ref="svg" width="400" height="250"></svg>'
})

new Vue({ el: '#d3-component-demo' })
<script src="https://cdnjs.cloudflare.com/ajax/libs/vue/2.5.17/vue.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/d3/5.7.0/d3.min.js"></script>

<div id="d3-component-demo">
  <d3-component/>
</div>

Leave a comment