8seg/planning/8seg_vis.html

214 lines
6.6 KiB
HTML

<!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>