Real-Time Data Visualization with D3.js and Vue.js.

Many web applications and solutions are becoming more dynamic and responsive. This is, in part, due to high compute capacity as a lot of web applications are deployed on various cloud platforms as a result of high reliability, availability and security…


This content originally appeared on DEV Community and was authored by Callis Ezenwaka

Many web applications and solutions are becoming more dynamic and responsive. This is, in part, due to high compute capacity as a lot of web applications are deployed on various cloud platforms as a result of high reliability, availability and security.

To add to this, is the end users' continual demand for real time experience. As organizations becomes more data-driven, many are using data visualizations to either tell their stories or share real time feedback with their customers.

This tutorial will use D3.js, a JavaScript library for manipulating documents based on data and Vue.js, a progressive JavaScript framework used for building user interfaces, to demonstrate real time visualization.

Firstly, we will create a vue.js project using vite.js, a build tool for modern web development that is designed to be fast and efficient. If you do not have vite already installed, run the following command npm create vite@latest.

Then, navigate to project directory and run npm init vue@latest and follow the prompt by picking a project name, selecting TypeScript and other relevant features.

✔ Project name: … <your-project-name>
✔ Add TypeScript? … No / Yes
✔ Add JSX Support? … No / Yes
✔ Add Vue Router for Single Page Application development? … No / Yes
✔ Add Pinia for state management? … No / Yes
✔ Add Vitest for Unit testing? … No / Yes
✔ Add Cypress for both Unit and End-to-End testing? … No / Yes
✔ Add ESLint for code quality? … No / Yes
✔ Add Prettier for code formatting? … No / Yes

Scaffolding project in ./<your-project-name>...
Done.

This will scaffold a vue.js project with similar project tree:

├── README.md
├── env.d.ts
├── index.html
├── node_modules
├── package-lock.json
├── package.json
├── public
│   └── favicon.ico
├── src
│   ├── App.vue
│   ├── assets
│   ├── components
│   ├── main.ts
│   ├── router
│   ├── types
│   └── views
├── tsconfig.app.json
├── tsconfig.config.json
├── tsconfig.json
├── tsconfig.vitest.json
└── vite.config.ts

Afterwards, confirm that your package.json file has the following dependencies, else copy and paste (more reliably install them individually if the latest version is your thing) them. Make sure that you are inside your project directory. Otherwise, change to your project directory and run npm install.

Navigate to the components directory and create the chart folder (Barchart for this example) and a BarChart.vue file as shown below:

├── BarChart
│   └── BarChart.vue

Open the .vue file and paste the following code:

<template>
  <div class="" ref="barChartRef"></div>
</template>

This is a vue.js code template with a ref?: VNodeRef property called barChartRef. We will define the ref inside the script section. Next create a script section and import the D3.js library and other Vue.js dependencies.

For demonstration purposes, we will be skipping some codes here but are available in the repository.

<script setup lang="ts">
// @ is an alias to /src
import * as d3 from "d3";
import { onMounted, onBeforeUnmount, computed, ref, reactive, watch, } from "vue";
...

</script>

We can also define our data, data interface (schema) and other variables for the chart.

interface Input {
  label: string;
  value: number;
}

const barChartRef = ref<HTMLElement | null>(null);
const margin = reactive({ top: 30, right: 20, bottom: 30, left: 40 });
const height = ref(360);
const width = ref(
  (barChartRef?.value?.offsetWidth || 300) - margin.left - margin.right
);

const revenue = ref([
  {
    label: "2013-06-30",
    value: 660,
  },
  {
    label: "2014-12-31",
    value: 814,
  },
  {
    label: "2015-06-30",
    value: 1131,
  },
  {
    label: "2016-12-31",
    value: 1267,
  },
  {
    label: "2017-06-30",
    value: 1514,
  },
  {
    label: "2018-12-31",
    value: 1763,
  },
  {
    label: "2019-06-30",
    value: 2653,
  },
  {
    label: "2020-12-31",
    value: 6148,
  },
  {
    label: "2021-06-30",
    value: 12394,
  },
  {
    label: "2022-12-31",
    value: 2162,
  },
]);

Then, we will transform our data to the right format as below using a computed function:

const data = computed(() => {
  return revenue.value.map((d: Input) => {
    return {
      label: d.label,
      value: d.value,
    };
  });
});

We are going to use other Vue.js native API functions to control how our chart is rendered on the page.

onMounted(async () => {
  window.addEventListener("resize", handleResize);
  handleResize();
  handleDraw();
});

onBeforeUnmount(() => {
  window.removeEventListener("resize", handleResize);
});

watch(
  () => width.value,
  () => {
    remove();
    handleDraw();
  }
);

To avoid having multiple charts when the page re-renders, we can create a function that checks if the number of charts on the page exceeds one. It true, it will purge all except one.

const remove = () => {
  // TODO: Get svg reference
  const svg = d3.select(barChartRef.value).selectAll("svg");

  // check the number of existing elements, if greater than 0; remove all existing ones
  if (svg.size()) svg.remove().exit();
};

We can make the chart to be responsive for every device screen by checking the user's screen size and displaying a chart within the width of the screen.

const handleResize = () => {
  if (barChartRef?.value?.offsetWidth) {
    width.value = barChartRef.value.offsetWidth - margin.left - margin.right;
    return;
  }

  if (window.innerWidth < 400) {
    width.value = 300 - margin.left - margin.right;
    return;
  }

  width.value = 550 - margin.left - margin.right;
  return;
};

Finally, let us create a function that with generate our chart every time the page renders.

const handleDraw = async () => {
  // append the svg object to the body of the page
  const svg = d3
    .select(barChartRef.value)
    .append("svg")
    .attr("width", width.value + margin.left + margin.right)
    .attr("height", height.value + margin.top + margin.bottom)
    .append("g")
    .attr("transform", `translate(${margin.left},${margin.top})`);

  // Add X axis
  const x = d3
    .scaleBand()
    .domain(data.value.map((d) => d.label))
    // .domain(data.value, (d) => d.label)
    // .domain([data.value.map((d) => d.label)] as unknown as string)
    .range([0, width.value])
    .padding(0.2);

  svg
    .append("g")
    .attr("transform", `translate(0, ${height.value})`)
    .call(d3.axisBottom(x))
    // .call(d3.axisBottom(x).tickFormat((x) => d3.timeFormat("%Y")(x)))
    .selectAll("text")
    .attr("transform", "translate(-10,0)rotate(-45)")
    .style("text-anchor", "end");

  // Add Y axis
  const y = d3
    .scaleLinear()
    .domain([0, d3.max(data.value, (d): number => d.value)] as number[])
    .range([height.value, 0]);

  svg.append("g").call(d3.axisLeft(y));

  // Bars
  svg
    .selectAll("mybar")
    .data(data.value)
    .enter()
    .append("rect")
    .attr("x", (d) => x(d.label) as number)
    .attr("y", (d) => y(d.value))
    .attr("width", x.bandwidth())
    .attr("height", (d) => height.value - y(d.value))
    .attr("fill", "#4682b4");

  svg
    .append("text")
    .attr("class", "title")
    .attr("x", width.value / 2)
    .attr("y", 0 - margin.top / 2)
    .attr("text-anchor", "middle")
    .text("Company Revenue in USD ($)");
};

A sample output should look like the image below:

Vue graph

That is all we need to do in order to create a real time responsive and dynamic visualization using D3.js and Vue.js. The repository for this tutorial is on GitHub.

If you like the article, do like and share with friends.


This content originally appeared on DEV Community and was authored by Callis Ezenwaka


Print Share Comment Cite Upload Translate Updates
APA

Callis Ezenwaka | Sciencx (2023-04-22T22:48:24+00:00) Real-Time Data Visualization with D3.js and Vue.js.. Retrieved from https://www.scien.cx/2023/04/22/real-time-data-visualization-with-d3-js-and-vue-js/

MLA
" » Real-Time Data Visualization with D3.js and Vue.js.." Callis Ezenwaka | Sciencx - Saturday April 22, 2023, https://www.scien.cx/2023/04/22/real-time-data-visualization-with-d3-js-and-vue-js/
HARVARD
Callis Ezenwaka | Sciencx Saturday April 22, 2023 » Real-Time Data Visualization with D3.js and Vue.js.., viewed ,<https://www.scien.cx/2023/04/22/real-time-data-visualization-with-d3-js-and-vue-js/>
VANCOUVER
Callis Ezenwaka | Sciencx - » Real-Time Data Visualization with D3.js and Vue.js.. [Internet]. [Accessed ]. Available from: https://www.scien.cx/2023/04/22/real-time-data-visualization-with-d3-js-and-vue-js/
CHICAGO
" » Real-Time Data Visualization with D3.js and Vue.js.." Callis Ezenwaka | Sciencx - Accessed . https://www.scien.cx/2023/04/22/real-time-data-visualization-with-d3-js-and-vue-js/
IEEE
" » Real-Time Data Visualization with D3.js and Vue.js.." Callis Ezenwaka | Sciencx [Online]. Available: https://www.scien.cx/2023/04/22/real-time-data-visualization-with-d3-js-and-vue-js/. [Accessed: ]
rf:citation
» Real-Time Data Visualization with D3.js and Vue.js. | Callis Ezenwaka | Sciencx | https://www.scien.cx/2023/04/22/real-time-data-visualization-with-d3-js-and-vue-js/ |

Please log in to upload a file.




There are no updates yet.
Click the Upload button above to add an update.

You must be logged in to translate posts. Please log in or register.