mirror of
https://github.com/Azornes/Comfyui-LayerForge.git
synced 2026-03-24 14:02:11 -03:00
Refactor CanvasLayers to use consistent canvas reference
Renamed the CanvasLayers constructor parameter from 'canvasLayers' to 'canvas' and updated all internal references accordingly for clarity and consistency. Adjusted CanvasView.js to call layer operations via canvas.canvasLayers. Updated REFACTORING_GUIDE.md to document these architectural changes and ensure all modules follow a unified naming convention.
This commit is contained in:
@@ -6,8 +6,8 @@ import {withErrorHandling, createValidationError} from "./ErrorHandler.js";
|
|||||||
const log = createModuleLogger('CanvasLayers');
|
const log = createModuleLogger('CanvasLayers');
|
||||||
|
|
||||||
export class CanvasLayers {
|
export class CanvasLayers {
|
||||||
constructor(canvasLayers) {
|
constructor(canvas) {
|
||||||
this.canvasLayers = canvasLayers;
|
this.canvas = canvas;
|
||||||
this.blendModes = [
|
this.blendModes = [
|
||||||
{name: 'normal', label: 'Normal'},
|
{name: 'normal', label: 'Normal'},
|
||||||
{name: 'multiply', label: 'Multiply'},
|
{name: 'multiply', label: 'Multiply'},
|
||||||
@@ -29,8 +29,8 @@ export class CanvasLayers {
|
|||||||
}
|
}
|
||||||
|
|
||||||
async copySelectedLayers() {
|
async copySelectedLayers() {
|
||||||
if (this.canvasLayers.selectedLayers.length === 0) return;
|
if (this.canvas.selectedLayers.length === 0) return;
|
||||||
this.internalClipboard = this.canvasLayers.selectedLayers.map(layer => ({...layer}));
|
this.internalClipboard = this.canvas.selectedLayers.map(layer => ({...layer}));
|
||||||
log.info(`Copied ${this.internalClipboard.length} layer(s) to internal clipboard.`);
|
log.info(`Copied ${this.internalClipboard.length} layer(s) to internal clipboard.`);
|
||||||
try {
|
try {
|
||||||
const blob = await this.getFlattenedSelectionAsBlob();
|
const blob = await this.getFlattenedSelectionAsBlob();
|
||||||
@@ -46,23 +46,23 @@ export class CanvasLayers {
|
|||||||
|
|
||||||
pasteLayers() {
|
pasteLayers() {
|
||||||
if (this.internalClipboard.length === 0) return;
|
if (this.internalClipboard.length === 0) return;
|
||||||
this.canvasLayers.saveState();
|
this.canvas.saveState();
|
||||||
const newLayers = [];
|
const newLayers = [];
|
||||||
const pasteOffset = 20;
|
const pasteOffset = 20;
|
||||||
|
|
||||||
this.internalClipboard.forEach(clipboardLayer => {
|
this.internalClipboard.forEach(clipboardLayer => {
|
||||||
const newLayer = {
|
const newLayer = {
|
||||||
...clipboardLayer,
|
...clipboardLayer,
|
||||||
x: clipboardLayer.x + pasteOffset / this.canvasLayers.viewport.zoom,
|
x: clipboardLayer.x + pasteOffset / this.canvas.viewport.zoom,
|
||||||
y: clipboardLayer.y + pasteOffset / this.canvasLayers.viewport.zoom,
|
y: clipboardLayer.y + pasteOffset / this.canvas.viewport.zoom,
|
||||||
zIndex: this.canvasLayers.layers.length
|
zIndex: this.canvas.layers.length
|
||||||
};
|
};
|
||||||
this.canvasLayers.layers.push(newLayer);
|
this.canvas.layers.push(newLayer);
|
||||||
newLayers.push(newLayer);
|
newLayers.push(newLayer);
|
||||||
});
|
});
|
||||||
|
|
||||||
this.canvasLayers.updateSelection(newLayers);
|
this.canvas.updateSelection(newLayers);
|
||||||
this.canvasLayers.render();
|
this.canvas.render();
|
||||||
log.info(`Pasted ${newLayers.length} layer(s).`);
|
log.info(`Pasted ${newLayers.length} layer(s).`);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -113,24 +113,24 @@ export class CanvasLayers {
|
|||||||
log.debug("Adding layer with image:", image, "with mode:", addMode);
|
log.debug("Adding layer with image:", image, "with mode:", addMode);
|
||||||
const imageId = generateUUID();
|
const imageId = generateUUID();
|
||||||
await saveImage(imageId, image.src);
|
await saveImage(imageId, image.src);
|
||||||
this.canvasLayers.imageCache.set(imageId, image.src);
|
this.canvas.imageCache.set(imageId, image.src);
|
||||||
|
|
||||||
let finalWidth = image.width;
|
let finalWidth = image.width;
|
||||||
let finalHeight = image.height;
|
let finalHeight = image.height;
|
||||||
let finalX, finalY;
|
let finalX, finalY;
|
||||||
|
|
||||||
if (addMode === 'fit') {
|
if (addMode === 'fit') {
|
||||||
const scale = Math.min(this.canvasLayers.width / image.width, this.canvasLayers.height / image.height);
|
const scale = Math.min(this.canvas.width / image.width, this.canvas.height / image.height);
|
||||||
finalWidth = image.width * scale;
|
finalWidth = image.width * scale;
|
||||||
finalHeight = image.height * scale;
|
finalHeight = image.height * scale;
|
||||||
finalX = (this.canvasLayers.width - finalWidth) / 2;
|
finalX = (this.canvas.width - finalWidth) / 2;
|
||||||
finalY = (this.canvasLayers.height - finalHeight) / 2;
|
finalY = (this.canvas.height - finalHeight) / 2;
|
||||||
} else if (addMode === 'mouse') {
|
} else if (addMode === 'mouse') {
|
||||||
finalX = this.canvasLayers.lastMousePosition.x - finalWidth / 2;
|
finalX = this.canvas.lastMousePosition.x - finalWidth / 2;
|
||||||
finalY = this.canvasLayers.lastMousePosition.y - finalHeight / 2;
|
finalY = this.canvas.lastMousePosition.y - finalHeight / 2;
|
||||||
} else { // 'center' or 'default'
|
} else { // 'center' or 'default'
|
||||||
finalX = (this.canvasLayers.width - finalWidth) / 2;
|
finalX = (this.canvas.width - finalWidth) / 2;
|
||||||
finalY = (this.canvasLayers.height - finalHeight) / 2;
|
finalY = (this.canvas.height - finalHeight) / 2;
|
||||||
}
|
}
|
||||||
|
|
||||||
const layer = {
|
const layer = {
|
||||||
@@ -143,16 +143,16 @@ export class CanvasLayers {
|
|||||||
originalWidth: image.width,
|
originalWidth: image.width,
|
||||||
originalHeight: image.height,
|
originalHeight: image.height,
|
||||||
rotation: 0,
|
rotation: 0,
|
||||||
zIndex: this.canvasLayers.layers.length,
|
zIndex: this.canvas.layers.length,
|
||||||
blendMode: 'normal',
|
blendMode: 'normal',
|
||||||
opacity: 1,
|
opacity: 1,
|
||||||
...layerProps
|
...layerProps
|
||||||
};
|
};
|
||||||
|
|
||||||
this.canvasLayers.layers.push(layer);
|
this.canvas.layers.push(layer);
|
||||||
this.canvasLayers.updateSelection([layer]);
|
this.canvas.updateSelection([layer]);
|
||||||
this.canvasLayers.render();
|
this.canvas.render();
|
||||||
this.canvasLayers.saveState();
|
this.canvas.saveState();
|
||||||
|
|
||||||
log.info("Layer added successfully");
|
log.info("Layer added successfully");
|
||||||
return layer;
|
return layer;
|
||||||
@@ -163,26 +163,26 @@ export class CanvasLayers {
|
|||||||
}
|
}
|
||||||
|
|
||||||
moveLayerUp() {
|
moveLayerUp() {
|
||||||
if (this.canvasLayers.selectedLayers.length === 0) return;
|
if (this.canvas.selectedLayers.length === 0) return;
|
||||||
const selectedIndicesSet = new Set(this.canvasLayers.selectedLayers.map(layer => this.canvasLayers.layers.indexOf(layer)));
|
const selectedIndicesSet = new Set(this.canvas.selectedLayers.map(layer => this.canvas.layers.indexOf(layer)));
|
||||||
|
|
||||||
const sortedIndices = Array.from(selectedIndicesSet).sort((a, b) => b - a);
|
const sortedIndices = Array.from(selectedIndicesSet).sort((a, b) => b - a);
|
||||||
|
|
||||||
sortedIndices.forEach(index => {
|
sortedIndices.forEach(index => {
|
||||||
const targetIndex = index + 1;
|
const targetIndex = index + 1;
|
||||||
|
|
||||||
if (targetIndex < this.canvasLayers.layers.length && !selectedIndicesSet.has(targetIndex)) {
|
if (targetIndex < this.canvas.layers.length && !selectedIndicesSet.has(targetIndex)) {
|
||||||
[this.canvasLayers.layers[index], this.canvasLayers.layers[targetIndex]] = [this.canvasLayers.layers[targetIndex], this.canvasLayers.layers[index]];
|
[this.canvas.layers[index], this.canvas.layers[targetIndex]] = [this.canvas.layers[targetIndex], this.canvas.layers[index]];
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
this.canvasLayers.layers.forEach((layer, i) => layer.zIndex = i);
|
this.canvas.layers.forEach((layer, i) => layer.zIndex = i);
|
||||||
this.canvasLayers.render();
|
this.canvas.render();
|
||||||
this.canvasLayers.saveState();
|
this.canvas.saveState();
|
||||||
}
|
}
|
||||||
|
|
||||||
moveLayerDown() {
|
moveLayerDown() {
|
||||||
if (this.canvasLayers.selectedLayers.length === 0) return;
|
if (this.canvas.selectedLayers.length === 0) return;
|
||||||
const selectedIndicesSet = new Set(this.canvasLayers.selectedLayers.map(layer => this.canvasLayers.layers.indexOf(layer)));
|
const selectedIndicesSet = new Set(this.canvas.selectedLayers.map(layer => this.canvas.layers.indexOf(layer)));
|
||||||
|
|
||||||
const sortedIndices = Array.from(selectedIndicesSet).sort((a, b) => a - b);
|
const sortedIndices = Array.from(selectedIndicesSet).sort((a, b) => a - b);
|
||||||
|
|
||||||
@@ -190,12 +190,12 @@ export class CanvasLayers {
|
|||||||
const targetIndex = index - 1;
|
const targetIndex = index - 1;
|
||||||
|
|
||||||
if (targetIndex >= 0 && !selectedIndicesSet.has(targetIndex)) {
|
if (targetIndex >= 0 && !selectedIndicesSet.has(targetIndex)) {
|
||||||
[this.canvasLayers.layers[index], this.canvasLayers.layers[targetIndex]] = [this.canvasLayers.layers[targetIndex], this.canvasLayers.layers[index]];
|
[this.canvas.layers[index], this.canvas.layers[targetIndex]] = [this.canvas.layers[targetIndex], this.canvas.layers[index]];
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
this.canvasLayers.layers.forEach((layer, i) => layer.zIndex = i);
|
this.canvas.layers.forEach((layer, i) => layer.zIndex = i);
|
||||||
this.canvasLayers.render();
|
this.canvas.render();
|
||||||
this.canvasLayers.saveState();
|
this.canvas.saveState();
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -203,14 +203,14 @@ export class CanvasLayers {
|
|||||||
* @param {number} scale - Skala zmiany rozmiaru
|
* @param {number} scale - Skala zmiany rozmiaru
|
||||||
*/
|
*/
|
||||||
resizeLayer(scale) {
|
resizeLayer(scale) {
|
||||||
if (this.canvasLayers.selectedLayers.length === 0) return;
|
if (this.canvas.selectedLayers.length === 0) return;
|
||||||
|
|
||||||
this.canvasLayers.selectedLayers.forEach(layer => {
|
this.canvas.selectedLayers.forEach(layer => {
|
||||||
layer.width *= scale;
|
layer.width *= scale;
|
||||||
layer.height *= scale;
|
layer.height *= scale;
|
||||||
});
|
});
|
||||||
this.canvasLayers.render();
|
this.canvas.render();
|
||||||
this.canvasLayers.saveState();
|
this.canvas.saveState();
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -218,18 +218,18 @@ export class CanvasLayers {
|
|||||||
* @param {number} angle - Kąt obrotu w stopniach
|
* @param {number} angle - Kąt obrotu w stopniach
|
||||||
*/
|
*/
|
||||||
rotateLayer(angle) {
|
rotateLayer(angle) {
|
||||||
if (this.canvasLayers.selectedLayers.length === 0) return;
|
if (this.canvas.selectedLayers.length === 0) return;
|
||||||
|
|
||||||
this.canvasLayers.selectedLayers.forEach(layer => {
|
this.canvas.selectedLayers.forEach(layer => {
|
||||||
layer.rotation += angle;
|
layer.rotation += angle;
|
||||||
});
|
});
|
||||||
this.canvasLayers.render();
|
this.canvas.render();
|
||||||
this.canvasLayers.saveState();
|
this.canvas.saveState();
|
||||||
}
|
}
|
||||||
|
|
||||||
getLayerAtPosition(worldX, worldY) {
|
getLayerAtPosition(worldX, worldY) {
|
||||||
for (let i = this.canvasLayers.layers.length - 1; i >= 0; i--) {
|
for (let i = this.canvas.layers.length - 1; i >= 0; i--) {
|
||||||
const layer = this.canvasLayers.layers[i];
|
const layer = this.canvas.layers[i];
|
||||||
|
|
||||||
const centerX = layer.x + layer.width / 2;
|
const centerX = layer.x + layer.width / 2;
|
||||||
const centerY = layer.y + layer.height / 2;
|
const centerY = layer.y + layer.height / 2;
|
||||||
@@ -256,9 +256,9 @@ export class CanvasLayers {
|
|||||||
}
|
}
|
||||||
|
|
||||||
async mirrorHorizontal() {
|
async mirrorHorizontal() {
|
||||||
if (this.canvasLayers.selectedLayers.length === 0) return;
|
if (this.canvas.selectedLayers.length === 0) return;
|
||||||
|
|
||||||
const promises = this.canvasLayers.selectedLayers.map(layer => {
|
const promises = this.canvas.selectedLayers.map(layer => {
|
||||||
return new Promise(resolve => {
|
return new Promise(resolve => {
|
||||||
const tempCanvas = document.createElement('canvas');
|
const tempCanvas = document.createElement('canvas');
|
||||||
const tempCtx = tempCanvas.getContext('2d');
|
const tempCtx = tempCanvas.getContext('2d');
|
||||||
@@ -279,14 +279,14 @@ export class CanvasLayers {
|
|||||||
});
|
});
|
||||||
|
|
||||||
await Promise.all(promises);
|
await Promise.all(promises);
|
||||||
this.canvasLayers.render();
|
this.canvas.render();
|
||||||
this.canvasLayers.saveState();
|
this.canvas.saveState();
|
||||||
}
|
}
|
||||||
|
|
||||||
async mirrorVertical() {
|
async mirrorVertical() {
|
||||||
if (this.canvasLayers.selectedLayers.length === 0) return;
|
if (this.canvas.selectedLayers.length === 0) return;
|
||||||
|
|
||||||
const promises = this.canvasLayers.selectedLayers.map(layer => {
|
const promises = this.canvas.selectedLayers.map(layer => {
|
||||||
return new Promise(resolve => {
|
return new Promise(resolve => {
|
||||||
const tempCanvas = document.createElement('canvas');
|
const tempCanvas = document.createElement('canvas');
|
||||||
const tempCtx = tempCanvas.getContext('2d');
|
const tempCtx = tempCanvas.getContext('2d');
|
||||||
@@ -307,8 +307,8 @@ export class CanvasLayers {
|
|||||||
});
|
});
|
||||||
|
|
||||||
await Promise.all(promises);
|
await Promise.all(promises);
|
||||||
this.canvasLayers.render();
|
this.canvas.render();
|
||||||
this.canvasLayers.saveState();
|
this.canvas.saveState();
|
||||||
}
|
}
|
||||||
|
|
||||||
async getLayerImageData(layer) {
|
async getLayerImageData(layer) {
|
||||||
@@ -345,22 +345,21 @@ export class CanvasLayers {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
updateOutputAreaSize(width, height, saveHistory = true) {
|
updateOutputAreaSize(width, height, saveHistory = true) {
|
||||||
if (saveHistory) {
|
if (saveHistory) {
|
||||||
this.canvasLayers.saveState();
|
this.canvas.saveState();
|
||||||
}
|
}
|
||||||
this.canvasLayers.width = width;
|
this.canvas.width = width;
|
||||||
this.canvasLayers.height = height;
|
this.canvas.height = height;
|
||||||
this.canvasLayers.maskTool.resize(width, height);
|
this.canvas.maskTool.resize(width, height);
|
||||||
|
|
||||||
this.canvasLayers.canvasLayers.width = width;
|
this.canvas.canvas.width = width;
|
||||||
this.canvasLayers.canvasLayers.height = height;
|
this.canvas.canvas.height = height;
|
||||||
|
|
||||||
this.canvasLayers.render();
|
this.canvas.render();
|
||||||
|
|
||||||
if (saveHistory) {
|
if (saveHistory) {
|
||||||
this.canvasLayers.saveStateToDB();
|
this.canvas.saveStateToDB();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -384,7 +383,7 @@ export class CanvasLayers {
|
|||||||
'sw': {x: -halfW, y: halfH},
|
'sw': {x: -halfW, y: halfH},
|
||||||
'w': {x: -halfW, y: 0},
|
'w': {x: -halfW, y: 0},
|
||||||
'nw': {x: -halfW, y: -halfH},
|
'nw': {x: -halfW, y: -halfH},
|
||||||
'rot': {x: 0, y: -halfH - 20 / this.canvasLayers.viewport.zoom}
|
'rot': {x: 0, y: -halfH - 20 / this.canvas.viewport.zoom}
|
||||||
};
|
};
|
||||||
|
|
||||||
const worldHandles = {};
|
const worldHandles = {};
|
||||||
@@ -399,11 +398,11 @@ export class CanvasLayers {
|
|||||||
}
|
}
|
||||||
|
|
||||||
getHandleAtPosition(worldX, worldY) {
|
getHandleAtPosition(worldX, worldY) {
|
||||||
if (this.canvasLayers.selectedLayers.length === 0) return null;
|
if (this.canvas.selectedLayers.length === 0) return null;
|
||||||
|
|
||||||
const handleRadius = 8 / this.canvasLayers.viewport.zoom;
|
const handleRadius = 8 / this.canvas.viewport.zoom;
|
||||||
for (let i = this.canvasLayers.selectedLayers.length - 1; i >= 0; i--) {
|
for (let i = this.canvas.selectedLayers.length - 1; i >= 0; i--) {
|
||||||
const layer = this.canvasLayers.selectedLayers[i];
|
const layer = this.canvas.selectedLayers[i];
|
||||||
const handles = this.getHandles(layer);
|
const handles = this.getHandles(layer);
|
||||||
|
|
||||||
for (const key in handles) {
|
for (const key in handles) {
|
||||||
@@ -456,14 +455,14 @@ export class CanvasLayers {
|
|||||||
slider.min = '0';
|
slider.min = '0';
|
||||||
slider.max = '100';
|
slider.max = '100';
|
||||||
|
|
||||||
slider.value = this.canvasLayers.selectedLayer.opacity ? Math.round(this.canvasLayers.selectedLayer.opacity * 100) : 100;
|
slider.value = this.canvas.selectedLayer.opacity ? Math.round(this.canvas.selectedLayer.opacity * 100) : 100;
|
||||||
slider.style.cssText = `
|
slider.style.cssText = `
|
||||||
width: 100%;
|
width: 100%;
|
||||||
margin: 5px 0;
|
margin: 5px 0;
|
||||||
display: none;
|
display: none;
|
||||||
`;
|
`;
|
||||||
|
|
||||||
if (this.canvasLayers.selectedLayer.blendMode === mode.name) {
|
if (this.canvas.selectedLayer.blendMode === mode.name) {
|
||||||
slider.style.display = 'block';
|
slider.style.display = 'block';
|
||||||
option.style.backgroundColor = '#3a3a3a';
|
option.style.backgroundColor = '#3a3a3a';
|
||||||
}
|
}
|
||||||
@@ -479,35 +478,35 @@ export class CanvasLayers {
|
|||||||
slider.style.display = 'block';
|
slider.style.display = 'block';
|
||||||
option.style.backgroundColor = '#3a3a3a';
|
option.style.backgroundColor = '#3a3a3a';
|
||||||
|
|
||||||
if (this.canvasLayers.selectedLayer) {
|
if (this.canvas.selectedLayer) {
|
||||||
this.canvasLayers.selectedLayer.blendMode = mode.name;
|
this.canvas.selectedLayer.blendMode = mode.name;
|
||||||
this.canvasLayers.render();
|
this.canvas.render();
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
slider.addEventListener('input', () => {
|
slider.addEventListener('input', () => {
|
||||||
if (this.canvasLayers.selectedLayer) {
|
if (this.canvas.selectedLayer) {
|
||||||
this.canvasLayers.selectedLayer.opacity = slider.value / 100;
|
this.canvas.selectedLayer.opacity = slider.value / 100;
|
||||||
this.canvasLayers.render();
|
this.canvas.render();
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
slider.addEventListener('change', async () => {
|
slider.addEventListener('change', async () => {
|
||||||
if (this.canvasLayers.selectedLayer) {
|
if (this.canvas.selectedLayer) {
|
||||||
this.canvasLayers.selectedLayer.opacity = slider.value / 100;
|
this.canvas.selectedLayer.opacity = slider.value / 100;
|
||||||
this.canvasLayers.render();
|
this.canvas.render();
|
||||||
const saveWithFallback = async (fileName) => {
|
const saveWithFallback = async (fileName) => {
|
||||||
try {
|
try {
|
||||||
const uniqueFileName = generateUniqueFileName(fileName, this.canvasLayers.node.id);
|
const uniqueFileName = generateUniqueFileName(fileName, this.canvas.node.id);
|
||||||
return await this.canvasLayers.saveToServer(uniqueFileName);
|
return await this.canvas.saveToServer(uniqueFileName);
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
console.warn(`Failed to save with unique name, falling back to original: ${fileName}`, error);
|
console.warn(`Failed to save with unique name, falling back to original: ${fileName}`, error);
|
||||||
return await this.canvasLayers.saveToServer(fileName);
|
return await this.canvas.saveToServer(fileName);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
await saveWithFallback(this.canvasLayers.widget.value);
|
await saveWithFallback(this.canvas.widget.value);
|
||||||
if (this.canvasLayers.node) {
|
if (this.canvas.node) {
|
||||||
app.graph.runStep();
|
app.graph.runStep();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -518,7 +517,7 @@ export class CanvasLayers {
|
|||||||
menu.appendChild(container);
|
menu.appendChild(container);
|
||||||
});
|
});
|
||||||
|
|
||||||
const container = this.canvasLayers.canvas.parentElement || document.body;
|
const container = this.canvas.canvas.parentElement || document.body;
|
||||||
container.appendChild(menu);
|
container.appendChild(menu);
|
||||||
|
|
||||||
const closeMenu = (e) => {
|
const closeMenu = (e) => {
|
||||||
@@ -560,11 +559,11 @@ export class CanvasLayers {
|
|||||||
async getFlattenedCanvasAsBlob() {
|
async getFlattenedCanvasAsBlob() {
|
||||||
return new Promise((resolve, reject) => {
|
return new Promise((resolve, reject) => {
|
||||||
const tempCanvas = document.createElement('canvas');
|
const tempCanvas = document.createElement('canvas');
|
||||||
tempCanvas.width = this.canvasLayers.width;
|
tempCanvas.width = this.canvas.width;
|
||||||
tempCanvas.height = this.canvasLayers.height;
|
tempCanvas.height = this.canvas.height;
|
||||||
const tempCtx = tempCanvas.getContext('2d');
|
const tempCtx = tempCanvas.getContext('2d');
|
||||||
|
|
||||||
const sortedLayers = [...this.canvasLayers.layers].sort((a, b) => a.zIndex - b.zIndex);
|
const sortedLayers = [...this.canvas.layers].sort((a, b) => a.zIndex - b.zIndex);
|
||||||
|
|
||||||
sortedLayers.forEach(layer => {
|
sortedLayers.forEach(layer => {
|
||||||
if (!layer.image) return;
|
if (!layer.image) return;
|
||||||
@@ -598,13 +597,13 @@ export class CanvasLayers {
|
|||||||
}
|
}
|
||||||
|
|
||||||
async getFlattenedSelectionAsBlob() {
|
async getFlattenedSelectionAsBlob() {
|
||||||
if (this.canvasLayers.selectedLayers.length === 0) {
|
if (this.canvas.selectedLayers.length === 0) {
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
return new Promise((resolve) => {
|
return new Promise((resolve) => {
|
||||||
let minX = Infinity, minY = Infinity, maxX = -Infinity, maxY = -Infinity;
|
let minX = Infinity, minY = Infinity, maxX = -Infinity, maxY = -Infinity;
|
||||||
this.canvasLayers.selectedLayers.forEach(layer => {
|
this.canvas.selectedLayers.forEach(layer => {
|
||||||
const centerX = layer.x + layer.width / 2;
|
const centerX = layer.x + layer.width / 2;
|
||||||
const centerY = layer.y + layer.height / 2;
|
const centerY = layer.y + layer.height / 2;
|
||||||
const rad = layer.rotation * Math.PI / 180;
|
const rad = layer.rotation * Math.PI / 180;
|
||||||
@@ -646,7 +645,7 @@ export class CanvasLayers {
|
|||||||
|
|
||||||
tempCtx.translate(-minX, -minY);
|
tempCtx.translate(-minX, -minY);
|
||||||
|
|
||||||
const sortedSelection = [...this.canvasLayers.selectedLayers].sort((a, b) => a.zIndex - b.zIndex);
|
const sortedSelection = [...this.canvas.selectedLayers].sort((a, b) => a.zIndex - b.zIndex);
|
||||||
|
|
||||||
sortedSelection.forEach(layer => {
|
sortedSelection.forEach(layer => {
|
||||||
if (!layer.image) return;
|
if (!layer.image) return;
|
||||||
|
|||||||
@@ -674,17 +674,17 @@ async function createCanvasWidget(node, widget, app) {
|
|||||||
$el("button.painter-button.requires-selection", {
|
$el("button.painter-button.requires-selection", {
|
||||||
textContent: "Rotate +90°",
|
textContent: "Rotate +90°",
|
||||||
title: "Rotate selected layer(s) by +90 degrees",
|
title: "Rotate selected layer(s) by +90 degrees",
|
||||||
onclick: () => canvas.rotateLayer(90)
|
onclick: () => canvas.canvasLayers.rotateLayer(90)
|
||||||
}),
|
}),
|
||||||
$el("button.painter-button.requires-selection", {
|
$el("button.painter-button.requires-selection", {
|
||||||
textContent: "Scale +5%",
|
textContent: "Scale +5%",
|
||||||
title: "Increase size of selected layer(s) by 5%",
|
title: "Increase size of selected layer(s) by 5%",
|
||||||
onclick: () => canvas.resizeLayer(1.05)
|
onclick: () => canvas.canvasLayers.resizeLayer(1.05)
|
||||||
}),
|
}),
|
||||||
$el("button.painter-button.requires-selection", {
|
$el("button.painter-button.requires-selection", {
|
||||||
textContent: "Scale -5%",
|
textContent: "Scale -5%",
|
||||||
title: "Decrease size of selected layer(s) by 5%",
|
title: "Decrease size of selected layer(s) by 5%",
|
||||||
onclick: () => canvas.resizeLayer(0.95)
|
onclick: () => canvas.canvasLayers.resizeLayer(0.95)
|
||||||
}),
|
}),
|
||||||
$el("button.painter-button.requires-selection", {
|
$el("button.painter-button.requires-selection", {
|
||||||
textContent: "Mirror H",
|
textContent: "Mirror H",
|
||||||
|
|||||||
@@ -162,11 +162,18 @@ canvas.imageReferenceManager.manualGarbageCollection()
|
|||||||
- CanvasView.js używa nowego podejścia modułowego
|
- CanvasView.js używa nowego podejścia modułowego
|
||||||
- Dokumentacja została zaktualizowana
|
- Dokumentacja została zaktualizowana
|
||||||
|
|
||||||
|
3. **Finalne poprawki architektury** ✅
|
||||||
|
- Poprawiono konstruktor CanvasLayers.js - zmieniono mylącą nazwę parametru z `canvasLayers` na `canvas`
|
||||||
|
- Zaktualizowano wszystkie odwołania `this.canvasLayers.` na `this.canvas.` w CanvasLayers.js
|
||||||
|
- Poprawiono wywołania w CanvasView.js - `canvas.rotateLayer()` → `canvas.canvasLayers.rotateLayer()`
|
||||||
|
- Wszystkie moduły używają teraz spójnej konwencji nazewnictwa
|
||||||
|
|
||||||
## Uwagi dla deweloperów
|
## Uwagi dla deweloperów
|
||||||
|
|
||||||
- ✅ **Refaktoryzacja zakończona** - wszystkie pliki zostały zaktualizowane
|
- ✅ **Refaktoryzacja zakończona** - wszystkie pliki zostały zaktualizowane
|
||||||
- ✅ **Nowy kod** używa modułów bezpośrednio zgodnie z wzorcem fasady
|
- ✅ **Nowy kod** używa modułów bezpośrednio zgodnie z wzorcem fasady
|
||||||
- ✅ **Wszystkie delegacje** wskazują na istniejące metody w modułach
|
- ✅ **Wszystkie delegacje** wskazują na istniejące metody w modułach
|
||||||
|
- ✅ **Spójna architektura** - wszystkie moduły używają poprawnych referencji
|
||||||
- ⚠️ **Metody delegujące** są zachowane dla kompatybilności, ale oznaczone jako tymczasowe
|
- ⚠️ **Metody delegujące** są zachowane dla kompatybilności, ale oznaczone jako tymczasowe
|
||||||
- 📚 **Dokumentacja** została zaktualizowana w tym przewodniku
|
- 📚 **Dokumentacja** została zaktualizowana w tym przewodniku
|
||||||
- 🔄 **Kompatybilność** z istniejącym kodem jest zachowana
|
- 🔄 **Kompatybilność** z istniejącym kodem jest zachowana
|
||||||
|
|||||||
Reference in New Issue
Block a user