D3 lets us add graphics to a front-end web app easily.
Vue is a popular front end web framework.
They work great together. In this article, we’ll look at how to add graphics to a Vue app with D3.
Find Elements in Selections
We can find elements in selections.
For example, we can write:
<template>
<div id="app">
<div>
<b>apple</b>
<b>orange</b>
<b>grape</b>
</div>
</div>
</template>
<script>
import * as d3 from "d3";
import Vue from "vue";
export default {
name: "App",
mounted() {
Vue.nextTick(() => {
let selection = d3.selectAll("b").filter(":nth-child(odd)").nodes();
selection.forEach((e) => {
console.log(e.textContent);
});
});
},
};
</script>
to get all the b
elements and filter them to get all the even index ones.
Then we call forEach
to get their text content.
We can call the filter
with the d3.matcher
method.
For instance, we can write:
<template>
<div id="app">
<div></div>
<div>
<h5>This is text1</h5>
<h5>This is text2</h5>
<h5>This is text3</h5>
<h5>This is text4</h5>
</div>
</div>
</template>
<script>
import * as d3 from "d3";
import Vue from "vue";
export default {
name: "App",
mounted() {
Vue.nextTick(() => {
const heading = d3.selectAll("h5");
const matcher = heading.filter(d3.matcher("h5")).node();
const filter = heading.filter(d3.matcher("h5")).node();
console.log(matcher);
console.log(filter);
});
},
};
</script>
to get the h5
elements with the matcher
method to get the h5
element.
We can call d3.creator
to create an element.
For instance, we can write:
<template>
<div id="app"></div>
</template>
<script>
import * as d3 from "d3";
import Vue from "vue";
export default {
name: "App",
mounted() {
Vue.nextTick(() => {
const selection = d3.select("body");
selection.append(d3.creator("div"));
const div = document.querySelector("div");
div.innerText = "hello world.";
});
},
};
</script>
The d3.creator
method creates a div.
Then we get the div
with querySelector
and set the innerText
property to add text content to it.
Paths API
We can add a shape with the paths API.
For example, we can write:
<template>
<div id="app">
<svg width="600" height="100">
<path transform="translate(20, 0)" />
</svg>
</div>
</template>
<script>
import * as d3 from "d3";
import Vue from "vue";
export default {
name: "App",
mounted() {
Vue.nextTick(() => {
const data = [
[0, 12],
[50, 20],
[100, 30],
[200, 40],
[300, 90],
];
const lineGenerator = d3.line();
const pathString = lineGenerator(data);
d3.select("path").attr("d", pathString);
});
},
};
</script>
<style>
path {
fill: green;
stroke: #aaa;
}
</style>
We create the svg
element.
Then we create the line with the d3.line
method.
And then we pass in the data
into the returned lineGenerator
function.
Then we pass in the returned pathString
into the attr
method so set the SVG’s path.
Scales API
We can use the scales API to transform data in various ways.
For example, we can write:
<template>
<div id="app"></div>
</template>
<script>
import * as d3 from "d3";
import Vue from "vue";
export default {
name: "App",
mounted() {
Vue.nextTick(() => {
const data = [100, 220, 330, 350, 400, 250];
const width = 500,
barHeight = 20,
margin = 1;
const scale = d3
.scaleLinear()
.domain([d3.min(data), d3.max(data)])
.range([100, 400]);
const svg = d3
.select("body")
.append("svg")
.attr("width", width)
.attr("height", barHeight * data.length);
const g = svg
.selectAll("g")
.data(data)
.enter()
.append("g")
.attr("transform", function (d, i) {
return `translate(0, ${i * barHeight})`;
});
g.append("rect")
.attr("width", function (d) {
return scale(d);
})
.attr("height", barHeight - margin);
g.append("text")
.attr("x", function (d) {
return scale(d);
})
.attr("y", barHeight / 2)
.attr("dy", ".35em")
.text(function (d) {
return d;
});
});
},
};
</script>
We have the data
to display as bars.
And we have the width
for the chart’s width.
barHeight
has the bars’ height.
We create the scale
object to scale the bars with:
const scale = d3
.scaleLinear()
.domain([d3.min(data), d3.max(data)])
.range([100, 400]);
The scaleLinear
method creates a continuous linear scale where we can map input data to the specified output range.
Then we add the SVG for the chart to the body
with:
const svg = d3
.select("body")
.append("svg")
.attr("width", width)
.attr("height", barHeight * data.length);
Next, we add the bar group by writing:
const g = svg
.selectAll("g")
.data(data)
.enter()
.append("g")
.attr("transform", function(d, i) {
return `translate(0, ${i * barHeight})`;
});
Then we set the widths of the bars by writing:
g.append("rect")
.attr("width", function(d) {
return scale(d);
})
.attr("height", barHeight - margin);
Then we set the bars to the length given by the data by writing:
g.append("text")
.attr("x", function(d) {
return scale(d);
})
.attr("y", barHeight / 2)
.attr("dy", ".35em")
.text(function(d) {
return d;
});
Conclusion
We can select items and create scales with D3.