mirror of
https://github.com/google/blockly.git
synced 2026-01-10 10:27:08 +01:00
Improve performance of block dragging. This is a backport of the blo… (#732)
Improve performance of block dragging. This is a backport of the block drag surface from scratch-blocks. At the beginning of a block drag, blocks get moved to a drag surface which then translates using translate3d to avoid repainting the entire svg on every mouse move. At the end of the drag, the blocks are dropped back in the svg in their new position.
This commit is contained in:
191
core/block_drag_surface.js
Normal file
191
core/block_drag_surface.js
Normal file
@@ -0,0 +1,191 @@
|
||||
/**
|
||||
* @license
|
||||
* Visual Blocks Editor
|
||||
*
|
||||
* Copyright 2016 Google Inc.
|
||||
* https://developers.google.com/blockly/
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
/**
|
||||
* @fileoverview A class that manages a surface for dragging blocks. When a
|
||||
* block drag is started, we move the block (and children) to a separate dom
|
||||
* element that we move around using translate3d. At the end of the drag, the
|
||||
* blocks are put back in into the svg they came from. This helps performance by
|
||||
* avoiding repainting the entire svg on every mouse move while dragging blocks.
|
||||
* @author picklesrus
|
||||
*/
|
||||
|
||||
'use strict';
|
||||
|
||||
goog.provide('Blockly.BlockDragSurfaceSvg');
|
||||
goog.require('Blockly.utils');
|
||||
goog.require('goog.asserts');
|
||||
goog.require('goog.math.Coordinate');
|
||||
|
||||
|
||||
/**
|
||||
* Class for a drag surface for the currently dragged block. This is a separate
|
||||
* SVG that contains only the currently moving block, or nothing.
|
||||
* @param {!Element} container Containing element.
|
||||
* @constructor
|
||||
*/
|
||||
Blockly.BlockDragSurfaceSvg = function(container) {
|
||||
/**
|
||||
* @type {!Element}
|
||||
* @private
|
||||
*/
|
||||
this.container_ = container;
|
||||
};
|
||||
|
||||
/**
|
||||
* The SVG drag surface. Set once by Blockly.BlockDragSurfaceSvg.createDom.
|
||||
* @type {Element}
|
||||
* @private
|
||||
*/
|
||||
Blockly.BlockDragSurfaceSvg.prototype.SVG_ = null;
|
||||
|
||||
/**
|
||||
* This is where blocks live while they are being dragged if the drag surface
|
||||
* is enabled.
|
||||
* @type {Element}
|
||||
* @private
|
||||
*/
|
||||
Blockly.BlockDragSurfaceSvg.prototype.dragGroup_ = null;
|
||||
|
||||
/**
|
||||
* Containing HTML element; parent of the workspace and the drag surface.
|
||||
* @type {Element}
|
||||
* @private
|
||||
*/
|
||||
Blockly.BlockDragSurfaceSvg.prototype.container_ = null;
|
||||
|
||||
/**
|
||||
* Cached value for the scale of the drag surface.
|
||||
* Used to set/get the correct translation during and after a drag.
|
||||
* @type {number}
|
||||
* @private
|
||||
*/
|
||||
Blockly.BlockDragSurfaceSvg.prototype.scale_ = 1;
|
||||
|
||||
/**
|
||||
* Create the drag surface and inject it into the container.
|
||||
*/
|
||||
Blockly.BlockDragSurfaceSvg.prototype.createDom = function() {
|
||||
if (this.SVG_) {
|
||||
return; // Already created.
|
||||
}
|
||||
this.SVG_ = Blockly.createSvgElement('svg', {
|
||||
'xmlns': Blockly.SVG_NS,
|
||||
'xmlns:html': Blockly.HTML_NS,
|
||||
'xmlns:xlink': 'http://www.w3.org/1999/xlink',
|
||||
'version': '1.1',
|
||||
'class': 'blocklyBlockDragSurface'
|
||||
}, this.container_);
|
||||
this.dragGroup_ = Blockly.createSvgElement('g', {}, this.SVG_);
|
||||
};
|
||||
|
||||
/**
|
||||
* Set the SVG blocks on the drag surface's group and show the surface.
|
||||
* Only one block group should be on the drag surface at a time.
|
||||
* @param {!Element} blocks Block or group of blocks to place on the drag
|
||||
* surface.
|
||||
*/
|
||||
Blockly.BlockDragSurfaceSvg.prototype.setBlocksAndShow = function(blocks) {
|
||||
goog.asserts.assert(this.dragGroup_.childNodes.length == 0,
|
||||
'Already dragging a block.');
|
||||
// appendChild removes the blocks from the previous parent
|
||||
this.dragGroup_.appendChild(blocks);
|
||||
this.SVG_.style.display = 'block';
|
||||
};
|
||||
|
||||
/**
|
||||
* Translate and scale the entire drag surface group to keep in sync with the
|
||||
* workspace.
|
||||
* @param {number} x X translation
|
||||
* @param {number} y Y translation
|
||||
* @param {number} scale Scale of the group.
|
||||
*/
|
||||
Blockly.BlockDragSurfaceSvg.prototype.translateAndScaleGroup = function(x, y, scale) {
|
||||
this.scale_ = scale;
|
||||
// This is a work-around to prevent a the blocks from rendering
|
||||
// fuzzy while they are being dragged on the drag surface.
|
||||
x = x.toFixed(0);
|
||||
y = y.toFixed(0);
|
||||
this.dragGroup_.setAttribute('transform', 'translate('+ x + ','+ y + ')' +
|
||||
' scale(' + scale + ')');
|
||||
};
|
||||
|
||||
/**
|
||||
* Translate the entire drag surface during a drag.
|
||||
* We translate the drag surface instead of the blocks inside the surface
|
||||
* so that the browser avoids repainting the SVG.
|
||||
* Because of this, the drag coordinates must be adjusted by scale.
|
||||
* @param {number} x X translation for the entire surface.
|
||||
* @param {number} y Y translation for the entire surface.
|
||||
*/
|
||||
Blockly.BlockDragSurfaceSvg.prototype.translateSurface = function(x, y) {
|
||||
var transform;
|
||||
x *= this.scale_;
|
||||
y *= this.scale_;
|
||||
// This is a work-around to prevent a the blocks from rendering
|
||||
// fuzzy while they are being dragged on the drag surface.
|
||||
x = x.toFixed(0);
|
||||
y = y.toFixed(0);
|
||||
transform =
|
||||
'transform: translate3d(' + x + 'px, ' + y + 'px, 0px); display: block;';
|
||||
this.SVG_.setAttribute('style', transform);
|
||||
};
|
||||
|
||||
/**
|
||||
* Reports the surface translation in scaled workspace coordinates.
|
||||
* Use this when finishing a drag to return blocks to the correct position.
|
||||
* @return {!goog.math.Coordinate} Current translation of the surface.
|
||||
*/
|
||||
Blockly.BlockDragSurfaceSvg.prototype.getSurfaceTranslation = function() {
|
||||
var xy = Blockly.getRelativeXY_(this.SVG_);
|
||||
return new goog.math.Coordinate(xy.x / this.scale_, xy.y / this.scale_);
|
||||
};
|
||||
|
||||
/**
|
||||
* Provide a reference to the drag group (primarily for
|
||||
* BlockSvg.getRelativeToSurfaceXY).
|
||||
* @return {Element} Drag surface group element.
|
||||
*/
|
||||
Blockly.BlockDragSurfaceSvg.prototype.getGroup = function() {
|
||||
return this.dragGroup_;
|
||||
};
|
||||
|
||||
/**
|
||||
* Get the current blocks on the drag surface, if any (primarily
|
||||
* for BlockSvg.getRelativeToSurfaceXY).
|
||||
* @return {!Element|undefined} Drag surface block DOM element, or undefined
|
||||
* if no blocks exist.
|
||||
*/
|
||||
Blockly.BlockDragSurfaceSvg.prototype.getCurrentBlock = function() {
|
||||
return this.dragGroup_.firstChild;
|
||||
};
|
||||
|
||||
/**
|
||||
* Clear the group and hide the surface; move the blocks off onto the provided
|
||||
* element.
|
||||
* @param {!Element} newSurface Surface the dragging blocks should be moved to.
|
||||
*/
|
||||
Blockly.BlockDragSurfaceSvg.prototype.clearAndHide = function(newSurface) {
|
||||
// appendChild removes the node from this.dragGroup_
|
||||
newSurface.appendChild(this.getCurrentBlock());
|
||||
this.SVG_.style.display = 'none';
|
||||
goog.asserts.assert(this.dragGroup_.childNodes.length == 0,
|
||||
'Drag group was not cleared.');
|
||||
};
|
||||
@@ -82,6 +82,14 @@ Blockly.BlockSvg = function(workspace, prototypeName, opt_id) {
|
||||
/** @type {boolean} */
|
||||
this.rendered = false;
|
||||
|
||||
/**
|
||||
* Whether to move the block to the drag surface when it is dragged.
|
||||
* True if it should move, false if it should be translated directly.
|
||||
* @type {boolean}
|
||||
* @private
|
||||
*/
|
||||
this.useDragSurface_ = Blockly.is3dSupported() && workspace.blockDragSurface_;
|
||||
|
||||
Blockly.Tooltip.bindMouseEvents(this.svgPath_);
|
||||
Blockly.BlockSvg.superClass_.constructor.call(this,
|
||||
workspace, prototypeName, opt_id);
|
||||
@@ -263,6 +271,7 @@ Blockly.BlockSvg.terminateDrag = function() {
|
||||
selected.moveConnections_(dxy.x, dxy.y);
|
||||
delete selected.draggedBubbles_;
|
||||
selected.setDragging_(false);
|
||||
selected.moveOffDragSurface_();
|
||||
selected.render();
|
||||
selected.workspace.setResizesEnabled(true);
|
||||
// Ensure that any snap and bump are part of this move's event group.
|
||||
@@ -320,6 +329,10 @@ Blockly.BlockSvg.prototype.setParent = function(newParent) {
|
||||
Blockly.BlockSvg.prototype.getRelativeToSurfaceXY = function() {
|
||||
var x = 0;
|
||||
var y = 0;
|
||||
|
||||
var dragSurfaceGroup = this.useDragSurface_ ?
|
||||
this.workspace.blockDragSurface_.getGroup() : null;
|
||||
|
||||
var element = this.getSvgRoot();
|
||||
if (element) {
|
||||
do {
|
||||
@@ -327,8 +340,17 @@ Blockly.BlockSvg.prototype.getRelativeToSurfaceXY = function() {
|
||||
var xy = Blockly.getRelativeXY_(element);
|
||||
x += xy.x;
|
||||
y += xy.y;
|
||||
// If this element is the current element on the drag surface, include
|
||||
// the translation of the drag surface itself.
|
||||
if (this.useDragSurface_ &&
|
||||
this.workspace.blockDragSurface_.getCurrentBlock() == element) {
|
||||
var surfaceTranslation = this.workspace.blockDragSurface_.getSurfaceTranslation();
|
||||
x += surfaceTranslation.x;
|
||||
y += surfaceTranslation.y;
|
||||
}
|
||||
element = element.parentNode;
|
||||
} while (element && element != this.workspace.getCanvas());
|
||||
} while (element && element != this.workspace.getCanvas() &&
|
||||
element != dragSurfaceGroup);
|
||||
}
|
||||
return new goog.math.Coordinate(x, y);
|
||||
};
|
||||
@@ -342,14 +364,70 @@ Blockly.BlockSvg.prototype.moveBy = function(dx, dy) {
|
||||
goog.asserts.assert(!this.parentBlock_, 'Block has parent.');
|
||||
var event = new Blockly.Events.Move(this);
|
||||
var xy = this.getRelativeToSurfaceXY();
|
||||
this.getSvgRoot().setAttribute('transform',
|
||||
'translate(' + (xy.x + dx) + ',' + (xy.y + dy) + ')');
|
||||
this.translate(xy.x + dx, xy.y + dy);
|
||||
this.moveConnections_(dx, dy);
|
||||
event.recordNew();
|
||||
this.workspace.resizeContents();
|
||||
Blockly.Events.fire(event);
|
||||
};
|
||||
|
||||
/**
|
||||
* Transforms a block by setting the translation on the transform attribute
|
||||
* of the block's SVG.
|
||||
* @param {number} x The x coordinate of the translation.
|
||||
* @param {number} y The y coordinate of the translation.
|
||||
*/
|
||||
Blockly.BlockSvg.prototype.translate = function(x, y) {
|
||||
this.getSvgRoot().setAttribute('transform',
|
||||
'translate(' + x + ',' + y + ')');
|
||||
};
|
||||
|
||||
/**
|
||||
* Move this block to its workspace's drag surface, accounting for positioning.
|
||||
* Generally should be called at the same time as setDragging_(true).
|
||||
* Does nothing if useDragSurface_ is false.
|
||||
* @private
|
||||
*/
|
||||
Blockly.BlockSvg.prototype.moveToDragSurface_ = function() {
|
||||
if (!this.useDragSurface_) {
|
||||
return;
|
||||
}
|
||||
// The translation for drag surface blocks,
|
||||
// is equal to the current relative-to-surface position,
|
||||
// to keep the position in sync as it move on/off the surface.
|
||||
var xy = this.getRelativeToSurfaceXY();
|
||||
this.clearTransformAttributes_();
|
||||
this.workspace.blockDragSurface_.translateSurface(xy.x, xy.y);
|
||||
// Execute the move on the top-level SVG component
|
||||
this.workspace.blockDragSurface_.setBlocksAndShow(this.getSvgRoot());
|
||||
};
|
||||
|
||||
/**
|
||||
* Move this block back to the workspace block canvas.
|
||||
* Generally should be called at the same time as setDragging_(false).
|
||||
* Does nothing if useDragSurface_ is false.
|
||||
* @private
|
||||
*/
|
||||
Blockly.BlockSvg.prototype.moveOffDragSurface_ = function() {
|
||||
if (!this.useDragSurface_) {
|
||||
return;
|
||||
}
|
||||
// Translate to current position, turning off 3d.
|
||||
var xy = this.getRelativeToSurfaceXY();
|
||||
this.clearTransformAttributes_();
|
||||
this.translate(xy.x, xy.y);
|
||||
this.workspace.blockDragSurface_.clearAndHide(this.workspace.getCanvas());
|
||||
};
|
||||
|
||||
/**
|
||||
* Clear the block of transform="..." attributes.
|
||||
* Used when the block is switching from 3d to 2d transform or vice versa.
|
||||
* @private
|
||||
*/
|
||||
Blockly.BlockSvg.prototype.clearTransformAttributes_ = function() {
|
||||
this.getSvgRoot().removeAttribute('transform');
|
||||
};
|
||||
|
||||
/**
|
||||
* Snap this block to the nearest grid point.
|
||||
*/
|
||||
@@ -880,14 +958,19 @@ Blockly.BlockSvg.prototype.onMouseMove_ = function(e) {
|
||||
this.disconnectUiEffect();
|
||||
}
|
||||
this.setDragging_(true);
|
||||
this.moveToDragSurface_();
|
||||
}
|
||||
}
|
||||
if (Blockly.dragMode_ == Blockly.DRAG_FREE) {
|
||||
// Unrestricted dragging.
|
||||
var dxy = goog.math.Coordinate.difference(oldXY, this.dragStartXY_);
|
||||
var group = this.getSvgRoot();
|
||||
group.translate_ = 'translate(' + newXY.x + ',' + newXY.y + ')';
|
||||
group.setAttribute('transform', group.translate_ + group.skew_);
|
||||
if (this.useDragSurface_) {
|
||||
this.workspace.blockDragSurface_.translateSurface(newXY.x, newXY.y);
|
||||
} else {
|
||||
group.translate_ = 'translate(' + newXY.x + ',' + newXY.y + ')';
|
||||
group.setAttribute('transform', group.translate_ + group.skew_);
|
||||
}
|
||||
// Drag all the nested bubbles.
|
||||
for (var i = 0; i < this.draggedBubbles_.length; i++) {
|
||||
var commentData = this.draggedBubbles_[i];
|
||||
|
||||
@@ -124,6 +124,13 @@ Blockly.dragMode_ = Blockly.DRAG_NONE;
|
||||
*/
|
||||
Blockly.flyoutButtonCallbacks_ = {};
|
||||
|
||||
/**
|
||||
* Cached value for whether 3D is supported.
|
||||
* @type {!boolean}
|
||||
* @private
|
||||
*/
|
||||
Blockly.cache3dSupported_ = null;
|
||||
|
||||
/**
|
||||
* Register a callback function associated with a given key, for clicks on
|
||||
* buttons and labels in the flyout.
|
||||
|
||||
13
core/css.js
13
core/css.js
@@ -148,6 +148,7 @@ Blockly.Css.CONTENT = [
|
||||
'.injectionDiv {',
|
||||
'height: 100%;',
|
||||
'position: relative;',
|
||||
'overflow: hidden;', /* So blocks in drag surface disappear at edges */
|
||||
'}',
|
||||
|
||||
'.blocklyNonSelectable {',
|
||||
@@ -157,6 +158,17 @@ Blockly.Css.CONTENT = [
|
||||
'-ms-user-select: none;',
|
||||
'}',
|
||||
|
||||
'.blocklyBlockDragSurface {',
|
||||
'display: none;',
|
||||
'position: absolute;',
|
||||
'top: 0;',
|
||||
'left: 0;',
|
||||
'right: 0;',
|
||||
'bottom: 0;',
|
||||
'overflow: visible !important;',
|
||||
'z-index: 50;', /* Display below toolbox, but above everything else. */
|
||||
'}',
|
||||
|
||||
'.blocklyTooltipDiv {',
|
||||
'background-color: #ffffc7;',
|
||||
'border: 1px solid #ddc;',
|
||||
@@ -448,6 +460,7 @@ Blockly.Css.CONTENT = [
|
||||
'overflow-x: visible;',
|
||||
'overflow-y: auto;',
|
||||
'position: absolute;',
|
||||
'z-index: 70;', /* so blocks go under toolbox when dragging */
|
||||
'}',
|
||||
|
||||
'.blocklyTreeRoot {',
|
||||
|
||||
@@ -1113,6 +1113,7 @@ Blockly.Flyout.prototype.createBlockFunc_ = function(originBlock) {
|
||||
block.onMouseDown_(e);
|
||||
Blockly.dragMode_ = Blockly.DRAG_FREE;
|
||||
block.setDragging_(true);
|
||||
block.moveToDragSurface_();
|
||||
// Disable workspace resizing. Reenable at the end of the drag.
|
||||
flyout.targetWorkspace_.setResizesEnabled(false);
|
||||
};
|
||||
|
||||
@@ -26,6 +26,7 @@
|
||||
|
||||
goog.provide('Blockly.inject');
|
||||
|
||||
goog.require('Blockly.BlockDragSurfaceSvg');
|
||||
goog.require('Blockly.Css');
|
||||
goog.require('Blockly.Options');
|
||||
goog.require('Blockly.WorkspaceSvg');
|
||||
@@ -54,7 +55,9 @@ Blockly.inject = function(container, opt_options) {
|
||||
var subContainer = goog.dom.createDom('div', 'injectionDiv');
|
||||
container.appendChild(subContainer);
|
||||
var svg = Blockly.createDom_(subContainer, options);
|
||||
var workspace = Blockly.createMainWorkspace_(svg, options);
|
||||
var blockDragSurface = new Blockly.BlockDragSurfaceSvg(subContainer);
|
||||
blockDragSurface.createDom();
|
||||
var workspace = Blockly.createMainWorkspace_(svg, options, blockDragSurface);
|
||||
Blockly.init_(workspace);
|
||||
workspace.markFocused();
|
||||
Blockly.bindEventWithChecks_(svg, 'focus', workspace, workspace.markFocused);
|
||||
@@ -183,12 +186,13 @@ Blockly.createDom_ = function(container, options) {
|
||||
* Create a main workspace and add it to the SVG.
|
||||
* @param {!Element} svg SVG element with pattern defined.
|
||||
* @param {!Blockly.Options} options Dictionary of options.
|
||||
* @param {!Blockly.BlockDragSurfaceSvg} blockDragSurface Drag surface SVG for the workspace.
|
||||
* @return {!Blockly.Workspace} Newly created main workspace.
|
||||
* @private
|
||||
*/
|
||||
Blockly.createMainWorkspace_ = function(svg, options) {
|
||||
Blockly.createMainWorkspace_ = function(svg, options, blockDragSurface) {
|
||||
options.parentWorkspace = null;
|
||||
var mainWorkspace = new Blockly.WorkspaceSvg(options);
|
||||
var mainWorkspace = new Blockly.WorkspaceSvg(options, blockDragSurface);
|
||||
mainWorkspace.scale = options.zoomOptions.startScale;
|
||||
svg.appendChild(mainWorkspace.createDom('blocklyMainBackground'));
|
||||
// A null translation will also apply the correct initial scale.
|
||||
|
||||
@@ -239,6 +239,15 @@ Blockly.isTargetInput_ = function(e) {
|
||||
e.target.isContentEditable;
|
||||
};
|
||||
|
||||
/**
|
||||
* Static regex to pull the x,y,z values out of a translate3d() style property.
|
||||
* Accounts for same exceptions as XY_REGEXP_.
|
||||
* @type {!RegExp}
|
||||
* @private
|
||||
*/
|
||||
Blockly.XY_3D_REGEXP_ =
|
||||
/transform:\s*translate3d\(\s*([-+\d.e]+)px([ ,]\s*([-+\d.e]+)\s*)px([ ,]\s*([-+\d.e]+)\s*)px\)?/;
|
||||
|
||||
/**
|
||||
* Return the coordinates of the top-left corner of this element relative to
|
||||
* its parent. Only for SVG elements and children (e.g. rect, g, path).
|
||||
@@ -266,6 +275,18 @@ Blockly.getRelativeXY_ = function(element) {
|
||||
xy.y += parseFloat(r[3]);
|
||||
}
|
||||
}
|
||||
|
||||
// Third, check for style="transform: translate3d(...)".
|
||||
var style = element.getAttribute('style');
|
||||
if (style && style.indexOf('translate3d') > -1) {
|
||||
var styleComponents = style.match(Blockly.XY_3D_REGEXP_);
|
||||
if (styleComponents) {
|
||||
xy.x += parseFloat(styleComponents[1]);
|
||||
if (styleComponents[3]) {
|
||||
xy.y += parseFloat(styleComponents[3]);
|
||||
}
|
||||
}
|
||||
}
|
||||
return xy;
|
||||
};
|
||||
|
||||
@@ -719,3 +740,43 @@ Blockly.utils.wrapToText_ = function(words, wordBreaks) {
|
||||
}
|
||||
return text.join('');
|
||||
};
|
||||
|
||||
/**
|
||||
* Check if 3D transforms are supported by adding an element
|
||||
* and attempting to set the property.
|
||||
* @return {boolean} true if 3D transforms are supported
|
||||
*/
|
||||
Blockly.is3dSupported = function() {
|
||||
if (Blockly.cache3dSupported_ !== null) {
|
||||
return Blockly.cache3dSupported_;
|
||||
}
|
||||
// CC-BY-SA Lorenzo Polidori
|
||||
// https://stackoverflow.com/questions/5661671/detecting-transform-translate3d-support
|
||||
if (!goog.global.getComputedStyle) {
|
||||
return false;
|
||||
}
|
||||
|
||||
var el = document.createElement('p'),
|
||||
has3d,
|
||||
transforms = {
|
||||
'webkitTransform': '-webkit-transform',
|
||||
'OTransform': '-o-transform',
|
||||
'msTransform': '-ms-transform',
|
||||
'MozTransform': '-moz-transform',
|
||||
'transform': 'transform'
|
||||
};
|
||||
|
||||
// Add it to the body to get the computed style.
|
||||
document.body.insertBefore(el, null);
|
||||
|
||||
for (var t in transforms) {
|
||||
if (el.style[t] !== undefined) {
|
||||
el.style[t] = 'translate3d(1px,1px,1px)';
|
||||
has3d = goog.global.getComputedStyle(el).getPropertyValue(transforms[t]);
|
||||
}
|
||||
}
|
||||
|
||||
document.body.removeChild(el);
|
||||
Blockly.cache3dSupported_ = !!(has3d && has3d !== 'none');
|
||||
return Blockly.cache3dSupported_;
|
||||
};
|
||||
|
||||
@@ -48,10 +48,12 @@ goog.require('goog.userAgent');
|
||||
* Class for a workspace. This is an onscreen area with optional trashcan,
|
||||
* scrollbars, bubbles, and dragging.
|
||||
* @param {!Blockly.Options} options Dictionary of options.
|
||||
* @param {Blockly.BlockDragSurfaceSvg=} opt_blockDragSurface Drag surface for
|
||||
* the workspace.
|
||||
* @extends {Blockly.Workspace}
|
||||
* @constructor
|
||||
*/
|
||||
Blockly.WorkspaceSvg = function(options) {
|
||||
Blockly.WorkspaceSvg = function(options, opt_blockDragSurface) {
|
||||
Blockly.WorkspaceSvg.superClass_.constructor.call(this, options);
|
||||
this.getMetrics =
|
||||
options.getMetrics || Blockly.WorkspaceSvg.getTopLevelWorkspaceMetrics_;
|
||||
@@ -60,6 +62,10 @@ Blockly.WorkspaceSvg = function(options) {
|
||||
|
||||
Blockly.ConnectionDB.init(this);
|
||||
|
||||
if (opt_blockDragSurface) {
|
||||
this.blockDragSurface_ = opt_blockDragSurface;
|
||||
}
|
||||
|
||||
/**
|
||||
* Database of pre-loaded sounds.
|
||||
* @private
|
||||
@@ -167,6 +173,13 @@ Blockly.WorkspaceSvg.prototype.trashcan = null;
|
||||
*/
|
||||
Blockly.WorkspaceSvg.prototype.scrollbar = null;
|
||||
|
||||
/**
|
||||
* This workspace's drag surface, if it exists.
|
||||
* @type {Blockly.BlockDragSurfaceSvg}
|
||||
* @private
|
||||
*/
|
||||
Blockly.WorkspaceSvg.prototype.blockDragSurface_ = null;
|
||||
|
||||
/**
|
||||
* Time that the last sound was played.
|
||||
* @type {Date}
|
||||
@@ -509,6 +522,9 @@ Blockly.WorkspaceSvg.prototype.translate = function(x, y) {
|
||||
'scale(' + this.scale + ')';
|
||||
this.svgBlockCanvas_.setAttribute('transform', translation);
|
||||
this.svgBubbleCanvas_.setAttribute('transform', translation);
|
||||
if (this.blockDragSurface_) {
|
||||
this.blockDragSurface_.translateAndScaleGroup(x, y, this.scale);
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
|
||||
Reference in New Issue
Block a user