Added focus on canvas

This commit is contained in:
Dariusz L
2025-06-21 03:01:49 +02:00
parent c46054e442
commit 181d9c89c7
2 changed files with 67 additions and 54 deletions

View File

@@ -84,6 +84,10 @@ export class Canvas {
this.canvas.style.backgroundColor = '#606060'; this.canvas.style.backgroundColor = '#606060';
this.canvas.style.width = '100%'; this.canvas.style.width = '100%';
this.canvas.style.height = '100%'; this.canvas.style.height = '100%';
this.canvas.tabIndex = 0;
this.canvas.style.outline = 'none';
} }
setupEventListeners() { setupEventListeners() {
@@ -93,8 +97,9 @@ export class Canvas {
this.canvas.addEventListener('mouseleave', this.handleMouseLeave.bind(this)); this.canvas.addEventListener('mouseleave', this.handleMouseLeave.bind(this));
this.canvas.addEventListener('wheel', this.handleWheel.bind(this), {passive: false}); this.canvas.addEventListener('wheel', this.handleWheel.bind(this), {passive: false});
document.addEventListener('keydown', this.handleKeyDown.bind(this));
document.addEventListener('keyup', this.handleKeyUp.bind(this)); this.canvas.addEventListener('keydown', this.handleKeyDown.bind(this));
this.canvas.addEventListener('keyup', this.handleKeyUp.bind(this));
this.canvas.addEventListener('mouseenter', () => { this.canvas.addEventListener('mouseenter', () => {
this.isMouseOver = true; this.isMouseOver = true;
@@ -124,8 +129,11 @@ export class Canvas {
this.canvas.style.cursor = 'default'; this.canvas.style.cursor = 'default';
} }
handleMouseDown(e) { handleMouseDown(e) {
this.canvas.focus();
const currentTime = Date.now(); const currentTime = Date.now();
const worldCoords = this.getMouseWorldCoordinates(e); const worldCoords = this.getMouseWorldCoordinates(e);
if (e.shiftKey && e.ctrlKey) { if (e.shiftKey && e.ctrlKey) {
@@ -381,33 +389,30 @@ export class Canvas {
this.render(); this.render();
} }
handleKeyDown(e) { handleKeyDown(e) {
if (this.isMouseOver) {
if (e.ctrlKey && e.key.toLowerCase() === 'c') {
if (this.selectedLayers.length > 0) {
e.preventDefault();
e.stopPropagation();
this.copySelectedLayers();
return;
}
}
if (e.ctrlKey && e.key.toLowerCase() === 'v') {
e.preventDefault();
e.stopPropagation();
this.handlePaste();
return;
}
}
if (e.key === 'Control') this.interaction.isCtrlPressed = true; if (e.key === 'Control') this.interaction.isCtrlPressed = true;
if (e.key === 'Alt') { if (e.key === 'Alt') {
this.interaction.isAltPressed = true; this.interaction.isAltPressed = true;
e.preventDefault(); e.preventDefault();
} }
if (e.ctrlKey && e.key.toLowerCase() === 'c') {
if (this.selectedLayers.length > 0) {
e.preventDefault();
e.stopPropagation();
this.copySelectedLayers();
return;
}
}
if (e.ctrlKey && e.key.toLowerCase() === 'v') {
e.preventDefault();
e.stopPropagation();
this.handlePaste();
return;
}
if (this.selectedLayer) { if (this.selectedLayer) {
if (e.key === 'Delete') { if (e.key === 'Delete') {
e.preventDefault();
e.stopPropagation();
this.layers = this.layers.filter(l => !this.selectedLayers.includes(l)); this.layers = this.layers.filter(l => !this.selectedLayers.includes(l));
this.updateSelection([]); this.updateSelection([]);
this.render(); this.render();
@@ -418,39 +423,31 @@ export class Canvas {
let needsRender = false; let needsRender = false;
switch (e.code) { switch (e.code) {
case 'ArrowLeft': case 'ArrowLeft':
this.selectedLayers.forEach(l => l.x -= step);
needsRender = true;
break;
case 'ArrowRight': case 'ArrowRight':
this.selectedLayers.forEach(l => l.x += step);
needsRender = true;
break;
case 'ArrowUp': case 'ArrowUp':
this.selectedLayers.forEach(l => l.y -= step);
needsRender = true;
break;
case 'ArrowDown': case 'ArrowDown':
this.selectedLayers.forEach(l => l.y += step);
needsRender = true;
break;
case 'BracketLeft': case 'BracketLeft':
this.selectedLayers.forEach(l => l.rotation -= step);
needsRender = true;
break;
case 'BracketRight': case 'BracketRight':
this.selectedLayers.forEach(l => l.rotation += step); e.preventDefault();
e.stopPropagation();
if (e.code === 'ArrowLeft') this.selectedLayers.forEach(l => l.x -= step);
if (e.code === 'ArrowRight') this.selectedLayers.forEach(l => l.x += step);
if (e.code === 'ArrowUp') this.selectedLayers.forEach(l => l.y -= step);
if (e.code === 'ArrowDown') this.selectedLayers.forEach(l => l.y += step);
if (e.code === 'BracketLeft') this.selectedLayers.forEach(l => l.rotation -= step);
if (e.code === 'BracketRight') this.selectedLayers.forEach(l => l.rotation += step);
needsRender = true; needsRender = true;
break; break;
} }
if (needsRender) { if (needsRender) {
e.preventDefault();
this.render(); this.render();
} }
} }
} }
handleKeyUp(e) { handleKeyUp(e) {
if (e.key === 'Control') this.interaction.isCtrlPressed = false; if (e.key === 'Control') this.interaction.isCtrlPressed = false;
if (e.key === 'Alt') this.interaction.isAltPressed = false; if (e.key === 'Alt') this.interaction.isAltPressed = false;
@@ -1444,7 +1441,6 @@ export class Canvas {
} }
async getFlattenedSelectionAsBlob() { async getFlattenedSelectionAsBlob() {
if (this.selectedLayers.length === 0) { if (this.selectedLayers.length === 0) {
return null; return null;

View File

@@ -171,6 +171,15 @@ async function createCanvasWidget(node, widget, app) {
font-size: 12px; font-size: 12px;
color: #d0d0d0; color: #d0d0d0;
} }
.painter-container.has-focus {
/* Używamy box-shadow, aby stworzyć efekt zewnętrznej ramki,
która nie wpłynie na rozmiar ani pozycję elementu. */
box-shadow: 0 0 0 2px white;
/* Możesz też zmienić kolor istniejącej ramki, ale box-shadow jest bardziej wyrazisty */
/* border-color: white; */
}
`; `;
document.head.appendChild(style); document.head.appendChild(style);
@@ -251,7 +260,6 @@ async function createCanvasWidget(node, widget, app) {
}, },
onmouseenter: (e) => { onmouseenter: (e) => {
const rect = e.target.getBoundingClientRect(); const rect = e.target.getBoundingClientRect();
// Pozycjonujemy dymek pod przyciskiem
helpTooltip.style.left = `${rect.left}px`; helpTooltip.style.left = `${rect.left}px`;
helpTooltip.style.top = `${rect.bottom + 5}px`; helpTooltip.style.top = `${rect.bottom + 5}px`;
helpTooltip.style.display = 'block'; helpTooltip.style.display = 'block';
@@ -634,6 +642,15 @@ async function createCanvasWidget(node, widget, app) {
} }
}, [canvas.canvas]); }, [canvas.canvas]);
canvas.canvas.addEventListener('focus', () => {
canvasContainer.classList.add('has-focus');
});
canvas.canvas.addEventListener('blur', () => {
canvasContainer.classList.remove('has-focus');
});
node.onResize = function () { node.onResize = function () {
canvas.render(); canvas.render();
}; };
@@ -641,6 +658,7 @@ async function createCanvasWidget(node, widget, app) {
canvas.canvas.addEventListener('mouseup', updateOutput); canvas.canvas.addEventListener('mouseup', updateOutput);
canvas.canvas.addEventListener('mouseleave', updateOutput); canvas.canvas.addEventListener('mouseleave', updateOutput);
const mainContainer = $el("div.painterMainContainer", { const mainContainer = $el("div.painterMainContainer", {
style: { style: {
position: "relative", position: "relative",
@@ -1008,7 +1026,6 @@ app.registerExtension({
const onRemoved = nodeType.prototype.onRemoved; const onRemoved = nodeType.prototype.onRemoved;
nodeType.prototype.onRemoved = function () { nodeType.prototype.onRemoved = function () {
// Usuń dymek z podpowiedziami, jeśli istnieje
const tooltip = document.getElementById(`painter-help-tooltip-${this.id}`); const tooltip = document.getElementById(`painter-help-tooltip-${this.id}`);
if (tooltip) { if (tooltip) {
tooltip.remove(); tooltip.remove();