Repository: tholman/texter Branch: master Commit: b03e4859fe35 Files: 4 Total size: 14.8 KB Directory structure: gitextract_j3q82qwt/ ├── css/ │ └── style.css ├── index.html └── js/ ├── header.js └── texter.js ================================================ FILE CONTENTS ================================================ ================================================ FILE: css/style.css ================================================ html, body { width: 100%; height: 100%; margin: 0px; overflow: hidden; } canvas { position: absolute; cursor: crosshair; -webkit-user-select: none; } /* ----- INFO & SHARING ----- */ #back { font-family: Helvetica, Arial, "Lucida Grande"; position: fixed; top: 7px; width: 190px; height: 36px; box-shadow: 0px 0px 4px 0px #888; line-height: 10px; left: -153px; background: #fff; z-index: 1000; -webkit-transition: left 250ms; -moz-transition: left 250ms; -o-transition: left 250ms; -ms-trantion: left 250ms; transition: left 250ms; } #back.open { left: 0px; } #back a { color: #1C86EE; margin-left: 0px; margin-right: 0px; padding: 13px; padding-right: 0px; position: absolute; } #back a:hover { color: hotpink; } #back span { font-size: 50px; line-height: 0px; color: #444; text-decoration: none; font-family: Times; position: absolute; right: 10px; top: 17px; -webkit-margin-before: -3px; } #info-tab * { -webkit-box-sizing: border-box; -moz-box-sizing: border-box; box-sizing: border-box } #info-tab { font-family: Helvetica, Arial, "Lucida Grande"; -webkit-box-shadow: 0px 0px 4px 0px #888; box-shadow: 0px 0px 4px 0px #888; -webkit-transition: left 300ms, -webkit-box-shadow 500ms; -moz-transition: left 300ms, -moz-box-shadow 500ms; -o-transition: left 300ms, -o-box-shadow 500ms; -ms-trantion: left 300ms, -ms-box-shadow 500ms; transition: left 300ms, box-shadow 500ms; background-color: #ffffff; height: 150px; position: fixed; padding-left: 5px; line-height: 36px; width: 630px; margin-top: 11px; font-size: 17px; color: #444; left: -598px; z-index: 1000; top: 40px; } #info-tab.open { left: 0px; } #info-tab.highlight { -webkit-box-shadow: 0px 0px 12px 0px #222; box-shadow: 0px 0px 12px 0px #222; } #info-tab.open #title { opacity: 0; } #info-tab #title { -webkit-transition: opacity 300ms; -moz-transition: opacity 300ms; -o-transition: opacity 300ms; -ms-trantion: opacity 300ms; transition: opacity 300ms; -webkit-transform: rotate( 90deg ) translateZ(0px); -moz-transform: rotate( 90deg ) translateZ(0px); -ms-transform: rotate( 90deg ) translateZ(0px); -o-transform: rotate( 90deg ) translateZ(0px); transform: rotate( 90deg ) translateZ(0px); -webkit-transform-origin: 100% 0%; -moz-transform-origin: 100% 0%; -ms-transform-origin: 100% 0%; -o-transform-origin: 100% 0%; transform-origin: 100% 0%; float: right; width: 150px; height: 30px; position: absolute; text-align: center; right: 0px; bottom: -30px; } #info-tab .info { margin-left: 18px; font-size: 14px; line-height: 16px; height: 110px; width: 282px; float: left; padding-right: 18px; margin-top: 20px; margin-bottom: 20px; color: #111; margin-right: 5px; position: relative; } #info-tab .first { border-right: 1px solid #ddd; } #info-tab p { position: absolute; bottom: 0px; font-size: 12px; margin: 0px; } #info-tab a { color: #1C86EE; } #info-tab a:hover { color: hotpink; } #info-tab iframe { vertical-align: bottom; } ================================================ FILE: index.html ================================================ Texter - Draw with Words
Texter is a little javascript experiment that lets you explore your creativity by drawing with words. This app is an extension of a demo from this book

Made by: Tim Holman - @twholman

This has been made using Javascript and the HTML5 canvas element. You can find the source on Github. If you feel like supporting me, you can always buy me a coffee.

Texter
More experiments
================================================ FILE: js/header.js ================================================ var headers = [ document.getElementById("back"), document.getElementById("info-tab"), ]; var headerMouseDown = false; var headerToggleTimeOut = []; document.addEventListener( "mousedown", function () { headerMouseDown = true; }, false ); document.addEventListener( "mouseup", function () { headerMouseDown = false; }, false ); for (var i = 0; i < headers.length; i++) { headerToggleTimeOut.push(-1); headers[i].addEventListener( "mouseover", function () { if (!headerMouseDown) { interval = clearInterval(interval); var _this = this; clearTimeout(headerToggleTimeOut); headerToggleTimeOut[i] = setTimeout(function () { _this.setAttribute("class", "open"); }, 50); } }, false ); headers[i].addEventListener( "mouseout", function () { var _this = this; clearTimeout(headerToggleTimeOut); headerToggleTimeOut[i] = setTimeout(function () { _this.setAttribute("class", ""); }, 50); }, false ); } function pulseHeader() { if (interval == undefined) { return; } headers[1].setAttribute("class", "highlight"); setTimeout(function () { if (interval == undefined) { return; } headers[1].setAttribute("class", ""); setTimeout(function () { if (interval == undefined) { return; } headers[1].setAttribute("class", "highlight"); setTimeout(function () { if (interval == undefined) { return; } headers[1].setAttribute("class", ""); }, 400); }, 400); }, 400); } var interval = setInterval(function () { pulseHeader(); }, 10000); ================================================ FILE: js/texter.js ================================================ /* * Texter - Drawing with Text. * - Ported from demo in Generative Design book - http://www.generative-gestaltung.de * - generative-gestalung.de original licence: http://www.apache.org/licenses/LICENSE-2.0 * * - Modified and maintained by Tim Holman - tholman.com - @twholman */ function Texter() { var _this = this; // Application variables position = { x: 0, y: window.innerHeight / 2 }; textIndex = 0; this.textColor = "#000000"; this.bgColor = "#ffffff"; this.minFontSize = 8; this.maxFontSize = 300; this.angleDistortion = 0.01; var queryString = window.location.search; var urlParams = new URLSearchParams(queryString); var urlText = urlParams.get('text') this.text = urlText || "There was a table set out under a tree in front of the house, and the March Hare and the Hatter were having tea at it: a Dormouse was sitting between them, fast asleep, and the other two were using it as a cushion, resting their elbows on it, and talking over its head. 'Very uncomfortable for the Dormouse,' thought Alice; 'only, as it's asleep, I suppose it doesn't mind.'"; // Drawing Variables canvas = null; context = null; mouse = { x: 0, y: 0, down: false }; bgCanvas = null; bgContext = null; this.initialize = function () { canvas = document.getElementById("canvas"); context = canvas.getContext("2d"); canvas.width = window.innerWidth; canvas.height = window.innerHeight; canvas.addEventListener("mousemove", onMove, false); canvas.addEventListener("mousedown", onDown, false); canvas.addEventListener("mouseup", onUp, false); canvas.addEventListener("mouseout", onUp, false); canvas.addEventListener("touchstart", onDown, false); canvas.addEventListener("touchmove", onMove, false); canvas.addEventListener("touchend", onUp, false); canvas.addEventListener("touchcancel", onUp, false); bgCanvas = document.createElement("canvas"); bgContext = bgCanvas.getContext("2d"); bgCanvas.width = canvas.width; bgCanvas.height = canvas.height; _this.setBackground(_this.bgColor); window.onresize = function (event) { canvas.width = window.innerWidth; canvas.height = window.innerHeight; bgCanvas.width = window.innerWidth; bgCanvas.height = window.innerHeight; _this.setBackground(_this.bgColor); _this.clear(); }; update(); }; var update = function () { requestAnimationFrame(update); draw(); }; var draw = function () { if (mouse.down) { var newDistance = distance(position, mouse); var fontSize = _this.minFontSize + newDistance / 2; if (fontSize > _this.maxFontSize) { fontSize = _this.maxFontSize; } var letter = _this.text[textIndex]; var stepSize = textWidth(letter, fontSize); if (newDistance > stepSize) { var angle = Math.atan2(mouse.y - position.y, mouse.x - position.x); context.font = fontSize + "px Georgia"; context.save(); context.translate(position.x, position.y); context.rotate( angle + (Math.random() * (_this.angleDistortion * 2) - _this.angleDistortion) ); context.fillText(letter, 0, 0); context.restore(); textIndex++; if (textIndex > _this.text.length - 1) { textIndex = 0; } position.x = position.x + Math.cos(angle) * stepSize; position.y = position.y + Math.sin(angle) * stepSize; } } }; var distance = function (pt, pt2) { var xs = 0; var ys = 0; xs = pt2.x - pt.x; xs = xs * xs; ys = pt2.y - pt.y; ys = ys * ys; return Math.sqrt(xs + ys); }; var onDown = function (event) { const eventObject = event.touches && event.touches.item(0) || event mouse.down = true; position.x = eventObject.pageX; position.y = eventObject.pageY; mouse.x = eventObject.pageX; mouse.y = eventObject.pageY; }; var onUp = function () { mouse.down = false; }; var onMove = function (event) { const eventObject = event.touches && event.touches.item(0) || event mouse.x = eventObject.pageX; mouse.y = eventObject.pageY; draw(); }; var textWidth = function (string, size) { context.font = size + "px Georgia"; if (context.fillText) { return context.measureText(string).width; } else if (context.mozDrawText) { return context.mozMeasureText(string); } }; this.clear = function () { canvas.width = canvas.width; context.fillStyle = _this.textColor; }; this.applyNewColor = function (value) { _this.textColor = value; context.fillStyle = _this.textColor; }; this.setBackground = function (value) { _this.bgColor = value; canvas.style.backgroundColor = value; }; this.onTextChange = function () { textIndex = 0; }; this.save = function () { // Prepare the background canvas's color bgContext.rect(0, 0, bgCanvas.width, bgCanvas.height); bgContext.fillStyle = _this.bgColor; bgContext.fill(); // Draw the front canvas onto the bg canvas bgContext.drawImage(canvas, 0, 0); // Open in a new window window.open(bgCanvas.toDataURL("image/png"), "mywindow"); }; }