Skip to content

Commit

Permalink
Merge pull request #108 from zero01101/testing
Browse files Browse the repository at this point in the history
dynamic canvas scaling?
  • Loading branch information
zero01101 committed Dec 18, 2022
2 parents 79ee065 + d571eca commit dd52529
Show file tree
Hide file tree
Showing 13 changed files with 700 additions and 122 deletions.
69 changes: 69 additions & 0 deletions css/ui/layers.css
Original file line number Diff line number Diff line change
Expand Up @@ -132,3 +132,72 @@
flex: 1;
height: 25px;
}

/* Resizing buttons */
.expand-button {
display: flex;

align-items: center;
justify-content: center;

margin: 0;
padding: 0;
border: 0;

background-color: transparent;

cursor: pointer;

transition-duration: 300ms;

border: 2px solid #293d3d30;
}

.expand-button::after {
content: "";

background-color: #293d3d77;

mask-image: url("/res/icons/chevron-up.svg");
mask-size: contain;

width: 60px;
height: 60px;
}

.expand-button:hover::after {
background-color: #466;
}

.expand-button.right::after {
transform: rotate(90deg);
}

.expand-button.bottom::after {
transform: rotate(180deg);
}

.expand-button.left::after {
transform: rotate(270deg);
}

.expand-button.left {
border-top-left-radius: 10px;
border-bottom-left-radius: 10px;
}
.expand-button.top {
border-top-left-radius: 10px;
border-top-right-radius: 10px;
}
.expand-button.right {
border-top-right-radius: 10px;
border-bottom-right-radius: 10px;
}
.expand-button.bottom {
border-bottom-right-radius: 10px;
border-bottom-left-radius: 10px;
}

.expand-button:hover {
background-color: #293d3d77;
}
19 changes: 12 additions & 7 deletions js/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -343,17 +343,14 @@ function newImage(evt) {
clearPaintedMask();
uil.layers.forEach(({layer}) => {
commands.runCommand("eraseImage", "Clear Canvas", {
x: 0,
y: 0,
w: layer.canvas.width,
h: layer.canvas.height,
...layer.bb,
ctx: layer.ctx,
});
});
}

function clearPaintedMask() {
maskPaintCtx.clearRect(0, 0, maskPaintCanvas.width, maskPaintCanvas.height);
maskPaintLayer.clear();
}

function march(bb, options = {}) {
Expand Down Expand Up @@ -558,8 +555,16 @@ function drawBackground() {
// Checkerboard
let darkTileColor = "#333";
let lightTileColor = "#555";
for (var x = 0; x < bgLayer.canvas.width; x += 64) {
for (var y = 0; y < bgLayer.canvas.height; y += 64) {
for (
var x = -bgLayer.origin.x - 64;
x < bgLayer.canvas.width - bgLayer.origin.x;
x += 64
) {
for (
var y = -bgLayer.origin.y - 64;
y < bgLayer.canvas.height - bgLayer.origin.y;
y += 64
) {
bgLayer.ctx.fillStyle =
(x + y) % 128 === 0 ? lightTileColor : darkTileColor;
bgLayer.ctx.fillRect(x, y, 64, 64);
Expand Down
13 changes: 13 additions & 0 deletions js/initalize/debug.populate.js
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,19 @@ mouse.listen.world.onmousemove.on((evn) => {
canvasYInfo.textContent = evn.y;
snapXInfo.textContent = evn.x + snap(evn.x);
snapYInfo.textContent = evn.y + snap(evn.y);

if (debug) {
debugLayer.clear();
debugCtx.fillStyle = "#F0F";
debugCtx.beginPath();
debugCtx.arc(viewport.cx, viewport.cy, 5, 0, Math.PI * 2);
debugCtx.fill();

debugCtx.fillStyle = "#0FF";
debugCtx.beginPath();
debugCtx.arc(evn.x, evn.y, 5, 0, Math.PI * 2);
debugCtx.fill();
}
});

/**
Expand Down
164 changes: 120 additions & 44 deletions js/initalize/layers.populate.js
Original file line number Diff line number Diff line change
Expand Up @@ -53,44 +53,97 @@ uiCanvas.width = uiCanvas.clientWidth;
uiCanvas.height = uiCanvas.clientHeight;
const uiCtx = uiCanvas.getContext("2d", {desynchronized: true});

debugLayer.hide(); // Hidden by default

layers.registerCollection("mask", {name: "Mask Layers", requiresActive: true});

// Where CSS and javascript magic happens to make the canvas viewport work
/**
* Ended up using a CSS transforms approach due to more flexibility on transformations
* and capability to automagically translate input coordinates to layer space.
* Here we setup canvas dynamic scaling
*/
mouse.registerContext(
"world",
(evn, ctx) => {
// Fix because in chrome layerX and layerY simply doesnt work
ctx.coords.prev.x = ctx.coords.pos.x;
ctx.coords.prev.y = ctx.coords.pos.y;

// Get element bounding rect
const bb = imageCollection.element.getBoundingClientRect();

// Get element width/height (css, cause I don't trust client sizes in chrome anymore)
const w = imageCollection.size.w;
const h = imageCollection.size.h;

// Get cursor position
const x = evn.clientX;
const y = evn.clientY;

// Map to layer space
const layerX = ((x - bb.left) / bb.width) * w;
const layerY = ((y - bb.top) / bb.height) * h;
(() => {
let expandSize = localStorage.getItem("expand-size") || 1024;
expandSize = parseInt(expandSize, 10);

const askSize = () => {
const by = prompt("How much do you want to expand by?", expandSize);

if (!by) return null;
else {
const len = parseInt(by, 10);
localStorage.setItem("expand-size", len);
expandSize = len;
return len;
}
};

const leftButton = makeElement("button", -64, 0);
leftButton.classList.add("expand-button", "left");
leftButton.style.width = "64px";
leftButton.style.height = `${imageCollection.size.h}px`;
leftButton.addEventListener("click", () => {
let size = null;
if ((size = askSize())) {
imageCollection.expand(size, 0, 0, 0);
drawBackground();
const newLeft = -imageCollection.inputOffset.x - imageCollection.origin.x;
leftButton.style.left = newLeft - 64 + "px";
topButton.style.left = newLeft + "px";
bottomButton.style.left = newLeft + "px";
topButton.style.width = imageCollection.size.w + "px";
bottomButton.style.width = imageCollection.size.w + "px";
}
});

const rightButton = makeElement("button", imageCollection.size.w, 0);
rightButton.classList.add("expand-button", "right");
rightButton.style.width = "64px";
rightButton.style.height = `${imageCollection.size.h}px`;
rightButton.addEventListener("click", () => {
let size = null;
if ((size = askSize())) {
imageCollection.expand(0, 0, size, 0);
drawBackground();
rightButton.style.left =
parseInt(rightButton.style.left, 10) + size + "px";
topButton.style.width = imageCollection.size.w + "px";
bottomButton.style.width = imageCollection.size.w + "px";
}
});

const topButton = makeElement("button", 0, -64);
topButton.classList.add("expand-button", "top");
topButton.style.height = "64px";
topButton.style.width = `${imageCollection.size.w}px`;
topButton.addEventListener("click", () => {
let size = null;
if ((size = askSize())) {
imageCollection.expand(0, size, 0, 0);
drawBackground();
const newTop = -imageCollection.inputOffset.y - imageCollection.origin.y;
topButton.style.top = newTop - 64 + "px";
leftButton.style.top = newTop + "px";
rightButton.style.top = newTop + "px";
leftButton.style.height = imageCollection.size.h + "px";
rightButton.style.height = imageCollection.size.h + "px";
}
});

const bottomButton = makeElement("button", 0, imageCollection.size.h);
bottomButton.classList.add("expand-button", "bottom");
bottomButton.style.height = "64px";
bottomButton.style.width = `${imageCollection.size.w}px`;
bottomButton.addEventListener("click", () => {
let size = null;
if ((size = askSize())) {
imageCollection.expand(0, 0, 0, size);
drawBackground();
bottomButton.style.top =
parseInt(bottomButton.style.top, 10) + size + "px";
leftButton.style.height = imageCollection.size.h + "px";
rightButton.style.height = imageCollection.size.h + "px";
}
});
})();

//
ctx.coords.pos.x = Math.round(layerX);
ctx.coords.pos.y = Math.round(layerY);
},
{target: imageCollection.inputElement}
);
debugLayer.hide(); // Hidden by default

// Where CSS and javascript magic happens to make the canvas viewport work
/**
* The global viewport object (may be modularized in the future). All
* coordinates given are of the center of the viewport
Expand Down Expand Up @@ -158,6 +211,31 @@ let worldInit = null;

viewport.transform(imageCollection.element);

/**
* Ended up using a CSS transforms approach due to more flexibility on transformations
* and capability to automagically translate input coordinates to layer space.
*/
mouse.registerContext(
"world",
(evn, ctx) => {
// Fix because in chrome layerX and layerY simply doesnt work
ctx.coords.prev.x = ctx.coords.pos.x;
ctx.coords.prev.y = ctx.coords.pos.y;

// Get cursor position
const x = evn.clientX;
const y = evn.clientY;

// Map to layer space
const layerCoords = viewport.viewToCanvas(x, y);

// Set coords
ctx.coords.pos.x = Math.round(layerCoords.x);
ctx.coords.pos.y = Math.round(layerCoords.y);
},
{target: imageCollection.inputElement}
);

mouse.listen.window.onwheel.on((evn) => {
if (evn.evn.ctrlKey) {
evn.evn.preventDefault();
Expand All @@ -176,14 +254,6 @@ mouse.listen.window.onwheel.on((evn) => {
viewport.transform(imageCollection.element);

toolbar.currentTool.redraw();

if (debug) {
debugCtx.clearRect(0, 0, debugCanvas.width, debugCanvas.height);
debugCtx.fillStyle = "#F0F";
debugCtx.beginPath();
debugCtx.arc(viewport.cx, viewport.cy, 5, 0, Math.PI * 2);
debugCtx.fill();
}
}
});

Expand All @@ -197,8 +267,14 @@ mouse.listen.window.btn.middle.onpaint.on((evn) => {
viewport.cy = worldInit.y + (evn.iy - evn.y) / viewport.zoom;

// Limits
viewport.cx = Math.max(Math.min(viewport.cx, imageCollection.size.w), 0);
viewport.cy = Math.max(Math.min(viewport.cy, imageCollection.size.h), 0);
viewport.cx = Math.max(
Math.min(viewport.cx, imageCollection.size.w - imageCollection.origin.x),
-imageCollection.origin.x
);
viewport.cy = Math.max(
Math.min(viewport.cy, imageCollection.size.h - imageCollection.origin.y),
-imageCollection.origin.y
);

// Draw Viewport location
}
Expand Down
47 changes: 47 additions & 0 deletions js/lib/layers.d.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,47 @@
/**
* A layer
*
* @typedef {object} Layer
* @property {string} id The id of the layer
* @property {string} key A identifier for the layer
* @property {string} name The display name of the layer
* @property {BoundingBox} bb The current bounding box of the layer, in layer coordinates
* @property {Size} resolution The resolution of the layer (canvas)
* @property {boolean} full If the layer is a full layer (occupies the full collection)
* @property {number} x The x coordinate of the layer
* @property {number} y The y coordinate of the layer
* @property {number} width The width of the layer
* @property {number} w The width of the layer
* @property {number} height The height of the layer
* @property {number} h The height of the layer
* @property {Point} origin The location of the origin ((0, 0) point) of the layer (If canvas goes from -64, -32 to 128, 512, it's (64, 32))
* @property {HTMLCanvasElement} canvas The canvas element of the layers
* @property {CanvasRenderingContext2D} ctx The context of the canvas of the layer
* @property {function} clear Clears the layer contents
* @property {function} moveAfter Moves this layer to another level (after given layer)
* @property {function} moveBefore Moves this layer to another level (before given layer)
* @property {function} moveTo Moves this layer to another location
* @property {function} resize Resizes the layer in place
* @property {function} hide Hides the layer
* @property {function} unhide Unhides the layer
*/

/**
* A layer collection
*
* @typedef {object} LayerCollection
* @property {string} id The id of the collection
* @property {string} key A identifier for the collection
* @property {string} name The display name of the collection
* @property {HTMLDivElement} element The base element of the collection
* @property {HTMLDivElement} inputElement The element used for input handling for the collection
* @property {Point} inputOffset The offset for calculating layer coordinates from input element input information
* @property {Point} origin The location of the origin ((0, 0) point) of the collection (If canvas goes from -64, -32 to 128, 512, it's (64, 32))
* @property {BoundingBox} bb The current bounding box of the collection, in layer coordinates
* @property {{[key: string]: Layer}} layers An object for quick access to named layers of the collection
* @property {Size} size The size of the collection (CSS)
* @property {Size} resolution The resolution of the collection (canvas)
* @property {function} expand Expands the collection and its full layers by the specified amounts
* @property {function} registerLayer Registers a new layer
* @property {function} deleteLayer Deletes a layer from the collection
*/
Loading

0 comments on commit dd52529

Please sign in to comment.