Added clocks tool

This commit is contained in:
Leon Mika 2025-09-26 08:13:29 +10:00
parent 8dc2621f87
commit 7073a2d3f2
23 changed files with 1061 additions and 3 deletions

54
site/clocks/index.html Normal file
View file

@ -0,0 +1,54 @@
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Clocks - Tools</title>
<link
rel="stylesheet"
href="https://cdn.jsdelivr.net/npm/@picocss/pico@2/css/pico.min.css"
>
<link rel="stylesheet" href="style.css">
</head>
<body class="container">
<header>
<hgroup>
<h1>Clocks</h1>
<p>Various time zones</p>
</hgroup>
</header>
<div class="grid">
<div class="clock" id="utc">
<div class="location"></div>
<div class="time"></div>
<div class="date"></div>
</div>
<div class="clock" id="mel">
<div class="location"></div>
<div class="time"></div>
<div class="date"></div>
</div>
<div class="clock" id="sg">
<div class="location"></div>
<div class="time"></div>
<div class="date"></div>
</div>
</div>
<div class="grid">
<div class="clock" id="nyc">
<div class="location"></div>
<div class="time"></div>
<div class="date"></div>
</div>
<div class="clock" id="la">
<div class="location"></div>
<div class="time"></div>
<div class="date"></div>
</div>
<div></div>
</div>
<script src="main.js" type="module"></script>
</body>
</html>

8
site/clocks/main.js Normal file
View file

@ -0,0 +1,8 @@
import "/wasm/wasm_exec.js";
const go = new Go();
WebAssembly.instantiateStreaming(fetch("/wasm/clocks.wasm"), go.importObject)
.then((result) => {
go.run(result.instance);
});

13
site/clocks/style.css Normal file
View file

@ -0,0 +1,13 @@
div.clock {
text-align: center;
margin-block-end: 1.8rem;
}
div.clock div.location {
color: rgb(175, 41, 29);
}
div.clock div.time {
font-size: 200%;
font-family: var(--pico-font-family-monospace);
}

View file

@ -0,0 +1,53 @@
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1">
<meta name="color-scheme" content="light dark">
<title>Freelens Logo Creator - Tools</title>
<link
rel="stylesheet"
href="https://cdn.jsdelivr.net/npm/@picocss/pico@2/css/pico.min.css"
>
<style>
canvas {
border: 1px solid #ccc;
display: block;
margin-bottom: 10px;
}
</style>
</head>
<body class="container">
<header>
<hgroup>
<h1>Freelens Logo Creator</h1>
<p>Create logos for K8S clusters in Freelens</p>
</hgroup>
</header>
<main class="grid">
<div>
<form id="logoForm">
<input type="text" id="upperText" name="Upper" placeholder="Upper">
<input type="text" id="lowerText" name="Lower" placeholder="Lower">
<label>Background:
<select id="bgColor" name="Background">
<option value="#cd2d2d">Red</option>
<option value="#d26800">Orange</option>
<option value="#f39c12">Amber</option>
<option value="#27ae60">Green</option>
<option value="#17a094">Teal</option>
<option value="#2980b9">Blue</option>
<option value="#8e44ad">Purple</option>
<option value="#7f8c8d">Gray</option>
</select>
</label>
</form>
</div>
<div>
<canvas id="logoCanvas" width="100" height="100"></canvas>
<button id="downloadBtn">Download PNG</button>
</div>
</main>
<script src="script.js"></script>
</body>
</html>

View file

@ -0,0 +1,78 @@
(function() {
const canvas = document.getElementById('logoCanvas');
const ctx = canvas.getContext('2d');
const upperInput = document.getElementById('upperText');
const lowerInput = document.getElementById('lowerText');
const colorSelect = document.getElementById('bgColor');
const downloadBtn = document.getElementById('downloadBtn');
const PADDING = 15;
const LINE_WIDTH = 2;
function fitText(text, maxWidth, maxHeight) {
let size = maxHeight;
ctx.font = `bold ${size}px sans-serif`;
while (ctx.measureText(text).width > maxWidth && size > 8) {
size--;
ctx.font = `bold ${size}px sans-serif`;
}
return size;
}
function draw() {
const width = canvas.width;
const height = canvas.height;
ctx.clearRect(0, 0, width, height);
ctx.fillStyle = colorSelect.value;
ctx.fillRect(0, 0, width, height);
const upper = upperInput.value;
const lower = lowerInput.value;
if (lower != "") {
ctx.strokeStyle = 'white';
ctx.lineWidth = LINE_WIDTH;
const yLine = height / 2;
ctx.beginPath();
ctx.moveTo(PADDING, yLine);
ctx.lineTo(width - PADDING, yLine);
ctx.stroke();
}
const availableWidth = width - PADDING * 2;
const availableHeight = height - PADDING * 2;
const halfHeight = availableHeight / 2;
ctx.fillStyle = 'white';
ctx.textAlign = 'center';
ctx.textBaseline = 'middle';
if (lower != "") {
let fontSize = fitText(upper, availableWidth, halfHeight);
ctx.font = `bold ${fontSize}px sans-serif`;
ctx.fillText(upper, width / 2, PADDING + halfHeight / 2);
fontSize = fitText(lower, availableWidth, halfHeight);
ctx.font = `bold ${fontSize}px sans-serif`;
ctx.fillText(lower, width / 2, height - PADDING - halfHeight / 2 + 4);
} else {
let fontSize = fitText(upper, availableWidth, halfHeight);
ctx.font = `bold ${fontSize}px sans-serif`;
ctx.fillText(upper, width / 2, height / 2);
}
}
upperInput.addEventListener('input', draw);
lowerInput.addEventListener('input', draw);
colorSelect.addEventListener('change', draw);
downloadBtn.addEventListener('click', function() {
const link = document.createElement('a');
link.download = 'logo.png';
link.href = canvas.toDataURL('image/png');
link.click();
});
draw();
})();

27
site/index.html Normal file
View file

@ -0,0 +1,27 @@
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1">
<meta name="color-scheme" content="light dark">
<title>Tools</title>
<link
rel="stylesheet"
href="https://cdn.jsdelivr.net/npm/@picocss/pico@2/css/pico.min.css"
>
</head>
<body class="container">
<header>
<hgroup>
<h1>Tools</h1>
<p>Collection of online tools</p>
</hgroup>
</header>
<main>
<ul>
<li><a href="/clocks/">Clocks</a></li>
<li><a href="/freelens-logo/">Freelens Logo maker</a></li>
</ul>
</main>
</body>
</html>