Browse Source

lazygit

main
Gregory Leeman 7 months ago
parent
commit
9e2e205f18
  1. 240
      render.js
  2. 1282
      temp2.js

240
render.js

@ -20,12 +20,9 @@ const shapes = ['circle', 'square'];
// VARS {{{ // VARS {{{
let brushColor = 'rgb(0, 0, 0)';
let brushShape = 'circle' let brushShape = 'circle'
let brushSize = 15; let brushSize = 10;
let zoom = 1; let zoom = 1;
let currentTool;
let prevTool = 'brush';
let startX = 0; let startX = 0;
let startY = 0; let startY = 0;
@ -43,6 +40,8 @@ let canvasDY = 0;
let isKeyDown = false; let isKeyDown = false;
let isMouseDown = false; let isMouseDown = false;
let interval;
// }}} // }}}
// HELPERS {{{ // HELPERS {{{
@ -57,22 +56,19 @@ function disableImageSmoothing(ctx) {
}; };
function hexToRgbArray(hex) { function hexToRgbArray(hex) {
if (hex.startsWith('#')) { hex = hex.replace(/^#/, '');
hex = hex.slice(1);
}
if (hex.length === 3) {
hex = hex.split('').map(char => char + char).join('');
}
const bigint = parseInt(hex, 16); const bigint = parseInt(hex, 16);
return [(bigint >> 16) & 255, (bigint >> 8) & 255, bigint & 255]; const r = (bigint >> 16) & 255;
const g = (bigint >> 8) & 255;
const b = bigint & 255;
return [r, g, b, 255]; // Add 255 for full opacity
} }
function colorsMatch(color1, color2, tolerance = 0) { function colorsMatch(color1, color2, tolerance = 0) {
return Math.abs(color1[0] - color2[0]) <= tolerance && return Math.abs(color1[0] - color2[0]) <= tolerance &&
Math.abs(color1[1] - color2[1]) <= tolerance && Math.abs(color1[1] - color2[1]) <= tolerance &&
Math.abs(color1[2] - color2[2]) <= tolerance; Math.abs(color1[2] - color2[2]) <= tolerance &&
Math.abs(color1[3] - color2[3]) <= tolerance; // Include alpha comparison
} }
function makeIconElement(htmlString) { function makeIconElement(htmlString) {
@ -117,6 +113,38 @@ function makeButtonElement({icon, name, func, key}) {
// }}} // }}}
// COLOR {{{
function makeColor(rgb) {
const color = {};
color.color = rgb;
color.toRgb = function() {
return color.rgb;
}
color.toHex = function() {
color.r = parseInt(rgb[0]);
color.g = parseInt(rgb[1]);
color.b = parseInt(rgb[2]);
return `#${color.r.toString(16)}${color.g.toString(16)}${color.b.toString(16)}`;
}
color.mix = function(color2, t) {
const color1 = color.color;
const newColor = mixbox.lerp(color1, color2, t);
color.color = newColor;
colorPreview.update();
}
return color;
}
const color = makeColor('rgb(0, 0, 0)');
// }}}
// LAYERS {{{ // LAYERS {{{
// FACTORY {{{ // FACTORY {{{
@ -203,7 +231,7 @@ function makeCanvas({height=600, width=800}) { // {{{
if (shape === 'square') { if (shape === 'square') {
canvas.ctx.fillRect(x - Math.floor(size / 2), y - Math.floor(size / 2), size, size); canvas.ctx.fillRect(x - Math.floor(size / 2), y - Math.floor(size / 2), size, size);
} else if (shape === 'circle') { } else if (shape === 'circle') {
let radius = Math.floor(size / 2); let radius = Math.floor(size / 1);
let radiusSquared = radius * radius; let radiusSquared = radius * radius;
for (let y1 = -radius; y1 <= radius; y1++) { for (let y1 = -radius; y1 <= radius; y1++) {
@ -260,25 +288,25 @@ function makeCanvas({height=600, width=800}) { // {{{
canvas.ctx.fillRect(0, 0, canvas.width, canvas.height); canvas.ctx.fillRect(0, 0, canvas.width, canvas.height);
} }
canvas.getColorAtPixel = function(data, x, y) { canvas.getColorAtPixelData = function(x, y, data) {
const index = (y * canvas.width + x) * 4; const index = (y * canvas.width + x) * 4;
return [data[index], data[index + 1], data[index + 2], data[index + 3]]; const color = [data[index], data[index + 1], data[index + 2], data[index + 3]];
return color;
} }
canvas.setColorAtPixel = function(data, x, y, color) { canvas.setColorAtPixelData = function(x, y, color, data) {
const index = (y * canvas.width + x) * 4; const index = (y * canvas.width + x) * 4;
data[index] = color[0]; data[index] = color[0];
data[index + 1] = color[1]; data[index + 1] = color[1];
data[index + 2] = color[2]; data[index + 2] = color[2];
data[index + 3] = 255; data[index + 3] = color[3];
} }
canvas.floodFill = function(x, y, color) { canvas.floodFill = function(x, y, color) {
console.log('flood fill');
const imageData = canvas.ctx.getImageData(0, 0, canvas.width, canvas.height); const imageData = canvas.ctx.getImageData(0, 0, canvas.width, canvas.height);
const data = imageData.data; const data = imageData.data;
const targetColor = canvas.getColorAtPixel(data, x, y); const targetColor = canvas.getColorAtPixelData(x, y, data);
const fillColorArray = hexToRgbArray(color); const fillColorArray = hexToRgbArray(color);
if (colorsMatch(targetColor, fillColorArray, tolerance)) { if (colorsMatch(targetColor, fillColorArray, tolerance)) {
@ -289,10 +317,10 @@ function makeCanvas({height=600, width=800}) { // {{{
while (stack.length > 0) { while (stack.length > 0) {
const {x, y} = stack.pop(); const {x, y} = stack.pop();
const currentColor = canvas.getColorAtPixel(data, x, y); const currentColor = canvas.getColorAtPixelData(x, y, data);
if (colorsMatch(currentColor, targetColor, tolerance)) { if (colorsMatch(currentColor, targetColor, tolerance)) {
canvas.setColorAtPixel(data, x, y, fillColorArray); canvas.setColorAtPixelData(x, y, fillColorArray, data);
if (x > 0) stack.push({x: x - 1, y}); if (x > 0) stack.push({x: x - 1, y});
if (x < canvas.width - 1) stack.push({x: x + 1, y}); if (x < canvas.width - 1) stack.push({x: x + 1, y});
@ -304,6 +332,19 @@ function makeCanvas({height=600, width=800}) { // {{{
canvas.ctx.putImageData(imageData, 0, 0); canvas.ctx.putImageData(imageData, 0, 0);
} }
canvas.getColorAtPixel = function(x, y) {
const data = canvas.ctx.getImageData(0, 0, canvas.width, canvas.height).data;
return canvas.getColorAtPixelData(x, y, data);
}
canvas.setColorAtPixel = function(x, y, color) {
const imageData = canvas.ctx.getImageData(0, 0, canvas.width, canvas.height);
const data = imageData.data;
canvas.setColorAtPixelData(x, y, color, data);
canvas.ctx.putImageData(new ImageData(data, canvas.width, canvas.height), 0, 0);
}
canvas.toDataUrl = function() { canvas.toDataUrl = function() {
const dataURL = canvas.toDataURL(); const dataURL = canvas.toDataURL();
const dimensions = `${canvas.width}x${canvas.height}`; const dimensions = `${canvas.width}x${canvas.height}`;
@ -491,11 +532,13 @@ function makeColorPreview() {
colorPreview.element = document.createElement('div'); colorPreview.element = document.createElement('div');
colorPreview.element.id = 'color-preview'; colorPreview.element.id = 'color-preview';
colorPreview.element.className = 'puck'; colorPreview.element.className = 'puck';
colorPreview.element.style.backgroundColor = brushColor; colorPreview.element.style.backgroundColor = color.color;
commandBarElement.appendChild(colorPreview.element); commandBarElement.appendChild(colorPreview.element);
colorPreview.update = function() { colorPreview.update = function() {
colorPreview.element.style.backgroundColor = brushColor; colorPreview.element.style.backgroundColor = color.color;
} }
return colorPreview;
} }
const colorPreview = makeColorPreview(); const colorPreview = makeColorPreview();
@ -674,7 +717,6 @@ function makeTool({name, key, icon, mouseDown, mouseMove, mouseUp}) {
tool.active = false; tool.active = false;
tool.activate = function() { tool.activate = function() {
currentTool = tool.name;
tool.active = true; tool.active = true;
tool.button.element.classList.add('active'); tool.button.element.classList.add('active');
} }
@ -701,6 +743,8 @@ function makeTool({name, key, icon, mouseDown, mouseMove, mouseUp}) {
function makeTools() { function makeTools() {
const tools = []; const tools = [];
tools.prevToolName = 'na';
tools.add = function({name, key, icon, mouseDown, mouseMove, mouseUp}) { tools.add = function({name, key, icon, mouseDown, mouseMove, mouseUp}) {
const tool = makeTool({name, key, icon, mouseDown, mouseMove, mouseUp}); const tool = makeTool({name, key, icon, mouseDown, mouseMove, mouseUp});
tools.push(tool); tools.push(tool);
@ -710,8 +754,22 @@ function makeTools() {
return tools.find(tool => tool.name === name); return tools.find(tool => tool.name === name);
} }
tools.getActive = function() {
return tools.find(tool => tool.active);
}
tools.activate = function(name) { tools.activate = function(name) {
const tool = tools.get(name); const tool = tools.get(name);
if (tool.active) return;
if (tools.getActive()) {
tools.prevToolName = tools.getActive().name;
tools.forEach(tool => tool.deactivate());
}
tool.activate();
}
tools.restore = function() {
const tool = tools.get(tools.prevToolName);
tools.forEach(tool => tool.deactivate()); tools.forEach(tool => tool.deactivate());
tool.activate(); tool.activate();
} }
@ -730,17 +788,17 @@ tools.add({ // brush {{{
mouseDown: function(e) { mouseDown: function(e) {
const canvas = layers.getActive().canvas; const canvas = layers.getActive().canvas;
if (brushSize === 1) { if (brushSize === 1) {
canvas.drawPixel(canvasStartX, canvasStartY, brushColor); canvas.drawPixel(canvasStartX, canvasStartY, color.color);
} else { } else {
canvas.drawShape(canvasStartX, canvasStartY, brushShape, brushSize, brushColor); canvas.drawShape(canvasStartX, canvasStartY, brushShape, brushSize, color.color);
} }
}, },
mouseMove: function(e) { mouseMove: function(e) {
const canvas = layers.getActive().canvas; const canvas = layers.getActive().canvas;
if (brushSize === 1) { if (brushSize === 1) {
canvas.drawLineWithPixels(canvasStartX, canvasStartY, canvasEndX, canvasEndY, brushColor); canvas.drawLineWithPixels(canvasStartX, canvasStartY, canvasEndX, canvasEndY, color.color);
} else { } else {
canvas.drawLineWithShape(canvasStartX, canvasStartY, canvasEndX, canvasEndY, brushShape, brushSize, brushColor); canvas.drawLineWithShape(canvasStartX, canvasStartY, canvasEndX, canvasEndY, brushShape, brushSize, color.color);
} }
canvasStartX = canvasEndX; canvasStartX = canvasEndX;
canvasStartY = canvasEndY; canvasStartY = canvasEndY;
@ -797,7 +855,7 @@ tools.add({ // bucket-fill {{{
icon: '<i class="fa-solid fa-fill"></i>', icon: '<i class="fa-solid fa-fill"></i>',
mouseDown: function(e) { mouseDown: function(e) {
const canvas = layers.getActive().canvas; const canvas = layers.getActive().canvas;
canvas.floodFill(canvasStartX, canvasStartY, brushColor); canvas.floodFill(canvasStartX, canvasStartY, color.color);
} }
}); // }}} }); // }}}
@ -809,7 +867,7 @@ tools.add({ // color-picker {{{
const canvas = layers.getActive().canvas; const canvas = layers.getActive().canvas;
const imageData = canvas.ctx.getImageData(canvasStartX, canvasStartY, 1, 1).data; const imageData = canvas.ctx.getImageData(canvasStartX, canvasStartY, 1, 1).data;
const pickedColor = `rgb(${imageData[0]}, ${imageData[1]}, ${imageData[2]})`; const pickedColor = `rgb(${imageData[0]}, ${imageData[1]}, ${imageData[2]})`;
brushColor = pickedColor; color.color = pickedColor;
colorPreview.update(); colorPreview.update();
} }
}); // }}} }); // }}}
@ -847,25 +905,29 @@ tools.add({ // resize {{{
} }
}); // }}} }); // }}}
tools.add({ // color-mix {{{ tools.add({ // color-mix {{{
name: 'color-mix', name: 'color-mix',
key: 'x', key: 'x',
icon: '<i class="fa-solid fa-mortar-pestle"></i>', icon: '<i class="fa-solid fa-mortar-pestle"></i>',
mouseMove: function(e) { mouseDown: function(e) {
// const canvas = layers.getActive().canvas; const startTime = Date.now();
const imageData = ctx.getImageData(canvasEndX, canvasEndY, 1, 1).data; const canvas = layers.getActive().canvas;
const canvasColor = `rgb(${imageData[0]}, ${imageData[1]}, ${imageData[2]})`; interval = setInterval(() => {
let canvasColor = canvas.getColorAtPixel(canvasEndX, canvasEndX);
const distance = Math.sqrt(Math.pow(e.clientX - startX, 2) + Math.pow(e.clientY - startY, 2)); console.log({canvasEndX, canvasEndY, canvasColor});
const t = Math.min(1, distance / 300); const elapsedTime = Date.now() - startTime;
const t = Math.min(1, elapsedTime / 10000);
const mixedColor = mixbox.lerp(brushColor, canvasColor, t); color.mix(canvasColor, t);
}, 50);
brushColor = mixedColor; },
mouseUp: function(e) {
clearInterval(interval);
},
mouseLeave: function(e) {
clearInterval(interval);
}
startX = e.clientX;
startY = e.clientY;
}
}); // }}} }); // }}}
// }}} // }}}
@ -901,38 +963,32 @@ function makePuck({puckColor, key, editable=true}) {
puck.element.appendChild(keyHint); puck.element.appendChild(keyHint);
} }
function mixx(startTime) {
var interval = setInterval(() => { puck.element.addEventListener('mousedown', (e) => {
const startTime = Date.now();
interval = setInterval(() => {
const elapsedTime = Date.now() - startTime; const elapsedTime = Date.now() - startTime;
const t = Math.min(1, elapsedTime / 10000); const t = Math.min(1, elapsedTime / 10000);
const mixedColor = mixbox.lerp(brushColor, puck.style.backgroundColor, t); color.mix(puck.element.style.backgroundColor, t);
brushColor = mixedColor;
colorPreview.update();
infos.update();
}, 50); }, 50);
return interval; });
}
puck.element.addEventListener('mousedown', () => { puck.element.addEventListener('mouseup', (e) => {
const startTime = Date.now(); clearInterval(interval);
var interval = mixx(startTime);
function onMouseUp() {
clearInterval(interval);
document.removeEventListener('mouseup', onMouseUp);
}
document.addEventListener('mouseup', onMouseUp);
}); });
puck.keydown = function(e) { puck.keydown = function(e) {
if (e.key == key) { const startTime = Date.now();
const startTime = Date.now(); var interval = setInterval(() => {
var interval = mixx(startTime); const elapsedTime = Date.now() - startTime;
function onKeyUp() { const t = Math.min(1, elapsedTime / 10000);
clearInterval(interval); color.mix(puck.element.style.backgroundColor, t);
document.removeEventListener('keyup', onKeyUp); }, 50);
} function onKeyUp() {
document.addEventListener('keyup', onKeyUp); clearInterval(interval);
document.removeEventListener('keyup', onKeyUp);
} }
document.addEventListener('keyup', onKeyUp);
} }
commandBarElement.appendChild(puck.element); commandBarElement.appendChild(puck.element);
@ -1078,7 +1134,7 @@ infos.add({
infos.add({ infos.add({
name: 'color', name: 'color',
updateFunction: function() { updateFunction: function() {
return brushColor; return color.color;
} }
}); });
@ -1103,6 +1159,13 @@ infos.add({
} }
}); });
infos.add({
name: 'tool',
updateFunction: function() {
return tools.getActive().name;
}
});
// }}} // }}}
// MOUSE EVENT LISTENERS {{{ // MOUSE EVENT LISTENERS {{{
@ -1114,10 +1177,12 @@ studioElement.addEventListener('mousedown', (e) => {
startY = e.clientY; startY = e.clientY;
canvasStartX = canvas.getPositionOnCanvas(e).x; canvasStartX = canvas.getPositionOnCanvas(e).x;
canvasStartY = canvas.getPositionOnCanvas(e).y; canvasStartY = canvas.getPositionOnCanvas(e).y;
canvasEndX = canvas.getPositionOnCanvas(e).x;
canvasEndX = canvas.getPositionOnCanvas(e).y;
for (var i = 0; i < tools.length; i++) { for (var i = 0; i < tools.length; i++) {
var tool = tools[i]; var tool = tools[i];
if (tool.name === currentTool) { if (tool.active) {
if (tool.mouseDown) { if (tool.mouseDown) {
tool.mouseDown(e); tool.mouseDown(e);
break; break;
@ -1140,7 +1205,7 @@ studioElement.addEventListener('mousemove', (e) => {
canvasDX = canvasEndX - canvasStartX; canvasDX = canvasEndX - canvasStartX;
canvasDY = canvasEndY - canvasStartY; canvasDY = canvasEndY - canvasStartY;
if (currentTool == 'brush-size') { if (tools.getActive().name === 'brush-size') {
brushPreviewElement.style.display = 'block'; brushPreviewElement.style.display = 'block';
brushPreviewElement.style.width = brushSize + 'px'; brushPreviewElement.style.width = brushSize + 'px';
brushPreviewElement.style.height = brushSize + 'px'; brushPreviewElement.style.height = brushSize + 'px';
@ -1151,7 +1216,7 @@ studioElement.addEventListener('mousemove', (e) => {
if (isMouseDown) { if (isMouseDown) {
for (var i = 0; i < tools.length; i++) { for (var i = 0; i < tools.length; i++) {
var tool = tools[i]; var tool = tools[i];
if (tool.name === currentTool) { if (tool.active) {
if (tool.mouseMove) { if (tool.mouseMove) {
tool.mouseMove(e); tool.mouseMove(e);
break; break;
@ -1166,11 +1231,33 @@ studioElement.addEventListener('mousemove', (e) => {
studioElement.addEventListener('mouseup', () => { studioElement.addEventListener('mouseup', () => {
isMouseDown = false; isMouseDown = false;
for (var i = 0; i < tools.length; i++) {
var tool = tools[i];
if (tool.active) {
if (tool.mouseUp) {
tool.mouseUp();
break;
}
}
}
infos.update(); infos.update();
}); });
studioElement.addEventListener('mouseleave', () => { studioElement.addEventListener('mouseleave', () => {
isMouseDown = false; isMouseDown = false;
for (var i = 0; i < tools.length; i++) {
var tool = tools[i];
if (tool.active) {
if (tool.mouseLeave) {
tool.mouseLeave();
break;
}
}
}
brushPreviewElement.style.display = 'none'; brushPreviewElement.style.display = 'none';
infos.update(); infos.update();
}); });
@ -1184,8 +1271,7 @@ document.addEventListener('keydown', (e) => {
tools.forEach(tool => { tools.forEach(tool => {
if (tool.key.toLowerCase() === e.key.toLowerCase()) { if (tool.key.toLowerCase() === e.key.toLowerCase()) {
prevTool = currentTool; tools.activate(tool.name);
currentTool = tool.name;
} }
}); });
@ -1208,7 +1294,7 @@ document.addEventListener('keydown', (e) => {
document.addEventListener('keyup', (e) => { document.addEventListener('keyup', (e) => {
tools.forEach(tool => { tools.forEach(tool => {
if (tool.key.toLowerCase() === e.key) { if (tool.key.toLowerCase() === e.key) {
currentTool = prevTool; tools.restore();
} }
}); });

1282
temp2.js

File diff suppressed because it is too large
Loading…
Cancel
Save