Browse Source

Update click drag scroll (#24)

Lutz Roeder 4 years ago
parent
commit
d9b3ac5cfa
4 changed files with 116 additions and 114 deletions
  1. 1 1
      source/electron.html
  2. 1 1
      source/index.html
  3. 29 29
      source/view-sidebar.js
  4. 85 83
      source/view.js

+ 1 - 1
source/electron.html

@@ -14,7 +14,7 @@ button { font-family: -apple-system, BlinkMacSystemFont, "Segoe WPC", "Segoe UI"
 .center { position: absolute; margin: auto; top: 0; right: 0; bottom: 0; left: 0; user-select: none; -webkit-user-select: none; -moz-user-select: none; }
 .select { user-select: text; -webkit-user-select: text; -moz-user-select: text; }
 .open-file-dialog { display: none; }
-.graph { touch-action: pan-x pan-y; overflow: auto; width: 100%; height: 100%; outline: none; }
+.graph { touch-action: pan-x pan-y; overflow: auto; height: 100%; outline: none; }
 .canvas { display: block; position: absolute; text-rendering: geometricPrecision; user-select: none; -webkit-user-select: none; -moz-user-select: none; }
 .toolbar { position: absolute; top: 10px; left: 10px; padding: 0; margin: 0; user-select: none; -webkit-user-select: none; -moz-user-select: none; }
 .toolbar button:focus { outline: 0; }

+ 1 - 1
source/index.html

@@ -34,7 +34,7 @@ button { font-family: -apple-system, BlinkMacSystemFont, "Segoe WPC", "Segoe UI"
 .select { user-select: text; -webkit-user-select: text; -moz-user-select: text; }
 .open-file-dialog { display: none; }
 .transparent { width: 100%; height: 100%; background-color: #000000; display: none; opacity: 0; }
-.graph { touch-action: pan-x pan-y; overflow: auto; width: 100%; height: 100%; outline: none; }
+.graph { touch-action: pan-x pan-y; overflow: auto; height: 100%; outline: none; }
 .canvas { display: block; position: absolute; text-rendering: geometricPrecision; user-select: none; -webkit-user-select: none; -moz-user-select: none; }
 .toolbar { position: absolute; top: 10px; left: 10px; padding: 0; margin: 0; user-select: none; -webkit-user-select: none; -moz-user-select: none; }
 .toolbar button:focus { outline: 0; }

+ 29 - 29
source/view-sidebar.js

@@ -55,20 +55,20 @@ sidebar.Sidebar = class {
     }
 
     _hide() {
-        const sidebarElement = this._getElementById('sidebar');
-        if (sidebarElement) {
-            sidebarElement.style.width = '0';
+        const sidebar = this._getElementById('sidebar');
+        if (sidebar) {
+            sidebar.style.width = '0px';
         }
-        const graphElement = this._getElementById('graph');
-        if (graphElement) {
-            graphElement.style.marginRight = '0';
-            graphElement.focus();
+        const graph = this._getElementById('graph');
+        if (graph) {
+            graph.style.marginRight = '0px';
+            graph.focus();
         }
     }
 
     _deactivate() {
-        const sidebarElement = this._getElementById('sidebar');
-        if (sidebarElement) {
+        const sidebar = this._getElementById('sidebar');
+        if (sidebar) {
             const closeButton = this._getElementById('sidebar-closebutton');
             if (closeButton) {
                 closeButton.removeEventListener('click', this._closeSidebarHandler);
@@ -81,14 +81,14 @@ sidebar.Sidebar = class {
 
     _activate(item) {
         const width = 'min(calc(100vw * 0.6), 500px)';
-        const sidebarElement = this._getElementById('sidebar');
-        if (sidebarElement) {
-            sidebarElement.innerHTML = '';
+        const sidebar = this._getElementById('sidebar');
+        if (sidebar) {
+            sidebar.innerHTML = '';
 
-            const titleElement = this._host.document.createElement('h1');
-            titleElement.classList.add('sidebar-title');
-            titleElement.innerHTML = item.title ? item.title.toUpperCase() : '';
-            sidebarElement.appendChild(titleElement);
+            const title = this._host.document.createElement('h1');
+            title.classList.add('sidebar-title');
+            title.innerHTML = item.title ? item.title.toUpperCase() : '';
+            sidebar.appendChild(title);
 
             const closeButton = this._host.document.createElement('a');
             closeButton.classList.add('sidebar-closebutton');
@@ -96,31 +96,31 @@ sidebar.Sidebar = class {
             closeButton.setAttribute('href', 'javascript:void(0)');
             closeButton.innerHTML = '×';
             closeButton.addEventListener('click', this._closeSidebarHandler);
-            sidebarElement.appendChild(closeButton);
+            sidebar.appendChild(closeButton);
 
-            const contentElement = this._host.document.createElement('div');
-            contentElement.classList.add('sidebar-content');
-            contentElement.setAttribute('id', 'sidebar-content');
-            sidebarElement.appendChild(contentElement);
+            const content = this._host.document.createElement('div');
+            content.classList.add('sidebar-content');
+            content.setAttribute('id', 'sidebar-content');
+            sidebar.appendChild(content);
 
-            if (typeof content == 'string') {
-                contentElement.innerHTML = item.content;
+            if (typeof item.content == 'string') {
+                content.innerHTML = item.content;
             }
             else if (item.content instanceof Array) {
                 for (const element of item.content) {
-                    contentElement.appendChild(element);
+                    content.appendChild(element);
                 }
             }
             else {
-                contentElement.appendChild(item.content);
+                content.appendChild(item.content);
             }
 
-            sidebarElement.style.width = width;
+            sidebar.style.width = width;
             this._host.document.addEventListener('keydown', this._closeSidebarKeyDownHandler);
         }
-        const graphElement = this._getElementById('graph');
-        if (graphElement) {
-            graphElement.style.marginRight = width;
+        const graph = this._getElementById('graph');
+        if (graph) {
+            graph.style.marginRight = width;
         }
     }
 };

+ 85 - 83
source/view.js

@@ -54,8 +54,8 @@ view.View = class {
                     const browser = userAgent.indexOf('safari') !== -1 && userAgent.indexOf('chrome') === -1 ? 'safari' : '';
                     const element = this._getElementById('graph');
                     element.addEventListener('scroll', (e) => this._scrollHandler(e));
-                    element.addEventListener('wheel', (e) => this._mouseWheelHandler(e));
-                    element.addEventListener('mousewheel', (e) => this._mouseWheelHandler(e));
+                    element.addEventListener('wheel', (e) => this._wheelHandler(e), { passive: false });
+                    // element.addEventListener('mousewheel', (e) => this._wheelHandler(e), { passive: false });
                     element.addEventListener('mousedown', (e) => this._mouseDownHandler(e));
                     switch (browser) {
                         case 'safari':
@@ -285,47 +285,49 @@ view.View = class {
     }
 
     _mouseDownHandler(e) {
-        const document = this._host.document.documentElement;
-        document.style.cursor = 'grabbing';
-        const element = this._getElementById('graph');
-        this._mousePosition = {
-            left: element.scrollLeft,
-            top: element.scrollTop,
-            x: e.clientX,
-            y: e.clientY
-        };
-        e.stopImmediatePropagation();
-        const mouseMoveHandler = (e) => {
-            e.preventDefault();
+        if (e.buttons === 1) {
+            const document = this._host.document.documentElement;
+            document.style.cursor = 'grabbing';
+            const element = this._getElementById('graph');
+            this._mousePosition = {
+                left: element.scrollLeft,
+                top: element.scrollTop,
+                x: e.clientX,
+                y: e.clientY
+            };
             e.stopImmediatePropagation();
-            const dx = e.clientX - this._mousePosition.x;
-            const dy = e.clientY - this._mousePosition.y;
-            this._mousePosition.moved = dx * dx + dy * dy > 0;
-            if (this._mousePosition.moved) {
-                const element = this._getElementById('graph');
-                element.scrollTop = this._mousePosition.top - dy;
-                element.scrollLeft = this._mousePosition.left - dx;
-            }
-        };
-        const mouseUpHandler = () => {
-            document.style.cursor = null;
-            element.removeEventListener('mousemove', mouseMoveHandler);
-            element.removeEventListener('mouseup', mouseUpHandler);
-            element.removeEventListener('mouseleave', mouseUpHandler);
-            if (this._mousePosition.moved) {
+            const mouseMoveHandler = (e) => {
                 e.preventDefault();
                 e.stopImmediatePropagation();
-                delete this._mousePosition;
-                document.addEventListener('click', clickHandler, true);
-            }
-        };
-        const clickHandler = (e) => {
-            e.stopPropagation();
-            document.removeEventListener('click', clickHandler, true);
-        };
-        element.addEventListener('mousemove', mouseMoveHandler);
-        element.addEventListener('mouseup', mouseUpHandler);
-        element.addEventListener('mouseleave', mouseUpHandler);
+                const dx = e.clientX - this._mousePosition.x;
+                const dy = e.clientY - this._mousePosition.y;
+                this._mousePosition.moved = dx * dx + dy * dy > 0;
+                if (this._mousePosition.moved) {
+                    const element = this._getElementById('graph');
+                    element.scrollTop = this._mousePosition.top - dy;
+                    element.scrollLeft = this._mousePosition.left - dx;
+                }
+            };
+            const mouseUpHandler = () => {
+                document.style.cursor = null;
+                element.removeEventListener('mousemove', mouseMoveHandler);
+                element.removeEventListener('mouseup', mouseUpHandler);
+                element.removeEventListener('mouseleave', mouseUpHandler);
+                if (this._mousePosition.moved) {
+                    e.preventDefault();
+                    e.stopImmediatePropagation();
+                    delete this._mousePosition;
+                    document.addEventListener('click', clickHandler, true);
+                }
+            };
+            const clickHandler = (e) => {
+                e.stopPropagation();
+                document.removeEventListener('click', clickHandler, true);
+            };
+            element.addEventListener('mousemove', mouseMoveHandler);
+            element.addEventListener('mouseup', mouseUpHandler);
+            element.addEventListener('mouseleave', mouseUpHandler);
+        }
     }
 
     _scrollHandler(e) {
@@ -337,9 +339,9 @@ view.View = class {
         }
     }
 
-    _mouseWheelHandler(e) {
+    _wheelHandler(e) {
         if (e.shiftKey || e.ctrlKey) {
-            const delta = -e.deltaY * (e.deltaMode === 1 ? 0.05 : e.deltaMode ? 1 : 0.002) * (e.ctrlKey ? 10 : 1);
+            const delta = -e.deltaY * (e.deltaMode === 1 ? 0.05 : e.deltaMode ? 1 : 0.002);
             this._updateZoom(this._zoom + delta, e);
             e.preventDefault();
         }
@@ -593,10 +595,10 @@ view.View = class {
 
     renderGraph(model, graph) {
         try {
-            const graphElement = this._getElementById('graph');
-            const canvasElement = this._getElementById('canvas');
-            while (canvasElement.lastChild) {
-                canvasElement.removeChild(canvasElement.lastChild);
+            const container = this._getElementById('graph');
+            const canvas = this._getElementById('canvas');
+            while (canvas.lastChild) {
+                canvas.removeChild(canvas.lastChild);
             }
             if (!graph) {
                 return Promise.resolve();
@@ -605,13 +607,13 @@ view.View = class {
                 switch (this._host.environment('zoom')) {
                     case 'scroll':
                         this._zoom = 1;
-                        canvasElement.style.position = 'static';
-                        canvasElement.style.margin = 'auto';
+                        canvas.style.position = 'static';
+                        canvas.style.margin = 'auto';
                         break;
                     case 'drag':
                         this._zoom = null;
-                        canvasElement.style.position = 'absolute';
-                        canvasElement.style.margin = '0';
+                        canvas.style.position = 'absolute';
+                        canvas.style.margin = '0px';
                         break;
                 }
 
@@ -736,27 +738,27 @@ view.View = class {
 
                 // Workaround for Safari background drag/zoom issue:
                 // https://stackoverflow.com/questions/40887193/d3-js-zoom-is-not-working-with-mousewheel-in-safari
-                const backgroundElement = this._host.document.createElementNS('http://www.w3.org/2000/svg', 'rect');
-                backgroundElement.setAttribute('id', 'background');
+                const background = this._host.document.createElementNS('http://www.w3.org/2000/svg', 'rect');
+                background.setAttribute('id', 'background');
                 if (this._host.environment('zoom') === 'drag') {
-                    backgroundElement.setAttribute('width', '100%');
-                    backgroundElement.setAttribute('height', '100%');
+                    background.setAttribute('width', '100%');
+                    background.setAttribute('height', '100%');
                 }
-                backgroundElement.setAttribute('fill', 'none');
-                backgroundElement.setAttribute('pointer-events', 'all');
-                canvasElement.appendChild(backgroundElement);
+                background.setAttribute('fill', 'none');
+                background.setAttribute('pointer-events', 'all');
+                canvas.appendChild(background);
 
-                const originElement = this._host.document.createElementNS('http://www.w3.org/2000/svg', 'g');
-                originElement.setAttribute('id', 'origin');
-                canvasElement.appendChild(originElement);
+                const origin = this._host.document.createElementNS('http://www.w3.org/2000/svg', 'g');
+                origin.setAttribute('id', 'origin');
+                canvas.appendChild(origin);
 
-                viewGraph.build(this._host.document, originElement);
+                viewGraph.build(this._host.document, origin);
 
                 switch (this._host.environment('zoom')) {
                     case 'drag': {
-                        this._zoom = new view.Zoom(canvasElement, 0.1, 1.4);
+                        this._zoom = new view.Zoom(canvas, 0.1, 1.4);
                         this._zoom.on('zoom', (sender, data) => {
-                            originElement.setAttribute('transform', data.transform.toString());
+                            origin.setAttribute('transform', data.transform.toString());
                         });
                         this._zoom.transform(view.Zoom.identity());
                         break;
@@ -771,9 +773,9 @@ view.View = class {
 
                     viewGraph.layout();
 
-                    const elements = Array.from(canvasElement.getElementsByClassName('graph-input') || []);
+                    const elements = Array.from(canvas.getElementsByClassName('graph-input') || []);
                     if (elements.length === 0) {
-                        const nodeElements = Array.from(canvasElement.getElementsByClassName('graph-node') || []);
+                        const nodeElements = Array.from(canvas.getElementsByClassName('graph-node') || []);
                         if (nodeElements.length > 0) {
                             elements.push(nodeElements[0]);
                         }
@@ -781,7 +783,7 @@ view.View = class {
 
                     switch (this._host.environment('zoom')) {
                         case 'drag': {
-                            const svgSize = canvasElement.getBoundingClientRect();
+                            const svgSize = canvas.getBoundingClientRect();
                             if (elements && elements.length > 0) {
                                 // Center view based on input elements
                                 const xs = [];
@@ -808,22 +810,22 @@ view.View = class {
                             break;
                         }
                         case 'scroll': {
-                            const size = canvasElement.getBBox();
+                            const size = canvas.getBBox();
                             const margin = 100;
                             const width = Math.ceil(margin + size.width + margin);
                             const height = Math.ceil(margin + size.height + margin);
-                            originElement.setAttribute('transform', 'translate(' + margin.toString() + ', ' + margin.toString() + ') scale(1)');
-                            backgroundElement.setAttribute('width', width);
-                            backgroundElement.setAttribute('height', height);
+                            origin.setAttribute('transform', 'translate(' + margin.toString() + ', ' + margin.toString() + ') scale(1)');
+                            background.setAttribute('width', width);
+                            background.setAttribute('height', height);
                             this._width = width;
                             this._height = height;
-                            this._zoom = 1;
                             delete this._scrollLeft;
                             delete this._scrollRight;
-                            canvasElement.setAttribute('viewBox', '0 0 ' + width + ' ' + height);
-                            canvasElement.setAttribute('width', width);
-                            canvasElement.setAttribute('height', height);
+                            canvas.setAttribute('viewBox', '0 0 ' + width + ' ' + height);
+                            canvas.setAttribute('width', width);
+                            canvas.setAttribute('height', height);
 
+                            this._zoom = 1;
                             this._updateZoom(this._zoom);
 
                             if (elements && elements.length > 0) {
@@ -842,19 +844,19 @@ view.View = class {
                                     x = xs.reduce((a, b) => a + b, 0) / xs.length;
                                 }
                                 // const canvasRect = graphElement.getBoundingClientRect();
-                                const graphRect = graphElement.getBoundingClientRect();
+                                const graphRect = container.getBoundingClientRect();
                                 // const sx = (canvasRect.width / (this._showHorizontal ? 4 : 2)) - x;
                                 // const sy = (canvasRect.height / (this._showHorizontal ? 2 : 4)) - y;
-                                const left = (graphElement.scrollLeft + x - graphRect.left) - (graphRect.width / 2);
-                                const top = (graphElement.scrollTop + y - graphRect.top) - (graphRect.height / 2);
-                                graphElement.scrollTo({ left: left, top: top, behavior: 'auto' });
+                                const left = (container.scrollLeft + x - graphRect.left) - (graphRect.width / 2);
+                                const top = (container.scrollTop + y - graphRect.top) - (graphRect.height / 2);
+                                container.scrollTo({ left: left, top: top, behavior: 'auto' });
                             }
                             else {
-                                const canvasRect = graphElement.getBoundingClientRect();
-                                const graphRect = graphElement.getBoundingClientRect();
-                                const left = (graphElement.scrollLeft + (canvasRect.width / 2) - graphRect.left) - (graphRect.width / 2);
-                                const top = (graphElement.scrollTop + (canvasRect.height / 2) - graphRect.top) - (graphRect.height / 2);
-                                graphElement.scrollTo({ left: left, top: top, behavior: 'auto' });
+                                const canvasRect = canvas.getBoundingClientRect();
+                                const graphRect = container.getBoundingClientRect();
+                                const left = (container.scrollLeft + (canvasRect.width / 2) - graphRect.left) - (graphRect.width / 2);
+                                const top = (container.scrollTop + (canvasRect.height / 2) - graphRect.top) - (graphRect.height / 2);
+                                container.scrollTo({ left: left, top: top, behavior: 'auto' });
                             }
                             break;
                         }