From a185ae4e15627f8901aef89d0eb4ce58205499ac Mon Sep 17 00:00:00 2001 From: Filip Barl Date: Tue, 15 Aug 2017 16:41:12 +0200 Subject: [PATCH] Introduced hand cursor and unified ZoomableCanvas usage. --- client/app/scripts/charts/nodes-chart.js | 16 +++- .../app/scripts/components/nodes-resources.js | 2 +- .../app/scripts/components/zoomable-canvas.js | 75 ++++++++----------- client/app/styles/_base.scss | 9 +++ 4 files changed, 55 insertions(+), 47 deletions(-) diff --git a/client/app/scripts/charts/nodes-chart.js b/client/app/scripts/charts/nodes-chart.js index e200efe1f..fcbc60a8d 100644 --- a/client/app/scripts/charts/nodes-chart.js +++ b/client/app/scripts/charts/nodes-chart.js @@ -3,6 +3,7 @@ import { connect } from 'react-redux'; import NodesChartElements from './nodes-chart-elements'; import ZoomableCanvas from '../components/zoomable-canvas'; +import { transformToString } from '../utils/transform-utils'; import { clickBackground } from '../actions/app-actions'; import { graphZoomLimitsSelector, @@ -43,17 +44,24 @@ class NodesChart extends React.Component { } } + renderContent(transform) { + return ( + + + + + ); + } + render() { - const { selectedNodeId } = this.props; return (
- - + disabled={this.props.selectedNodeId}> + {transform => this.renderContent(transform)}
); diff --git a/client/app/scripts/components/nodes-resources.js b/client/app/scripts/components/nodes-resources.js index 50f257ab3..28d91d182 100644 --- a/client/app/scripts/components/nodes-resources.js +++ b/client/app/scripts/components/nodes-resources.js @@ -39,8 +39,8 @@ class NodesResources extends React.Component { return (
{transform => this.renderLayers(transform)} diff --git a/client/app/scripts/components/zoomable-canvas.js b/client/app/scripts/components/zoomable-canvas.js index 1f5264795..a37dca26a 100644 --- a/client/app/scripts/components/zoomable-canvas.js +++ b/client/app/scripts/components/zoomable-canvas.js @@ -1,4 +1,5 @@ import React from 'react'; +import classNames from 'classnames'; import { connect } from 'react-redux'; import { clamp, debounce, pick } from 'lodash'; import { fromJS } from 'immutable'; @@ -10,7 +11,6 @@ import Logo from '../components/logo'; import ZoomControl from '../components/zoom-control'; import { cacheZoomState } from '../actions/app-actions'; import { zoomFactor } from '../utils/zoom-utils'; -import { transformToString } from '../utils/transform-utils'; import { activeTopologyZoomCacheKeyPathSelector } from '../selectors/zooming'; import { canvasMarginsSelector, @@ -35,6 +35,7 @@ class ZoomableCanvas extends React.Component { super(props, context); this.state = { + isPanning: false, minTranslateX: 0, maxTranslateX: 0, minTranslateY: 0, @@ -50,16 +51,23 @@ class ZoomableCanvas extends React.Component { this.debouncedCacheZoom = debounce(this.cacheZoom.bind(this), ZOOM_CACHE_DEBOUNCE_INTERVAL); this.handleZoomControlAction = this.handleZoomControlAction.bind(this); this.canChangeZoom = this.canChangeZoom.bind(this); + this.handleZoom = this.handleZoom.bind(this); + this.handlePanStart = this.handlePanStart.bind(this); + this.handlePanEnd = this.handlePanEnd.bind(this); this.handlePan = this.handlePan.bind(this); } componentDidMount() { - this.zoomRestored = false; - this.svg = select('svg#canvas'); - this.drag = drag().on('drag', this.handlePan); + this.svg = select('.zoomable-canvas svg'); + this.drag = drag() + .on('start', this.handlePanStart) + .on('end', this.handlePanEnd) + .on('drag', this.handlePan); this.svg.call(this.drag); + this.zoomRestored = false; + this.updateZoomLimits(this.props); this.restoreZoomState(this.props); } @@ -96,21 +104,14 @@ class ZoomableCanvas extends React.Component { } render() { - // `forwardTransform` says whether the zoom transform is forwarded to the child - // component. The advantage of that is more control rendering control in the - // children, while the disadvantage is that it's slower, as all the children - // get updated on every zoom/pan action. - const { children, forwardTransform } = this.props; - const transform = forwardTransform ? '' : transformToString(this.state); + const className = classNames({ panning: this.state.isPanning }); return (
- + - - {forwardTransform ? children(this.state) : children} + + {this.props.children(this.state)} {this.canChangeZoom() && viewportMinPoint.x) { - state.translateX -= minPoint.x - viewportMinPoint.x; - } - if (maxPoint.y < viewportMaxPoint.y) { - state.translateY += viewportMaxPoint.y - maxPoint.y; - } else if (minPoint.y > viewportMinPoint.y) { - state.translateY -= minPoint.y - viewportMinPoint.y; - } - } else { - if (minPoint.x > viewportMaxPoint.x) { - state.translateX -= minPoint.x - viewportMaxPoint.x; - } else if (maxPoint.x < viewportMinPoint.x) { - state.translateX += viewportMinPoint.x - maxPoint.x; - } - if (minPoint.y > viewportMaxPoint.y) { - state.translateY -= minPoint.y - viewportMaxPoint.y; - } else if (maxPoint.y < viewportMinPoint.y) { - state.translateY += viewportMinPoint.y - maxPoint.y; - } - } + state.translateX += Math.max(0, viewportMaxPoint.x - maxPoint.x); + state.translateX += Math.min(0, viewportMinPoint.x - minPoint.x); + state.translateY += Math.max(0, viewportMaxPoint.y - maxPoint.y); + state.translateY += Math.min(0, viewportMinPoint.y - minPoint.y); } + return state; } diff --git a/client/app/styles/_base.scss b/client/app/styles/_base.scss index a859eb655..e2ccdfc98 100644 --- a/client/app/styles/_base.scss +++ b/client/app/styles/_base.scss @@ -358,6 +358,15 @@ a { } } +.zoomable-canvas { + svg { + @extend .grabbable; + width: 100%; + height: 100%; + + &.panning { @extend .grabbing; } + } +} .topologies { margin: 0 4px;