Add zoom support for single-direction-scroll (#4653)

* Add zoom support for single-direction scroll
This commit is contained in:
Monica Kozbial
2021-03-05 14:37:41 -08:00
committed by GitHub
parent 26104d280d
commit f837f1e44e
7 changed files with 60 additions and 31 deletions

View File

@@ -28,11 +28,13 @@ goog.require('Blockly.utils.object');
* event.
* @param {string=} opt_workspaceId The workspace identifier for this event.
* Undefined for a blank event.
* @param {number=} opt_oldScale The old scale of the workspace. Undefined for a
* blank event.
* @extends {Blockly.Events.UiBase}
* @constructor
*/
Blockly.Events.ViewportChange = function(opt_top, opt_left, opt_scale,
opt_workspaceId) {
opt_workspaceId, opt_oldScale) {
Blockly.Events.ViewportChange.superClass_.constructor.call(this, opt_workspaceId);
/**
@@ -54,6 +56,12 @@ Blockly.Events.ViewportChange = function(opt_top, opt_left, opt_scale,
* @type {number|undefined}
*/
this.scale = opt_scale;
/**
* The old scale of the workspace.
* @type {number|undefined}
*/
this.oldScale = opt_oldScale;
};
Blockly.utils.object.inherits(Blockly.Events.ViewportChange,
Blockly.Events.UiBase);
@@ -73,6 +81,7 @@ Blockly.Events.ViewportChange.prototype.toJson = function() {
json['viewTop'] = this.viewTop;
json['viewLeft'] = this.viewLeft;
json['scale'] = this.scale;
json['oldScale'] = this.oldScale;
return json;
};
@@ -85,6 +94,7 @@ Blockly.Events.ViewportChange.prototype.fromJson = function(json) {
this.viewTop = json['viewTop'];
this.viewLeft = json['viewLeft'];
this.scale = json['scale'];
this.oldScale = json['oldScale'];
};
Blockly.registry.register(Blockly.registry.Type.EVENT,

View File

@@ -245,32 +245,38 @@ Blockly.bumpTopObjectsIntoBounds_ = function(workspace) {
Blockly.bumpIntoBoundsHandler_ = function(workspace) {
return function(e) {
var metricsManager = workspace.getMetricsManager();
if (!metricsManager.hasFixedEdges() || workspace.isDragging() ||
Blockly.Events.BUMP_EVENTS.indexOf(e.type) === -1) {
if (!metricsManager.hasFixedEdges || workspace.isDragging()) {
return;
}
var scrollMetricsInWsCoords = metricsManager.getScrollMetrics(true);
if (Blockly.Events.BUMP_EVENTS.indexOf(e.type) !== -1) {
var scrollMetricsInWsCoords = metricsManager.getScrollMetrics(true);
// Triggered by move/create event
var object = Blockly.extractObjectFromEvent_(workspace, e);
if (!object) {
return;
}
// Handle undo.
var oldGroup = Blockly.Events.getGroup();
Blockly.Events.setGroup(e.group);
// Triggered by move/create event
var object = Blockly.extractObjectFromEvent_(workspace, e);
if (!object) {
return;
}
// Handle undo.
var oldGroup = Blockly.Events.getGroup();
Blockly.Events.setGroup(e.group);
var wasBumped = Blockly.bumpObjectIntoBounds_(
workspace, scrollMetricsInWsCoords,
/** @type {!Blockly.IBoundedElement} */ (object));
var wasBumped = Blockly.bumpObjectIntoBounds_(
workspace, scrollMetricsInWsCoords,
/** @type {!Blockly.IBoundedElement} */ (object));
if (wasBumped && !e.group) {
console.warn('Moved object in bounds but there was no' +
' event group. This may break undo.');
}
if (oldGroup !== null) {
Blockly.Events.setGroup(oldGroup);
if (wasBumped && !e.group) {
console.warn('Moved object in bounds but there was no' +
' event group. This may break undo.');
}
if (oldGroup !== null) {
Blockly.Events.setGroup(oldGroup);
}
} else if (e.type === Blockly.Events.VIEWPORT_CHANGE) {
var viewportEvent = /** @type {!Blockly.Events.ViewportChange} */ (e);
if (viewportEvent.scale > viewportEvent.oldScale) {
Blockly.bumpTopObjectsIntoBounds_(workspace);
}
}
};
};

View File

@@ -275,10 +275,10 @@ Blockly.Options.parseMoveOptions_ = function(options, hasCategories) {
} else {
moveOptions.scrollbars = !!move['scrollbars'] || !!options['scrollbars'];
}
if (!moveOptions.scrollbars || move['wheel'] === undefined) {
// Defaults to false so that developers' settings don't appear to change.
moveOptions.wheel = false;
// Defaults to true if single-direction scroll is enabled.
moveOptions.wheel = typeof moveOptions.scrollbars == 'object';
} else {
moveOptions.wheel = !!move['wheel'];
}

View File

@@ -1238,7 +1238,7 @@ Blockly.WorkspaceSvg.prototype.maybeFireViewportChangeEvent = function() {
return;
}
var event = new (Blockly.Events.get(Blockly.Events.VIEWPORT_CHANGE))(top,
left, scale, this.id);
left, scale, this.id, this.oldScale_);
this.oldScale_ = scale;
this.oldTop_ = top;
this.oldLeft_ = left;

View File

@@ -450,9 +450,21 @@ Blockly.ZoomControls.prototype.createZoomResetSvg_ = function(rnd) {
*/
Blockly.ZoomControls.prototype.resetZoom_ = function(e) {
this.workspace_.markFocused();
this.workspace_.setScale(this.workspace_.options.zoomOptions.startScale);
// zoom is passed amount and computes the new scale using the formula:
// targetScale = currentScale * Math.pow(speed, amount)
var targetScale = this.workspace_.options.zoomOptions.startScale;
var currentScale = this.workspace_.scale;
var speed = this.workspace_.options.zoomOptions.scaleSpeed;
// To compute amount:
// amount = log(speed, (targetScale / currentScale))
// Math.log computes natural logarithm (ln), to change the base, use formula:
// log(base, value) = ln(value) / ln(base)
var amount = Math.log(targetScale / currentScale) / Math.log(speed);
this.workspace_.beginCanvasTransition();
this.workspace_.scrollCenter();
this.workspace_.zoomCenter(amount);
setTimeout(this.workspace_.endCanvasTransition.bind(this.workspace_), 500);
this.fireZoomEvent_();
Blockly.Touch.clearTouchIdentifier(); // Don't block future drags.

View File

@@ -551,13 +551,13 @@ suite('Events', function() {
getArgs: (thisObj) => [true, thisObj.workspace.id],
getExpectedJson: () => ({type: 'trashcan_open', isOpen: true})},
{title: 'Viewport change', class: Blockly.Events.ViewportChange,
getArgs: (thisObj) => [2.666, 1.333, 1.2, thisObj.workspace.id],
getArgs: (thisObj) => [2.666, 1.333, 1.2, thisObj.workspace.id, 1],
getExpectedJson: () => ({type: 'viewport_change', viewTop: 2.666,
viewLeft: 1.333, scale: 1.2})},
viewLeft: 1.333, scale: 1.2, oldScale: 1})},
{title: 'Viewport change (0,0)', class: Blockly.Events.ViewportChange,
getArgs: (thisObj) => [0, 0, 1.2, thisObj.workspace.id],
getArgs: (thisObj) => [0, 0, 1.2, thisObj.workspace.id, 1],
getExpectedJson: () => ({type: 'viewport_change', viewTop: 0,
viewLeft: 0, scale: 1.2})},
viewLeft: 0, scale: 1.2, oldScale: 1})},
];
var blockEventTestCases = [
{title: 'Block change', class: Blockly.Events.BlockChange,

View File

@@ -178,6 +178,7 @@ suite('WorkspaceSvg', function() {
var metrics = workspace.getMetrics();
var expectedProperties = {
scale: workspace.scale,
oldScale: 1,
viewTop: metrics.viewTop,
viewLeft: metrics.viewLeft
};