text to image

generate image and base64 data url from text

by Laurens Maneschijn

HTML

<div style="float:right;">
	related:
	<a target="_blank" href="https://www.amp-what.com/">1</a>
	<a target="_blank" href="https://favicon.io/favicon-generator/">2</a>
	<a target="_blank" href="https://favicon.io/favicon-generator/">2</a>
	
</div>

<form>
	<button type="reset">&circlearrowleft;</button><br>
	query:
	<textarea id="query">☺☻♥♦♣♠•◘○◙⠟abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ123</textarea>
	<br>
	font-size: <input id="font_size" type="number" XXXstep="1" min="1" max="1000" placeholder="16" value="16" style="width: 4em;">px<br>
	font-family: <input id="font_family" type="text" placeholder="serif" list="font_family_datalist" name="font-family"><br>
	bold: <input id="font_bold" type="checkbox" value="1"><br>
	color: <input id="color" type="color" placeholder="#000000" list="color_datalist"> &alpha; <input id="color_alpha" type="range" min="0" max="255" value="255" list="color_alpha_datalist"><br>
	bgcolor: <input id="bgcolor" type="color" value="#ffffff" placeholder="#ffffff" list="color_datalist"> &alpha; <input id="bgcolor_alpha" type="range" min="0" max="255" value="0" list="color_alpha_datalist"><br>
	<label>center: <input id="center" type="checkbox" value="1"></label><br>
	padding
	top    <input id="padding_top"    type="number" step="1" placeholder="0" value="0" style="width: 3em;">
	bottom <input id="padding_bottom" type="number" step="1" placeholder="0" value="0" style="width: 3em;">
	left   <input id="padding_left"   type="number" step="1" placeholder="0" value="0" style="width: 3em;">
	right  <input id="padding_right"  type="number" step="1" placeholder="0" value="0" style="width: 3em;">
	<br>

	<datalist id="font_family_datalist">
	 	<option value="serif"/>
	 	<option value="sans-serif"/>
	 	<option value="monospace"/>
	 	<option value="courier"/>
		<option value="comic sans ms"/>
	 	<option value="webdings"/>
	 	<option value="wingdings"/>
	</datalist>
	<datalist id="color_datalist">
	 	<option value=""/>
	 	<option...

CSS

img {
	min-height: 2px;
	min-width: 2px;
    border: 1px solid transparent;
}
canvas {
	min-height: 2px;
	min-width: 2px;
    border: 1px solid transparent;
}
img:not(:hover) {
	background: #f0f2;
    border: 1px solid #f0f;
}
canvas:not(:hover) {
	background: #f0f2;
    border: 1px solid #00f;
}
textarea {
	width: 90%;
	height: 100px;
	vertical-align: top;
}
[readonly] {
	background: #8882;
}
#data, #data2 {
	user-select: all;
}
form {
	margin: 0;
}

JavaScript

var $ = document.querySelector.bind(document);
var $$ = document.querySelectorAll.bind(document);

Array.from($$('form, form input, form textarea, form button')).forEach((el) => {
	el.onchange = update;
	el.onreset = update;
	el.onkeyup = update;
	el.click = update;
});
Array.from($$('input, textarea')).forEach((el) => {
	el.addEventListener('keyup', function(e){
		if (e.which == 27) {
			this.value = this.getAttribute('value') || '';
			this.dispatchEvent(new Event('change'));
			this.focus();
		}
	});
});

var update_timeout;
function update() {
	clearTimeout(update_timeout);
	update_timeout = setTimeout(update2, 1);
}
function update2() {
	// https://developer.mozilla.org/en-US/docs/Web/API/Canvas_API/Tutorial/Drawing_text
	// https://developer.mozilla.org/en-US/docs/Web/API/CanvasRenderingContext2D/fillText
	var query_text = $('#query').value;
	var lines = query_text.split(/\r?\n/);
	var padding = {top: 0, bottom: 0, left: 0, right: 0};
	padding.top    = parseFloat($('#padding_top').value) || 0;
	padding.bottom = parseFloat($('#padding_bottom').value) || 0;
	padding.left   = parseFloat($('#padding_left').value) || 0;
	padding.right  = parseFloat($('#padding_right').value) || 0;
	console.log(padding);

	var center = $('#center:checked') ? true : false;
	var fontsize = parseFloat($('#font_size').value) || 16;
	var lineheight = fontsize;
	fontsize = Math.max(1, Math.min(1000, fontsize));
	var fontfamily = $('#font_family').value || 'serif';
	var font = fontsize + 'px ' + fontfamily;
	if ($('#font_bold:checked')) {
		font = 'bold ' + font;
	}

	var ctx = $('#canvas').getContext('2d');
	var width = 16; // update this below
	var height = fontsize * lines.length;

	// for ctx.measureText() to work need to set canvas size and font first:
	ctx.canvas.width = width;
	ctx.canvas.height = height;
	ctx.font = font;

	// figure out max line width:
	width = 0;
	for (var i=0; i<lines.length; i++) {
		var textmetrics = ctx.measureText(lines[i]);
		width = Math.max(width,...