senäh

17senäh und so…

Code Snippet Thumb

HTML/CSS/JS
27. Okt 2011
Kommentare: 0

Code Snippet: Bilder in Canvas-Elemente konvertieren

Kategorien: HTML/CSS/JS | 27. Okt 2011 | Kommentare: 0

Heute zeige ich euch ein kleines aber feines Plugin für jQuery mit dem ihr Bilder in Canvas-Elemente konvertieren könnt. Die <img>-Tags werden dabei komplett durch <canvas>-Tags ersetzt. Inhalt, Position im DOM und Größe (und wenn gewünscht die Klassen) bleiben dabei identisch. Los geht’s!

Quellcode

/**
 * IMG TO CANVAS - 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.imgToCanvas = function(options) {
        var canvasArr = [];
        var selectorClass = this.selector.split(".")[1];

        this.each(function() {
            /* CONFIG */

            var defaultOptions = {
                transferClasses: true,
                dontTransferSelectorClass: true
            };
            var config = $.extend(true, {}, defaultOptions, options);

            /* VARS */

            var $this = $(this);

            /* HELPER */
            var getInt = function(string) {
                return parseInt(string.replace(new RegExp("[^0-9]", "g"), ""));
            };

            /* INIT */

            (function() {
                var canvas = document.createElement("canvas");

                // never set height/width of a canvas with $(canvas).css("height", "200pX");
                // this results in wrong aspects ratios if you draw images on the canvas!
                // use canvas.height or canvas.width instead!
                canvas.width = getInt($this.css("width"));
                canvas.height = getInt($this.css("height"));

                canvas.getContext("2d").drawImage(
                        $this[0], // img
                        0, // x
                        0, // y
                        getInt($this.css("width")), // width
                        getInt($this.css("height")));   // height

                $(canvas).insertBefore($this);
                if (config.transferClasses)
                    $(canvas).addClass($this.attr("class"));
                if (config.dontTransferSelectorClass)
                    $(canvas).removeClass(selectorClass);
                $this.remove();

                canvasArr.push(canvas);
            })();
        });

        return $(canvasArr);
    };
})(jQuery);

Neben dem Plugin benötigt ihr natürlich noch jQuery. Das Plugin ist wieder unter Beerware lizensiert 😉

Verwendung

Ruft eure Bilder einfach mit einem gewünschten Selektor auf und übergebt sie dem Plugin. Folgende Varianten sind vollkommen legitim:

$("img").imgToCanvas();
$(".convertToCanvas").imgToCanvas();
$("#convertToCanvas").imgToCanvas();

Ihr könnt dem Plugin noch ein config-Objekte mitgeben. Dies könnte so aussehen:

$(".convertToCanvas").imgToCanvas({
                transferClasses: true,
                dontTransferSelectorClass: true
            });

Diese Einstellungen sind zwar die Defaultwerte, reichen aber zur Veranschaulichung. „transferClasses“ gibt an, ob die Klassen, welche auf dem <img>-Tag liegen, auch an das <canvas>-Tag übertragen werden sollen. „dontTransferSelectorClass“ gibt an, dass bei eben diesen Klassen der ursprüngliche Selektor ignoriert werden soll (in diesem Beispiel „.convertToCanvas“, welche keinen Sinn ergeben würde, wenn sie auf einem Canvas-Element liegen würde). Dies ist natürlich nur relevant, wenn der ursprüngliche Selektor eine Klasse darstellt.

Das wars. Anschließend erhaltet ihr ein nigelnagelneues Canvas-Element, welches genauso aussieht, wie das vorige Element und sich auch an der gleichen Position im DOM befindet. Das ursprüngliche Bild wird entfernt.

Das heißt im Umkehrschluss, dass „.imgToCanvas()“ die Canvas-Elemente zurückgibt und nicht die Bilder! Das müsst ihr beachten, wenn ihr die Funktion verketten wollt. „$(„.convertToCanvas“).imgToCanvas().hide();“  versteckt also die Canvas-Elemente, weil die Bilder gar nicht mehr im DOM existieren.

Warum sollte man Bilder in Canvas-Elemente konvertieren wollen? Angenommen ich habe ein weiteres Plugin namens Pixelator, welches die Oberfläche eines Canvas-Elements verpixeln soll, dann könnte ich dieses Plugin nun ganz einfach auch auf ein Bild anwenden, wenn ich das Bild vorher in ein Canvas-Element konvertiere (sprich: $(„.convertToCanvas“).imgToCanvas().pixelator();“).

Ein genaues Beispiel zeige ich euch morgen! 😉 Allerdings werde ich keine Bilder verpixeln. Wie das geht, könnt ihr euch aber hier anschauen. Ich möchte etwas anderes machen… Hui! Mysteriös!

Ciaosen!

Update: Lessons learned

Jetzt hatte ich doch glatt meine „Lessons learned“ vergessen! Aber die gehen dieses Mal recht fix.

Never ever dürft ihr die Größe eures Canvas-Elements mit CSS festlegen! Dies führt zu Verzerrungen, wenn man anschließend Bilder auf das Canvas zeichnen möchte. Legt die Größe stattdessen direkt über die Attribute fest (bzw. in JavaScript über canvas.width/canvas.height). Eine ausführlichere Beschreibung des Problems von MDN:

The <canvas> element has only two attributes – width and height. These are both optional and can also be set using DOM properties. When no width and height attributes are specified, the canvas will initially be 300 pixels wide and 150 pixels high. The element can be sized arbitrarily by CSS, but during rendering the image is scaled to fit its layout size. (If your renderings seem distorted, try specifying your width and height attributes explicitly in the <canvas> attributes, and not with CSS.)

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.