Browse Source

lazygit

main
Gregory Leeman 7 months ago
parent
commit
e453aec077
  1. 0
      archive/cool.js
  2. 0
      archive/history.js
  3. 25
      archive/temp.css
  4. 774
      archive/temp.js
  5. 0
      archive/temp2.js
  6. 682
      render.js
  7. 724
      temp.js

0
cool.js → archive/cool.js

0
history.js → archive/history.js

25
archive/temp.css

@ -1,25 +0,0 @@
.puck {
width: 100px;
height: 120px;
padding: 2px;
background-color: #ddd;
border: 1px solid;
position: absolute;
display: flex;
flex-direction: column;
}
.well {
width: 100%;
flex-grow: 1;
border: 1px solid;
}
.puck-menu {
display: flex;
flex-direction: row;
justify-content: space-between;
padding-top: 2px;
}

774
archive/temp.js

@ -1,124 +1,724 @@
function createPuck(c) { const colorPreview = document.createElement('div');
const puck = document.createElement('div'); colorPreview.id = 'color-preview';
puck.className = 'puck'; colorPreview.className = 'puck';
colorPreview.style.backgroundColor = color;
menuBar.appendChild(colorPreview);
const well = document.createElement('div');
well.className = 'well';
well.style.backgroundColor = c;
puck.appendChild(well);
const puckMenu = document.createElement('div'); // }}}
puckMenu.className = 'puck-menu';
puck.appendChild(puckMenu);
const selectHandle = document.createElement('div'); // helpers {{{
selectHandle.className = 'select-handle';
selectHandle.innerHTML = '<i class="fa-solid fa-droplet"></i>';
puckMenu.appendChild(selectHandle);
const copyHandle = document.createElement('div');
copyHandle.className = 'copy-handle';
copyHandle.innerHTML = '<i class="fa-regular fa-copy"></i>';
puckMenu.appendChild(copyHandle);
const deleteHandle = document.createElement('div'); function saveCanvas() {
deleteHandle.className = 'delete-handle'; const dataURL = canvas.toDataURL();
deleteHandle.innerHTML = '<i class="fa-solid fa-trash-can"></i>'; const dimensions = `${canvas.width}x${canvas.height}`;
puckMenu.appendChild(deleteHandle); localStorage.setItem('mixxCanvas', dataURL);
localStorage.setItem('mixxDimensions', dimensions);
console.log('Canvas saved');
}
function loadCanvas() {
const dataURL = localStorage.getItem('mixxCanvas');
const dimensions = localStorage.getItem('mixxDimensions');
if (dataURL && dimensions) {
const img = new Image();
img.src = dataURL;
img.onload = function() {
canvas.width = dimensions.split('x')[0];
canvas.height = dimensions.split('x')[1];
canvas.style.width = canvas.width * zoom + 'px';
canvas.style.height = canvas.height * zoom + 'px';
canvasWidth = canvas.width;
canvasHeight = canvas.height;
ctx.drawImage(img, 0, 0);
}
} else {
console.log('No saved canvas found');
}
}
const updateHandle = document.createElement('div'); function clearCanvasFromLocalStorage() {
updateHandle.className = 'update-handle'; localStorage.removeItem('savedCanvas');
updateHandle.innerHTML = '<i class="fa-solid fa-fill"></i>'; localStorage.removeItem('canvasDimensions');
puckMenu.appendChild(updateHandle); }
function saveState() {
if (undoStack.length >= maxHistory) {
undoStack.shift(); // Remove the oldest state if the stack exceeds the limit
}
const dragHandle = document.createElement('div'); undoStack.push({
dragHandle.className = 'drag-handle'; imageData: canvas.toDataURL(),
dragHandle.innerHTML = '<i class="fa-solid fa-bars"></i>'; width: canvas.width,
puckMenu.appendChild(dragHandle); height: canvas.height
});
well.addEventListener('mousedown', (e) => { redoStack = []; // Clear the redo stack whenever a new action is performed
let isMixing = true; }
let startX = e.clientX;
let startY = e.clientY;
document.addEventListener('mousemove', onMouseMove); function undo() {
document.addEventListener('mouseup', onMouseUp); if (undoStack.length > 0) {
const currentState = {
imageData: canvas.toDataURL(),
width: canvas.width,
height: canvas.height
};
redoStack.push(currentState); // Save current state to the redo stack
const lastState = undoStack.pop(); // Get the last state from the undo stack
canvas.width = lastState.width;
canvas.height = lastState.height;
canvas.style.width = canvas.width * zoom + 'px';
canvas.style.height = canvas.height * zoom + 'px';
canvasWidth = canvas.width;
canvasHeight = canvas.height;
const img = new Image();
img.src = lastState.imageData;
img.onload = function() {
ctx.clearRect(0, 0, canvas.width, canvas.height);
ctx.drawImage(img, 0, 0);
};
}
}
function redo() {
if (redoStack.length > 0) {
const currentState = {
imageData: canvas.toDataURL(),
width: canvas.width,
height: canvas.height
};
undoStack.push(currentState); // Save current state to the undo stack
const nextState = redoStack.pop(); // Get the last state from the redo stack
canvas.width = nextState.width;
canvas.height = nextState.height;
canvas.style.width = canvas.width * zoom + 'px';
canvas.style.height = canvas.height * zoom + 'px';
canvasWidth = canvas.width;
canvasHeight = canvas.height;
const img = new Image();
img.src = nextState.imageData;
img.onload = function() {
ctx.clearRect(0, 0, canvas.width, canvas.height);
ctx.drawImage(img, 0, 0);
};
}
}
function onMouseMove(e) { function getPositionOnCanvas(e) {
if (isMixing) { const rect = canvas.getBoundingClientRect();
const distance = Math.sqrt(Math.pow(e.clientX - startX, 2) + Math.pow(e.clientY - startY, 2)); return {
x: Math.round((e.clientX - rect.left) / zoom),
y: Math.round((e.clientY - rect.top) / zoom),
};
}
function drawCircle(x, y) {
ctx.beginPath();
ctx.arc(x, y, brushSize / 2, 0, 2 * Math.PI, false);
ctx.fillStyle = color;
ctx.fill();
}
function drawLineWithCircles(x1, y1, x2, y2) {
const dx = x2 - x1;
const dy = y2 - y1;
const distance = Math.sqrt(dx * dx + dy * dy);
const steps = Math.ceil(distance / (brushSize / 5));
for (let i = 0; i <= steps; i++) {
const x = x1 + (dx * i) / steps;
const y = y1 + (dy * i) / steps;
drawCircle(x, y);
}
}
const t = Math.min(1, distance / 300); function saveCanvasContents() {
tempCanvas = document.createElement('canvas');
tempCanvas.width = canvas.width;
tempCanvas.height = canvas.height;
const tempCtx = tempCanvas.getContext('2d');
tempCtx.drawImage(canvas, 0, 0);
}
const mixedColor = mixbox.lerp(color, well.style.backgroundColor, t); function updateColorPreview() {
colorPreview.style.backgroundColor = color;
}
color = mixedColor; function hexToRgbArray(hex) {
if (hex.startsWith('#')) {
hex = hex.slice(1);
}
startX = e.clientX; if (hex.length === 3) {
startY = e.clientY; hex = hex.split('').map(char => char + char).join('');
}
const bigint = parseInt(hex, 16);
return [(bigint >> 16) & 255, (bigint >> 8) & 255, bigint & 255];
}
function floodFill(x, y, fillColor) {
const imageData = ctx.getImageData(0, 0, canvas.width, canvas.height);
const data = imageData.data;
const targetColor = getColorAtPixel(data, x, y);
const fillColorArray = hexToRgbArray(fillColor);
if (colorsMatch(targetColor, fillColorArray)) {
return; // The clicked point is already the fill color
}
const stack = [{x, y}];
while (stack.length > 0) {
const {x, y} = stack.pop();
const currentColor = getColorAtPixel(data, x, y);
if (colorsMatch(currentColor, targetColor)) {
setColorAtPixel(data, x, y, fillColorArray);
if (x > 0) stack.push({x: x - 1, y});
if (x < canvas.width - 1) stack.push({x: x + 1, y});
if (y > 0) stack.push({x, y: y - 1});
if (y < canvas.height - 1) stack.push({x, y: y + 1});
}
}
ctx.putImageData(imageData, 0, 0);
}
function getColorAtPixel(data, x, y) {
const index = (y * canvas.width + x) * 4;
return [data[index], data[index + 1], data[index + 2], data[index + 3]];
}
function setColorAtPixel(data, x, y, color) {
const index = (y * canvas.width + x) * 4;
data[index] = color[0];
data[index + 1] = color[1];
data[index + 2] = color[2];
data[index + 3] = 255; // Set alpha to fully opaque
}
function colorsMatch(a, b) {
return a[0] === b[0] && a[1] === b[1] && a[2] === b[2] && a[3] === b[3];
}
// }}}
// mousedown {{{
canvasArea.addEventListener('mousedown', (e) => {
if (e.target.closest('.puck')) return;
startX = e.clientX;
startY = e.clientY;
canvasStartX = getPositionOnCanvas(e).x;
canvasStartY = getPositionOnCanvas(e).y;
saveCanvasContents();
isMouseDown = true;
if (
tool === 'brush' ||
tool === 'content-move' ||
tool === 'resize' ||
tool === 'zoom' ||
tool === 'bucket-fill'
) {
saveState();
}
if (tool === 'brush') {
console.log('brush');
drawCircle(canvasStartX, canvasStartY);
} else if (tool === 'bucket-fill') {
floodFill(canvasStartX, canvasStartY, color);
return;
} else if (tool === 'move') {
startX = e.clientX - canvasContainer.offsetLeft;
startY = e.clientY - canvasContainer.offsetTop;
} else if (tool === 'color-picker') {
const imageData = ctx.getImageData(canvasStartX, canvasStartY, 1, 1).data;
const pickedColor = `rgb(${imageData[0]}, ${imageData[1]}, ${imageData[2]})`;
color = pickedColor;
console.log('Picked Color:', pickedColor);
updateColorPreview();
return;
}
});
// }}}
// mousemove {{{
canvasArea.addEventListener('mousemove', (e) => {
endX = e.clientX;
endY = e.clientY;
dX = endX - startX;
dY = endY - startY;
canvasEndX = getPositionOnCanvas(e).x;
canvasEndY = getPositionOnCanvas(e).y;
canvasDX = canvasEndX - canvasStartX;
canvasDY = canvasEndY - canvasStartY;
if (tool == 'brush-size') {
brushPreview.style.display = 'block';
brushPreview.style.width = brushSize + 'px';
brushPreview.style.height = brushSize + 'px';
brushPreview.style.left = e.clientX - brushSize / 2 + 'px';
brushPreview.style.top = e.clientY - brushSize / 2 + 'px';
}
if (isMouseDown) {
if (tool === 'brush-size') {
brushSize += dX * dBrushSize;
if (brushSize < 1) brushSize = 1;
if (brushSize > maxBrushSize) brushSize = maxBrushSize;
startX = endX;
} else if (tool === 'brush') {
drawLineWithCircles(canvasStartX, canvasStartY, canvasEndX, canvasEndY);
canvasStartX = canvasEndX;
canvasStartY = canvasEndY;
} else if (tool === 'content-move') {
ctx.clearRect(0, 0, canvas.width, canvas.height);
ctx.fillStyle = backgroundColor;
ctx.fillRect(0, 0, canvas.width, canvas.height);
ctx.drawImage(tempCanvas, dX, dY);
} else if (tool === 'move') {
canvasContainer.style.left = dX + 'px';
canvasContainer.style.top = dY + 'px';
} else if (tool === 'zoom') {
zoom += dX * dZoom;
if (zoom < 0.1) zoom = 0.1;
canvas.style.height = canvasHeight * zoom + 'px';
canvas.style.width = canvasWidth * zoom + 'px';
startX = endX;
} else if (tool === 'resize') {
let newWidth = canvasWidth + dX / zoom;
let newHeight = canvasHeight + dY / zoom;
if (newWidth > 0 && newHeight > 0) {
canvas.width = newWidth;
canvas.height = newHeight;
canvas.style.width = newWidth * zoom + 'px';
canvas.style.height = newHeight * zoom + 'px';
ctx.clearRect(0, 0, canvas.width, canvas.height);
ctx.fillStyle = backgroundColor;
ctx.fillRect(0, 0, canvas.width, canvas.height);
ctx.drawImage(tempCanvas, 0, 0);
} }
} } else if (tool === 'color-mix') {
function onMouseUp() { const imageData = ctx.getImageData(canvasEndX, canvasEndY, 1, 1).data;
isMixing = false; const canvasColor = `rgb(${imageData[0]}, ${imageData[1]}, ${imageData[2]})`;
document.removeEventListener('mousemove', onMouseMove);
document.removeEventListener('mouseup', onMouseUp); const distance = Math.sqrt(Math.pow(e.clientX - startX, 2) + Math.pow(e.clientY - startY, 2));
const t = Math.min(1, distance / 300);
const mixedColor = mixbox.lerp(color, canvasColor, t);
color = mixedColor;
startX = e.clientX;
startY = e.clientY;
}
}
updateInfos();
updateColorPreview();
});
// }}}
// mouseup {{{
canvasArea.addEventListener('mouseup', (e) => {
isMouseDown = false;
if (tool === 'brush') {
ctx.closePath();
} else if (tool === 'resize') {
canvasWidth = canvas.width;
canvasHeight = canvas.height;
}
updateColorPreview();
});
// }}}
// mouseleave {{{
canvasArea.addEventListener('mouseleave', (e) => {
isMouseDown = false;
brushPreview.style.display = 'none';
});
// }}}
// keybindings {{{
const toolKeyBindings = {}
const functionKeyBindings = {
}
document.addEventListener('keydown', (e) => {
if (keyDown) return;
const newTool = toolKeyBindings[e.key.toLowerCase()]
if (newTool) {
prevTool = tool;
keyDown = true;
changeTool(newTool);
return;
}
const func = functionKeyBindings[e.key];
if (func) {
func();
return;
}
});
document.addEventListener('keyup', (e) => {
const currentTool = toolKeyBindings[e.key.toLowerCase()]
if (currentTool) {
keyDown = false;
if (e.key == e.key.toLowerCase()) {
changeTool(prevTool);
return;
} }
}
});
// }}}
// tools {{{
var toolButtons = [];
function changeTool(toolName) {
toolButtons.forEach(button => button.button.classList.remove('active'));
toolButtons.find(button => button.name === toolName).button.classList.add('active');
tool = toolName;
brushPreview.style.display = 'none';
updateInfos();
}
function createToolButton(toolName, displayName, icon, key=undefined) {
const button = document.createElement('div');
button.classList.add('button');
button.classList.add('tool');
button.innerHTML = icon;
button.title = displayName;
button.addEventListener('click', () => {
changeTool(toolName);
}); });
dragHandle.addEventListener('mousedown', (e) => { if (key) {
let isMovingPuck = true; const keyHint = document.createElement('span');
let startX = e.clientX; keyHint.className = 'key-hint';
let startY = e.clientY; keyHint.innerHTML = key;
let left = puck.offsetLeft; button.appendChild(keyHint);
let top = puck.offsetTop; toolKeyBindings[key] = toolName;
document.addEventListener('mousemove', (e) => { }
if (isMovingPuck) {
puck.style.left = left + e.clientX - startX + 'px'; toolBar.appendChild(button);
puck.style.top = top + e.clientY - startY + 'px'; toolButtons.push({'name': toolName, 'button': button});
return button;
}
createToolButton('brush', 'Brush', '<i class="fa-solid fa-paintbrush"></i>', 'b');
createToolButton('content-move', 'Move Content', '<i class="fa-regular fa-hand"></i>', 'h');
createToolButton('move', 'Move Canvas', '<i class="fa-solid fa-arrows-up-down-left-right"></i>', 'm');
createToolButton('zoom', 'Zoom', '<i class="fa-solid fa-magnifying-glass"></i>', 'z');
createToolButton('resize', 'Resize', '<i class="fa-solid fa-ruler-combined"></i>', 'r');
createToolButton('color-picker', 'Color Picker', '<i class="fa-solid fa-eye-dropper"></i>', 'a');
createToolButton('color-mix', 'Color Mix', '<i class="fa-solid fa-mortar-pestle"></i>', 'x');
createToolButton('brush-size', 'Brush Size', '<i class="fa-regular fa-circle-dot"></i>', 'd');
createToolButton('bucket-fill', 'Bucket Fill', '<i class="fa-solid fa-fill"></i>', 'k');
// }}}
// menu functons {{{
function flipCanvasHorizontally(e) {
saveState();
ctx.save();
saveCanvasContents();
ctx.clearRect(0, 0, canvas.width, canvas.height);
ctx.scale(-1, 1);
ctx.translate(-canvas.width, 0);
ctx.drawImage(tempCanvas, 0, 0);
ctx.restore();
}
function flipCanvasVertically(e) {
saveState();
ctx.save();
saveCanvasContents();
ctx.clearRect(0, 0, canvas.width, canvas.height);
ctx.scale(1, -1);
ctx.translate(0, -canvas.height);
ctx.drawImage(tempCanvas, 0, 0);
ctx.restore();
}
function exportCanvas(e) {
const link = document.createElement('a');
link.download = 'canvas.png';
link.href = canvas.toDataURL();
link.click();
}
function importCanvas(e) {
const input = document.createElement('input');
input.type = 'file';
input.accept = 'image/*';
input.onchange = (e) => {
const file = e.target.files[0];
const reader = new FileReader();
reader.onload = (e) => {
const img = new Image();
img.onload = () => {
canvas.width = img.width;
canvas.height = img.height;
ctx.drawImage(img, 0, 0);
} }
img.src = e.target.result;
}
reader.readAsDataURL(file);
}
input.click();
}
function clearCanvas(e) {
saveState();
ctx.clearRect(0, 0, canvas.width, canvas.height);
ctx.fillStyle = backgroundColor;
ctx.fillRect(0, 0, canvas.width, canvas.height);
}
function resetZoom(e) {
zoom = 1;
canvas.style.width = canvas.width * zoom + 'px';
canvas.style.height = canvas.height * zoom + 'px';
canvasWidth = canvas.width;
canvasHeight = canvas.height;
canvasAreaRect = canvasArea.getBoundingClientRect();
canvasContainer.style.left = `${canvasAreaRect.left}px`;
canvasContainer.style.top = `${canvasAreaRect.top}px`;
}
// }}}
// menu {{{
var menuButtons = [];
function createMenuButton(icon, name, clickFunction, key=undefined) {
const button = document.createElement('div');
button.className = 'button';
button.innerHTML = icon;
button.title = name;
if (clickFunction) {
button.addEventListener('click', () => {
clickFunction()
updateInfos();
}); });
document.addEventListener('mouseup', () => { }
isMovingPuck = false; menuBar.appendChild(button);
document.removeEventListener('mousemove', () => {}); if (key) {
document.removeEventListener('mouseup', () => {}); const keyHint = document.createElement('span');
keyHint.className = 'key-hint';
keyHint.innerHTML = key;
button.appendChild(keyHint);
functionKeyBindings[key] = clickFunction;
}
return button;
}
menuButtons.push(createMenuButton('<i class="fa-solid fa-download"></i>', 'Save', saveCanvas, 's'));
menuButtons.push(createMenuButton('<i class="fa-solid fa-upload"></i>', 'Load', loadCanvas));
menuButtons.push(createMenuButton('<i class="fa-solid fa-trash-can"></i>', 'Clear', clearCanvas));
menuButtons.push(createMenuButton('<i class="fa-solid fa-floppy-disk"></i>', 'Export', exportCanvas));
menuButtons.push(createMenuButton('<i class="fa-regular fa-folder-open"></i>', 'Import', importCanvas));
menuButtons.push(createMenuButton('<i class="fa-solid fa-left-right"></i>', 'Flip Horizontally', flipCanvasHorizontally, 'f'));
menuButtons.push(createMenuButton('<i class="fa-solid fa-up-down"></i>', 'Flip Vertically', flipCanvasVertically, 'v'));
menuButtons.push(createMenuButton('<i class="fa-solid fa-undo"></i>', 'Undo', undo, 'u'));
menuButtons.push(createMenuButton('<i class="fa-solid fa-redo"></i>', 'Redo', redo, 'y'));
menuButtons.push(createMenuButton('<i class="fa-solid fa-pump-soap"></i>', 'Clear', clearCanvas, 'c'));
menuButtons.push(createMenuButton('<i class="fa-solid fa-house"></i>', 'Reset', resetZoom, 't'));
menuButtons.push(createMenuButton('<i class="fa-solid fa-plus"></i>', 'Add Color', createPuck));
// }}}
// pucks {{{
function createPuck(c, editable=true, key=undefined) {
if (c === undefined) {
c = color;
}
const puck = document.createElement('div');
puck.className = 'puck';
puck.style.backgroundColor = c;
// const selectHandle = document.createElement('div');
// selectHandle.className = 'select-handle';
// selectHandle.innerHTML = '<i class="fa-solid fa-droplet"></i>';
// puck.appendChild(selectHandle);
// selectHandle.addEventListener('click', () => {
// color = puck.style.backgroundColor;
// updateColorPreview();
// updateInfos();
// });
if (editable) {
// const updateHandle = document.createElement('div');
// updateHandle.className = 'update-handle';
// updateHandle.innerHTML = '<i class="fa-solid fa-fill"></i>';
// puck.appendChild(updateHandle);
// updateHandle.addEventListener('click', () => {
// puck.style.backgroundColor = color;
// });
const deleteHandle = document.createElement('div');
deleteHandle.className = 'delete-handle';
deleteHandle.innerHTML = '<i class="fa-solid fa-trash-can"></i>';
puck.appendChild(deleteHandle);
deleteHandle.addEventListener('click', () => {
console.log("test");
puck.remove();
}); });
}); }
updateHandle.addEventListener('click', () => { if (key) {
console.log('update'); const keyHint = document.createElement('div');
well.style.backgroundColor = color; keyHint.className = 'key-hint';
}); keyHint.innerHTML = key;
puck.appendChild(keyHint);
}
selectHandle.addEventListener('click', () => { function mixx(startTime) {
console.log('select'); var interval = setInterval(() => {
color = well.style.backgroundColor; const elapsedTime = Date.now() - startTime;
console.log(color); const t = Math.min(1, elapsedTime / 10000);
updateColorPreview(); const mixedColor = mixbox.lerp(color, puck.style.backgroundColor, t);
}); color = mixedColor;
updateColorPreview();
updateInfos();
}, 50);
return interval;
}
copyHandle.addEventListener('click', () => { puck.addEventListener('mousedown', (e) => {
pucks.push(createPuck(well.style.backgroundColor)); const startTime = Date.now();
var interval = mixx(startTime);
function onMouseUp() {
clearInterval(interval);
document.removeEventListener('mouseup', onMouseUp);
}
document.addEventListener('mouseup', onMouseUp);
}); });
deleteHandle.addEventListener('click', () => { document.addEventListener('keydown', (e) => {
pucks = pucks.filter(p => p !== puck); if (e.key == key) {
puck.remove(); console.log(e.key);
const startTime = Date.now();
var interval = mixx(startTime);
function onKeyUp() {
clearInterval(interval);
document.removeEventListener('keyup', onKeyUp);
}
document.addEventListener('keyup', onKeyUp);
}
}); });
menuBar.appendChild(puck);
}
createPuck(c='rgb(0, 0, 0)', editable=false, key='1');
createPuck(c='rgb(255, 0, 0)', editale=false, key='2');
createPuck(c='rgb(0, 0, 255)', editale=false, key='3');
createPuck(c='rgb(255, 255, 0)', editale=false, key='4');
createPuck(c='rgb(99, 60, 22)', editale=false, key='5');
createPuck(c='rgb(0, 255, 0)', editale=false, key='6');
createPuck(c='rgb(255, 0, 255)', editale=false, key='7');
createPuck(c='rgb(0, 255, 255)', editale=false, key='8');
createPuck(c='rgb(255, 255, 255)', editale=false, key='9');
canvasArea.appendChild(puck);
let canvasWidth = canvasArea.offsetWidth; // }}}
let canvasHeight = canvasArea.offsetHeight;
let randonX = Math.floor(Math.random() * canvasWidth); // info {{{
let randonY = Math.floor(Math.random() * canvasHeight);
puck.style.left = randonX + 'px'; var infos = [];
puck.style.top = randonY + 'px';
return puck; function createInfo(name, updateFunction) {
const info = document.createElement('span');
info.className = 'info';
const key = document.createElement('span');
key.className = 'key';
key.innerHTML = name + ':';
const value = document.createElement('span');
value.className = 'value';
value.innerHTML = '0';
info.appendChild(key);
info.appendChild(value);
infoBar.appendChild(info);
function update() {
let v = updateFunction();
if (v === undefined) v = '?';
value.innerHTML = v;
}
return update;
} }
infos.push(createInfo('zoom', function() {
var percent = zoom * 100;
return percent.toFixed(0) + '%';
}));
infos.push(createInfo('brush', function() { return brushSize; }));
infos.push(createInfo('x', function() { return canvasEndX; }));
infos.push(createInfo('y', function() { return canvasEndY; }));
infos.push(createInfo('color', function() { return color; }));
infos.push(createInfo('width', function() { return canvas.width; }));
infos.push(createInfo('height', function() { return canvas.height; }));
function updateInfos() {
infos.forEach(info => info());
}
// }}}
// start {{{
ctx.fillStyle = backgroundColor;
ctx.fillRect(0, 0, canvas.width, canvas.height);
updateInfos();
toolButtons[0]['button'].click();
// }}}

0
temp2.js → archive/temp2.js

682
render.js

File diff suppressed because it is too large

724
temp.js

@ -1,724 +0,0 @@
const colorPreview = document.createElement('div');
colorPreview.id = 'color-preview';
colorPreview.className = 'puck';
colorPreview.style.backgroundColor = color;
menuBar.appendChild(colorPreview);
// }}}
// helpers {{{
function saveCanvas() {
const dataURL = canvas.toDataURL();
const dimensions = `${canvas.width}x${canvas.height}`;
localStorage.setItem('mixxCanvas', dataURL);
localStorage.setItem('mixxDimensions', dimensions);
console.log('Canvas saved');
}
function loadCanvas() {
const dataURL = localStorage.getItem('mixxCanvas');
const dimensions = localStorage.getItem('mixxDimensions');
if (dataURL && dimensions) {
const img = new Image();
img.src = dataURL;
img.onload = function() {
canvas.width = dimensions.split('x')[0];
canvas.height = dimensions.split('x')[1];
canvas.style.width = canvas.width * zoom + 'px';
canvas.style.height = canvas.height * zoom + 'px';
canvasWidth = canvas.width;
canvasHeight = canvas.height;
ctx.drawImage(img, 0, 0);
}
} else {
console.log('No saved canvas found');
}
}
function clearCanvasFromLocalStorage() {
localStorage.removeItem('savedCanvas');
localStorage.removeItem('canvasDimensions');
}
function saveState() {
if (undoStack.length >= maxHistory) {
undoStack.shift(); // Remove the oldest state if the stack exceeds the limit
}
undoStack.push({
imageData: canvas.toDataURL(),
width: canvas.width,
height: canvas.height
});
redoStack = []; // Clear the redo stack whenever a new action is performed
}
function undo() {
if (undoStack.length > 0) {
const currentState = {
imageData: canvas.toDataURL(),
width: canvas.width,
height: canvas.height
};
redoStack.push(currentState); // Save current state to the redo stack
const lastState = undoStack.pop(); // Get the last state from the undo stack
canvas.width = lastState.width;
canvas.height = lastState.height;
canvas.style.width = canvas.width * zoom + 'px';
canvas.style.height = canvas.height * zoom + 'px';
canvasWidth = canvas.width;
canvasHeight = canvas.height;
const img = new Image();
img.src = lastState.imageData;
img.onload = function() {
ctx.clearRect(0, 0, canvas.width, canvas.height);
ctx.drawImage(img, 0, 0);
};
}
}
function redo() {
if (redoStack.length > 0) {
const currentState = {
imageData: canvas.toDataURL(),
width: canvas.width,
height: canvas.height
};
undoStack.push(currentState); // Save current state to the undo stack
const nextState = redoStack.pop(); // Get the last state from the redo stack
canvas.width = nextState.width;
canvas.height = nextState.height;
canvas.style.width = canvas.width * zoom + 'px';
canvas.style.height = canvas.height * zoom + 'px';
canvasWidth = canvas.width;
canvasHeight = canvas.height;
const img = new Image();
img.src = nextState.imageData;
img.onload = function() {
ctx.clearRect(0, 0, canvas.width, canvas.height);
ctx.drawImage(img, 0, 0);
};
}
}
function getPositionOnCanvas(e) {
const rect = canvas.getBoundingClientRect();
return {
x: Math.round((e.clientX - rect.left) / zoom),
y: Math.round((e.clientY - rect.top) / zoom),
};
}
function drawCircle(x, y) {
ctx.beginPath();
ctx.arc(x, y, brushSize / 2, 0, 2 * Math.PI, false);
ctx.fillStyle = color;
ctx.fill();
}
function drawLineWithCircles(x1, y1, x2, y2) {
const dx = x2 - x1;
const dy = y2 - y1;
const distance = Math.sqrt(dx * dx + dy * dy);
const steps = Math.ceil(distance / (brushSize / 5));
for (let i = 0; i <= steps; i++) {
const x = x1 + (dx * i) / steps;
const y = y1 + (dy * i) / steps;
drawCircle(x, y);
}
}
function saveCanvasContents() {
tempCanvas = document.createElement('canvas');
tempCanvas.width = canvas.width;
tempCanvas.height = canvas.height;
const tempCtx = tempCanvas.getContext('2d');
tempCtx.drawImage(canvas, 0, 0);
}
function updateColorPreview() {
colorPreview.style.backgroundColor = color;
}
function hexToRgbArray(hex) {
if (hex.startsWith('#')) {
hex = hex.slice(1);
}
if (hex.length === 3) {
hex = hex.split('').map(char => char + char).join('');
}
const bigint = parseInt(hex, 16);
return [(bigint >> 16) & 255, (bigint >> 8) & 255, bigint & 255];
}
function floodFill(x, y, fillColor) {
const imageData = ctx.getImageData(0, 0, canvas.width, canvas.height);
const data = imageData.data;
const targetColor = getColorAtPixel(data, x, y);
const fillColorArray = hexToRgbArray(fillColor);
if (colorsMatch(targetColor, fillColorArray)) {
return; // The clicked point is already the fill color
}
const stack = [{x, y}];
while (stack.length > 0) {
const {x, y} = stack.pop();
const currentColor = getColorAtPixel(data, x, y);
if (colorsMatch(currentColor, targetColor)) {
setColorAtPixel(data, x, y, fillColorArray);
if (x > 0) stack.push({x: x - 1, y});
if (x < canvas.width - 1) stack.push({x: x + 1, y});
if (y > 0) stack.push({x, y: y - 1});
if (y < canvas.height - 1) stack.push({x, y: y + 1});
}
}
ctx.putImageData(imageData, 0, 0);
}
function getColorAtPixel(data, x, y) {
const index = (y * canvas.width + x) * 4;
return [data[index], data[index + 1], data[index + 2], data[index + 3]];
}
function setColorAtPixel(data, x, y, color) {
const index = (y * canvas.width + x) * 4;
data[index] = color[0];
data[index + 1] = color[1];
data[index + 2] = color[2];
data[index + 3] = 255; // Set alpha to fully opaque
}
function colorsMatch(a, b) {
return a[0] === b[0] && a[1] === b[1] && a[2] === b[2] && a[3] === b[3];
}
// }}}
// mousedown {{{
canvasArea.addEventListener('mousedown', (e) => {
if (e.target.closest('.puck')) return;
startX = e.clientX;
startY = e.clientY;
canvasStartX = getPositionOnCanvas(e).x;
canvasStartY = getPositionOnCanvas(e).y;
saveCanvasContents();
isMouseDown = true;
if (
tool === 'brush' ||
tool === 'content-move' ||
tool === 'resize' ||
tool === 'zoom' ||
tool === 'bucket-fill'
) {
saveState();
}
if (tool === 'brush') {
console.log('brush');
drawCircle(canvasStartX, canvasStartY);
} else if (tool === 'bucket-fill') {
floodFill(canvasStartX, canvasStartY, color);
return;
} else if (tool === 'move') {
startX = e.clientX - canvasContainer.offsetLeft;
startY = e.clientY - canvasContainer.offsetTop;
} else if (tool === 'color-picker') {
const imageData = ctx.getImageData(canvasStartX, canvasStartY, 1, 1).data;
const pickedColor = `rgb(${imageData[0]}, ${imageData[1]}, ${imageData[2]})`;
color = pickedColor;
console.log('Picked Color:', pickedColor);
updateColorPreview();
return;
}
});
// }}}
// mousemove {{{
canvasArea.addEventListener('mousemove', (e) => {
endX = e.clientX;
endY = e.clientY;
dX = endX - startX;
dY = endY - startY;
canvasEndX = getPositionOnCanvas(e).x;
canvasEndY = getPositionOnCanvas(e).y;
canvasDX = canvasEndX - canvasStartX;
canvasDY = canvasEndY - canvasStartY;
if (tool == 'brush-size') {
brushPreview.style.display = 'block';
brushPreview.style.width = brushSize + 'px';
brushPreview.style.height = brushSize + 'px';
brushPreview.style.left = e.clientX - brushSize / 2 + 'px';
brushPreview.style.top = e.clientY - brushSize / 2 + 'px';
}
if (isMouseDown) {
if (tool === 'brush-size') {
brushSize += dX * dBrushSize;
if (brushSize < 1) brushSize = 1;
if (brushSize > maxBrushSize) brushSize = maxBrushSize;
startX = endX;
} else if (tool === 'brush') {
drawLineWithCircles(canvasStartX, canvasStartY, canvasEndX, canvasEndY);
canvasStartX = canvasEndX;
canvasStartY = canvasEndY;
} else if (tool === 'content-move') {
ctx.clearRect(0, 0, canvas.width, canvas.height);
ctx.fillStyle = backgroundColor;
ctx.fillRect(0, 0, canvas.width, canvas.height);
ctx.drawImage(tempCanvas, dX, dY);
} else if (tool === 'move') {
canvasContainer.style.left = dX + 'px';
canvasContainer.style.top = dY + 'px';
} else if (tool === 'zoom') {
zoom += dX * dZoom;
if (zoom < 0.1) zoom = 0.1;
canvas.style.height = canvasHeight * zoom + 'px';
canvas.style.width = canvasWidth * zoom + 'px';
startX = endX;
} else if (tool === 'resize') {
let newWidth = canvasWidth + dX / zoom;
let newHeight = canvasHeight + dY / zoom;
if (newWidth > 0 && newHeight > 0) {
canvas.width = newWidth;
canvas.height = newHeight;
canvas.style.width = newWidth * zoom + 'px';
canvas.style.height = newHeight * zoom + 'px';
ctx.clearRect(0, 0, canvas.width, canvas.height);
ctx.fillStyle = backgroundColor;
ctx.fillRect(0, 0, canvas.width, canvas.height);
ctx.drawImage(tempCanvas, 0, 0);
}
} else if (tool === 'color-mix') {
const imageData = ctx.getImageData(canvasEndX, canvasEndY, 1, 1).data;
const canvasColor = `rgb(${imageData[0]}, ${imageData[1]}, ${imageData[2]})`;
const distance = Math.sqrt(Math.pow(e.clientX - startX, 2) + Math.pow(e.clientY - startY, 2));
const t = Math.min(1, distance / 300);
const mixedColor = mixbox.lerp(color, canvasColor, t);
color = mixedColor;
startX = e.clientX;
startY = e.clientY;
}
}
updateInfos();
updateColorPreview();
});
// }}}
// mouseup {{{
canvasArea.addEventListener('mouseup', (e) => {
isMouseDown = false;
if (tool === 'brush') {
ctx.closePath();
} else if (tool === 'resize') {
canvasWidth = canvas.width;
canvasHeight = canvas.height;
}
updateColorPreview();
});
// }}}
// mouseleave {{{
canvasArea.addEventListener('mouseleave', (e) => {
isMouseDown = false;
brushPreview.style.display = 'none';
});
// }}}
// keybindings {{{
const toolKeyBindings = {}
const functionKeyBindings = {
}
document.addEventListener('keydown', (e) => {
if (keyDown) return;
const newTool = toolKeyBindings[e.key.toLowerCase()]
if (newTool) {
prevTool = tool;
keyDown = true;
changeTool(newTool);
return;
}
const func = functionKeyBindings[e.key];
if (func) {
func();
return;
}
});
document.addEventListener('keyup', (e) => {
const currentTool = toolKeyBindings[e.key.toLowerCase()]
if (currentTool) {
keyDown = false;
if (e.key == e.key.toLowerCase()) {
changeTool(prevTool);
return;
}
}
});
// }}}
// tools {{{
var toolButtons = [];
function changeTool(toolName) {
toolButtons.forEach(button => button.button.classList.remove('active'));
toolButtons.find(button => button.name === toolName).button.classList.add('active');
tool = toolName;
brushPreview.style.display = 'none';
updateInfos();
}
function createToolButton(toolName, displayName, icon, key=undefined) {
const button = document.createElement('div');
button.classList.add('button');
button.classList.add('tool');
button.innerHTML = icon;
button.title = displayName;
button.addEventListener('click', () => {
changeTool(toolName);
});
if (key) {
const keyHint = document.createElement('span');
keyHint.className = 'key-hint';
keyHint.innerHTML = key;
button.appendChild(keyHint);
toolKeyBindings[key] = toolName;
}
toolBar.appendChild(button);
toolButtons.push({'name': toolName, 'button': button});
return button;
}
createToolButton('brush', 'Brush', '<i class="fa-solid fa-paintbrush"></i>', 'b');
createToolButton('content-move', 'Move Content', '<i class="fa-regular fa-hand"></i>', 'h');
createToolButton('move', 'Move Canvas', '<i class="fa-solid fa-arrows-up-down-left-right"></i>', 'm');
createToolButton('zoom', 'Zoom', '<i class="fa-solid fa-magnifying-glass"></i>', 'z');
createToolButton('resize', 'Resize', '<i class="fa-solid fa-ruler-combined"></i>', 'r');
createToolButton('color-picker', 'Color Picker', '<i class="fa-solid fa-eye-dropper"></i>', 'a');
createToolButton('color-mix', 'Color Mix', '<i class="fa-solid fa-mortar-pestle"></i>', 'x');
createToolButton('brush-size', 'Brush Size', '<i class="fa-regular fa-circle-dot"></i>', 'd');
createToolButton('bucket-fill', 'Bucket Fill', '<i class="fa-solid fa-fill"></i>', 'k');
// }}}
// menu functons {{{
function flipCanvasHorizontally(e) {
saveState();
ctx.save();
saveCanvasContents();
ctx.clearRect(0, 0, canvas.width, canvas.height);
ctx.scale(-1, 1);
ctx.translate(-canvas.width, 0);
ctx.drawImage(tempCanvas, 0, 0);
ctx.restore();
}
function flipCanvasVertically(e) {
saveState();
ctx.save();
saveCanvasContents();
ctx.clearRect(0, 0, canvas.width, canvas.height);
ctx.scale(1, -1);
ctx.translate(0, -canvas.height);
ctx.drawImage(tempCanvas, 0, 0);
ctx.restore();
}
function exportCanvas(e) {
const link = document.createElement('a');
link.download = 'canvas.png';
link.href = canvas.toDataURL();
link.click();
}
function importCanvas(e) {
const input = document.createElement('input');
input.type = 'file';
input.accept = 'image/*';
input.onchange = (e) => {
const file = e.target.files[0];
const reader = new FileReader();
reader.onload = (e) => {
const img = new Image();
img.onload = () => {
canvas.width = img.width;
canvas.height = img.height;
ctx.drawImage(img, 0, 0);
}
img.src = e.target.result;
}
reader.readAsDataURL(file);
}
input.click();
}
function clearCanvas(e) {
saveState();
ctx.clearRect(0, 0, canvas.width, canvas.height);
ctx.fillStyle = backgroundColor;
ctx.fillRect(0, 0, canvas.width, canvas.height);
}
function resetZoom(e) {
zoom = 1;
canvas.style.width = canvas.width * zoom + 'px';
canvas.style.height = canvas.height * zoom + 'px';
canvasWidth = canvas.width;
canvasHeight = canvas.height;
canvasAreaRect = canvasArea.getBoundingClientRect();
canvasContainer.style.left = `${canvasAreaRect.left}px`;
canvasContainer.style.top = `${canvasAreaRect.top}px`;
}
// }}}
// menu {{{
var menuButtons = [];
function createMenuButton(icon, name, clickFunction, key=undefined) {
const button = document.createElement('div');
button.className = 'button';
button.innerHTML = icon;
button.title = name;
if (clickFunction) {
button.addEventListener('click', () => {
clickFunction()
updateInfos();
});
}
menuBar.appendChild(button);
if (key) {
const keyHint = document.createElement('span');
keyHint.className = 'key-hint';
keyHint.innerHTML = key;
button.appendChild(keyHint);
functionKeyBindings[key] = clickFunction;
}
return button;
}
menuButtons.push(createMenuButton('<i class="fa-solid fa-download"></i>', 'Save', saveCanvas, 's'));
menuButtons.push(createMenuButton('<i class="fa-solid fa-upload"></i>', 'Load', loadCanvas));
menuButtons.push(createMenuButton('<i class="fa-solid fa-trash-can"></i>', 'Clear', clearCanvas));
menuButtons.push(createMenuButton('<i class="fa-solid fa-floppy-disk"></i>', 'Export', exportCanvas));
menuButtons.push(createMenuButton('<i class="fa-regular fa-folder-open"></i>', 'Import', importCanvas));
menuButtons.push(createMenuButton('<i class="fa-solid fa-left-right"></i>', 'Flip Horizontally', flipCanvasHorizontally, 'f'));
menuButtons.push(createMenuButton('<i class="fa-solid fa-up-down"></i>', 'Flip Vertically', flipCanvasVertically, 'v'));
menuButtons.push(createMenuButton('<i class="fa-solid fa-undo"></i>', 'Undo', undo, 'u'));
menuButtons.push(createMenuButton('<i class="fa-solid fa-redo"></i>', 'Redo', redo, 'y'));
menuButtons.push(createMenuButton('<i class="fa-solid fa-pump-soap"></i>', 'Clear', clearCanvas, 'c'));
menuButtons.push(createMenuButton('<i class="fa-solid fa-house"></i>', 'Reset', resetZoom, 't'));
menuButtons.push(createMenuButton('<i class="fa-solid fa-plus"></i>', 'Add Color', createPuck));
// }}}
// pucks {{{
function createPuck(c, editable=true, key=undefined) {
if (c === undefined) {
c = color;
}
const puck = document.createElement('div');
puck.className = 'puck';
puck.style.backgroundColor = c;
// const selectHandle = document.createElement('div');
// selectHandle.className = 'select-handle';
// selectHandle.innerHTML = '<i class="fa-solid fa-droplet"></i>';
// puck.appendChild(selectHandle);
// selectHandle.addEventListener('click', () => {
// color = puck.style.backgroundColor;
// updateColorPreview();
// updateInfos();
// });
if (editable) {
// const updateHandle = document.createElement('div');
// updateHandle.className = 'update-handle';
// updateHandle.innerHTML = '<i class="fa-solid fa-fill"></i>';
// puck.appendChild(updateHandle);
// updateHandle.addEventListener('click', () => {
// puck.style.backgroundColor = color;
// });
const deleteHandle = document.createElement('div');
deleteHandle.className = 'delete-handle';
deleteHandle.innerHTML = '<i class="fa-solid fa-trash-can"></i>';
puck.appendChild(deleteHandle);
deleteHandle.addEventListener('click', () => {
console.log("test");
puck.remove();
});
}
if (key) {
const keyHint = document.createElement('div');
keyHint.className = 'key-hint';
keyHint.innerHTML = key;
puck.appendChild(keyHint);
}
function mixx(startTime) {
var interval = setInterval(() => {
const elapsedTime = Date.now() - startTime;
const t = Math.min(1, elapsedTime / 10000);
const mixedColor = mixbox.lerp(color, puck.style.backgroundColor, t);
color = mixedColor;
updateColorPreview();
updateInfos();
}, 50);
return interval;
}
puck.addEventListener('mousedown', (e) => {
const startTime = Date.now();
var interval = mixx(startTime);
function onMouseUp() {
clearInterval(interval);
document.removeEventListener('mouseup', onMouseUp);
}
document.addEventListener('mouseup', onMouseUp);
});
document.addEventListener('keydown', (e) => {
if (e.key == key) {
console.log(e.key);
const startTime = Date.now();
var interval = mixx(startTime);
function onKeyUp() {
clearInterval(interval);
document.removeEventListener('keyup', onKeyUp);
}
document.addEventListener('keyup', onKeyUp);
}
});
menuBar.appendChild(puck);
}
createPuck(c='rgb(0, 0, 0)', editable=false, key='1');
createPuck(c='rgb(255, 0, 0)', editale=false, key='2');
createPuck(c='rgb(0, 0, 255)', editale=false, key='3');
createPuck(c='rgb(255, 255, 0)', editale=false, key='4');
createPuck(c='rgb(99, 60, 22)', editale=false, key='5');
createPuck(c='rgb(0, 255, 0)', editale=false, key='6');
createPuck(c='rgb(255, 0, 255)', editale=false, key='7');
createPuck(c='rgb(0, 255, 255)', editale=false, key='8');
createPuck(c='rgb(255, 255, 255)', editale=false, key='9');
// }}}
// info {{{
var infos = [];
function createInfo(name, updateFunction) {
const info = document.createElement('span');
info.className = 'info';
const key = document.createElement('span');
key.className = 'key';
key.innerHTML = name + ':';
const value = document.createElement('span');
value.className = 'value';
value.innerHTML = '0';
info.appendChild(key);
info.appendChild(value);
infoBar.appendChild(info);
function update() {
let v = updateFunction();
if (v === undefined) v = '?';
value.innerHTML = v;
}
return update;
}
infos.push(createInfo('zoom', function() {
var percent = zoom * 100;
return percent.toFixed(0) + '%';
}));
infos.push(createInfo('brush', function() { return brushSize; }));
infos.push(createInfo('x', function() { return canvasEndX; }));
infos.push(createInfo('y', function() { return canvasEndY; }));
infos.push(createInfo('color', function() { return color; }));
infos.push(createInfo('width', function() { return canvas.width; }));
infos.push(createInfo('height', function() { return canvas.height; }));
function updateInfos() {
infos.forEach(info => info());
}
// }}}
// start {{{
ctx.fillStyle = backgroundColor;
ctx.fillRect(0, 0, canvas.width, canvas.height);
updateInfos();
toolButtons[0]['button'].click();
// }}}
Loading…
Cancel
Save