Tutorial: Make an Heart "clicker" with vue.js and firebase
Tags: javascript, html, firebase, vue
Published: 2021-01-30 17:42:55

Hi!
In this tutorial you will learn how to make a "heart clicker" interaction/game!
![Alt Text](https://dev-to-uploads.s3.amazonaws.com/i/r01ikf4zg5j5ffh2d523.gif)
This tutorial can be a good practice for anyone who want to learn javascript, vue, web-development, it can also fit experience developers who needs a little refreshment.
To make this tutorial work for your best, please prepare the following, I'll be waiting here:

**- Vue app (you can use [vue-cli](https://cli.vuejs.org/guide/installation.html)).**
**- firebase project and App (we'll setup it later).**

Ok good, now we're ready to start.

**Part 1 - Create the heart**
In this part we'll focus on drawing the heart using javascript canvas element.
Create a new component, name it HeartClicker and replace all the App.vue template with this component, so your app template should look like follow:
```html
<template>
  <div id="app">
    <HeartClicker />
  </div>
</template>
```

Add a canvas element to your template, you can wrap it with a div for later use.
```html
<template>
  <div>
    <canvas 
      id="heart" 
      :width="width" 
      :height="height"></canvas>
  </div>
</template>
```

Now, define the width and height properties for the heart in your component's data:
```javascript
data() {
  return {
    width: 150,
    height: 150
  }
}
```

Drawing the heart will be done in the mounted method, which will be called after view is rendered, according to Vue [documentation](https://vuejs.org/v2/api/#mounted):
> _Called after the instance has been mounted, where el is replaced by the newly created vm.$el. If the root instance is mounted to an in-document element, vm.$el will also be in-document when mounted is called._

Grabbing the html canvas to draw the heart:
```javascript
const canvas = this.$el.querySelector('#heart');
if (canvas.getContext) {
    const ctx = canvas.getContext('2d');
    ctx.beginPath();
    ctx.moveTo(75, 40);
    ctx.bezierCurveTo(75, 37, 70, 25, 50, 25);
    ctx.bezierCurveTo(20, 25, 20, 62.5, 20, 62.5);
    ctx.bezierCurveTo(20, 80, 40, 102, 75, 120);
    ctx.bezierCurveTo(110, 102, 130, 80, 130, 62.5);
    ctx.bezierCurveTo(130, 62.5, 130, 25, 100, 25);
    ctx.bezierCurveTo(85, 25, 75, 37, 75, 40);
    ctx.fillStyle = '#FF0000'; // heart color
    ctx.fill(); // fill the shape we draw
}

```

Check your browser, it should display a heart:
![HEART](https://dev-to-uploads.s3.amazonaws.com/i/24tppih9b34w79bdztug.png)

**Part 2 - firebase setup**
Add a realtime database in **test mode** for now (you can change it later).
Create a field name 'count' with value of zero:
![firebase count](https://dev-to-uploads.s3.amazonaws.com/i/qnvts43t7lhtrqy3179q.gif)

Now add firebase to your project with npm or yarn:
```
npm i firebase
```

In the **src** folder create a new folder **services** and add a file **ClickCountManager.js**.
Separating the logic for firebase is a good practice, you can use this script in other projects that are not vue.
ClickCountManager.js:
```javascript
import firebase from 'firebase';

const firebaseConfig = {
    ...
};

firebase.initializeApp(firebaseConfig);
const db = firebase.database();
const firebaseCountRef = db.ref('/count');

const registerToCounts = (onValue) => {
     firebaseCountRef.on('value', snapshot => onValue(snapshot.val()));
}

const addClick = () => {
    firebaseCountRef.transaction(function(count) {
        return count + 1;
    })
}

export {addClick, registerToCounts}

```

Copy the firebaseConfig from firebase settings under *'your apps'*

Let's analyze the script.
First we initialize the firebase app using `firebase.initializeApp(firebaseConfig)` function, then we reference to firebase database and the count field that we created earlier in our realtime database:
```javascript
const db = firebase.database();
const firebaseCountRef = db.ref('/count');
```

**registerToCounts** function will be used to get updates to the global counter that we save in firebase.
**addClick** function adds and save a new click to our count field.
We export these functions to use in our HeartClicker component.

**Part 3 - use firebase in our component**
Now that we have firebase ready and set we can use it in our HeartClicker component.
Go back to the HeartClicker component, import ClickCountManager methods:
```javascript
import {addClick, registerToCounts} from '../services/ClickCountManager';
```
Add a new globalClicks field to our data:
```javascript
data() {
    ...
    globalClicks: 0,
}
```

then add a new 'onClick' handler [method](https://v1.vuejs.org/guide/events.html#Method-Handler) in HeartClicker component:
```javascript
methods: {
    onClick(e) {
        addClick();
    }
```

Attach the method to the canvas element:
```html
<template>
  <div>
    <canvas 
        id="heart" 
        :width="width" 
        :height="height" 
        @click="onClick"></canvas>
    <p>{{globalClicks}}</p>
  </div>
</template>
```
And lastly, register to count updates in the created function of your component:
```javascript
created() {
    registerToCounts(globalClicks => {
        this.globalClicks = globalClicks;
    })
},
```
I register to counts in the [created] lifecycle hook (https://vuejs.org/v2/api/#created) so we'll have that data before the component mounts. I recommend to have a look at Vue [lifecycle diagram](https://vuejs.org/v2/guide/instance.html#Lifecycle-Diagram).

Open the browser and click the heart, you should see the count field in firebase and the globalCount property update.

**Summary**
What you've learned:
- Create a Vue component
- Use data in a Vue component
- Vue lifecycle
- Use and integrate firebase realtime database
I hope you enjoyed this tutorial, please write your thoughts/feedback in the discussion below.
 
**Bonus Level! - add "juice"**
If you want to spice things up, you can continue to the bonus level where you will learn how to add "juice" to your heart by using some simple css and canvas particles.
The bonus level is in another post:
{% link https://dev.to/venatus/bonus-level-vue-js-and-firebase-heart-click-3ep %}

You can grab the source here: 
{% github sangress/vue_heart_clicker no-readme %}