Histogram & Scatterplot : Fix panning with normal mouse. (https://github.com/enso-org/ide/pull/1394)

Original commit: 2b2f1207bc
This commit is contained in:
Maciej Mikołajek 2021-03-31 17:45:14 +02:00 committed by GitHub
parent 72f1822e3e
commit 8947270c66
2 changed files with 76 additions and 41 deletions

View File

@ -236,6 +236,7 @@ class Histogram extends Visualization {
const maxScale = 20 const maxScale = 20
const rightButton = 2 const rightButton = 2
const midButton = 1 const midButton = 1
const midButtonClicked = 4
const scrollWheel = 0 const scrollWheel = 0
const extent = [minScale, maxScale] const extent = [minScale, maxScale]
let startPos let startPos
@ -280,32 +281,40 @@ class Histogram extends Visualization {
const self = this const self = this
let transformedScale = Object.assign({}, self.scale) let transformedScale = Object.assign({}, self.scale)
let tempRmbScale = Object.assign({}, self.scale)
/** /**
* Helper function called on pan/scroll. * Helper function called on pan/scroll.
*/ */
function zoomed() { function zoomed() {
if (d3.event.sourceEvent != null && d3.event.sourceEvent.buttons === rightButton) { function rescale(transformEvent) {
const rmbDivider = 5000.0 transformedScale.x = transformEvent.rescaleX(transformedScale.x)
const zoomAmount = rmbZoomValue(d3.event.sourceEvent) / rmbDivider if (transformEvent.rescaleY(transformedScale.y).domain()[0] >= 0) {
const scale = Math.exp(zoomAmount) transformedScale.y = transformEvent.rescaleY(transformedScale.y)
const focus = startPos }
const distanceScale = d3.zoomIdentity }
function getScaleForZoom(scale, focus) {
return d3.zoomIdentity
.translate(focus.x - (Y_AXIS_LABEL_WIDTH + MARGIN), focus.y - MARGIN) .translate(focus.x - (Y_AXIS_LABEL_WIDTH + MARGIN), focus.y - MARGIN)
.scale(scale) .scale(scale)
.translate(-focus.x + (Y_AXIS_LABEL_WIDTH + MARGIN), -focus.y + MARGIN) .translate(-focus.x + (Y_AXIS_LABEL_WIDTH + MARGIN), -focus.y + MARGIN)
}
if (d3.event.sourceEvent != null && d3.event.sourceEvent.buttons === rightButton) {
transformedScale.x = tempRmbScale.x
const rmbDivider = 100.0
const zoomAmount = rmbZoomValue(d3.event.sourceEvent) / rmbDivider
const scale = Math.exp(zoomAmount)
const distanceScale = getScaleForZoom(scale, startPos)
transformedScale.x = distanceScale.rescaleX(transformedScale.x) transformedScale.x = distanceScale.rescaleX(transformedScale.x)
transformedScale.zoom = transformedScale.zoom * scale transformedScale.zoom = tempRmbScale.zoom * scale
} else if (d3.event.sourceEvent != null && d3.event.sourceEvent.type === 'wheel') { } else if (d3.event.sourceEvent != null && d3.event.sourceEvent.type === 'wheel') {
if (d3.event.sourceEvent.ctrlKey) { if (d3.event.sourceEvent.ctrlKey) {
const pinchDivider = 100.0 const pinchDivider = 100.0
const zoomAmount = -d3.event.sourceEvent.deltaY / pinchDivider const zoomAmount = -d3.event.sourceEvent.deltaY / pinchDivider
const scale = Math.exp(zoomAmount) const scale = Math.exp(zoomAmount)
const focus = startPos const distanceScale = getScaleForZoom(scale, startPos)
const distanceScale = d3.zoomIdentity
.translate(focus.x - (Y_AXIS_LABEL_WIDTH + MARGIN), focus.y - MARGIN)
.scale(scale)
.translate(-focus.x + (Y_AXIS_LABEL_WIDTH + MARGIN), -focus.y + MARGIN)
transformedScale.x = distanceScale.rescaleX(transformedScale.x) transformedScale.x = distanceScale.rescaleX(transformedScale.x)
transformedScale.zoom = transformedScale.zoom * scale transformedScale.zoom = transformedScale.zoom * scale
} else { } else {
@ -313,16 +322,20 @@ class Histogram extends Visualization {
-d3.event.sourceEvent.deltaX, -d3.event.sourceEvent.deltaX,
-d3.event.sourceEvent.deltaY -d3.event.sourceEvent.deltaY
) )
transformedScale.x = distanceScale.rescaleX(transformedScale.x) rescale(distanceScale)
if (distanceScale.rescaleY(transformedScale.y).domain()[0] >= 0) {
transformedScale.y = distanceScale.rescaleY(transformedScale.y)
}
} }
} else if (
d3.event.sourceEvent != null &&
d3.event.sourceEvent.buttons === midButtonClicked
) {
const movementFactor = 2
const distanceScale = d3.zoomIdentity.translate(
d3.event.sourceEvent.movementX / movementFactor,
d3.event.sourceEvent.movementY / movementFactor
)
rescale(distanceScale)
} else { } else {
transformedScale.x = d3.event.transform.rescaleX(transformedScale.x) rescale(d3.event.transform)
if (d3.event.transform.rescaleY(transformedScale.y).domain()[0] >= 0) {
transformedScale.y = d3.event.transform.rescaleY(transformedScale.y)
}
} }
self.rescale(transformedScale, false) self.rescale(transformedScale, false)
@ -332,8 +345,11 @@ class Histogram extends Visualization {
* Return the position of this event in local canvas coordinates. * Return the position of this event in local canvas coordinates.
*/ */
function getPos(event) { function getPos(event) {
if (ok(event)) {
return { x: event.offsetX, y: event.offsetY } return { x: event.offsetX, y: event.offsetY }
} }
return { x: 0, y: 0 }
}
/** /**
* Return the zoom value computed from the initial right-mouse-button event to the current * Return the zoom value computed from the initial right-mouse-button event to the current
@ -351,6 +367,7 @@ class Histogram extends Visualization {
*/ */
function startZoom() { function startZoom() {
startPos = getPos(d3.event.sourceEvent) startPos = getPos(d3.event.sourceEvent)
tempRmbScale = Object.assign({}, transformedScale)
} }
return { zoomElem, zoom, transformedScale } return { zoomElem, zoom, transformedScale }

View File

@ -175,6 +175,7 @@ class ScatterPlot extends Visualization {
const maxScale = 20 const maxScale = 20
const rightButton = 2 const rightButton = 2
const midButton = 1 const midButton = 1
const midButtonClicked = 4
const scrollWheel = 0 const scrollWheel = 0
const extent = [minScale, maxScale] const extent = [minScale, maxScale]
let startPos let startPos
@ -217,46 +218,59 @@ class ScatterPlot extends Visualization {
.call(zoom) .call(zoom)
let transformedScale = Object.assign({}, scaleAndAxis) let transformedScale = Object.assign({}, scaleAndAxis)
let tempRmbScale = Object.assign({}, scaleAndAxis)
const self = this const self = this
/** /**
* Helper function called on pan/scroll. * Helper function called on pan/scroll.
*/ */
function zoomed() { function zoomed() {
if (d3.event.sourceEvent != null && d3.event.sourceEvent.buttons === rightButton) { function rescale(distanceScale) {
const rmbDivider = 5000.0 transformedScale.xScale = distanceScale.rescaleX(transformedScale.xScale)
const zoomAmount = rmbZoomValue(d3.event.sourceEvent) / rmbDivider transformedScale.yScale = distanceScale.rescaleY(transformedScale.yScale)
const scale = Math.exp(zoomAmount) }
const focus = startPos
const distanceScale = d3.zoomIdentity function getScaleForZoom(scale, focus) {
return d3.zoomIdentity
.translate(focus.x - self.margin.left, focus.y - self.margin.top) .translate(focus.x - self.margin.left, focus.y - self.margin.top)
.scale(scale) .scale(scale)
.translate(-focus.x + self.margin.left, -focus.y + self.margin.top) .translate(-focus.x + self.margin.left, -focus.y + self.margin.top)
transformedScale.xScale = distanceScale.rescaleX(transformedScale.xScale) }
transformedScale.yScale = distanceScale.rescaleY(transformedScale.yScale)
if (d3.event.sourceEvent != null && d3.event.sourceEvent.buttons === rightButton) {
transformedScale.xScale = tempRmbScale.xScale
transformedScale.yScale = tempRmbScale.yScale
const rmbDivider = 100.0
const zoomAmount = rmbZoomValue(d3.event.sourceEvent) / rmbDivider
const scale = Math.exp(zoomAmount)
const distanceScale = getScaleForZoom(scale, startPos)
rescale(distanceScale)
} else if (d3.event.sourceEvent != null && d3.event.sourceEvent.type === 'wheel') { } else if (d3.event.sourceEvent != null && d3.event.sourceEvent.type === 'wheel') {
if (d3.event.sourceEvent.ctrlKey) { if (d3.event.sourceEvent.ctrlKey) {
const pinchDivider = 100.0 const pinchDivider = 100.0
const zoomAmount = -d3.event.sourceEvent.deltaY / pinchDivider const zoomAmount = -d3.event.sourceEvent.deltaY / pinchDivider
const scale = Math.exp(zoomAmount) const scale = Math.exp(zoomAmount)
const focus = startPos const distanceScale = getScaleForZoom(scale, startPos)
const distanceScale = d3.zoomIdentity rescale(distanceScale)
.translate(focus.x - self.margin.left, focus.y - self.margin.top)
.scale(scale)
.translate(-focus.x + self.margin.left, -focus.y + self.margin.top)
transformedScale.xScale = distanceScale.rescaleX(transformedScale.xScale)
transformedScale.yScale = distanceScale.rescaleY(transformedScale.yScale)
} else { } else {
const distanceScale = d3.zoomIdentity.translate( const distanceScale = d3.zoomIdentity.translate(
-d3.event.sourceEvent.deltaX, -d3.event.sourceEvent.deltaX,
-d3.event.sourceEvent.deltaY -d3.event.sourceEvent.deltaY
) )
transformedScale.xScale = distanceScale.rescaleX(transformedScale.xScale) rescale(distanceScale)
transformedScale.yScale = distanceScale.rescaleY(transformedScale.yScale)
} }
} else if (
d3.event.sourceEvent != null &&
d3.event.sourceEvent.buttons === midButtonClicked
) {
const movementFactor = 2
const distanceScale = d3.zoomIdentity.translate(
d3.event.sourceEvent.movementX / movementFactor,
d3.event.sourceEvent.movementY / movementFactor
)
rescale(distanceScale)
} else { } else {
transformedScale.xScale = d3.event.transform.rescaleX(transformedScale.xScale) rescale(d3.event.transform)
transformedScale.yScale = d3.event.transform.rescaleY(transformedScale.yScale)
} }
scaleAndAxis.xAxis.call( scaleAndAxis.xAxis.call(
@ -287,8 +301,11 @@ class ScatterPlot extends Visualization {
* Return the position of this event in local canvas coordinates. * Return the position of this event in local canvas coordinates.
*/ */
function getPos(event) { function getPos(event) {
if (event != null) {
return { x: event.offsetX, y: event.offsetY } return { x: event.offsetX, y: event.offsetY }
} }
return { x: 0, y: 0 }
}
/** /**
* Return the zoom value computed from the initial right-mouse-button event to the current * Return the zoom value computed from the initial right-mouse-button event to the current
@ -306,6 +323,7 @@ class ScatterPlot extends Visualization {
*/ */
function startZoom() { function startZoom() {
startPos = getPos(d3.event.sourceEvent) startPos = getPos(d3.event.sourceEvent)
tempRmbScale = Object.assign({}, transformedScale)
} }
return { zoomElem, zoom, transformedScale } return { zoomElem, zoom, transformedScale }