loading...
Cover image for Creating stunning charts with Vue.js and Chart.js

Creating stunning charts with Vue.js and Chart.js

apertureless profile image Jakub Juszczak ・4 min read

Dive into the options of chart.js to create stunning charts.

Interactive charts can provide a cool way to visualize your data.
However most out of the box solutions are not as beautiful as they could be, with default options.

I will show you how to customize your chart.js options to make some cool charts!

âš¡ Quick Start

What we will use:

We use vue-cli to create a basic structure. So I hope you got it installed already. And we use vue-chartjs as a wrapper for chart.js.

vue init webpack awesome-charts

Then we go into our project folder and install our dependencies.

cd awesome-charts && yarn install

And we add vue-chartjs :

yarn add vue-chartjs -S

Our first chart

So, let's create our first line chart.

touch src/components/LineChart.js && subl .

Now we need to import the Line BaseChart from vue-chartjs and create our component.

In the mount() function we need to call the renderChart() method with our data and options.

import {Line} from 'vue-chartjs'

export default Line.extend({
  mounted () {

    this.renderChart({
      labels: ['January', 'February', 'March', 'April', 'May', 'June', 'July'],
      datasets: [
        {
          label: 'Data One',
          backgroundColor: '#FC2525',
          data: [40, 39, 10, 40, 39, 80, 40]
        },{
          label: 'Data Two',
          backgroundColor: '#05CBE1',
          data: [60, 55, 32, 10, 2, 12, 53]
        }
      ]
    }, {responsive: true, maintainAspectRatio: false})

  }
})

We pass in a basic chart.js data object with some sample data and in the option parameter, we pass responsive: true. So the chart will grow based on our outer container.

☝ We can call the method renderChart() because we extended the BaseChart, were this method and some props are defined.

Mount & Test it

Now we delete the Hello.vue component from our App.vue and import our chart.

<template>
  <div id="app">
    <div class="container">
      <div class="Chart__list">
        <div class="Chart">
          <h2>Linechart</h2>
          <line-example></line-example>
        </div>
      </div>
    </div>
  </div>
</template>

<script>
import LineExample from './components/LineChart.js'
export default {
  name: 'app',
  components: {
    LineExample
  }
}
</script>

<style>
#app {
  font-family: 'Avenir', Helvetica, Arial, sans-serif;
  -webkit-font-smoothing: antialiased;
  -moz-osx-font-smoothing: grayscale;
  text-align: center;
  color: #2c3e50;
  margin-top: 60px;
}
.container {
  max-width: 800px;
  margin:  0 auto;
}
</style>

And after we run the dev script in our terminal, we should see our chart.

yarn run dev 

💄 Make me beautiful

Okay, now it is time for some beautification 💅. There are a few cool tricks in chart.js. We can pass a color hex value to backgroundColor; But we can also pass a rgba() value. So we can make our color transparent.
And as chart.js is using html canvas to draw, we can utilize createLinearGradient().

This is where the fun starts. 🎢 But to use it we need the canvas object. But this is not a big deal, as vue-chartjs holds a reference to it. We can access it over this.$refs.canvas

So in our LineChart.js we create two variables to store a gradient. Because we have to datasets.

Then we create two gradients:

this.gradient = this.$refs.canvas
 .getContext('2d')
 .createLinearGradient(0, 0, 0, 450)
this.gradient2 = this.$refs.canvas
 .getContext('2d')
 .createLinearGradient(0, 0, 0, 450)

There is another cool function we can use: addColorStop()

We create three colorStops for each gradient. For 0%, 50% and 100%.

this.gradient.addColorStop(0, 'rgba(255, 0,0, 0.5)')
this.gradient.addColorStop(0.5, 'rgba(255, 0, 0, 0.25)');
this.gradient.addColorStop(1, 'rgba(255, 0, 0, 0)');

this.gradient2.addColorStop(0, 'rgba(0, 231, 255, 0.9)')
this.gradient2.addColorStop(0.5, 'rgba(0, 231, 255, 0.25)');
this.gradient2.addColorStop(1, 'rgba(0, 231, 255, 0)');

Now we can pass this.gradient to backgroundColor. And we have a very nice gradient. To get a nicer effect we also set the borderColor to the individual color with an alpha of 1. (or we use the hex value) And set the borderWidth to 1 and last but not least the pointColor.

borderColor: '#FC2525', 
pointBackgroundColor: 'white', 
borderWidth: 1, 
pointBorderColor: 'white',
import {Line} from 'vue-chartjs'

export default Line.extend({
  data () {
    return {
      gradient: null,
      gradient2: null
    }
  },
  mounted () {
    this.gradient = this.$refs.canvas.getContext('2d').createLinearGradient(0, 0, 0, 450)
    this.gradient2 = this.$refs.canvas.getContext('2d').createLinearGradient(0, 0, 0, 450)

    this.gradient.addColorStop(0, 'rgba(255, 0,0, 0.5)')
    this.gradient.addColorStop(0.5, 'rgba(255, 0, 0, 0.25)');
    this.gradient.addColorStop(1, 'rgba(255, 0, 0, 0)');

    this.gradient2.addColorStop(0, 'rgba(0, 231, 255, 0.9)')
    this.gradient2.addColorStop(0.5, 'rgba(0, 231, 255, 0.25)');
    this.gradient2.addColorStop(1, 'rgba(0, 231, 255, 0)');


    this.renderChart({
      labels: ['January', 'February', 'March', 'April', 'May', 'June', 'July'],
      datasets: [
        {
          label: 'Data One',
          borderColor: '#FC2525',
          pointBackgroundColor: 'white',
          borderWidth: 1,
          pointBorderColor: 'white',
          backgroundColor: this.gradient,
          data: [40, 39, 10, 40, 39, 80, 40]
        },{
          label: 'Data Two',
          borderColor: '#05CBE1',
          pointBackgroundColor: 'white',
          pointBorderColor: 'white',
          borderWidth: 1,
          backgroundColor: this.gradient2,
          data: [60, 55, 32, 10, 2, 12, 53]
        }
      ]
    }, {responsive: true, maintainAspectRatio: false})

  }
})

Presentation

Last step is to add some styling to the container in our App.vue

.Chart {
  background: #212733;
  border-radius: 15px;
  box-shadow: 0px 2px 15px rgba(25, 25, 25, 0.27);
  margin:  25px 0;
}

.Chart h2 {
  margin-top: 0;
  padding: 15px 0;
  color:  rgba(255, 0,0, 0.5);
  border-bottom: 1px solid #323d54;
}

👏 Final Result

Discussion

pic
Editor guide
Collapse
l_alcubo profile image
Luis

Hello friends I have a problem with the code, it works perfect, the problem is that once I paint everything, I return and sending other values paints them with the current value, perfect, but if I place the cursor on the line it overlaps with The old value

codepen.io/lalcubo/pen/VWrJwG

sorry for my english and for my code, but i dont know use good the site codepen.io for work the code please download the code and create the file .html and file .js and the library vue and vue-chart thanks

Collapse
apertureless profile image
Jakub Juszczak Author

Hey,

for a working codepen, you need to include vue-chartjs from the cdn

https://cdnjs.cloudflare.com/ajax/libs/vue-chartjs/2.6.5/vue-chartjs.full.min.js

To work with "live" data, you will need to inlcude the reactiveProp Mixin or reactiveData Mixin, depending on if you're passing your chartdata as a prop to your component or you're using a local data model.

Check out the docs: vue-chartjs.org/#/home?id=reactive...

Collapse
l_alcubo profile image
Luis

I got my code to work finally on the website codepen: codepen.io/lalcubo/pen/VWrJwG

My problem its the following:
When i press the button it graphs correctly, and you can see it draws a dot (caption) with it's value.
If you press the button again, it graphs perfectly again with a random value,
if you mouseover the new value(dot) show the current value, but if you mouseover the cursor over the previous value(dot) it will show the old value(dot) overlaping it.
I need to show only the current value, not the previous ones.

thanks

Collapse
plavookac profile image
Jelena Jovanovic

Great post! I recently published also Chart.js tutorial, on how to create gradient line charts. Keep up the good work! :)

Collapse
samarmustafa profile image
Collapse
bhaskar_vk profile image
Bhaskar Karambelkar

Nice and thanks!