Added Gradient bands
All checks were successful
/ publish (push) Successful in 45s

This commit is contained in:
Leon Mika 2025-09-27 10:57:14 +10:00
parent d1dee7bc3d
commit f53aad9a94
4 changed files with 160 additions and 0 deletions

View file

@ -0,0 +1,56 @@
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Gradient Bands - 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>Gradient Bands</h1>
<p>Generate colour gradients with customisable bands</p>
</hgroup>
</header>
<main>
<section>
<div class="grid">
<div>
<label for="start-color">Start Colour</label>
<input type="color" id="start-color" value="#ff0000">
</div>
<div>
<label for="end-color">End Colour</label>
<input type="color" id="end-color" value="#0000ff">
</div>
<div>
<label for="bands">Number of Bands</label>
<input type="number" id="bands" value="10" min="1" max="100">
</div>
<div>
<label for="func">Function</label>
<select id="func">
<option value="linear">Linear</option>
<option value="quad">Quadratic</option>
<option value="cubic">Cubic</option>
<option value="sin">Sinusoidal</option>
</select>
</div>
</div>
</section>
<section>
<canvas id="gradient-canvas" width="800" height="400"></canvas>
<button id="download-btn">Download PNG</button>
</section>
</main>
<script src="main.js" type="module"></script>
</body>
</html>

View file

@ -0,0 +1,99 @@
function hexToRgb(hex) {
const result = /^#?([a-f\d]{2})([a-f\d]{2})([a-f\d]{2})$/i.exec(hex);
return result ? {
r: parseInt(result[1], 16),
g: parseInt(result[2], 16),
b: parseInt(result[3], 16)
} : null;
}
function interpolateColor(startRgb, endRgb, t) {
return {
r: Math.round(startRgb.r + (endRgb.r - startRgb.r) * t),
g: Math.round(startRgb.g + (endRgb.g - startRgb.g) * t),
b: Math.round(startRgb.b + (endRgb.b - startRgb.b) * t)
};
}
function rgbToString(rgb) {
return `rgb(${rgb.r}, ${rgb.g}, ${rgb.b})`;
}
function getBandColorAtT(startRgb, endRgb, bands, t) {
const bandIndex = Math.floor(t * bands);
const bandT = bandIndex / (bands - 1);
const clampedBandT = Math.max(0, Math.min(1, bandT));
return interpolateColor(startRgb, endRgb, clampedBandT);
}
function applyFunction(t, funcType) {
switch ( funcType) {
case 'linear':
return t;
case 'quad':
return t * t;
case 'cubic':
return t * t * t;
case 'sin':
return -Math.cos(t * Math.PI) / 2.0 + 0.5;
}
}
function renderGradient() {
const canvas = document.getElementById('gradient-canvas');
const ctx = canvas.getContext('2d');
const startColor = document.getElementById('start-color').value;
const endColor = document.getElementById('end-color').value;
const bands = parseInt(document.getElementById('bands').value);
const funcType = document.getElementById('func').value;
const startRgb = hexToRgb(startColor);
const endRgb = hexToRgb(endColor);
if (!startRgb || !endRgb || bands < 1) {
return;
}
const width = canvas.width;
const height = canvas.height;
const imageData = ctx.createImageData(width, height);
const data = imageData.data;
for (let y = 0; y < height; y++) {
const t = y / (height - 1);
const u = applyFunction(t, funcType);
const color = getBandColorAtT(startRgb, endRgb, bands, u);
for (let x = 0; x < width; x++) {
const index = (y * width + x) * 4;
data[index] = color.r;
data[index + 1] = color.g;
data[index + 2] = color.b;
data[index + 3] = 255;
}
}
ctx.putImageData(imageData, 0, 0);
}
function downloadCanvas() {
const canvas = document.getElementById('gradient-canvas');
const link = document.createElement('a');
link.download = 'gradient-bands.png';
link.href = canvas.toDataURL();
link.click();
}
function initializeEventListeners() {
document.getElementById('start-color').addEventListener('input', renderGradient);
document.getElementById('end-color').addEventListener('input', renderGradient);
document.getElementById('bands').addEventListener('input', renderGradient);
document.getElementById('func').addEventListener('input', renderGradient);
document.getElementById('download-btn').addEventListener('click', downloadCanvas);
}
document.addEventListener('DOMContentLoaded', () => {
initializeEventListeners();
renderGradient();
});

View file

@ -0,0 +1,4 @@
canvas {
display: block;
margin-block-end: 12px;
}

View file

@ -22,6 +22,7 @@
<li><a href="/clocks/">Clocks</a></li> <li><a href="/clocks/">Clocks</a></li>
<li><a href="/freelens-logo/">Freelens Logo Maker</a></li> <li><a href="/freelens-logo/">Freelens Logo Maker</a></li>
<li><a href="/gotemplate/">Go Template Playground</a></li> <li><a href="/gotemplate/">Go Template Playground</a></li>
<li><a href="/gradient-bands/">Gradient Bands</a></li>
<li><a href="/2lcc/">Two-letter Country Codes</a></li> <li><a href="/2lcc/">Two-letter Country Codes</a></li>
</ul> </ul>
</main> </main>