tp-flow-nodes/panning.js

127 lines
3.8 KiB
JavaScript
Raw Normal View History

2024-12-18 21:27:29 +01:00
import { TpFlowNode } from './tp-flow-node.js';
export const panning = function(superClass) {
return class extends superClass {
static get properties() {
return {
isDragging: { type: Boolean },
currentX: { type: Number },
currentY: { type: Number },
initialX: { type: Number },
initialY: { type: Number },
xOffset: { type: Number },
yOffset: { type: Number },
highestZIndex: { type: Number }
};
}
constructor() {
super();
this.isDragging = false;
this.currentX = 0;
this.currentY = 0;
this.initialX = 0;
this.initialY = 0;
this.xOffset = 0;
this.yOffset = 0;
this.targetElement = null;
this.highestZIndex = 1;
}
firstUpdated() {
this.canvas = this.shadowRoot.querySelector('.canvas');
this.addEventListener('mousedown', this._startDrag.bind(this));
document.addEventListener('mousemove', this._drag.bind(this));
document.addEventListener('mouseup', this._endDrag.bind(this));
2024-12-18 22:11:06 +01:00
super.firstUpdated();
2024-12-18 21:27:29 +01:00
}
_getTopNodeAtPoint(x, y) {
const nodes = this.shadowRoot.elementsFromPoint(x, y)
.filter(el => el instanceof TpFlowNode)
.sort((a, b) => {
const aZ = parseInt(getComputedStyle(a).zIndex) || 0;
const bZ = parseInt(getComputedStyle(b).zIndex) || 0;
return bZ - aZ;
});
return nodes[0] || null;
}
_bringToFront(element) {
if (!(element instanceof TpFlowNode)) return;
this.highestZIndex++;
element.style.zIndex = this.highestZIndex;
}
_startDrag(e) {
const topNode = this._getTopNodeAtPoint(e.clientX, e.clientY);
if (topNode) {
this.targetElement = topNode;
this._bringToFront(topNode);
} else {
this.targetElement = this.canvas;
}
if (this.targetElement) {
this.isDragging = true;
const transform = window.getComputedStyle(this.targetElement).transform;
const matrix = new DOMMatrix(transform);
this.xOffset = matrix.m41;
this.yOffset = matrix.m42;
2024-12-18 22:27:27 +01:00
if (this.targetElement === this.canvas) {
this.initialX = e.clientX - this.xOffset;
this.initialY = e.clientY - this.yOffset;
} else {
// For nodes, compensate for scale in initial position too
this.initialX = e.clientX - (this.xOffset * this.scale);
this.initialY = e.clientY - (this.yOffset * this.scale);
}
2024-12-18 21:27:29 +01:00
}
}
_drag(e) {
if (this.isDragging && this.targetElement) {
e.preventDefault();
2024-12-18 22:27:27 +01:00
if (this.targetElement === this.canvas) {
// For canvas panning, no scale compensation needed
this.currentX = e.clientX - this.initialX;
this.currentY = e.clientY - this.initialY;
this.targetElement.style.transform =
`translate(${this.currentX}px, ${this.currentY}px) scale(${this.scale})`;
} else {
// For nodes, compensate for canvas scale
this.currentX = (e.clientX - this.initialX) / this.scale;
this.currentY = (e.clientY - this.initialY) / this.scale;
this.targetElement.style.transform =
`translate(${this.currentX}px, ${this.currentY}px)`;
}
2024-12-20 10:29:39 +01:00
this.requestUpdate();
2024-12-18 21:27:29 +01:00
}
}
_endDrag() {
2024-12-20 10:29:39 +01:00
if (this.isDragging && this.targetElement instanceof TpFlowNode) {
this._dispatchChangeEvent({
type: 'node-moved',
data: {
nodeId: this.targetElement.id,
position: {
x: this.currentX,
y: this.currentY
}
}
});
}
2024-12-18 21:27:29 +01:00
this.isDragging = false;
this.targetElement = null;
}
};
};