Skip to content

Storing animations

Howon Song edited this page Sep 7, 2020 · 2 revisions

One question I came across is how to store animations/dynamic text. Asked for an official method and there was none. We extend the canvas object to include an "anim" parameter. We then loop over the objects looking for any items set with "anim: time" and replace the text with time.

Here's my gumped up monkey hack:

var canvas = new fabric.Canvas('c');
    // Monkey patch in support for anim parameter
    fabric.Object.prototype.toObject = (function (toObject) {
        return function (additionalProperties) {
            const obj = additionalProperties.reduce((acc, key) => {
                acc[key] = this[key];
                return acc;
            }, {});
            return fabric.util.object.extend(toObject.call(this), {
                ...obj,
                anim: this.anim
            });
        };
    })(fabric.Object.prototype.toObject);
    //Add a text block
    var text = new fabric.Text("time", {fill: '#999', anim: 'time', top: 50});
    canvas.add(text);

    canvas.forEachObject(function(obj){
        if (obj.get('type') == 'text') {
            if (obj.get('anim') == 'time') {
                obj.set('text', currentTime());
            }
        }
    });
    function currentTime () {
        var currentTime = new Date();
        var hours = currentTime.getHours();
        var minutes = currentTime.getMinutes()
        if (minutes < 10) {minutes = "0" + minutes;}
        var suffix = "AM";`
        if (hours >= 12) {
            suffix = "PM";
            hours = hours - 12;
        }
        if (hours == 0) {hours = 12;}
        return hours+":"+minutes+" "+suffix;
    }

For other animations, you can do the same.

if (obj.get('anim') == 'blink') {
	console.log("We found our blinker.");
	startAnimate(obj);
}

         function startAnimate(obj) {
            setTimeout(function animate(obj) {
                // Blink black n' white
                if (obj.getFill() == '#000') {
                    obj.set('fill', '#FFF');
                } else {
                    obj.set('fill', '#000');
                }
                canvas.renderAll();
                setTimeout(animate(obj), 1000);
            }, 1000);
         }

I hope this helps someone out there.