Tag Archives: setInterval

Vue Basics – Moving Objects Around the Screen

I’ve recently been playing around with Vue. One of the things that I typically do when I’m learning some kind of front-end technology, is to work out how I might write a game in that technology – that usually tests the boundaries of what you can do. If you’re interested, this is a car game that I created in React.

Let’s start by having a look at what a bog standard “Hello World” app looks like in Vue:

<!DOCTYPE html>
<html>
    <head>
        <meta charset="UTF-8">
        <title>Testing Vue</title>
    </head>
    <body>
        <script src="https://cdn.jsdelivr.net/npm/[email protected]/dist/vue.js"></script>
        
        <div id="app">
            <h1>{{ title }}</h1>
        </div>
        <script>
            new Vue({
                el: '#app',
                data: {
                    title: 'Hello World'
                }
            });
        </script>        
    </body>
</html>

Another way that you can write that, would be like this:

<p v-text="testdata"></p>

This kind of synthax actually lets you bind any property, for example:

<h1 v-bind:title="testdata"></h1>

That’s pretty much the bit that I was looking for; if you can bind the title, then you can bind the style; for example:

<div v-bind:style="location">test</div>

Inside the data section, I can expose a location; for example:

new Vue({
    el: '#app',
    data: {
        testdata: 'some data',
        location: 'width: 500px; height: 100px; left: 20px;border: 1px solid #000; position: absolute;'
                    
    },

Okay, so now we’re binding the style to a piece of data, so can we now do something like this:

data: {
    testdata: 'some data',
    posx: 100,
    location: 'width: 500px; height: 100px; left:' + this.posx + 'px; border: 1px solid #000; position: absolute;'
},

Unfortunately (or perhaps fortunately, I haven’t decided yet) not. Anything that changes needs to be in a separate section, called computed:

data: {
    testdata: 'some data',
    posx: 100                    
},
computed: {                    
    location: function() {
        return 'width:500px; height:100px; left:' + this.posx + 'px; border:1px solid #000; position: absolute;';
    } 
},

We’re actually nearly there now; all that’s missing is the thing that actually updates the variable, and therefore moves the div across the screen. The next thing we come across is the mounted method – this is a lifecycle event for each component, so we’ll need that to initialise our timer; now we can do this:

methods: {
    init() {
        setInterval(this.moveObject, 10);
    },
    moveObject() {
        this.posx += 1;                        
    }
},
mounted() {
    this.init();
}

It’s not hugely exciting, I’ll grant you, but moving an object around a screen is the basis for any game. For completeness, here’s the full code:

<!DOCTYPE html>
<html>
    <head>
        <meta charset="UTF-8">
        <title>Testing Vue</title>
    </head>
    <body>
        <script src="https://cdn.jsdelivr.net/npm/[email protected]/dist/vue.js"></script>
        <div id="app">
            <h1>{{ testdata }}</h1>
            <p v-text="testdata"></p>
            <div v-bind:style="location">test</div>
        </div>
        <script>
            new Vue({
                el: '#app',
                data: {
                    testdata: 'some data',
                    posx: 100                    
                },
                computed: {                    
                    location: function() {
                        return 'width:500px;height:100px; left:' + this.posx + 'px;border:1px solid #000; position: absolute;';
                    } 
                },
                methods: {
                    init() {
                        setInterval(this.moveObject, 10);
                    },
                    moveObject() {
                        this.posx += 1;                        
                    }
                },
                mounted() {
                    this.init();
                }
            });
            
        </script>        
    </body>
</html>

References

Vue.js Tutorial From Scratch – e01 – Introduction, Installation & Outputting Data

Drawing Custom Graphs in HTML and Javascript

While recently playing with the HTML Canvas again, it occurred to me that this power could be used for evil (or statistics are it is commonly known these days).

In this post, I’m going to draw an animated chart using the HTML Canvas and Javascript.

Let’s start with the HTML:

<!DOCTYPE html>
<html>
<head>
    <link rel="stylesheet" type="text/css" href="test.css">
    <script src="test.js"></script>
</head>
<body onload="doDrawing()">
    <canvas id="canvas">
    </canvas>
</body>
</html>

Again, as with my previous post (linked above), I’ll remind you that this will not cope with screen resizing. The CSS, again, isn’t much to write home about:

* { 
    margin:0; 
    padding:0; 
}
canvas {  
    display: block;    
}

Javascript

Finally, we come to the Javascript: this is a bit more involved, so I’ll break it down into the individual functions; we’ll start with the top level one:

const doDrawing = () => {
    var c = document.getElementById("canvas");
    
    c.width = window.innerWidth;
    c.height = window.innerHeight;
    var ctx = c.getContext("2d");    
    drawGraphTop(50, 5, 500);
    drawColumn(100, 500, 4, 'January');
    drawColumn(150, 350, 5, 'February');
    drawColumn(200, 150, 6, 'March');
}

All we’re doing here is getting a handle to the canvas, setting the height and width so that we fill the screen, and then calling some functions to do the drawing. The helper method to get the context is trivial, but for completeness:

function getContext() {
    var c = document.getElementById("canvas");    
    var ctx = c.getContext("2d");        
    return ctx;
}

There’s not much to explain here, we’re just getting the context from the canvas and returning it – thereby saving 3 lines of code each time we do that. The drawGraphTop function is a little more interesting:

const drawGraphTop = (top, interval, width) => {
    let ctx = getContext();
    ctx.beginPath();
    ctx.rect(1, top, width, 2);
    let stage = width / interval;
    for (let i = 0; i <= interval; i++) {
        ctx.rect(i * stage, top, 2, 5);
    }
    ctx.stroke();
}

The idea here is that we display a flat, horizontal line across the top of the screen, with markers. There is no line method on the canvas context, so a flat rectangle is the best we can do.

The more complex method is the drawColumn method (technically, it isn’t actually drawing columnns – but they still feel like columns – at least, more than rows):

const drawColumn = (top, target, speed, label) => {
    let ctx = getContext();
    let x = 10;    
    let directionHorizontal = speed;

    let intervalHandle = setInterval(() => {
        const buffer = 15;
        const height = 30;
        let showText = false;
        ctx.beginPath();
        ctx.clearRect(1, top - 1, target + buffer + Math.abs(directionHorizontal) + 2, height + 2);

        if (directionHorizontal === 1 && x <= target + buffer) {
            
        } else if (directionHorizontal > 0 && x >= target + buffer) {
            directionHorizontal = -1;
        } else if (directionHorizontal < 0 && x <= target) {
            clearInterval(intervalHandle);
            directionHorizontal = 0;
            showText = true;            
        }

        x += directionHorizontal;
        ctx.rect(1, top, x, height);
        ctx.stroke();

        if (showText) {                        
            ctx.fillText(label, 10, top + 20);
        }
    }, 1);
    
}

There is quite a lot to this; let’s focus on the interval; we take a handle to the interval, so that we can cancel it when we’ve finished drawing.

The first thing we do with the context is call beginPath – this allows us to group a series of updates into a single screen update; then we’re clearing an area, just wide of, the size of the rectangle.

We then have a conditional check – if we’re heading right, and have yet to reach the target (which has a small buffer appended for the purpose of animation), then this drops through to the code below; if we’ve reached that then we change direction; and when we’re back to the actual target, we cancel the update and set a flag to make the text appear.

Subsequently, we draw the (horizontal) column and, if we’ve finished, display the text.

Output and Caveats

It’s worth bearing in mind that the way this code is structured is probably not the best for performance – ideally, you would have a sort of game loop and draw, and then update the entire screen in one go.

Code

You can find the code for this here.