Created

Embed URL

HTTPS clone URL

SSH clone URL

You can clone with HTTPS or SSH.

Download Gist

Automatically generated images via JavaScript Canvas API

View Description.md

This is a quick prototype I knocked together (in under an hour) for a family member who had a business idea that he wasn't sure how to implement.

I had never used the HTML5 Canvas API before but it sounded like it could be a good fit for what he was trying to achieve.

It was a fun little thing to work on as it gave me a chance to play around with using Canvas and I discovered that text written in Canvas cannot (currently) wrap to the width of the Canvas element. Although I believe there may now be some new additions to the API which works around this wrapping issue.

View Description.md
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168
<!doctype html>
<html dir="ltr" lang="en">
<head>
<meta charset="utf-8">
<title>HTML5 Canvas</title>
<style type="text/css">
body {
font: normal large Helvetica, sans-serif;
}
#card {
border: 1px solid red;
}
</style>
</head>
<body>
<p>Status:</p>
<ul id="status"></ul>
<script type="text/javascript">
var doc = document,
status = doc.getElementById("status"),
canvas = doc.createElement("canvas"),
counter = 0;
cards = [
{ img: "card1", txt: "card 1 text" },
{ img: "card2", txt: "card 2 text" },
{ img: "card3", txt: "card 3 text" }
];
canvas.width = 960;
canvas.height = 739;
cards.forEach(function (card) {
var img = new Image();
img.id = "Card" + ++counter;
img.src = card.img + ".png";
img.onload = function(){
// First argument of drawImage (see further down) should be an image and not a string
// So we must replace string in object to be the image just created
card.img = img;
// Now create a new canvas for this image
createCanvas(card);
};
});
function createCanvas(card) {
var newCanvas = canvas.cloneNode(false), // shallow clone
ctx = newCanvas.getContext("2d");
// Now load relevant image into this canvas
loadImageIntoCanvas(card, newCanvas, ctx);
}
function loadImageIntoCanvas (card, newCanvas, ctx) {
// Load the specified image into the canvas (image, x, y, width[optional], height[optional])
ctx.drawImage(card.img, 0, 0, 700, 400); // I've purposedly squashed the image
// Now image is loaded we'll draw some text into the canvas
writeText(card, newCanvas, ctx);
}
function writeText (card, newCanvas, ctx) {
// Place text into the canvas (beware the text can't wrap so you might need multiple 'fillText' calls)
ctx.fillStyle = "#CC0000";
ctx.font = "italic bold 25px Helvetica";
ctx.fillText(card.txt, 125, 180);
// Now lets save this image
saveImage(card, newCanvas, ctx);
}
function checkHTTPSuccess (xhr) {
try {
// If no server status is provided, and we're actually
// requesting a local file, then it was successful
return !xhr.status && location.protocol == 'file:' ||
// Any status in the 200 range is good
( xhr.status >= 200 && xhr.status < 300 ) ||
// Successful if the document has not been modified
xhr.status == 304 ||
// Safari returns an empty status if the file has not been modified
navigator.userAgent.indexOf('Safari') >= 0 && typeof xhr.status == 'undefined';
} catch(e){
// Throw a corresponding error
throw new Error("httpSuccess Error = " + e);
}
// If checking the status failed, then assume that the request failed too
return false;
}
function getHTTPData (xhr, type) {
if (type === 'json') {
return JSON.parse(xhr.responseText);
}
else if (type === 'html') {
return xhr.responseText;
}
else if (type === 'xml') {
return xhr.responseXML;
}
// Attempt to work out the content type
else {
// Get the content-type header
var contentType = xhr.getResponseHeader("content-type"),
data = !type && contentType && contentType.indexOf("xml") >= 0; // If no default type was provided, determine if some form of XML was returned from the server
// Get the XML Document object if XML was returned from the server,
// otherwise return the text contents returned by the server
data = (type == "xml" || data) ? xhr.responseXML : xhr.responseText;
// Return the response data (either an XML Document or a text string)
return data;
}
}
function onSuccessfulImageProcessing (card, newCanvas, ctx, response) {
// Clean-up after ourselves to save application memory
newCanvas = null;
ctx = null;
// Update status list
var txt = doc.createTextNode(card.img.id + " has now been generated."),
li = doc.createElement("li");
li.appendChild(txt);
status.appendChild(li);
}
function saveImage(card, newCanvas, ctx) {
// Can't use standard library AJAX methods (such as…)
// data: "imgdata=" + newCanvas.toDataURL()
// Not sure why it doesn't work as we're only abstracting an API over the top of the native XHR object?
// To make this work we need to use a proper FormData object (no data on browser support)
var formData = new FormData();
formData.append("imgdata", newCanvas.toDataURL());
var xhr = new XMLHttpRequest();
xhr.open("POST", "saveimage.php");
xhr.send(formData);
// Watch for when the state of the document gets updated
xhr.onreadystatechange = function(){
// Wait until the data is fully loaded, and make sure that the request hasn't already timed out
if (xhr.readyState == 4) {
// Check to see if the request was successful
if (checkHTTPSuccess(xhr)) {
// Execute the success callback
onSuccessfulImageProcessing(card, newCanvas, ctx, getHTTPData(xhr));
}
else {
throw new Error("checkHTTPSuccess failed = " + e);
}
xhr.onreadystatechange = null;
xhr = null;
}
};
}
</script>
</body>
</html>
View Description.md
1 2 3 4 5 6 7 8 9 10
<?php
// Get data
$data = $_POST['imgdata'];
// Remove the "data:image/png;base64," part
$uri = substr($data, strpos($data, ",") + 1);
// Save the file to the machine (try to make it unique)
file_put_contents("./Generated/card-" . mt_rand() . ".png", base64_decode($uri));
?>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Something went wrong with that request. Please try again.