<!doctype html> <html> <head> <title>8seg dimension planning</title> <style> canvas { } body { margin-left: auto; margin-right: auto; width: min-content; } #form { max-width: 1000px; margin-left: auto; margin-right: auto; display: grid; grid-template-columns: max-content auto; } #form > label { text-align: right; padding-right: 0.5em; } #form > input[type="number"] { max-width: 5em; } #form > input { justify-self: start; } </style> </head> <body> <canvas id="viz" width="1800px" height="500px"> </canvas> <div id="form"> <label for="text">Text</label><input type="text" id="text" value="Sphinx of black quartz/judge my vow"/> <label for="digit_width">Digit width</label><input type="number" id="digit_width" step="0.01" value="1.0"> <label for="digit_height">Digit height</label><input type="number" id="digit_height" step="0.01" value="1.6"> <label for="digit_space">Digit spacing</label><input type="number" id="digit_space" step="0.01" value="0.4"> <label for="digit_num">Number of digits</label><input type="number" id="digit_num" value="36"> <label for="leds_per_m">LEDs per meter</label><input type="number" id="leds_per_m" value="10"> <label for="individual_leds">Render individual LEDs</label><input type="checkbox" id="individual_leds"> <label for="line_width">Visualization line width</label><input type="number" id="line_width", value=0.05> </div> <script> const seg_map = { " ": 0x00, "a": 0x2e, "b": 0xd6, "c": 0xd0, "d": 0xc5, "e": 0x59, "f": 0x98, "g": 0xd4, "h": 0x8c, "i": 0x5c, "j": 0x78, "k": 0x8e, "l": 0xc0, "m": 0xa3, "n": 0xa5, "o": 0xf0, "p": 0x93, "q": 0xf4, "r": 0x9e, "s": 0x55, "t": 0xc8, "u": 0xe0, "v": 0x8a, "w": 0xac, "x": 0x0f, "y": 0x0b, "z": 0x5a, "0": 0x13, "1": 0x20, "2": 0x16, "3": 0x56, "4": 0x23, "5": 0x1c, "6": 0x4e, "7": 0x1a, "8": 0x5f, "9": 0x33, "/": 0x0a, "\\": 0x05, }; function map_digit(codepoint) { if (!seg_map.hasOwnProperty(codepoint)) { return seg_map[" "]; } return seg_map[codepoint]; } function do_line(ctx, x1, y1, x2, y2, scale) { if (document.querySelector("#individual_leds").checked) { const leds_per_m = parseFloat(document.querySelector("#leds_per_m").value); const dist = Math.sqrt((x2-x1)*(x2-x1) + (y2-y1)*(y2-y1)); const num_leds = dist * leds_per_m; const d_off = (num_leds % 1.0) / 2; for (var i=0; i<num_leds; i++) { const frac_d = ((d_off + i)/leds_per_m); const x = x1*scale + (x2-x1)*scale*frac_d/dist; const y = y1*scale + (y2-y1)*scale*frac_d/dist; ctx.moveTo(x-0.5, y-0.5); ctx.lineTo(x+0.5, y+0.5); } } else { ctx.moveTo(x1*scale, y1*scale); ctx.lineTo(x2*scale, y2*scale); } } function draw_digit(ctx, x, y, w, h, seg, scale) { for (var i=0; i<2; i++) { if (i == 0) { ctx.strokeStyle = '#e00000'; } else { ctx.strokeStyle = '#404040'; seg = ~seg; } ctx.beginPath(); if (seg & 0x80) { do_line(ctx, x, y, x, y+h, scale); } if (seg & 0x40) { do_line(ctx, x, y+h, x+w, y+h, scale); } if (seg & 0x20) { do_line(ctx, x+w, y+h, x+w, y, scale); } if (seg & 0x10) { do_line(ctx, x+w, y, x, y, scale); } if (seg & 0x01) { do_line(ctx, x+w/2, y+h/2, x, y, scale); } if (seg & 0x02) { do_line(ctx, x+w/2, y+h/2, x+w, y, scale); } if (seg & 0x08) { do_line(ctx, x+w/2, y+h/2, x, y+h, scale); } if (seg & 0x04) { do_line(ctx, x+w/2, y+h/2, x+w, y+h, scale); } ctx.stroke(); } } function update() { const canvas = document.querySelector("#viz"); const ctx = canvas.getContext("2d"); ctx.fillStyle = '#202020'; ctx.fillRect(0, 0, canvas.width, canvas.height); const digit_num = parseFloat(document.querySelector("#digit_num").value); const digit_width = parseFloat(document.querySelector("#digit_width").value); const digit_height = parseFloat(document.querySelector("#digit_height").value); const digit_space = parseFloat(document.querySelector("#digit_space").value); const line_width = parseFloat(document.querySelector("#line_width").value); const text = document.querySelector("#text").value.toLowerCase(); const segs = []; for (var codepoint of text) { segs.push(map_digit(codepoint)); } for (var i=0; i<digit_num; i++) { segs.push(map_digit(" ")); } const total_w = digit_num * digit_width + (digit_num - 1) * digit_space; const total_h = digit_height; const fill_factor = 0.8; const scale = canvas.width * fill_factor / total_w; var x = (canvas.width/scale - total_w) / 2; var y = (canvas.height/scale - total_h) / 2; ctx.lineWidth = scale*line_width*digit_width; for (var i=0; i<digit_num; i++) { draw_digit(ctx, x, y, digit_width, digit_height, segs[i], scale); x += digit_width + digit_space; } } function handle_change(evt) { update(); } document.querySelector("#digit_width").addEventListener('change', handle_change); document.querySelector("#digit_height").addEventListener('change', handle_change); document.querySelector("#digit_space").addEventListener('change', handle_change); document.querySelector("#digit_num").addEventListener('change', handle_change); document.querySelector("#line_width").addEventListener('change', handle_change); document.querySelector("#leds_per_m").addEventListener('change', handle_change); document.querySelector("#individual_leds").addEventListener('change', handle_change); document.querySelector("#text").addEventListener('input', handle_change); update(); </script> </body> </html>