- Регистрация
- 1 Мар 2015
- Сообщения
- 1,481
- Баллы
- 155
Creating data visualizations in modern web apps often requires both flexibility and reactivity. Vue.js, a progressive JavaScript framework, is excellent for managing reactive UIs, while D3.js is one of the most powerful libraries for data-driven document manipulation and visualization.
In this guide, we’ll explore how to combine Vue and D3 to build dynamic, interactive charts.
Enjoy!
? Why using D3 for Vue?
Vue handles the DOM reactively using a component-based structure, which is great for app state management. D3, on the other hand, directly manipulates the DOM to render SVG elements based on data. While that might seem like a conflict, with proper structure, they can complement each other well:
Check of data visualization with D3.
? Building a basic chart component
Let's create a simple bar chart component.
1.Create a new file BarChart.vue:
<template>
<svg ref="svg"></svg>
</template>
<script setup>
import { onMounted, ref, watch } from 'vue'
import * as d3 from 'd3'
const props = defineProps({
data: {
type: Array,
required: true
},
width: {
type: Number,
default: 400
},
height: {
type: Number,
default: 200
}
})
const svg = ref(null)
const drawChart = () => {
const svgEl = d3.select(svg.value)
svgEl.selectAll('*').remove() // Clear previous renders
svgEl.attr('width', props.width).attr('height', props.height)
const x = d3
.scaleBand()
.domain(props.data.map((d, i) => i))
.range([0, props.width])
.padding(0.1)
const y = d3
.scaleLinear()
.domain([0, d3.max(props.data)])
.nice()
.range([props.height, 0])
svgEl
.selectAll('rect')
.data(props.data)
.join('rect')
.attr('x', (_, i) => x(i))
.attr('y', d => y(d))
.attr('width', x.bandwidth())
.attr('height', d => props.height - y(d))
.attr('fill', 'steelblue')
}
onMounted(drawChart)
watch(() => props.data, drawChart)
</script>
Let's stop for a second here to explain each part of the drawChart method:
const drawChart = () => {
const svgEl = d3.select(svg.value)
svgEl.selectAll('*').remove() // Clear previous renders
svgEl.attr('width', props.width).attr('height', props.height)
const x = d3
.scaleBand()
.domain(props.data.map((d, i) => i))
.range([0, props.width])
.padding(0.1)
const y = d3
.scaleLinear()
.domain([0, d3.max(props.data)])
.nice()
.range([props.height, 0])
svgEl
.selectAll('rect')
.data(props.data)
.join('rect')
.attr('x', (_, i) => x(i))
.attr('y', d => y(d))
.attr('width', x.bandwidth())
.attr('height', d => props.height - y(d))
.attr('fill', 'steelblue')
2.Use the BarChart component in your main app file:
<template>
<div>
<BarChart :data="chartData" />
</div>
</template>
<script setup>
import { ref } from 'vue'
import BarChart from './components/BarChart.vue'
const chartData = ref([10, 15, 20, 25, 30])
</script>
The chart should look more or less like this:
To scale up your Vue and D3 app, make sure to utilize following approaches:
If you would like to learn more about Vue, Nuxt, JavaScript or other useful technologies, checkout VueSchool by clicking this or by clicking the image below:
It covers most important concepts while building modern Vue or Nuxt applications that can help you in your daily work or side projects ?
Summary
By combining Vue’s reactive data handling with D3’s powerful visualization tools, you can build highly interactive, performant data visualizations. This approach is perfect for dashboards, real-time analytics, and more.
Take care and see you next time!
And happy coding as always ?️
In this guide, we’ll explore how to combine Vue and D3 to build dynamic, interactive charts.
Enjoy!
? Why using D3 for Vue?
Vue handles the DOM reactively using a component-based structure, which is great for app state management. D3, on the other hand, directly manipulates the DOM to render SVG elements based on data. While that might seem like a conflict, with proper structure, they can complement each other well:
- Vue manages application state and layout.
- D3 handles drawing and updating the visualization.
Check of data visualization with D3.
? Building a basic chart component
Let's create a simple bar chart component.
1.Create a new file BarChart.vue:
<template>
<svg ref="svg"></svg>
</template>
<script setup>
import { onMounted, ref, watch } from 'vue'
import * as d3 from 'd3'
const props = defineProps({
data: {
type: Array,
required: true
},
width: {
type: Number,
default: 400
},
height: {
type: Number,
default: 200
}
})
const svg = ref(null)
const drawChart = () => {
const svgEl = d3.select(svg.value)
svgEl.selectAll('*').remove() // Clear previous renders
svgEl.attr('width', props.width).attr('height', props.height)
const x = d3
.scaleBand()
.domain(props.data.map((d, i) => i))
.range([0, props.width])
.padding(0.1)
const y = d3
.scaleLinear()
.domain([0, d3.max(props.data)])
.nice()
.range([props.height, 0])
svgEl
.selectAll('rect')
.data(props.data)
.join('rect')
.attr('x', (_, i) => x(i))
.attr('y', d => y(d))
.attr('width', x.bandwidth())
.attr('height', d => props.height - y(d))
.attr('fill', 'steelblue')
}
onMounted(drawChart)
watch(() => props.data, drawChart)
</script>
Let's stop for a second here to explain each part of the drawChart method:
const drawChart = () => {
const svgEl = d3.select(svg.value)
svgEl.selectAll('*').remove() // Clear previous renders
- d3.select(svg.value): Selects the actual <svg> element from the DOM.
- selectAll('*').remove(): Clears any previously drawn chart elements to avoid overlap when re-rendering.
svgEl.attr('width', props.width).attr('height', props.height)
- Sets the SVG canvas dimensions.
const x = d3
.scaleBand()
.domain(props.data.map((d, i) => i))
.range([0, props.width])
.padding(0.1)
- d3.scaleBand(): Creates a scale for discrete bands (bars).
- domain: Maps indices of data to bands.
- range: Spans the scale from 0 to the total width.
- padding(0.1): Adds spacing between bars.
const y = d3
.scaleLinear()
.domain([0, d3.max(props.data)])
.nice()
.range([props.height, 0])
- d3.scaleLinear(): Linear scale for bar heights.
- domain: Goes from 0 to the max value in the data.
- nice(): Rounds the domain to nice round numbers.
- range: From SVG height (bottom) to 0 (top) because SVG Y-coordinates increase downward.
svgEl
.selectAll('rect')
.data(props.data)
.join('rect')
.attr('x', (_, i) => x(i))
.attr('y', d => y(d))
.attr('width', x.bandwidth())
.attr('height', d => props.height - y(d))
.attr('fill', 'steelblue')
- .selectAll('rect'): Prepares to bind data to <rect> elements (bars).
- .data(props.data): Binds the array of values.
- .join('rect'): Efficiently adds/removes <rect> elements as needed.
- .attr('x', ...): Sets the x-position for each bar.
- .attr('y', ...): Sets the y-position (top) of each bar.
- .attr('width', ...): Sets bar width based on the scale’s bandwidth.
- .attr('height', ...): Calculates bar height from value.
- .attr('fill', ...): Sets bar color.
2.Use the BarChart component in your main app file:
<template>
<div>
<BarChart :data="chartData" />
</div>
</template>
<script setup>
import { ref } from 'vue'
import BarChart from './components/BarChart.vue'
const chartData = ref([10, 15, 20, 25, 30])
</script>
The chart should look more or less like this:
To scale up your Vue and D3 app, make sure to utilize following approaches:
- Encapsulate D3 logic in composables if complexity grows.
- Use transitions from D3 for smooth updates.
- Consider watching window size to make charts responsive.
- For advanced use cases, look into D3 modules like d3-axis, d3-shape, and d3-brush.
If you would like to learn more about Vue, Nuxt, JavaScript or other useful technologies, checkout VueSchool by clicking this or by clicking the image below:
It covers most important concepts while building modern Vue or Nuxt applications that can help you in your daily work or side projects ?
By combining Vue’s reactive data handling with D3’s powerful visualization tools, you can build highly interactive, performant data visualizations. This approach is perfect for dashboards, real-time analytics, and more.
Take care and see you next time!
And happy coding as always ?️