Erweiterungen
This commit is contained in:
Binary file not shown.
@@ -310,12 +310,68 @@ window.initProfileInvoiceGenerator = function() {
|
||||
return x >= ex && x <= ex + ew && y >= ey && y <= ey + eh;
|
||||
}
|
||||
|
||||
// Resizing state
|
||||
var isResizing = false;
|
||||
var resizeHandle = -1;
|
||||
var resizeStart = { x: 0, y: 0, width: 0, height: 0 };
|
||||
|
||||
// Helper function to check if a point is on a resize handle
|
||||
function getResizeHandle(x, y, el) {
|
||||
if (!el || el.isStatic) return -1;
|
||||
|
||||
var ex = pageX + (el.x * zoomFactor);
|
||||
var ey = pageY + (el.y * zoomFactor);
|
||||
var ew = (el.width || 100) * zoomFactor;
|
||||
var eh = (el.height || 30) * zoomFactor;
|
||||
var hs = Math.max(6, 8 * zoomFactor);
|
||||
var halfHs = hs / 2;
|
||||
|
||||
// Handle positions: 0=TL, 1=TC, 2=TR, 3=ML, 4=MR, 5=BL, 6=BC, 7=BR
|
||||
var handles = [
|
||||
{ x: ex - halfHs, y: ey - halfHs },
|
||||
{ x: ex + ew/2 - halfHs, y: ey - halfHs },
|
||||
{ x: ex + ew - halfHs, y: ey - halfHs },
|
||||
{ x: ex - halfHs, y: ey + eh/2 - halfHs },
|
||||
{ x: ex + ew - halfHs, y: ey + eh/2 - halfHs },
|
||||
{ x: ex - halfHs, y: ey + eh - halfHs },
|
||||
{ x: ex + ew/2 - halfHs, y: ey + eh - halfHs },
|
||||
{ x: ex + ew - halfHs, y: ey + eh - halfHs }
|
||||
];
|
||||
|
||||
for (var i = 0; i < handles.length; i++) {
|
||||
if (x >= handles[i].x && x <= handles[i].x + hs &&
|
||||
y >= handles[i].y && y <= handles[i].y + hs) {
|
||||
return i;
|
||||
}
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
|
||||
// Mouse events
|
||||
canvas.addEventListener('mousedown', function(e) {
|
||||
var rect = canvas.getBoundingClientRect();
|
||||
var x = e.clientX - rect.left;
|
||||
var y = e.clientY - rect.top;
|
||||
|
||||
// Check if clicking on a resize handle of selected element
|
||||
if (selectedElement) {
|
||||
var handle = getResizeHandle(x, y, selectedElement);
|
||||
if (handle >= 0) {
|
||||
isResizing = true;
|
||||
resizeHandle = handle;
|
||||
resizeStart = {
|
||||
x: x,
|
||||
y: y,
|
||||
width: selectedElement.width || 100,
|
||||
height: selectedElement.height || 30,
|
||||
elemX: selectedElement.x,
|
||||
elemY: selectedElement.y
|
||||
};
|
||||
e.preventDefault();
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
// Check if clicking on an element
|
||||
var clickedElement = null;
|
||||
for (var i = elements.length - 1; i >= 0; i--) {
|
||||
@@ -345,7 +401,62 @@ window.initProfileInvoiceGenerator = function() {
|
||||
var x = e.clientX - rect.left;
|
||||
var y = e.clientY - rect.top;
|
||||
|
||||
if (isDragging && selectedElement) {
|
||||
if (isResizing && selectedElement) {
|
||||
// Calculate delta in base coordinates
|
||||
var dx = (x - resizeStart.x) / zoomFactor;
|
||||
var dy = (y - resizeStart.y) / zoomFactor;
|
||||
|
||||
var newWidth = resizeStart.width;
|
||||
var newHeight = resizeStart.height;
|
||||
var newX = resizeStart.elemX;
|
||||
var newY = resizeStart.elemY;
|
||||
|
||||
// Handle indices: 0=TL, 1=TC, 2=TR, 3=ML, 4=MR, 5=BL, 6=BC, 7=BR
|
||||
switch(resizeHandle) {
|
||||
case 0: // Top-left
|
||||
newWidth = Math.max(20, resizeStart.width - dx);
|
||||
newHeight = Math.max(20, resizeStart.height - dy);
|
||||
newX = resizeStart.elemX + (resizeStart.width - newWidth);
|
||||
newY = resizeStart.elemY + (resizeStart.height - newHeight);
|
||||
break;
|
||||
case 1: // Top-center
|
||||
newHeight = Math.max(20, resizeStart.height - dy);
|
||||
newY = resizeStart.elemY + (resizeStart.height - newHeight);
|
||||
break;
|
||||
case 2: // Top-right
|
||||
newWidth = Math.max(20, resizeStart.width + dx);
|
||||
newHeight = Math.max(20, resizeStart.height - dy);
|
||||
newY = resizeStart.elemY + (resizeStart.height - newHeight);
|
||||
break;
|
||||
case 3: // Middle-left
|
||||
newWidth = Math.max(20, resizeStart.width - dx);
|
||||
newX = resizeStart.elemX + (resizeStart.width - newWidth);
|
||||
break;
|
||||
case 4: // Middle-right
|
||||
newWidth = Math.max(20, resizeStart.width + dx);
|
||||
break;
|
||||
case 5: // Bottom-left
|
||||
newWidth = Math.max(20, resizeStart.width - dx);
|
||||
newHeight = Math.max(20, resizeStart.height + dy);
|
||||
newX = resizeStart.elemX + (resizeStart.width - newWidth);
|
||||
break;
|
||||
case 6: // Bottom-center
|
||||
newHeight = Math.max(20, resizeStart.height + dy);
|
||||
break;
|
||||
case 7: // Bottom-right
|
||||
newWidth = Math.max(20, resizeStart.width + dx);
|
||||
newHeight = Math.max(20, resizeStart.height + dy);
|
||||
break;
|
||||
}
|
||||
|
||||
selectedElement.width = snapToGrid(newWidth);
|
||||
selectedElement.height = snapToGrid(newHeight);
|
||||
selectedElement.x = snapToGrid(newX);
|
||||
selectedElement.y = snapToGrid(newY);
|
||||
|
||||
draw();
|
||||
notifyElementSelected(selectedElement);
|
||||
} else if (isDragging && selectedElement) {
|
||||
// Adjust mouse movement by zoom factor to get stored coordinates
|
||||
var dx = (x - dragStart.x) / zoomFactor;
|
||||
var dy = (y - dragStart.y) / zoomFactor;
|
||||
@@ -364,25 +475,47 @@ window.initProfileInvoiceGenerator = function() {
|
||||
draw();
|
||||
notifyElementSelected(selectedElement);
|
||||
} else {
|
||||
// Update cursor
|
||||
var hovering = false;
|
||||
for (var i = elements.length - 1; i >= 0; i--) {
|
||||
if (hitTest(x, y, elements[i])) {
|
||||
hovering = true;
|
||||
break;
|
||||
// Update cursor based on resize handles or element hover
|
||||
if (selectedElement && !selectedElement.isStatic) {
|
||||
var handle = getResizeHandle(x, y, selectedElement);
|
||||
if (handle >= 0) {
|
||||
// Set cursor based on handle type
|
||||
var cursors = ['nwse-resize', 'ns-resize', 'nesw-resize', 'ew-resize', 'ew-resize', 'nesw-resize', 'ns-resize', 'nwse-resize'];
|
||||
canvas.style.cursor = cursors[handle];
|
||||
} else {
|
||||
var hovering = false;
|
||||
for (var i = elements.length - 1; i >= 0; i--) {
|
||||
if (hitTest(x, y, elements[i])) {
|
||||
hovering = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
canvas.style.cursor = hovering ? 'move' : 'default';
|
||||
}
|
||||
} else {
|
||||
var hovering = false;
|
||||
for (var i = elements.length - 1; i >= 0; i--) {
|
||||
if (hitTest(x, y, elements[i])) {
|
||||
hovering = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
canvas.style.cursor = hovering ? 'move' : 'default';
|
||||
}
|
||||
canvas.style.cursor = hovering ? 'move' : 'default';
|
||||
}
|
||||
});
|
||||
|
||||
canvas.addEventListener('mouseup', function() {
|
||||
isDragging = false;
|
||||
isResizing = false;
|
||||
resizeHandle = -1;
|
||||
canvas.style.cursor = 'default';
|
||||
});
|
||||
|
||||
canvas.addEventListener('mouseleave', function() {
|
||||
isDragging = false;
|
||||
isResizing = false;
|
||||
resizeHandle = -1;
|
||||
canvas.style.cursor = 'default';
|
||||
});
|
||||
|
||||
|
||||
Reference in New Issue
Block a user