DEV Community

Cover image for Tutorial: Make an Heart "clicker" with vue.js and firebase
Shai Angress
Shai Angress

Posted on • Edited on

Tutorial: Make an Heart "clicker" with vue.js and firebase

Hi!
In this tutorial you will learn how to make a "heart clicker" interaction/game!
Alt Text
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).
- 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:

<template>
  <div id="app">
    <HeartClicker />
  </div>
</template>
Enter fullscreen mode Exit fullscreen mode

Add a canvas element to your template, you can wrap it with a div for later use.

<template>
  <div>
    <canvas 
      id="heart" 
      :width="width" 
      :height="height"></canvas>
  </div>
</template>
Enter fullscreen mode Exit fullscreen mode

Now, define the width and height properties for the heart in your component's data:

data() {
  return {
    width: 150,
    height: 150
  }
}
Enter fullscreen mode Exit fullscreen mode

Drawing the heart will be done in the mounted method, which will be called after view is rendered, according to Vue documentation:

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:

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
}

Enter fullscreen mode Exit fullscreen mode

Check your browser, it should display a heart:
HEART

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

Now add firebase to your project with npm or yarn:

npm i firebase
Enter fullscreen mode Exit fullscreen mode

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:

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}

Enter fullscreen mode Exit fullscreen mode

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:

const db = firebase.database();
const firebaseCountRef = db.ref('/count');
Enter fullscreen mode Exit fullscreen mode

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:

import {addClick, registerToCounts} from '../services/ClickCountManager';
Enter fullscreen mode Exit fullscreen mode

Add a new globalClicks field to our data:

data() {
    ...
    globalClicks: 0,
}
Enter fullscreen mode Exit fullscreen mode

then add a new 'onClick' handler method in HeartClicker component:

methods: {
    onClick(e) {
        addClick();
    }
Enter fullscreen mode Exit fullscreen mode

Attach the method to the canvas element:

<template>
  <div>
    <canvas 
        id="heart" 
        :width="width" 
        :height="height" 
        @click="onClick"></canvas>
    <p>{{globalClicks}}</p>
  </div>
</template>
Enter fullscreen mode Exit fullscreen mode

And lastly, register to count updates in the created function of your component:

created() {
    registerToCounts(globalClicks => {
        this.globalClicks = globalClicks;
    })
},
Enter fullscreen mode Exit fullscreen mode

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.

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:

You can grab the source here:

GitHub logo sangress / vue_heart_clicker

Heart "clicker" with vue.js and firebase

Top comments (2)

Collapse
 
jodoron profile image
yonatan doron

What a fantastic walkthrough to get a grip of both Firebase and Vue.js.
Thank you for sharing this valuable resource Shai.

Thrilled to see more of your content

Collapse
 
venatus profile image
Shai Angress

Thanks! glad you enjoyed!