{"id":3013,"date":"2017-10-24T11:11:50","date_gmt":"2017-10-24T11:11:50","guid":{"rendered":"https:\/\/anexia.com\/blog\/de\/?p=3013"},"modified":"2022-07-29T11:08:20","modified_gmt":"2022-07-29T09:08:20","slug":"meme-generator-mit-jquery-und-canvas","status":"publish","type":"post","link":"https:\/\/anexia.com\/blog\/de\/meme-generator-mit-jquery-und-canvas\/","title":{"rendered":"Memegenerator mit jQuery und Canvas"},"content":{"rendered":"<p>In diesem Tutorial werde ich euch zeigen, wie man mit dem HTML-Element Canvas einen Memegenerator bzw. Meme Creator erstellen kann.<\/p>\n<h2>Was ist ein Meme?<\/h2>\n<p>Bei Memes handelt es sich um Pseudo-Bilder mit einer meist mehr oder weniger sinnhaften Text\u00fcberblendung. Von der Themenwahl her gibt es praktisch keine Vorgaben, wodurch deren Entstehung jeweils meist auf Zufall oder die individuelle Kreativit\u00e4t des Erstellers zur\u00fcckzuf\u00fchren ist. Memes sind zu einem wahren Hype im Internet geworden,\u00a0 was man aber vielleicht auf deren leichte Erstellungsm\u00f6glichkeiten zur\u00fcckf\u00fchren k\u00f6nnte.<\/p>\n<h2>Canvas &#8211; wenn der Browser zeichnen lernt<\/h2>\n<p>Bei Canvas handelt es sich um ein HTML-Element mit frei definierbarer H\u00f6he und Breite\u00a0\u2013 vergleichbar mit einer Leinwand \u2013\u00a0 innerhalb dessen mit Hilfe von Javascript &#8222;gezeichnet&#8220; werden kann.<\/p>\n<p>Hierbei sind die Funktionen aber nicht nur auf Linien und Rechtecke besch\u00e4nkt, sondern es k\u00f6nnen auch Kreisb\u00f6gen, Farbverl\u00e4ufe und Texte verarbeitet werden. Wer noch eins drauflegen m\u00f6chte, kann damit dann sogar B\u00e9zierkurven darstellen. Auch der Einsatz von externen Grafiken ist (bis zu einem gewissen Punkt) m\u00f6glich.\u00a0 So k\u00f6nnen diese nicht nur skaliert oder neu positioniert, sondern auch in deren Format beschnitten werden.<\/p>\n<p>Dabei behandelt Canvas jedes eingef\u00fcgte Objekt bzw. Objektgruppe als eigenst\u00e4ndiges Element, welches individuell verschoben, skaliert oder auch rotiert werden kann.<\/p>\n<p><a href=\"https:\/\/anexia.com\/blog\/wp-content\/uploads\/2017\/10\/canvas-meme-generator.png\"><img loading=\"lazy\" decoding=\"async\" class=\"alignnone wp-image-3015\" src=\"https:\/\/anexia.com\/blog\/wp-content\/uploads\/2017\/10\/canvas-meme-generator.png\" alt=\"Meme-Generator mit Canvas und jQuery\" width=\"599\" height=\"303\" srcset=\"https:\/\/anexia.com\/blog\/wp-content\/uploads\/2017\/10\/canvas-meme-generator.png 1920w, https:\/\/anexia.com\/blog\/wp-content\/uploads\/2017\/10\/canvas-meme-generator-325x164.png 325w, https:\/\/anexia.com\/blog\/wp-content\/uploads\/2017\/10\/canvas-meme-generator-300x152.png 300w, https:\/\/anexia.com\/blog\/wp-content\/uploads\/2017\/10\/canvas-meme-generator-768x388.png 768w, https:\/\/anexia.com\/blog\/wp-content\/uploads\/2017\/10\/canvas-meme-generator-1024x518.png 1024w\" sizes=\"(max-width: 599px) 100vw, 599px\" \/><\/a><\/p>\n<p>&nbsp;<\/p>\n<p>Bei unserem Memegenerator werden wir ein beliebiges Bild oder Foto ausw\u00e4hlen k\u00f6nnen und anschlie\u00dfend zwei Textbereiche individuell mit Hilfe von ein paar Slider-Elementen darauf ausrichten.<\/p>\n<p>Nachdem wir hier nur mit Javascript arbeiten, ist f\u00fcr die Grundfunktionalit\u00e4t auch kein serverseitiges Script bzw. Skriptsprache (wie beispielsweise <a href=\"https:\/\/anexia.com\/de\/softwareentwicklung\/webentwicklung\/php-entwicklung\/\">PHP<\/a>) notwendig.<\/p>\n<p>&nbsp;<\/p>\n<h2>Schritt 1: HTML-Markup f\u00fcr Konfigurator anlegen<\/h2>\n<p>Unser Memegenerator bzw. Meme Creator wird im Prinzip nur aus drei Teilen bestehen: einer <a href=\"https:\/\/anexia.com\/de\/softwareentwicklung\/webentwicklung\/htmlcss-entwicklung\/\">HTML-Seite<\/a> mit den Konfigurationsoptionen, einer minimalistischen CSS-Datei (da wir mit dem CSS-Framework Bootstrap arbeiten) und einer Javascript-Datei mit unserer Logik.<\/p>\n<p>Beginnen wir also mit dem ersten Teil, der HTML-Konfigurationsseite.<\/p>\n<p>Im Grunde legen wir uns hier (wie ihr auch im Beispiel-Screenshot von oben sehen k\u00f6nnt) nur ein Bootrap Grid-Layout an,\u00a0 bei dem links das mit Canvas generierte Meme, und rechts daneben die Konfigurationssoptionen (mit Hilfe von Slider-Elementen) angezeigt werden.<\/p>\n<pre class=\"lang:xhtml decode:true\">&lt;html&gt;\r\n\t&lt;head&gt;\r\n\t\t&lt;title&gt;Meme Generator&lt;\/title&gt;\r\n\t\t\r\n\t\t&lt;link rel=\"stylesheet\" href=\"https:\/\/maxcdn.bootstrapcdn.com\/bootstrap\/4.0.0-beta\/css\/bootstrap.min.css\" integrity=\"sha384-\/Y6pD6FV\/Vv2HJnA6t+vslU6fwYXjCFtcEpHbNJ0lyAFsXTsjBbfaDjzALeQsN6M\" crossorigin=\"anonymous\"&gt;\r\n\t\t&lt;link rel=\"stylesheet\" href=\"https:\/\/maxcdn.bootstrapcdn.com\/font-awesome\/4.7.0\/css\/font-awesome.min.css\" \/&gt;\r\n\t\t&lt;link rel=\"stylesheet\" href=\"style.css\"\/&gt;\r\n\t&lt;\/head&gt;\r\n\t&lt;body&gt;\r\n\t\r\n\t&lt;nav class=\"navbar navbar-expand-md navbar-dark bg-dark fixed-top\"&gt;\r\n\t\t&lt;a class=\"navbar-brand\" href=\"#\"&gt;Meme Generator&lt;\/a&gt;\r\n\t\t&lt;button class=\"navbar-toggler\" type=\"button\" data-toggle=\"collapse\" data-target=\"#navbarsExampleDefault\" aria-controls=\"navbarsExampleDefault\" aria-expanded=\"false\" aria-label=\"Toggle navigation\"&gt;\r\n\t\t\t&lt;span class=\"navbar-toggler-icon\"&gt;&lt;\/span&gt;\r\n\t\t&lt;\/button&gt;\r\n\r\n\t\t&lt;div class=\"collapse navbar-collapse\" id=\"navbarsExampleDefault\"&gt;\r\n\t\t\t&lt;ul class=\"navbar-nav mr-auto\"&gt;\r\n\t\t\t\t&lt;li class=\"nav-item active\"&gt;\r\n\t\t\t\t\t&lt;a class=\"nav-link\" href=\"#\"&gt;Home &lt;span class=\"sr-only\"&gt;(current)&lt;\/span&gt;&lt;\/a&gt;\r\n\t\t\t\t&lt;\/li&gt;\r\n\t\t\t\t&lt;li class=\"nav-item\"&gt;\r\n\t\t\t\t\t&lt;a class=\"nav-link\" href=\"#\"&gt;Gallery&lt;\/a&gt;\r\n\t\t\t\t&lt;\/li&gt;\r\n\t\t\t\t&lt;li class=\"nav-item\"&gt;\r\n\t\t\t\t\t&lt;a class=\"nav-link\" href=\"#\"&gt;About&lt;\/a&gt;\r\n\t\t\t\t&lt;\/li&gt;\r\n\t\t\t&lt;\/ul&gt;\r\n\t\t&lt;\/div&gt;\r\n\t&lt;\/nav&gt;\r\n\r\n\t&lt;div class=\"container\"&gt;\r\n\t\r\n\t\t&lt;div class=\"page-header\"&gt;\r\n\t\t\t&lt;h1&gt;&lt;i class=\"fa fa-2x fa-paint-brush\" aria-hidden=\"true\"&gt;&lt;\/i&gt; Create your awesome Meme now!&lt;\/h1&gt;\r\n\t\t&lt;\/div&gt;\r\n\t\r\n\t\t&lt;p&gt;&amp;nbsp;&lt;\/p&gt;\r\n\t\t\r\n\t\t&lt;div class=\"row\"&gt;\r\n\t\t\t&lt;div class=\"col-md-4\"&gt;\r\n\t\t\t\r\n\t\t\t\t&lt;!-- BEGIN: Canvas rendering of generated Meme --&gt;\r\n\t\t\t\t&lt;canvas id=\"meme\" class=\"img-thumbnail img-fluid\"&gt;\r\n\t\t\t\t\tUnfortunately your browser does not support canvas.\r\n\t\t\t\t&lt;\/canvas&gt;\r\n\t\t\t\t&lt;!-- END: Canvas rendering of generated Meme --&gt;\r\n\t\t\t\r\n\t\t\t\r\n\t\t\t\t&lt;a href=\"javascript:;\" class=\"btn btn-primary btn-block\" id=\"download_meme\"&gt;\r\n\t\t\t\t\t&lt;i class=\"fa fa-download\" aria-hidden=\"true\"&gt;&lt;\/i&gt; Download\r\n\t\t\t\t&lt;\/a&gt;\r\n\t\t\t\r\n\t\t\t\r\n\t\t\t\t&lt;img id=\"start-image\" src=\"image.jpg\" alt=\"\" \/&gt;\r\n\t\t\t&lt;\/div&gt;\r\n\t\t\t&lt;div class=\"col-md-8\"&gt;\r\n\t\t\t\r\n\t\t\t\t&lt;div class=\"row\"&gt;\r\n\t\t\t\t\t&lt;div class=\"col-md-12\"&gt;\r\n\t\t\t\t\t\r\n\t\t\t\t\t\t&lt;div class=\"input-group\"&gt;\r\n\t\t\t\t\t\t\t&lt;span class=\"input-group-addon\"&gt;Image:&lt;\/span&gt;\r\n\t\t\t\t\t\t\t&lt;input type=\"file\" class=\"form-control\" id=\"imgInp\" \/&gt;\r\n\t\t\t\t\t\t&lt;\/div&gt;\r\n\t\t\t\t\t\t\r\n\t\t\t\t\t&lt;\/div&gt;\r\n\t\t\t\t&lt;\/div&gt;\r\n\t\t\t\t\r\n\t\t\t\t\r\n\t\t\t\t\r\n\t\t\t\t&lt;hr \/&gt;\r\n\t\t\t\t\r\n\t\t\t\t&lt;h3&gt;Text 1:&lt;\/h3&gt;\r\n\t\t\t\t\r\n\t\t\t\t&lt;div class=\"form-group\"&gt;\r\n\t\t\t\t\t&lt;input type=\"text\" class=\"form-control form-control-lg\" value=\"Have you expected this to be\" id=\"text_top\" \/&gt;\r\n\t\t\t\t&lt;\/div&gt;\r\n\t\t\t\t\r\n\t\t\t\t&lt;div class=\"form-group\"&gt;\r\n\t\t\t\t\t&lt;div class=\"row\"&gt;\r\n\t\t\t\t\t\t&lt;label class=\"control-label col-md-3\" for=\"text_top_offset\"&gt;Offset from top:&lt;\/label&gt;\r\n\t\t\t\t\t\t&lt;div class=\"col-md-7\"&gt;\r\n\t\t\t\t\t\t\t&lt;input style=\"width:100%\" id=\"text_top_offset\" type=\"range\" min=\"0\" max=\"500\" value=\"50\"\/&gt;\r\n\t\t\t\t\t\t&lt;\/div&gt;\r\n\t\t\t\t\t\t&lt;div class=\"col-md-2 setting-value\"&gt;\r\n\t\t\t\t\t\t\t&lt;span id=\"text_top_offset__val\"&gt;50&lt;\/span&gt;px\r\n\t\t\t\t\t\t&lt;\/div&gt;\r\n\t\t\t\t\t&lt;\/div&gt;\r\n\t\t\t\t&lt;\/div&gt;\r\n\t\t\t\t\r\n\t\t\t\t\r\n\t\t\t\t&lt;p&gt;&amp;nbsp;&lt;\/p&gt;\r\n\t\t\t\t\r\n\t\t\t\t&lt;h3&gt;Text 2:&lt;\/h3&gt;\r\n\t\t\t\t\r\n\t\t\t\t&lt;div class=\"form-group\"&gt;\r\n\t\t\t\t\t&lt;input type=\"text\" class=\"form-control form-control-lg\" value=\"funny?\" id=\"text_bottom\" \/&gt;\r\n\t\t\t\t&lt;\/div&gt;\r\n\t\t\t\t\r\n\t\t\t\t&lt;div class=\"form-group\"&gt;\r\n\t\t\t\t\t&lt;div class=\"row\"&gt;\r\n\t\t\t\t\t\t&lt;label class=\"control-label col-md-3\" for=\"text_bottom_offset\"&gt;Offset from top:&lt;\/label&gt;\r\n\t\t\t\t\t\t&lt;div class=\"col-md-7\"&gt;\r\n\t\t\t\t\t\t\t&lt;input style=\"width:100%\" id=\"text_bottom_offset\" type=\"range\" min=\"0\" max=\"500\" value=\"450\"\/&gt;\r\n\t\t\t\t\t\t&lt;\/div&gt;\r\n\t\t\t\t\t\t&lt;div class=\"col-md-2 setting-value\"&gt;\r\n\t\t\t\t\t\t\t&lt;span id=\"text_bottom_offset__val\"&gt;450&lt;\/span&gt;px\r\n\t\t\t\t\t\t&lt;\/div&gt;\r\n\t\t\t\t\t&lt;\/div&gt;\r\n\t\t\t\t&lt;\/div&gt;\r\n\t\t\t\t\r\n\t\t\t\t\r\n\t\t\t\t&lt;hr \/&gt;\r\n\t\t\t\t\r\n\t\t\t\t&lt;p&gt;&amp;nbsp;&lt;\/p&gt;\r\n\r\n\t\t\t\t&lt;div class=\"card\"&gt;\r\n\t\t\t\t\t&lt;div class=\"card-header\"&gt;\r\n\t\t\t\t\t\t&lt;i class=\"fa fa-cogs\" aria-hidden=\"true\"&gt;&lt;\/i&gt; More options\r\n\t\t\t\t\t&lt;\/div&gt;\r\n\t\t\t\t\t&lt;div class=\"card-body\"&gt;\r\n\t\t\t\t\t\r\n\t\t\t\t\t\t&lt;div class=\"row\"&gt;\r\n\t\t\t\t\t\t\t&lt;div class=\"col-md-12\"&gt;\r\n\t\t\t\t\t\t\t\r\n\t\t\t\t\t\t\t\t&lt;div class=\"form-group\"&gt;\r\n\t\t\t\t\t\t\t\t\t&lt;div class=\"row\"&gt;\r\n\t\t\t\t\t\t\t\t\t\t&lt;label class=\"control-label col-md-3\" for=\"canvas_size\"&gt;Meme size:&lt;\/label&gt;\r\n\t\t\t\t\t\t\t\t\t\t&lt;div class=\"col-md-7\"&gt;\r\n\t\t\t\t\t\t\t\t\t\t\t&lt;input style=\"width:100%\" id=\"canvas_size\" type=\"range\" min=\"0\" max=\"1000\" value=\"500\"\/&gt;\r\n\t\t\t\t\t\t\t\t\t\t&lt;\/div&gt;\r\n\t\t\t\t\t\t\t\t\t\t&lt;div class=\"col-md-2 setting-value\"&gt;\r\n\t\t\t\t\t\t\t\t\t\t\t&lt;span id=\"canvas_size__val\"&gt;500&lt;\/span&gt;px\r\n\t\t\t\t\t\t\t\t\t\t&lt;\/div&gt;\r\n\t\t\t\t\t\t\t\t\t&lt;\/div&gt;\r\n\t\t\t\t\t\t\t\t&lt;\/div&gt;\r\n\t\t\t\t\t\t\t\t\r\n\t\t\t\t\t\t\t\t&lt;div class=\"form-group\"&gt;\r\n\t\t\t\t\t\t\t\t\t&lt;div class=\"row\"&gt;\r\n\t\t\t\t\t\t\t\t\t\t&lt;label class=\"control-label col-md-3\" for=\"text_font_size\"&gt;Font size:&lt;\/label&gt;\r\n\t\t\t\t\t\t\t\t\t\t&lt;div class=\"col-md-7\"&gt;\r\n\t\t\t\t\t\t\t\t\t\t\t&lt;input style=\"width:100%\" id=\"text_font_size\" type=\"range\" min=\"0\" max=\"72\" value=\"28\"\/&gt;\r\n\t\t\t\t\t\t\t\t\t\t&lt;\/div&gt;\r\n\t\t\t\t\t\t\t\t\t\t&lt;div class=\"col-md-2 setting-value\"&gt;\r\n\t\t\t\t\t\t\t\t\t\t\t&lt;span id=\"text_font_size__val\"&gt;28&lt;\/span&gt;pt\r\n\t\t\t\t\t\t\t\t\t\t&lt;\/div&gt;\r\n\t\t\t\t\t\t\t\t\t&lt;\/div&gt;\r\n\t\t\t\t\t\t\t\t&lt;\/div&gt;\r\n\t\t\t\t\t\t\t\t\r\n\t\t\t\t\t\t\t\t&lt;div class=\"form-group\"&gt;\r\n\t\t\t\t\t\t\t\t\t&lt;div class=\"row\"&gt;\r\n\t\t\t\t\t\t\t\t\t\t&lt;label class=\"control-label col-md-3\" for=\"text_line_height\"&gt;Line height:&lt;\/label&gt;\r\n\t\t\t\t\t\t\t\t\t\t&lt;div class=\"col-md-7\"&gt;\r\n\t\t\t\t\t\t\t\t\t\t\t&lt;input style=\"width:100%\" id=\"text_line_height\" type=\"range\" min=\"0\" max=\"100\" value=\"15\"\/&gt;\r\n\t\t\t\t\t\t\t\t\t\t&lt;\/div&gt;\r\n\t\t\t\t\t\t\t\t\t\t&lt;div class=\"col-md-2 setting-value\"&gt;\r\n\t\t\t\t\t\t\t\t\t\t\t&lt;span id=\"text_line_height__val\"&gt;15&lt;\/span&gt;pt\r\n\t\t\t\t\t\t\t\t\t\t&lt;\/div&gt;\r\n\t\t\t\t\t\t\t\t\t&lt;\/div&gt;\r\n\t\t\t\t\t\t\t\t&lt;\/div&gt;\r\n\t\t\t\t\t\t\t\t\r\n\t\t\t\t\t\t\t\t&lt;div class=\"form-group\"&gt;\r\n\t\t\t\t\t\t\t\t\t&lt;div class=\"row\"&gt;\r\n\t\t\t\t\t\t\t\t\t\t&lt;label class=\"control-label col-md-3\" for=\"text_stroke_width\"&gt;Stroke width:&lt;\/label&gt;\r\n\t\t\t\t\t\t\t\t\t\t&lt;div class=\"col-md-7\"&gt;\r\n\t\t\t\t\t\t\t\t\t\t\t&lt;input style=\"width:100%\" id=\"text_stroke_width\" type=\"range\" min=\"0\" max=\"20\" value=\"4\"\/&gt;\r\n\t\t\t\t\t\t\t\t\t\t&lt;\/div&gt;\r\n\t\t\t\t\t\t\t\t\t\t&lt;div class=\"col-md-2 setting-value\"&gt;\r\n\t\t\t\t\t\t\t\t\t\t\t&lt;span id=\"text_stroke_width__val\"&gt;4&lt;\/span&gt;pt\r\n\t\t\t\t\t\t\t\t\t\t&lt;\/div&gt;\r\n\t\t\t\t\t\t\t\t\t&lt;\/div&gt;\r\n\t\t\t\t\t\t\t\t&lt;\/div&gt;\r\n\t\t\t\t\t\t\t\t\r\n\t\t\t\t\t\t\t&lt;\/div&gt;\r\n\t\t\t\t\t\t&lt;\/div&gt;\r\n\t\t\t\t\t\r\n\t\t\t\t\t&lt;\/div&gt;\r\n\t\t\t\t&lt;\/div&gt;\r\n\r\n\t\t\t\t\r\n\t\t\t\t\r\n\t\t\t&lt;\/div&gt;\r\n\t\t&lt;\/div&gt;\r\n\t\t\r\n\t\t\r\n\t&lt;\/div&gt;\r\n\r\n\t\r\n\t&lt;!-- Bootstrap core JavaScript\r\n\t================================================== --&gt;\r\n\t&lt;!-- Placed at the end of the document so the pages load faster --&gt;\r\n\t&lt;script src=\"https:\/\/code.jquery.com\/jquery-3.2.1.slim.min.js\" integrity=\"sha384-KJ3o2DKtIkvYIK3UENzmM7KCkRr\/rE9\/Qpg6aAZGJwFDMVNA\/GpGFF93hXpG5KkN\" crossorigin=\"anonymous\"&gt;&lt;\/script&gt;\r\n\t&lt;script src=\"https:\/\/cdnjs.cloudflare.com\/ajax\/libs\/popper.js\/1.11.0\/umd\/popper.min.js\" integrity=\"sha384-b\/U6ypiBEHpOf\/4+1nzFpr53nxSS+GLCkfwBdFNTxtclqqenISfwAzpKaMNFNmj4\" crossorigin=\"anonymous\"&gt;&lt;\/script&gt;\r\n\t&lt;script src=\"https:\/\/maxcdn.bootstrapcdn.com\/bootstrap\/4.0.0-beta\/js\/bootstrap.min.js\" integrity=\"sha384-h0AbiXch4ZDo7tp9hKZ4TsHbi047NrKGLO3SEJAg45jXxnGIfYzk4Si90RDIqNm1\" crossorigin=\"anonymous\"&gt;&lt;\/script&gt;\r\n\t&lt;script src=\"app.js\"&gt;&lt;\/script&gt;\r\n\t\r\n\t&lt;\/body&gt;\r\n&lt;\/html&gt;<\/pre>\n<p>Wie ihr hier seht, reicht es f\u00fcr Canvas vollkommen aus, einfach einen &#8222;<em><strong>canvas<\/strong><\/em>&#8220; HTML-Tag zu definieren. Optional k\u00f6nnen die Abmessungen anstatt via CSS-Definitionen auch direkt inline mitgegeben werden. Der Text innerhalb des Canvas-Tags wird nur in Browsern angezeigt,\u00a0die diese Technologie nicht unterst\u00fctzen.<\/p>\n<p>Die Slider-Elemente bekommen alle eine eigenst\u00e4ndige ID zugewiesen, \u00fcber welche wir sp\u00e4ter mittels Javascript bzw. jQuery zugreifen werden. So bekommen wir nicht nur deren eingestellten Wert, sondern k\u00f6nnen deren Start- und Endbereich auch dynamisch anhand der Metadaten der Bilddatei (im Bezug auf dessen Abmessungen) setzen.<\/p>\n<p>&nbsp;<\/p>\n<h2>Schritt 2: CSS-Datei vorbereiten<\/h2>\n<p>Wie zuvor bereits erw\u00e4hnt, wird sich sich CSS-Datei <strong>style.css<\/strong> sehr minimalistisch gestalten, da wir hier in diesem Tutorial auf die Standard-Elemente von <a href=\"http:\/\/getbootstrap.com\/\" target=\"_blank\" rel=\"noopener\">Bootstrap<\/a> zur\u00fcckgreifen.<\/p>\n<pre class=\"lang:css decode:true\">body {\r\n  padding-top: 5rem;\r\n}\r\n\r\nimg#start-image {\r\n\tposition: absolute;\r\n\tleft: -10000px;\r\n\ttop: -10000px;\r\n}\r\n\r\n.setting-value {\r\n\ttext-align: center;\r\n\tfont-weight: bold;\r\n}<\/pre>\n<p>Das Bootstrap-Framework selbst haben wir vorhin bereit \u00fcber deren CDN eingebunden (inkl. den zugeh\u00f6rigen Javascript-Ressourcen).<\/p>\n<p>Das Bild mit der ID &#8222;<em>start-image<\/em>&#8220; dient lediglich als Tr\u00e4ger unserer Quell-Bilddatei f\u00fcr das Canvas-Rendering. Aus diesem Grund verschieben wir es der Einfachheit halber aus dem sichtbaren Bereich vom Bildschirm raus.<\/p>\n<p>&nbsp;<\/p>\n<h2>Schritt 3: Javascript-Logik einbauen<\/h2>\n<p>Um die Javascript-Logik einbauen zu k\u00f6nnen, erstellen wir uns zuallererst die (bereits im HTML verlinkte) Datei namens <strong>app.js<\/strong> mit folgendem jQuery-Grundger\u00fcst.<\/p>\n<pre class=\"lang:js decode:true\">$(document).ready(function(){\r\n\r\n\t\/\/ here will be the whole application logic...\r\n\r\n});<\/pre>\n<p>Innerhalb dieses Blocks folgen nun alle weiteren Schritte.<\/p>\n<p>Daf\u00fcr beginnen wir als Erstes mit der Initialisierung vom Canvas-Element mit der ID &#8222;meme&#8220;:<\/p>\n<pre class=\"lang:js decode:true \">var canvas = document.getElementById('meme');\r\nctx = canvas.getContext('2d');<\/pre>\n<p>In der Variable <em><strong>ctx<\/strong> <\/em>steht uns nun innerhalb des jQuery-Scopes der Anwendungskontext unseres Canvas-Element zur Verf\u00fcgung,\u00a0das selbst \u00fcber die Variable <strong><em>canvas<\/em> <\/strong>zur Verf\u00fcgung steht.<\/p>\n<p>Beginnen wir damit, unserer Applikation Leben einzuhauchen, indem wir die Haupt-Funktion f\u00fcr die Meme-Generierung erstellen. Dazu erstellen wir zuerst eine leere Funktion namens <em>drawMeme()<\/em>.<\/p>\n<pre class=\"lang:default decode:true \">\/\/ core drawing function\r\nvar drawMeme = function() {\r\n\t\/\/ here will be our \"drawing-code\" for our memes...\r\n\r\n};<\/pre>\n<p>Die eigentliche Funktionslogik hierf\u00fcr folgt dann ein wenig sp\u00e4ter.<\/p>\n<p>Nachdem wir vorhin in unserem HTML-Markup bereits die beiden Textfelder f\u00fcr den oberen und unteren Textbereich sowie auch die Slider-Eingabefelder f\u00fcr die Konfigurationsm\u00f6glichkeiten angelegt haben, registrieren wir nun unsere drawMeme()-Funktion f\u00fcr alle relevanten Events dieser Felder.<\/p>\n<p>In erster Linie sind dies <strong><em>change<\/em><\/strong>, <strong><em>keyup <\/em><\/strong>und <strong><em>keydown<\/em> <\/strong>f\u00fcr die Felder mit Texteingabe, sowie der <strong><em>change<\/em><\/strong>-Event f\u00fcr unsere Slider-Eingabefelder.<\/p>\n<pre class=\"lang:js decode:true\">\/\/ register event listeners\r\n\r\n$(document).on('change keydown keyup', '#text_top', function() {\r\n\tdrawMeme();\r\n});\r\n\r\n$(document).on('change keydown keyup', '#text_bottom', function() {\r\n\tdrawMeme();\r\n});\r\n\r\n$(document).on('input change', '#text_top_offset', function() {\r\n\t$('#text_top_offset__val').text( $(this).val() );\r\n\tdrawMeme();\r\n});\r\n\r\n$(document).on('input change', '#text_bottom_offset', function() {\r\n\t$('#text_bottom_offset__val').text( $(this).val() );\r\n\tdrawMeme();\r\n});\r\n\r\n$(document).on('input change', '#text_font_size', function() {\r\n\t$('#text_font_size__val').text( $(this).val() );\r\n\tdrawMeme();\r\n});\r\n\r\n$(document).on('input change', '#text_line_height', function() {\r\n\t$('#text_line_height__val').text( $(this).val() );\r\n\tdrawMeme();\r\n});\r\n\r\n$(document).on('input change', '#text_stroke_width', function() {\r\n\t$('#text_stroke_width__val').text( $(this).val() );\r\n\tdrawMeme();\r\n});\r\n\r\n$(document).on('input change', '#canvas_size', function() {\r\n\t$('#canvas_size__val').text( $(this).val() );\r\n\tdrawMeme();\r\n});<\/pre>\n<p>Der zus\u00e4tzliche <strong><em>input<\/em><\/strong>-Event bei diesen Feldern sorgt daf\u00fcr, dass diese Handler auch w\u00e4hrend der Benutzung des Slider-Eingabgefelds (also w\u00e4hrend dem Hin- und Herziehen mit der Maus) getriggert werden.<\/p>\n<p>Zus\u00e4tzlich zeigen wir den gesetzten Wert dieser Felder noch im Konfigurationsformular an, indem wir mit Hilfe der <a href=\"http:\/\/api.jquery.com\/text\/\" target=\"_blank\" rel=\"noopener\">text<\/a>-Funktion diesen in das entsprechende Element \u00fcbergeben, und dessen Inhalt mit\u00a0dem\u00a0Neuen \u00fcberschreiben.<\/p>\n<p>Nun beginnen wir, nach und nach unsere <em>drawMeme()<\/em>-Funktion aufzubauen.<\/p>\n<pre class=\"lang:default decode:true \">\/\/ core drawing function\r\nvar drawMeme = function() {\r\n\tvar img = document.getElementById('start-image');\r\n\r\n\tvar fontSize = parseInt( $('#text_font_size').val() );\r\n\tvar memeSize = parseInt( $('#canvas_size').val() );\r\n\t\r\n\t\/\/ set form field properties\r\n\t$('#text_top_offset').attr('max', memeSize);\r\n\t$('#text_bottom_offset').attr('max', memeSize);\r\n\t\r\n\t\r\n};<\/pre>\n<p>Wir holen uns hier in die Variable <strong><em>img<\/em> <\/strong>unsere Quell-Bilddatei, welche wir mit der ID &#8222;start-image&#8220; versehen haben. Uns steht nun das entsprechende Javascript-Objekt davon in dieser Variable zur Verf\u00fcgung.<\/p>\n<p>Der Grund, warum hier mit dem blanken Javascript-Objekt, anstatt dem jQuery-Equivalent gearbeitet wird, ist, dass wir f\u00fcr die Canvas-Funktionen dieses Javascript-Objekt in dieser unber\u00fchrten Form ben\u00f6tigen.<\/p>\n<p>Des Weiteren greifen wir auch die gew\u00fcnschte Gr\u00f6\u00dfe unseres Memes vom Eingabefeld ab, und setzen im weiteren Schritt auch dementsprechend die Maximum-Werte f\u00fcr unsere Offset-Konfigurationsoptionen (f\u00fcr die vertikale Verschiebung der Texte), damit die Slider-Elemente auch entsprechend begrenzt sind.<\/p>\n<p>Als N\u00e4chstes konfigurieren wir das Canvas-Element, indem wir dessen Abmessungen festlegen. Im Zuge dessen \u00fcbergeben wir diesem mittels der Canvas-Funktion <a href=\"https:\/\/www.w3schools.com\/tags\/canvas_drawimage.asp\" target=\"_blank\" rel=\"noopener\"><em>drawImage()<\/em><\/a> auch unsere Quelle-Bilddatei,\u00a0die wir vorhin in der Variable <strong><em>img<\/em> <\/strong>gespeichert haben.<\/p>\n<pre class=\"lang:js decode:true\">\/\/ initialize canvas element with desired dimensions\r\ncanvas.width = memeSize;\r\ncanvas.height = memeSize;\r\n\r\nctx.clearRect(0, 0, canvas.width, canvas.height);\r\n\r\n\/\/ calculate minimum cropping dimension\r\nvar croppingDimension = img.height;\r\nif( img.width &lt; croppingDimension ){\r\n\tcroppingDimension = img.width;\r\n}\r\n\r\nctx.drawImage(img, 0, 0, croppingDimension, croppingDimension, 0, 0, memeSize, memeSize);<\/pre>\n<p>Um Verzerrungen vom Quell-Bild zu vermeiden, nutzen wir die von Canvas bereitgestellte Beschneidungsfunktion (&#8222;Cropping&#8220;). Den Maximalwert daf\u00fcr holen wir uns direkt von unserer Quell-Datei, indem wir dessen H\u00f6he und Breite miteinander vergleichen, und so die geeignete Gr\u00f6\u00dfe ermitteln.<\/p>\n<p>Nachdem ein Meme in der Regel immer quadratisch ist (Gr\u00f6\u00dfe in der Variable <em><strong>memeSize<\/strong> <\/em>definiert),\u00a0sollte die Bilddatei ebenfalls im gleichen quatratischen Bildverh\u00e4ltnis (Gr\u00f6\u00dfe in der Variable <em><strong>croppingDimension<\/strong> <\/em>definiert) vorliegen.<\/p>\n<p>Die Quell-Bilddatei wird in diesem Fall auf die Meme-Abmessungen herunterskaliert, und zu einem quadratischen Bild zurecht geschnitten. Der Einfachheit halber verzichten wir auf weitere Ausrichtungen f\u00fcr diesen &#8222;Cropping&#8220;-Vorgang.<\/p>\n<p>Um die Texte nun in unserem Meme-Canvas positionieren zu k\u00f6nnen, schreiben wir uns eine kleine Hilfsfunktion <em>wrapText()<\/em> (au\u00dferhalb der <em>drawMeme()<\/em>-Funktion):<\/p>\n<pre class=\"lang:js decode:true\">\/\/ build inner container for wrapping text inside\r\nvar wrapText = function(context, text, x, y, maxWidth, lineHeight, fromBottom) {\r\n\tvar pushMethod = (fromBottom) ? 'unshift' : 'push';\r\n\r\n\tlineHeight = (fromBottom) ? -lineHeight : lineHeight;\r\n\r\n\tvar lines = [];\r\n\tvar y = y;\r\n\tvar line = '';\r\n\tvar words = text.split(' ');\r\n\r\n\tfor (var n = 0; n &lt; words.length; n++) {\r\n\t\tvar testLine = line + ' ' + words[n];\r\n\t\tvar metrics = context.measureText(testLine);\r\n\t\tvar testWidth = metrics.width;\r\n\r\n\t\tif (testWidth &gt; maxWidth) {\r\n\t\t\tlines[pushMethod](line);\r\n\t\t\tline = words[n] + ' ';\r\n\t\t} else {\r\n\t\t\tline = testLine;\r\n\t\t}\r\n\t}\r\n\tlines[pushMethod](line);\r\n\r\n\tfor (var k in lines) {\r\n\t\tcontext.strokeText(lines[k], x, y + lineHeight * k);\r\n\t\tcontext.fillText(lines[k], x, y + lineHeight * k);\r\n\t}\r\n};<\/pre>\n<p>Im Grunde \u00fcbergeben wir hier nur den Canvas-Scope \u00fcber den Parameter <strong><em>context<\/em><\/strong>, ein paar Parameter, die den einzuf\u00fcgenden Text\u00a0 betreffen, sowie dessen Positionierungs-Eigenschaften.<\/p>\n<p>Es geht hier darum, anhand der Schriftgr\u00f6\u00dfe und dem Zeilenabstand die konkreten X- und Y-Koordinaten zu berechnen, und in den Canvas-Scope (Variable <em><strong>context<\/strong><\/em>) zu \u00fcbergeben &#8211; ihr k\u00f6nnt das aber mal &#8222;einfach so&#8220; \u00fcbernehmen.<\/p>\n<p>Zur\u00fcck in der\u00a0<em>drawMeme()<\/em>-Funktion legen wir nun anhand unserer Konfigurationsfelder aus der HTML-Maske die Grundeinstellungen f\u00fcr den Canvas-Text fest.<\/p>\n<p>Anschlie\u00dfend \u00e4ndern wir die Texteingabe auf Gro\u00dfbuchstaben, und \u00fcbergeben die gew\u00fcnschte Y-Position. Die X-Koordinate ist genau die H\u00e4lfte der Meme-Breite, da der Text mittig positioniert werden soll.<\/p>\n<pre class=\"lang:js decode:true\">ctx.lineWidth  = parseInt( $('#text_stroke_width').val() );\r\nctx.font = fontSize + 'pt sans-serif';\r\nctx.strokeStyle = 'black';\r\nctx.fillStyle = 'white';\r\nctx.textAlign = 'center';\r\nctx.textBaseline = 'top';\r\n\r\nvar text1 = $('#text_top').val();\r\ntext1 = text1.toUpperCase();\r\nx = memeSize \/ 2;\r\ny = parseInt( $('#text_top_offset').val() );\r\n\r\nvar lineHeight = fontSize + parseInt( $('#text_line_height').val() );\r\nvar maxTextAreaWidth = memeSize * 0.85;\r\n\r\nwrapText(ctx, text1, x, y, maxTextAreaWidth, lineHeight, false);<\/pre>\n<p>Mit der Variable <strong><em>maxTextAreaWidth<\/em> <\/strong>schr\u00e4nken wir die maximale Textbreite auf 85% ein. Dies hat aber in erster Linie nur optische Gr\u00fcnde.<\/p>\n<p>Das Gleiche wiederholen wir dann auch f\u00fcr den unteren Text, nur dass wir die Grundeinstellungen der Schrift nicht mehr neu definieren, sondern einfach f\u00fcr die entsprechenden Eigenschaften \u00fcberschreiben m\u00fcssen.<\/p>\n<pre class=\"lang:default decode:true\">ctx.textBaseline = 'bottom';\r\nvar text2 = $('#text_bottom').val();\r\ntext2 = text2.toUpperCase();\r\ny = parseInt( $('#text_bottom_offset').val() );\r\n\r\nwrapText(ctx, text2, x, y, maxTextAreaWidth, lineHeight, true);<\/pre>\n<p>Damit ihr nun auch beliebige Bilder ausw\u00e4hlen k\u00f6nnt, verleihen wir unserem File-Eingabefeld auch die entsprechende Funktion:<\/p>\n<pre class=\"lang:default decode:true\">\/\/ read selected input image from upload field and display it in browser\r\n$(\"#imgInp\").change(function(){\r\n\tvar input = this;\r\n\t\r\n\tif (input.files &amp;&amp; input.files[0]) {\r\n\t\tvar reader = new FileReader();\r\n\t\t\r\n\t\treader.onload = function (e) {\r\n\t\t\t$('#start-image').attr('src', e.target.result);\r\n\t\t}\r\n\r\n\t\treader.readAsDataURL(input.files[0]);\r\n\t}\r\n\t\r\n\twindow.setTimeout(function(){\r\n\t\tdrawMeme();\r\n\t}, 500);\r\n});<\/pre>\n<p>Wenn ein neues Bild ausgew\u00e4hlt wird, liest der Javascript-FileReader dieses ein und setzt dessen Base64-String als Source (&#8222;src&#8220;-Attribut) unserer Quell-Bilddatei (mit der ID &#8222;start-image&#8220;).<\/p>\n<p>Anschlie\u00dfend triggern wir wieder die <em>drawMeme()<\/em>-Funktion, damit diese nun das neue Bild einliest und entsprechend verarbeitet.<\/p>\n<p>&nbsp;<\/p>\n<p>Nun sollte sich auf der Meme-Generator-Seite bereits etwas tun, wenn ihr mal einen der Slider-Elemente oder Eingabefelder \u00e4ndert, da dann mindestens ein Change-Event getriggert wird, durch welchen die <em>drawMeme()<\/em>-Funktion aufgerufen wird.<\/p>\n<p>Damit auch gleich beim Seitenaufruf was zu sehen ist, rufen wir die <em>drawMeme()<\/em>-Funktion einfach initial beim Laden der Seite auf:<\/p>\n<pre class=\"lang:default decode:true \">\/\/ init at startup\r\nwindow.setTimeout(function(){\r\n\tdrawMeme();\r\n}, 100);<\/pre>\n<p>Das funktionierende Beispiel k\u00f6nnt ihr euch hier herunterladen:<\/p>\n<p style=\"text-align: left;\"><a href=\"https:\/\/anexia.com\/blog\/wp-content\/uploads\/2017\/10\/canvas-meme-generator_mwu.zip\" target=\"_blank\" rel=\"noopener\">DEMO HERUNTERLADEN<\/a><\/p>\n<p>&nbsp;<\/p>\n<h2>Schritt 4: Optionalen Download-Link hinzuf\u00fcgen<\/h2>\n<p>Ihr k\u00f6nnt von eurem Canvas-Element mit Hilfe der Funktion <em>toDataURL()<\/em> jederzeit das aktuelle Bild als Base64-String auslesen.<\/p>\n<p>Eine M\u00f6glichkeit w\u00e4re es, diesen Base64-String als &#8222;href&#8220;-Attribut f\u00fcr euren Download-Link zu setzen, und mittels dem &#8222;download&#8220;-Attribut den gew\u00fcnschten Dateinamen anzugeben.<\/p>\n<pre class=\"lang:default decode:true\">$('#download_meme').click(function(e){\r\n\t$(this).attr('href', canvas.toDataURL());\r\n\t$(this).attr('download', 'meme.png');\r\n});<\/pre>\n<p>Beachtet hier aber, dass dies nicht von allen Browsern unterst\u00fctzt wird, und demensprechend nicht \u00fcberall funktionieren wird.<\/p>\n<p>Im Idealfall solltet ihr diesen Base64-String beispielsweise mittels <a href=\"https:\/\/api.jquery.com\/jquery.post\/\" target=\"_blank\" rel=\"noopener\">jQuery.post()<\/a> oder <a href=\"http:\/\/api.jquery.com\/jquery.ajax\/\" target=\"_blank\" rel=\"noopener\">jQuery.ajax<\/a> an ein serverseitiges Script senden, welches euch\u00a0den String dann mit dem entsprechenden <em>&#8222;Content-Type&#8220;<\/em>-Header (&#8222;image\/png&#8220;) wieder zur\u00fcckliefert.<\/p>\n<p>So w\u00e4re sichergestellt, dass es wirklich in allen Browsern funktioniert.<\/p>\n<p>&nbsp;<\/p>\n<h2>Fazit Memegenerator<\/h2>\n<p>Mit Canvas bekommt ihr ein m\u00e4chtiges Tool in die Hand gelegt, wenn es darum geht, dynamisch Grafiken im Browser mittels Javascript zu zeichnen.<\/p>\n<p>Am h\u00e4ufigsten werdet ihr Canvas im Zusammenhang mit Graph-Libraries finden, da sich diese Technik vor allem im Statistik-Bereich sehr etabliert hat.<\/p>\n<p>Mit Canvas zu arbeiten ist nicht besonders schwierig. Das einzige, was schnell mal kompliziert werden kann, ist \u2013 wie in unserem Beispiel des Meme-Generators \u2013 meist die korrekte Ermittlung bzw. Berechnung der einzelnen Positionen der generierten Elemente.<\/p>\n","protected":false},"excerpt":{"rendered":"<p>In diesem Tutorial werde ich euch zeigen, wie man mit dem HTML-Element Canvas einen Memegenerator bzw. Meme Creator erstellen kann. Was ist ein Meme? Bei Memes handelt es sich um Pseudo-Bilder mit einer meist mehr oder weniger sinnhaften Text\u00fcberblendung. Von der Themenwahl her gibt es praktisch keine Vorgaben, wodurch deren Entstehung jeweils meist auf Zufall [&hellip;]<\/p>\n","protected":false},"author":15,"featured_media":2961,"comment_status":"closed","ping_status":"closed","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[4],"tags":[419,422,2283,2281,77],"yoast_head":"<!-- This site is optimized with the Yoast SEO plugin v22.2 - https:\/\/yoast.com\/wordpress\/plugins\/seo\/ -->\n<title>Memegenerator mit jQuery und Canvas - ANEXIA Blog<\/title>\n<meta name=\"description\" content=\"Einfaches und verst\u00e4ndliches Tutorial, wie man mit dem HTML-Element Canvas einen Memegenerator bzw. Meme Creator erstellen kann.\" \/>\n<meta name=\"robots\" content=\"index, follow, max-snippet:-1, max-image-preview:large, max-video-preview:-1\" \/>\n<link rel=\"canonical\" href=\"https:\/\/anexia.com\/blog\/de\/meme-generator-mit-jquery-und-canvas\/\" \/>\n<meta property=\"og:locale\" content=\"de_DE\" \/>\n<meta property=\"og:type\" content=\"article\" \/>\n<meta property=\"og:title\" content=\"Memegenerator mit jQuery und Canvas - ANEXIA Blog\" \/>\n<meta property=\"og:description\" content=\"Einfaches und verst\u00e4ndliches Tutorial, wie man mit dem HTML-Element Canvas einen Memegenerator bzw. Meme Creator erstellen kann.\" \/>\n<meta property=\"og:url\" content=\"https:\/\/anexia.com\/blog\/de\/meme-generator-mit-jquery-und-canvas\/\" \/>\n<meta property=\"og:site_name\" content=\"ANEXIA Blog\" \/>\n<meta property=\"article:publisher\" content=\"https:\/\/www.facebook.com\/anexiagmbh\/\" \/>\n<meta property=\"article:published_time\" content=\"2017-10-24T11:11:50+00:00\" \/>\n<meta property=\"article:modified_time\" content=\"2022-07-29T09:08:20+00:00\" \/>\n<meta property=\"og:image\" content=\"https:\/\/anexia.com\/blog\/wp-content\/uploads\/2017\/09\/ManuelWutte-Blog-Teaser.jpg\" \/>\n\t<meta property=\"og:image:width\" content=\"672\" \/>\n\t<meta property=\"og:image:height\" content=\"372\" \/>\n\t<meta property=\"og:image:type\" content=\"image\/jpeg\" \/>\n<meta name=\"author\" content=\"Manuel Wutte\" \/>\n<meta name=\"twitter:card\" content=\"summary_large_image\" \/>\n<meta name=\"twitter:creator\" content=\"@_ANEXIA\" \/>\n<meta name=\"twitter:site\" content=\"@_ANEXIA\" \/>\n<meta name=\"twitter:label1\" content=\"Verfasst von\" \/>\n\t<meta name=\"twitter:data1\" content=\"Manuel Wutte\" \/>\n\t<meta name=\"twitter:label2\" content=\"Gesch\u00e4tzte Lesezeit\" \/>\n\t<meta name=\"twitter:data2\" content=\"13\u00a0Minuten\" \/>\n<script type=\"application\/ld+json\" class=\"yoast-schema-graph\">{\"@context\":\"https:\/\/schema.org\",\"@graph\":[{\"@type\":\"WebPage\",\"@id\":\"https:\/\/anexia.com\/blog\/de\/meme-generator-mit-jquery-und-canvas\/\",\"url\":\"https:\/\/anexia.com\/blog\/de\/meme-generator-mit-jquery-und-canvas\/\",\"name\":\"Memegenerator mit jQuery und Canvas - ANEXIA Blog\",\"isPartOf\":{\"@id\":\"https:\/\/anexia.com\/blog\/#website\"},\"primaryImageOfPage\":{\"@id\":\"https:\/\/anexia.com\/blog\/de\/meme-generator-mit-jquery-und-canvas\/#primaryimage\"},\"image\":{\"@id\":\"https:\/\/anexia.com\/blog\/de\/meme-generator-mit-jquery-und-canvas\/#primaryimage\"},\"thumbnailUrl\":\"https:\/\/anexia.com\/blog\/wp-content\/uploads\/2017\/09\/ManuelWutte-Blog-Teaser.jpg\",\"datePublished\":\"2017-10-24T11:11:50+00:00\",\"dateModified\":\"2022-07-29T09:08:20+00:00\",\"author\":{\"@id\":\"https:\/\/anexia.com\/blog\/#\/schema\/person\/926f6b9e5aeed88b145cf86d87fd09de\"},\"description\":\"Einfaches und verst\u00e4ndliches Tutorial, wie man mit dem HTML-Element Canvas einen Memegenerator bzw. Meme Creator erstellen kann.\",\"breadcrumb\":{\"@id\":\"https:\/\/anexia.com\/blog\/de\/meme-generator-mit-jquery-und-canvas\/#breadcrumb\"},\"inLanguage\":\"de\",\"potentialAction\":[{\"@type\":\"ReadAction\",\"target\":[\"https:\/\/anexia.com\/blog\/de\/meme-generator-mit-jquery-und-canvas\/\"]}]},{\"@type\":\"ImageObject\",\"inLanguage\":\"de\",\"@id\":\"https:\/\/anexia.com\/blog\/de\/meme-generator-mit-jquery-und-canvas\/#primaryimage\",\"url\":\"https:\/\/anexia.com\/blog\/wp-content\/uploads\/2017\/09\/ManuelWutte-Blog-Teaser.jpg\",\"contentUrl\":\"https:\/\/anexia.com\/blog\/wp-content\/uploads\/2017\/09\/ManuelWutte-Blog-Teaser.jpg\",\"width\":672,\"height\":372},{\"@type\":\"BreadcrumbList\",\"@id\":\"https:\/\/anexia.com\/blog\/de\/meme-generator-mit-jquery-und-canvas\/#breadcrumb\",\"itemListElement\":[{\"@type\":\"ListItem\",\"position\":1,\"name\":\"Home\",\"item\":\"https:\/\/anexia.com\/blog\/de\/\"},{\"@type\":\"ListItem\",\"position\":2,\"name\":\"Memegenerator mit jQuery und Canvas\"}]},{\"@type\":\"WebSite\",\"@id\":\"https:\/\/anexia.com\/blog\/#website\",\"url\":\"https:\/\/anexia.com\/blog\/\",\"name\":\"ANEXIA Blog\",\"description\":\"[:de] ANEXIA Blog - Technischen Themen, Anexia News und Insights [:]\",\"potentialAction\":[{\"@type\":\"SearchAction\",\"target\":{\"@type\":\"EntryPoint\",\"urlTemplate\":\"https:\/\/anexia.com\/blog\/?s={search_term_string}\"},\"query-input\":\"required name=search_term_string\"}],\"inLanguage\":\"de\"},{\"@type\":\"Person\",\"@id\":\"https:\/\/anexia.com\/blog\/#\/schema\/person\/926f6b9e5aeed88b145cf86d87fd09de\",\"name\":\"Manuel Wutte\",\"image\":{\"@type\":\"ImageObject\",\"inLanguage\":\"de\",\"@id\":\"https:\/\/anexia.com\/blog\/#\/schema\/person\/image\/\",\"url\":\"https:\/\/secure.gravatar.com\/avatar\/9528a61f48f4294cd5f7cd8a4141bd55?s=96&d=mm&r=g\",\"contentUrl\":\"https:\/\/secure.gravatar.com\/avatar\/9528a61f48f4294cd5f7cd8a4141bd55?s=96&d=mm&r=g\",\"caption\":\"Manuel Wutte\"},\"url\":\"https:\/\/anexia.com\/blog\/author\/mwu\/\"}]}<\/script>\n<!-- \/ Yoast SEO plugin. -->","yoast_head_json":{"title":"Memegenerator mit jQuery und Canvas - ANEXIA Blog","description":"Einfaches und verst\u00e4ndliches Tutorial, wie man mit dem HTML-Element Canvas einen Memegenerator bzw. Meme Creator erstellen kann.","robots":{"index":"index","follow":"follow","max-snippet":"max-snippet:-1","max-image-preview":"max-image-preview:large","max-video-preview":"max-video-preview:-1"},"canonical":"https:\/\/anexia.com\/blog\/de\/meme-generator-mit-jquery-und-canvas\/","og_locale":"de_DE","og_type":"article","og_title":"Memegenerator mit jQuery und Canvas - ANEXIA Blog","og_description":"Einfaches und verst\u00e4ndliches Tutorial, wie man mit dem HTML-Element Canvas einen Memegenerator bzw. Meme Creator erstellen kann.","og_url":"https:\/\/anexia.com\/blog\/de\/meme-generator-mit-jquery-und-canvas\/","og_site_name":"ANEXIA Blog","article_publisher":"https:\/\/www.facebook.com\/anexiagmbh\/","article_published_time":"2017-10-24T11:11:50+00:00","article_modified_time":"2022-07-29T09:08:20+00:00","og_image":[{"width":672,"height":372,"url":"https:\/\/anexia.com\/blog\/wp-content\/uploads\/2017\/09\/ManuelWutte-Blog-Teaser.jpg","type":"image\/jpeg"}],"author":"Manuel Wutte","twitter_card":"summary_large_image","twitter_creator":"@_ANEXIA","twitter_site":"@_ANEXIA","twitter_misc":{"Verfasst von":"Manuel Wutte","Gesch\u00e4tzte Lesezeit":"13\u00a0Minuten"},"schema":{"@context":"https:\/\/schema.org","@graph":[{"@type":"WebPage","@id":"https:\/\/anexia.com\/blog\/de\/meme-generator-mit-jquery-und-canvas\/","url":"https:\/\/anexia.com\/blog\/de\/meme-generator-mit-jquery-und-canvas\/","name":"Memegenerator mit jQuery und Canvas - ANEXIA Blog","isPartOf":{"@id":"https:\/\/anexia.com\/blog\/#website"},"primaryImageOfPage":{"@id":"https:\/\/anexia.com\/blog\/de\/meme-generator-mit-jquery-und-canvas\/#primaryimage"},"image":{"@id":"https:\/\/anexia.com\/blog\/de\/meme-generator-mit-jquery-und-canvas\/#primaryimage"},"thumbnailUrl":"https:\/\/anexia.com\/blog\/wp-content\/uploads\/2017\/09\/ManuelWutte-Blog-Teaser.jpg","datePublished":"2017-10-24T11:11:50+00:00","dateModified":"2022-07-29T09:08:20+00:00","author":{"@id":"https:\/\/anexia.com\/blog\/#\/schema\/person\/926f6b9e5aeed88b145cf86d87fd09de"},"description":"Einfaches und verst\u00e4ndliches Tutorial, wie man mit dem HTML-Element Canvas einen Memegenerator bzw. Meme Creator erstellen kann.","breadcrumb":{"@id":"https:\/\/anexia.com\/blog\/de\/meme-generator-mit-jquery-und-canvas\/#breadcrumb"},"inLanguage":"de","potentialAction":[{"@type":"ReadAction","target":["https:\/\/anexia.com\/blog\/de\/meme-generator-mit-jquery-und-canvas\/"]}]},{"@type":"ImageObject","inLanguage":"de","@id":"https:\/\/anexia.com\/blog\/de\/meme-generator-mit-jquery-und-canvas\/#primaryimage","url":"https:\/\/anexia.com\/blog\/wp-content\/uploads\/2017\/09\/ManuelWutte-Blog-Teaser.jpg","contentUrl":"https:\/\/anexia.com\/blog\/wp-content\/uploads\/2017\/09\/ManuelWutte-Blog-Teaser.jpg","width":672,"height":372},{"@type":"BreadcrumbList","@id":"https:\/\/anexia.com\/blog\/de\/meme-generator-mit-jquery-und-canvas\/#breadcrumb","itemListElement":[{"@type":"ListItem","position":1,"name":"Home","item":"https:\/\/anexia.com\/blog\/de\/"},{"@type":"ListItem","position":2,"name":"Memegenerator mit jQuery und Canvas"}]},{"@type":"WebSite","@id":"https:\/\/anexia.com\/blog\/#website","url":"https:\/\/anexia.com\/blog\/","name":"ANEXIA Blog","description":"[:de] ANEXIA Blog - Technischen Themen, Anexia News und Insights [:]","potentialAction":[{"@type":"SearchAction","target":{"@type":"EntryPoint","urlTemplate":"https:\/\/anexia.com\/blog\/?s={search_term_string}"},"query-input":"required name=search_term_string"}],"inLanguage":"de"},{"@type":"Person","@id":"https:\/\/anexia.com\/blog\/#\/schema\/person\/926f6b9e5aeed88b145cf86d87fd09de","name":"Manuel Wutte","image":{"@type":"ImageObject","inLanguage":"de","@id":"https:\/\/anexia.com\/blog\/#\/schema\/person\/image\/","url":"https:\/\/secure.gravatar.com\/avatar\/9528a61f48f4294cd5f7cd8a4141bd55?s=96&d=mm&r=g","contentUrl":"https:\/\/secure.gravatar.com\/avatar\/9528a61f48f4294cd5f7cd8a4141bd55?s=96&d=mm&r=g","caption":"Manuel Wutte"},"url":"https:\/\/anexia.com\/blog\/author\/mwu\/"}]}},"lang":"de","translations":{"de":3013,"en":6750},"amp_enabled":true,"pll_sync_post":[],"_links":{"self":[{"href":"https:\/\/anexia.com\/blog\/wp-json\/wp\/v2\/posts\/3013"}],"collection":[{"href":"https:\/\/anexia.com\/blog\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/anexia.com\/blog\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/anexia.com\/blog\/wp-json\/wp\/v2\/users\/15"}],"replies":[{"embeddable":true,"href":"https:\/\/anexia.com\/blog\/wp-json\/wp\/v2\/comments?post=3013"}],"version-history":[{"count":40,"href":"https:\/\/anexia.com\/blog\/wp-json\/wp\/v2\/posts\/3013\/revisions"}],"predecessor-version":[{"id":7570,"href":"https:\/\/anexia.com\/blog\/wp-json\/wp\/v2\/posts\/3013\/revisions\/7570"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/anexia.com\/blog\/wp-json\/wp\/v2\/media\/2961"}],"wp:attachment":[{"href":"https:\/\/anexia.com\/blog\/wp-json\/wp\/v2\/media?parent=3013"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/anexia.com\/blog\/wp-json\/wp\/v2\/categories?post=3013"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/anexia.com\/blog\/wp-json\/wp\/v2\/tags?post=3013"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}