DEV Community

Cover image for How to add a sparkline to your Vue.js app
Corentin for Mailmeteor

Posted on β€’ Edited on

11 3

How to add a sparkline to your Vue.js app

Very recently, I was looking to add a neat sparkline to a Vue.js application of my own.

As always, I googled just that, looking for sparkline vue.js or sparkline npm. But I couldn't find something that was easy, with a small footprint and yet customizable.

After playing a bit with Chart.js, I just stopped and considered how I could build a decent, yet very simple, sparkline component (i.e. without any dependency).

If you look at how npm's sparkline works as well as the ones from Stripe's dashboard, you will quickly realize that it's just a SVG element that you customize with JavaScript.

So bear with me, I'll show you how to do just that.

Demo

Behind the scene

The sparkline is just a Vue.js component where you provide the coordinates of the sparkline as an array. Here's how I've rendered the sparkline in the example above:

<sparkline v-bind:data="[2, 3, 5, 7, 11, 13, 17, 19, 23, 29, 31]"></sparkline>
Enter fullscreen mode Exit fullscreen mode

The source code of the component is the following:

<template>
<svg class="sparkline" :width="width" :height="height" :stroke-width="stroke">
<path class="sparkline--line" :d="shape" fill="none"></path>
<path
class="sparkline--fill"
:d="[shape, fillEndPath].join(' ')"
stroke="none"
></path>
</svg>
</template>
<script>
export default {
props: ["data"],
data() {
return {
stroke: 3,
width: 256,
height: 80,
};
},
computed: {
shape() {
const stroke = this.stroke;
const width = this.width;
const height = this.height - stroke * 2;
const data = this.data || [];
const highestPoint = Math.max.apply(null, data) + 1;
const coordinates = [];
const totalPoints = this.data.length - 1;
data.forEach((item, n) => {
const x = (n / totalPoints) * width + stroke;
const y = height - (item / highestPoint) * height + stroke;
coordinates.push({ x, y });
});
if (!coordinates[0]) {
return (
"M 0 " +
this.stroke +
" L 0 " +
this.stroke +
" L " +
this.width +
" " +
this.stroke
);
}
const path = [];
coordinates.forEach((point) =>
path.push(["L", point.x, point.y].join(" "))
);
return ["M" + coordinates[0].x, coordinates[0].y, ...path].join(" ");
},
fillEndPath() {
return `V ${this.height} L 4 ${this.height} Z`;
},
},
};
</script>
<style>
svg {
stroke: #1f8ceb;
fill: rgba(31, 140, 235, 0.06);
transition: all 1s ease-in-out;
}
svg path {
box-sizing: border-box;
}
</style>
view raw Sparkline.vue hosted with ❀ by GitHub

As you might have noticed, the code renders an <svg> HTML element by computing the coordinates of the different <path>.

There are two <path>. One for the blue line. And another one for the blue background. I've used the color #1f8ceb but of course this is totally customizable, just like the width/height of the sparkline.

That component is pretty basic and contrary to NPM or Stripe, it doesn't handle when a mouse hovers the <svg>. I didn't need that for my use case, but if ever you implement it, feel free to edit the gist and share it with the community.

Neon image

Set up a Neon project in seconds and connect from a Next.js application

If you're starting a new project, Neon has got your databases covered. No credit cards. No trials. No getting in your way.

Get started β†’

Top comments (2)

Collapse
 
cuireuncroco profile image
Jean β€’

Clever use of Vue!

Collapse
 
frenchcooc profile image
Corentin β€’ β€’ Edited

As always, feel free to share your thoughts/improvements in the comment πŸ€—

Neon image

Next.js applications: Set up a Neon project in seconds

If you're starting a new project, Neon has got your databases covered. No credit cards. No trials. No getting in your way.

Get started β†’

πŸ‘‹ Kindness is contagious

Explore a trove of insights in this engaging article, celebrated within our welcoming DEV Community. Developers from every background are invited to join and enhance our shared wisdom.

A genuine "thank you" can truly uplift someone’s day. Feel free to express your gratitude in the comments below!

On DEV, our collective exchange of knowledge lightens the road ahead and strengthens our community bonds. Found something valuable here? A small thank you to the author can make a big difference.

Okay