I’m incorporating D3JS charts in my VueJS application and am having trouble understanding how to connect the D3 component to a div in a .vue.js file. The D3 chart renders beautifully when I attach it to the HTML body, but I don’t want it to appear on every view, just the view that I’ve imported it to and just to the div I want.
I’ve looked at other answers that do mounting and computing of D3 components in the vue.js — all of which seems excessively complicated.
Likely I’m not understanding how D3 charts should work as vue.js components. I’m trying to keep it simple as possible. Here’s my Home.vue.js in views/
<template>
<div id=”chart”>
</div>
</template>
<script>
import MainChart from “@/components/MainChart.vue”;
export default {
name: ‘chart’,
components: {
MainChart
}
}
</script>
And then my MainChart component in components/
<template>
<div id=”chart”>
</div>
</div>
</template>
<script>
import * as d3 from “d3”;
export default {
name: “MainChart”,
};
// 2. Use the margin convention practice
var margin = {top: 50, right: 50, bottom: 50, left: 50}
, width = window.innerWidth - margin.left - margin.right // Use the window’s width
, height = window.innerHeight - margin.top - margin.bottom; // Use the window’s height
// The number of datapoints
var n = 30;
// 5. X scale will use the index of our data
var xScale = d3.scalePow()
.domain([0, n-1]) // input
.range([0, width]); // output
// 6. Y scale will use the randomly generate number
var yScale = d3.scalePow()
.domain([0, 1000]) // input
.range([height, 0]); // output
// 1. Add the SVG to the page and employ #2
var svg = d3.select(“#chart”).append(“svg”)
.attr(“width”, width + margin.left + margin.right)
.attr(“height”, height + margin.top + margin.bottom)
.append(“g”)
.attr(“transform”, “translate(“ + margin.left + “,” + margin.top + “)”);
// 3. Call the x axis in a group tag
svg.append(“g”)
.attr(“class”, “x axis”)
.attr(“transform”, “translate(0,” + height + “)”)
.call(d3.axisBottom(xScale)); // Create an axis component with d3.axisBottom
svg.append(“text”)
.attr(“class”, “x label”)
.attr(“text-anchor”, “end”)
.attr(“x”, width)
.attr(“y”, height - 6)
.text(“Time”);
// 4. Call the y axis in a group tag
svg.append(“g”)
.attr(“class”, “y axis”)
.call(d3.axisLeft(yScale)); // Create an axis component with d3.axisLeft
svg.append(“text”)
.attr(“class”, “y label”)
.attr(“text-anchor”, “end”)
.attr(“y”, 6)
.attr(“dy”, “.75em”)
.attr(“transform”, “rotate(-90)”)
.text(“Views”);
// 7. d3’s line generator
var line = d3.line()
.x(function(d, i) { return xScale(i); }) // set the x values for the line generator
.y(function(d) { return yScale(d.y); }) // set the y values for the line generator
.curve(d3.curveMonotoneX) // apply smoothing to the line
// 8. An array of objects of length N. Each object has key -> value pair, the key being “y” and the value is a random number
// var dataset = d3.range(n).map(function(d) { return {“y”: d3.randomUniform(1)() } })
var dataset = [],
n = 30,
a = 20,
b = 1.15;
for (var k = 0; k < n; k++) {
dataset.push({x: 1 * k, y: a * Math.pow(b, k)});
}
// 9. Append the path, bind the data, and call the line generator
svg.append(“path”)
.datum(dataset) // 10. Binds data to the line
.attr(“class”, “line”) // Assign a class for styling
.attr(“d”, line) // 11. Calls the line generator
.attr(“stroke-dasharray”, 100 + “ “ + 100)
.attr(“stroke-dashoffset”, 1000)
.attr(“fill”, “none”)
.transition()
.duration(10000)
.ease(d3.easeLinear)
.attr(“stroke-dashoffset”, 0);
// 12. Appends a circle for each datapoint
svg.selectAll(“.dot”)
.data(dataset)
.enter().append(“circle”) // Uses the enter().append() method
.attr(“class”, “dot”) // Assign a class for styling
.attr(“cx”, function(d, i) { return xScale(i) })
.attr(“cy”, function(d) { return yScale(d.y) })
.attr(“r”, 5);
</script>
<style>
/* 13. Basic Styling with CSS */
/* Style the lines by removing the fill and applying a stroke */
.line {
fill: none;
stroke: #678C1A;
stroke-width: 3;
}
.axis text { display: none; }
/* Style the dots by assigning a fill and stroke */
.dot {
fill: #C7D941;
stroke: #fff;
}
</style>
Because it works fine when I attach the svg to “body” it must be the case that the D3 chart isn’t finding the div when it loads into the Home.vue, right?
Solution :
From the examples posted I see some syntax errors.
Home.vue
<template>
<div id=”home”>
<MainChart></MainChart>
</div>
</template>
<script>
import MainChart from “@/components/MainChart.vue”;
export default {
name: ‘chart’,
components: {
MainChart
}
}
</script>
MainChart.vue
<template>
<div id=”chart”></div>
</template>
<script>
import * as d3 from “d3”;
export default {
name: “MainChart”,
};
// 2. Use the margin convention practice
var margin = {top: 50, right: 50, bottom: 50, left: 50}
, width = window.innerWidth - margin.left - margin.right // Use the window’s width
, height = window.innerHeight - margin.top - margin.bottom; // Use the window’s height
// The number of datapoints
var n = 30;
// 5. X scale will use the index of our data
var xScale = d3.scalePow()
.domain([0, n-1]) // input
.range([0, width]); // output
// 6. Y scale will use the randomly generate number
var yScale = d3.scalePow()
.domain([0, 1000]) // input
.range([height, 0]); // output
// 1. Add the SVG to the page and employ #2
var svg = d3.select(“#chart”).append(“svg”)
.attr(“width”, width + margin.left + margin.right)
.attr(“height”, height + margin.top + margin.bottom)
.append(“g”)
.attr(“transform”, “translate(“ + margin.left + “,” + margin.top + “)”);
// 3. Call the x axis in a group tag
svg.append(“g”)
.attr(“class”, “x axis”)
.attr(“transform”, “translate(0,” + height + “)”)
.call(d3.axisBottom(xScale)); // Create an axis component with d3.axisBottom
svg.append(“text”)
.attr(“class”, “x label”)
.attr(“text-anchor”, “end”)
.attr(“x”, width)
.attr(“y”, height - 6)
.text(“Time”);
// 4. Call the y axis in a group tag
svg.append(“g”)
.attr(“class”, “y axis”)
.call(d3.axisLeft(yScale)); // Create an axis component with d3.axisLeft
svg.append(“text”)
.attr(“class”, “y label”)
.attr(“text-anchor”, “end”)
.attr(“y”, 6)
.attr(“dy”, “.75em”)
.attr(“transform”, “rotate(-90)”)
.text(“Views”);
// 7. d3’s line generator
var line = d3.line()
.x(function(d, i) { return xScale(i); }) // set the x values for the line generator
.y(function(d) { return yScale(d.y); }) // set the y values for the line generator
.curve(d3.curveMonotoneX) // apply smoothing to the line
// 8. An array of objects of length N. Each object has key -> value pair, the key being “y” and the value is a random number
// var dataset = d3.range(n).map(function(d) { return {“y”: d3.randomUniform(1)() } })
var dataset = [],
n = 30,
a = 20,
b = 1.15;
for (var k = 0; k < n; k++) {
dataset.push({x: 1 * k, y: a * Math.pow(b, k)});
}
// 9. Append the path, bind the data, and call the line generator
svg.append(“path”)
.datum(dataset) // 10. Binds data to the line
.attr(“class”, “line”) // Assign a class for styling
.attr(“d”, line) // 11. Calls the line generator
.attr(“stroke-dasharray”, 100 + “ “ + 100)
.attr(“stroke-dashoffset”, 1000)
.attr(“fill”, “none”)
.transition()
.duration(10000)
.ease(d3.easeLinear)
.attr(“stroke-dashoffset”, 0);
// 12. Appends a circle for each datapoint
svg.selectAll(“.dot”)
.data(dataset)
.enter().append(“circle”) // Uses the enter().append() method
.attr(“class”, “dot”) // Assign a class for styling
.attr(“cx”, function(d, i) { return xScale(i) })
.attr(“cy”, function(d) { return yScale(d.y) })
.attr(“r”, 5);
</script>
<style>
.line {
fill: none;
stroke: #678C1A;
stroke-width: 3;
}
.axis text {
display: none;
}
.dot {
fill: #C7D941;
stroke: #fff;
}
</style>