senäh

17senäh und so…

CanvasTileCreator Thumb 140x93

HTML/CSS/JS
01. Nov 2011
Kommentare: 0

Fancy Kacheleffekt für Bilder: Canvas sei dank!

Kategorien: HTML/CSS/JS | 01. Nov 2011 | Kommentare: 0

Heute mal wieder ein kleines jQuery Plugin! Dieses Mal zerlege ich ein Canvas-Element in viele kleine Kacheln, welche einzeln animiert werden können. So sieht das Ganze am Ende aus:

CanvasTileCreator

CanvasTileCreator

In Bewegung ist der Effekt natürlich beeindruckender. Einen Link zu einem Live-Beispiel findet ihr am Ende des Artikels 😉

Voraussetzungen

Für das Plugin benötigt ihr zwei Dinge:

Falls ihr mit tween.js oder Tweening ganz allgemein nicht vertraut seid, findet ihr hier ein Tutorial als Einstieg.

Das Plugin: CanvasTileCreator

Hier das Plugin:

/**
 * CANVAS TILE CREATOR - JQUERY PLUGIN
 *
 * Ver.: 0.1
 *
 * ----------------------------------------------------------------------------
 * "THE BEER-WARE LICENSE" (Revision 42): As long as you retain this notice you
 * can do whatever you want with this stuff. If we meet some day, and you think
 * this stuff is worth it, you can buy me a beer in return.
 * ----------------------------------------------------------------------------
 *
 * @author Philipp Zins/Donald Pipowitch
 * @link http://www.senaeh.de
 */

(function($) {
    $.fn.canvasTileCreator = function(options) {
        return this.each(function() {
            /* CONFIG */

            var defaultOptions = {
                divisionsWidth: 5,
                divisionsHeight: 5,
                tweeningFunc: function(tile) {

                    var origin = {
                        width : tile.width,
                        height: tile.height,
                        x: tile.x,
                        y: tile.y
                    };
                    var target = {
                        width : tile.width / 2,
                        height: tile.height / 2,
                        x: tile.x + tile.width / 4,
                        y: tile.y + tile.height / 4
                    };

                    var tween = new TWEEN.
                            Tween(tile).
                            to(target, 2000).
                            onUpdate(
                            function() {
                                tile.width = this.width;
                                tile.height = this.height;
                            }
                    ).
                            easing(TWEEN.Easing.Cubic.EaseInOut);
                    var reverseTween = new TWEEN.
                            Tween(tile).
                            to(origin, 2000).
                            onUpdate(
                            function() {
                                tile.width = this.width;
                                tile.height = this.height;
                            }
                    ).
                            easing(TWEEN.Easing.Cubic.EaseInOut);
                    tween.chain(reverseTween);
                    reverseTween.chain(tween);
                    tween.delay(Math.random() * 2000).start();
                }
            };
            var config = $.extend(true, {}, defaultOptions, options);

            /* VARS */

            var $this = $(this);
            var canvas = this;
            var context = canvas.getContext("2d");
            var width = canvas.width;
            var height = canvas.height;

            var tiles = [];

            /* TILE CLASS */

            var Tile = function(row, column) {
                this.canvas = document.createElement("canvas");
                this.canvas.width = Math.floor(width / config.divisionsWidth);
                this.canvas.height = Math.floor(height / config.divisionsHeight);

                this.width = this.canvas.width;
                this.height = this.canvas.height;
                this.x = column * this.width;
                this.y = row * this.height;
                this.context = this.canvas.getContext("2d");

                config.tweeningFunc(this);
            };

            /* LOOP */

            var loop = function() {
                requestAnimFrame(loop);
                TWEEN.update();
                draw();
            };

            // requestAnim shim layer by Paul Irish
            // thanks to http://paulirish.com/2011/requestanimationframe-for-smart-animating/
            window.requestAnimFrame = (function() {
                return  window.requestAnimationFrame ||
                        window.webkitRequestAnimationFrame ||
                        window.mozRequestAnimationFrame ||
                        window.oRequestAnimationFrame ||
                        window.msRequestAnimationFrame ||
                        function(callback) {
                            window.setTimeout(callback, 1000 / 60); // 16 ms = ~60 fps
                        };
            })();

            var draw = function() {
                context.clearRect(0, 0, width, height);
                var tilesLength = tiles.length;
                for (var i = 0; i < tilesLength; i++) {
                    var tile = tiles[i];
                    context.drawImage(
                            tile.canvas,
                            tile.x,
                            tile.y,
                            tile.width,
                            tile.height
                    );
                }
            };

            /* INIT */

            (function() {

                for (var i = 0; i < config.divisionsHeight; i++) {
                    for (var j = 0; j < config.divisionsWidth; j++) {
                        var tile = new Tile(i, j);
                        tile.context.drawImage(
                                $this[0], // img
                                tile.x, // src x
                                tile.y, // src y
                                tile.width, // src width
                                tile.height, // src height
                                0, // x
                                0, // y
                                tile.width, // width
                                tile.height);   // height
                        tiles.push(tile);
                    }
                }

                loop();
            })();
        });
    };
})(jQuery);

Ruft das Plugin ganz normal mit einem oder mehreren Canvas-Elementen als Selektoren auf:

$("canvas").canvasTileCreator(config);

Das config-Objekt kann drei Attribute besitzen:

  • divisionsWidth: Unterteilungen in der Breite (default: 5).
  • divisionsHeight: Unterteilungen in der Höhe (default: 5).
  • tweeningFunc: Die Animationsfunktion für jede Kachel  (function(tile) { /* animate here */ }). Der Animationsfunktion wird ein tile-Objekt übergeben, welches x, y, width und height Attribute besitzt, die manipuliert werden können.
Die Defaultanimation halbiert die Kacheln und vergrößert sie anschließend wieder auf die Ursprungsgröße, wobei jede Kachel zeitlich versetzt mit der Animation beginnt. Der Code dafür lautet:
tweeningFunc: function(tile) {

                    var origin = {
                        width : tile.width,
                        height: tile.height,
                        x: tile.x,
                        y: tile.y
                    };
                    var target = {
                        width : tile.width / 2,
                        height: tile.height / 2,
                        x: tile.x + tile.width / 4,
                        y: tile.y + tile.height / 4
                    };

                    var tween = new TWEEN.
                            Tween(tile).
                            to(target, 2000).
                            onUpdate(
                            function() {
                                tile.width = this.width;
                                tile.height = this.height;
                            }
                    ).
                            easing(TWEEN.Easing.Cubic.EaseInOut);
                    var reverseTween = new TWEEN.
                            Tween(tile).
                            to(origin, 2000).
                            onUpdate(
                            function() {
                                tile.width = this.width;
                                tile.height = this.height;
                            }
                    ).
                            easing(TWEEN.Easing.Cubic.EaseInOut);
                    tween.chain(reverseTween);
                    reverseTween.chain(tween);
                    tween.delay(Math.random() * 2000).start();
                }

Falls ihr das Plugin irgendwo nutzt, lasst es mich wissen 🙂

Natürlich gibt es wie immer noch ein Live-Beispiel.

Autor: Pipo

...kommt ursprünglich aus der Designerecke, ist aber im Laufe seines Studiums in die Webentwicklung gestolpert. Kann sich seit dem nicht so richtig entscheiden wo er hingehört und wagt deswegen vielleicht die Flucht nach vorne in ein komplett neues Gebiet. Vielleicht Management? Niemand weiß es. Auch er nicht.