Fixed jitter when bumping blocks if objects were too large for the workspace. (#2778)

This commit is contained in:
Beka Westberg
2019-08-12 09:11:27 -07:00
committed by RoboErikG
parent 6425287daa
commit 37efbd0559

View File

@@ -247,6 +247,8 @@ Blockly.createMainWorkspace_ = function(svg, options, blockDragSurface,
var defaultMetrics = mainWorkspace.getMetrics();
var scale = mainWorkspace.scale;
workspaceMetrics.RTL = mainWorkspace.RTL;
// Get the view metrics in workspace units.
workspaceMetrics.viewLeft = defaultMetrics.viewLeft / scale;
workspaceMetrics.viewTop = defaultMetrics.viewTop / scale;
@@ -276,6 +278,13 @@ Blockly.createMainWorkspace_ = function(svg, options, blockDragSurface,
return workspaceMetrics;
};
var getObjectMetrics = function(object) {
var objectMetrics = object.getBoundingRectangle();
objectMetrics.height = objectMetrics.bottom - objectMetrics.top;
objectMetrics.width = objectMetrics.right - objectMetrics.left;
return objectMetrics;
};
var bumpObjects = function(e) {
// We always check isMovable_ again because the original
// "not movable" state of isMovable_ could have been changed.
@@ -306,31 +315,54 @@ Blockly.createMainWorkspace_ = function(svg, options, blockDragSurface,
break;
}
if (object) {
var objectMetrics = object.getBoundingRectangle();
var objectMetrics = getObjectMetrics(object);
// Bump any object that's above the top back inside.
var overflowTop = metrics.viewTop - objectMetrics.top;
if (overflowTop > 0) {
object.moveBy(0, overflowTop);
// The idea is to find the region of valid coordinates for the top
// left corner of the object, and then clamp the object's
// top left corner within that region.
// The top of the object should always be at or below the top of
// the workspace.
var topClamp = metrics.viewTop;
// The top of the object should ideally be positioned so that
// the bottom of the object is not below the bottom of the
// workspace.
var bottomClamp = metrics.viewBottom - objectMetrics.height;
// If the object is taller than the workspace we want to
// top-align the block, which means setting the bottom clamp to
// match.
bottomClamp = Math.max(topClamp, bottomClamp);
var newYPosition = Blockly.utils.math.clamp(
topClamp, objectMetrics.top, bottomClamp);
var deltaY = newYPosition - objectMetrics.top;
// Note: Even in RTL mode the "anchor" of the object is the
// top-left corner of the object.
// The left edge of the object should ideally be positioned at
// or to the right of the left edge of the workspace.
var leftClamp = metrics.viewLeft;
// The left edge of the object should ideally be positioned so
// that the right of the object is not outside the workspace bounds.
var rightClamp = metrics.viewRight - objectMetrics.width;
if (metrics.RTL) {
// If the object is wider than the workspace and we're in RTL
// mode we want to right-align the block, which means setting
// the left clamp to match.
leftClamp = Math.min(rightClamp, leftClamp);
} else {
// If the object is wider than the workspace and we're in LTR
// mode we want to left-align the block, which means setting
// the right clamp to match.
rightClamp = Math.max(leftClamp, rightClamp);
}
// Bump any object that's below the bottom back inside.
var overflowBottom = metrics.viewBottom - objectMetrics.bottom;
if (overflowBottom < 0) {
object.moveBy(0, overflowBottom);
}
var newXPosition = Blockly.utils.math.clamp(
leftClamp, objectMetrics.left, rightClamp);
var deltaX = newXPosition - objectMetrics.left;
// Bump any object that's off the left back inside.
var overflowLeft = metrics.viewLeft - objectMetrics.left;
if (overflowLeft > 0) {
object.moveBy(overflowLeft, 0);
}
// Bump any object that's off the right back inside.
var overflowRight = metrics.viewRight - objectMetrics.right;
if (overflowRight < 0) {
object.moveBy(overflowRight, 0);
}
object.moveBy(deltaX, deltaY);
}
if (e) {
if (!e.group) {