wip
This commit is contained in:
		@@ -101,13 +101,13 @@ export const connections = function(superClass) {
 | 
			
		||||
      const canvasRect = this.canvas.getBoundingClientRect();
 | 
			
		||||
 | 
			
		||||
      const start = {
 | 
			
		||||
        x: sourceRect.left + sourceRect.width/2 - canvasRect.left,
 | 
			
		||||
        y: sourceRect.top + sourceRect.height/2 - canvasRect.top
 | 
			
		||||
        x: (sourceRect.left + sourceRect.width/2 - canvasRect.left) / this.scale,
 | 
			
		||||
        y: (sourceRect.top + sourceRect.height/2 - canvasRect.top) / this.scale
 | 
			
		||||
      };
 | 
			
		||||
      
 | 
			
		||||
      const end = {
 | 
			
		||||
        x: this.mousePosition.x - canvasRect.left,
 | 
			
		||||
        y: this.mousePosition.y - canvasRect.top
 | 
			
		||||
        x: (this.mousePosition.x - canvasRect.left) / this.scale,
 | 
			
		||||
        y: (this.mousePosition.y - canvasRect.top) / this.scale
 | 
			
		||||
      };
 | 
			
		||||
 | 
			
		||||
      const controlPoint1 = {
 | 
			
		||||
@@ -150,13 +150,13 @@ export const connections = function(superClass) {
 | 
			
		||||
      const canvasRect = this.canvas.getBoundingClientRect();
 | 
			
		||||
 | 
			
		||||
      const start = {
 | 
			
		||||
        x: sourceRect.left + sourceRect.width/2 - canvasRect.left,
 | 
			
		||||
        y: sourceRect.top + sourceRect.height/2 - canvasRect.top
 | 
			
		||||
        x: (sourceRect.left + sourceRect.width/2 - canvasRect.left) / this.scale,
 | 
			
		||||
        y: (sourceRect.top + sourceRect.height/2 - canvasRect.top) / this.scale
 | 
			
		||||
      };
 | 
			
		||||
      
 | 
			
		||||
      const end = {
 | 
			
		||||
        x: targetRect.left + targetRect.width/2 - canvasRect.left,
 | 
			
		||||
        y: targetRect.top + targetRect.height/2 - canvasRect.top
 | 
			
		||||
        x: (targetRect.left + targetRect.width/2 - canvasRect.left) / this.scale,
 | 
			
		||||
        y: (targetRect.top + targetRect.height/2 - canvasRect.top) / this.scale
 | 
			
		||||
      };
 | 
			
		||||
 | 
			
		||||
      const controlPoint1 = {
 | 
			
		||||
 
 | 
			
		||||
							
								
								
									
										16
									
								
								panning.js
									
									
									
									
									
								
							
							
						
						
									
										16
									
								
								panning.js
									
									
									
									
									
								
							@@ -73,8 +73,14 @@ export const panning = function(superClass) {
 | 
			
		||||
        this.xOffset = matrix.m41;
 | 
			
		||||
        this.yOffset = matrix.m42;
 | 
			
		||||
        
 | 
			
		||||
        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);
 | 
			
		||||
        }
 | 
			
		||||
      }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
@@ -82,13 +88,21 @@ export const panning = function(superClass) {
 | 
			
		||||
      if (this.isDragging && this.targetElement) {
 | 
			
		||||
        e.preventDefault();
 | 
			
		||||
        
 | 
			
		||||
        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)`;
 | 
			
		||||
        }
 | 
			
		||||
      }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    _endDrag() {
 | 
			
		||||
      this.isDragging = false;
 | 
			
		||||
 
 | 
			
		||||
@@ -7,8 +7,9 @@ This program is available under Apache License Version 2.0
 | 
			
		||||
import { LitElement, html, css } from 'lit';
 | 
			
		||||
import { connections, connectionStyles } from './connections.js';
 | 
			
		||||
import { panning } from './panning.js';
 | 
			
		||||
import { zoom } from './zoom.js';
 | 
			
		||||
 | 
			
		||||
class TpFlowNodes extends panning(connections(LitElement)) {
 | 
			
		||||
class TpFlowNodes extends zoom(panning(connections(LitElement))) {
 | 
			
		||||
  static get styles() {
 | 
			
		||||
    return [
 | 
			
		||||
      connectionStyles,
 | 
			
		||||
@@ -23,8 +24,10 @@ class TpFlowNodes extends panning(connections(LitElement)) {
 | 
			
		||||
          width: 100%;
 | 
			
		||||
          height: 100%;
 | 
			
		||||
          user-select: none;
 | 
			
		||||
          position: relative;
 | 
			
		||||
          overflow: hidden;
 | 
			
		||||
          position: absolute;
 | 
			
		||||
          min-width: 100%;
 | 
			
		||||
          min-height: 100%;
 | 
			
		||||
          overflow: visible;
 | 
			
		||||
          transform: translate(0px, 0px);
 | 
			
		||||
        }
 | 
			
		||||
      `
 | 
			
		||||
 
 | 
			
		||||
							
								
								
									
										91
									
								
								zoom.js
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										91
									
								
								zoom.js
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,91 @@
 | 
			
		||||
export const zoom = function(superClass) {
 | 
			
		||||
  return class extends superClass {
 | 
			
		||||
    static get properties() {
 | 
			
		||||
      return {
 | 
			
		||||
        scale: { type: Number }
 | 
			
		||||
      };
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    constructor() {
 | 
			
		||||
      super();
 | 
			
		||||
      this.scale = 1;
 | 
			
		||||
      this._handleWheel = this._handleWheel.bind(this);
 | 
			
		||||
      this.MIN_SCALE = 0.1;
 | 
			
		||||
      this.MAX_SCALE = 1.0;
 | 
			
		||||
      this.SCALE_STEP = 0.1;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    firstUpdated() {
 | 
			
		||||
      super.firstUpdated();
 | 
			
		||||
      this.canvas = this.shadowRoot.querySelector('.canvas');
 | 
			
		||||
      this.addEventListener('wheel', this._handleWheel, { passive: false });
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    _handleWheel(e) {
 | 
			
		||||
      e.preventDefault();
 | 
			
		||||
      
 | 
			
		||||
      if (e.deltaY > 0) {
 | 
			
		||||
        this.zoomOut();
 | 
			
		||||
      } else if (e.deltaY < 0) {
 | 
			
		||||
        this.zoomIn();
 | 
			
		||||
      }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * Zooms out the canvas by one step
 | 
			
		||||
     * @returns {boolean} True if zoom was applied, false if already at minimum
 | 
			
		||||
     */
 | 
			
		||||
    zoomOut() {
 | 
			
		||||
      const newScale = Math.max(this.MIN_SCALE, this.scale - this.SCALE_STEP);
 | 
			
		||||
      if (newScale !== this.scale) {
 | 
			
		||||
        this._applyZoom(newScale);
 | 
			
		||||
        return true;
 | 
			
		||||
      }
 | 
			
		||||
      return false;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * Zooms in the canvas by one step
 | 
			
		||||
     * @returns {boolean} True if zoom was applied, false if already at maximum
 | 
			
		||||
     */
 | 
			
		||||
    zoomIn() {
 | 
			
		||||
      const newScale = Math.min(this.MAX_SCALE, this.scale + this.SCALE_STEP);
 | 
			
		||||
      if (newScale !== this.scale) {
 | 
			
		||||
        this._applyZoom(newScale);
 | 
			
		||||
        return true;
 | 
			
		||||
      }
 | 
			
		||||
      return false;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * Immediately resets zoom to 100%
 | 
			
		||||
     */
 | 
			
		||||
    resetZoom() {
 | 
			
		||||
      this._applyZoom(this.MAX_SCALE);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * Applies the zoom scale to the canvas
 | 
			
		||||
     * @private
 | 
			
		||||
     */
 | 
			
		||||
    _applyZoom(newScale) {
 | 
			
		||||
      this.scale = newScale;
 | 
			
		||||
      
 | 
			
		||||
      // Get current translation
 | 
			
		||||
      const transform = window.getComputedStyle(this.canvas).transform;
 | 
			
		||||
      const matrix = new DOMMatrix(transform);
 | 
			
		||||
      const currentX = matrix.m41;
 | 
			
		||||
      const currentY = matrix.m42;
 | 
			
		||||
    
 | 
			
		||||
      // Apply both transforms
 | 
			
		||||
      this.canvas.style.transform = `translate(${currentX}px, ${currentY}px) scale(${this.scale})`;
 | 
			
		||||
      this.canvas.style.transformOrigin = 'center center';
 | 
			
		||||
      this.requestUpdate();
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    disconnectedCallback() {
 | 
			
		||||
      super.disconnectedCallback();
 | 
			
		||||
      this.removeEventListener('wheel', this._handleWheel);
 | 
			
		||||
    }
 | 
			
		||||
  };
 | 
			
		||||
}
 | 
			
		||||
		Reference in New Issue
	
	Block a user