Skip to content

Instantly share code, notes, and snippets.

@Frenchcooc
Last active May 31, 2023 16:29
Show Gist options
  • Star 3 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save Frenchcooc/e4748ad6275984a01868153e3c0d8a1e to your computer and use it in GitHub Desktop.
Save Frenchcooc/e4748ad6275984a01868153e3c0d8a1e to your computer and use it in GitHub Desktop.
Simple sparkline component for Vue.js
<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>
@Frenchcooc
Copy link
Author

Use it like that:

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

@TXG-Ryan
Copy link

is it possible to pull in data from an api and then pass it to v-bind:data="[]"?

@Frenchcooc
Copy link
Author

I’m pretty sure that’s doable. Feel free to share how you’ve made it.

@TXG-Ryan
Copy link

Ive tried and I can't figure it out. My knowledge is limited so perhaps you may find this easier. If you manage to do so then please do share as i've been trying to do something like this for a while :)

@hgarciag
Copy link

hgarciag commented Feb 5, 2023

I suggest to add (+1) to line #30

const highestPoint = Math.max.apply(null, data)+1;

To avoid dividing by zero like in :

<sparkline v-bind:data="[0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]"/>

Thanks

@Frenchcooc
Copy link
Author

👍

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment