mirror of
https://github.com/scratchfoundation/scratch-blocks.git
synced 2025-08-28 22:10:31 -04:00
Implement new zoom controls. Resolves GH-43
* WIP: New zoom controls * Adjust sizing as per discussion with Carl * Update icons and spacing as per discussions with Carl * Remove unused 'rnd' function * Updated icons * Resolve issues from PR review
This commit is contained in:
parent
57c3666198
commit
292296af30
7 changed files with 113 additions and 86 deletions
10
core/css.js
10
core/css.js
|
@ -573,15 +573,7 @@ Blockly.Css.CONTENT = [
|
|||
'}',
|
||||
|
||||
'.blocklyZoom>image {',
|
||||
'opacity: .4;',
|
||||
'}',
|
||||
|
||||
'.blocklyZoom>image:hover {',
|
||||
'opacity: .6;',
|
||||
'}',
|
||||
|
||||
'.blocklyZoom>image:active {',
|
||||
'opacity: .8;',
|
||||
'opacity: 1;',
|
||||
'}',
|
||||
|
||||
/* Darken flyout scrollbars due to being on a grey background. */
|
||||
|
|
|
@ -56,7 +56,7 @@ Blockly.Options = function(options) {
|
|||
languageTree.getElementsByTagName('category').length);
|
||||
var hasTrashcan = options['trashcan'];
|
||||
if (hasTrashcan === undefined) {
|
||||
hasTrashcan = hasCategories;
|
||||
hasTrashcan = false;
|
||||
}
|
||||
var hasCollapse = options['collapse'];
|
||||
if (hasCollapse === undefined) {
|
||||
|
|
|
@ -39,33 +39,61 @@ Blockly.ZoomControls = function(workspace) {
|
|||
this.workspace_ = workspace;
|
||||
};
|
||||
|
||||
/**
|
||||
* Zoom in icon path.
|
||||
* @type {string}
|
||||
* @private
|
||||
*/
|
||||
Blockly.ZoomControls.prototype.ZOOM_IN_PATH_ = 'zoom-in.svg';
|
||||
|
||||
/**
|
||||
* Zoom out icon path.
|
||||
* @type {string}
|
||||
* @private
|
||||
*/
|
||||
Blockly.ZoomControls.prototype.ZOOM_OUT_PATH_ = 'zoom-out.svg';
|
||||
|
||||
/**
|
||||
* Zoom reset icon path.
|
||||
* @type {string}
|
||||
* @private
|
||||
*/
|
||||
Blockly.ZoomControls.prototype.ZOOM_RESET_PATH_ = 'zoom-reset.svg';
|
||||
|
||||
/**
|
||||
* Width of the zoom controls.
|
||||
* @type {number}
|
||||
* @private
|
||||
*/
|
||||
Blockly.ZoomControls.prototype.WIDTH_ = 32;
|
||||
Blockly.ZoomControls.prototype.WIDTH_ = 36;
|
||||
|
||||
/**
|
||||
* Height of the zoom controls.
|
||||
* @type {number}
|
||||
* @private
|
||||
*/
|
||||
Blockly.ZoomControls.prototype.HEIGHT_ = 110;
|
||||
Blockly.ZoomControls.prototype.HEIGHT_ = 124;
|
||||
|
||||
/**
|
||||
* Distance between each zoom control.
|
||||
* @type {number}
|
||||
* @private
|
||||
*/
|
||||
Blockly.ZoomControls.prototype.MARGIN_BETWEEN_ = 8;
|
||||
|
||||
/**
|
||||
* Distance between zoom controls and bottom edge of workspace.
|
||||
* @type {number}
|
||||
* @private
|
||||
*/
|
||||
Blockly.ZoomControls.prototype.MARGIN_BOTTOM_ = 20;
|
||||
Blockly.ZoomControls.prototype.MARGIN_BOTTOM_ = 12;
|
||||
|
||||
/**
|
||||
* Distance between zoom controls and right edge of workspace.
|
||||
* @type {number}
|
||||
* @private
|
||||
*/
|
||||
Blockly.ZoomControls.prototype.MARGIN_SIDE_ = 20;
|
||||
Blockly.ZoomControls.prototype.MARGIN_SIDE_ = 12;
|
||||
|
||||
/**
|
||||
* The SVG group containing the zoom controls.
|
||||
|
@ -95,82 +123,79 @@ Blockly.ZoomControls.prototype.top_ = 0;
|
|||
Blockly.ZoomControls.prototype.createDom = function() {
|
||||
var workspace = this.workspace_;
|
||||
/* Here's the markup that will be generated:
|
||||
<g class="blocklyZoom">
|
||||
<clippath id="blocklyZoomoutClipPath837493">
|
||||
<rect width="32" height="32" y="77"></rect>
|
||||
</clippath>
|
||||
<image width="96" height="124" x="-64" y="-15" xlink:href="media/sprites.png"
|
||||
clip-path="url(#blocklyZoomoutClipPath837493)"></image>
|
||||
<clippath id="blocklyZoominClipPath837493">
|
||||
<rect width="32" height="32" y="43"></rect>
|
||||
</clippath>
|
||||
<image width="96" height="124" x="-32" y="-49" xlink:href="media/sprites.png"
|
||||
clip-path="url(#blocklyZoominClipPath837493)"></image>
|
||||
<clippath id="blocklyZoomresetClipPath837493">
|
||||
<rect width="32" height="32"></rect>
|
||||
</clippath>
|
||||
<image width="96" height="124" y="-92" xlink:href="media/sprites.png"
|
||||
clip-path="url(#blocklyZoomresetClipPath837493)"></image>
|
||||
<g class="blocklyZoom" transform="translate(822,594)">
|
||||
<image width="36" height="36" y="0" xlink:href="../media/zoom-in.svg">
|
||||
</image>
|
||||
<image width="36" height="36" y="44" xlink:href="../media/zoom-out.svg">
|
||||
</image>
|
||||
<image width="36" height="36" y="88" xlink:href="../media/zoom-reset.svg">
|
||||
</image>
|
||||
</g>
|
||||
*/
|
||||
this.svgGroup_ = Blockly.utils.createSvgElement('g',
|
||||
{'class': 'blocklyZoom'}, null);
|
||||
var rnd = String(Math.random()).substring(2);
|
||||
this.svgGroup_ = Blockly.utils.createSvgElement(
|
||||
'g',
|
||||
{'class': 'blocklyZoom'},
|
||||
null
|
||||
);
|
||||
|
||||
var clip = Blockly.utils.createSvgElement('clipPath',
|
||||
{'id': 'blocklyZoomoutClipPath' + rnd},
|
||||
this.svgGroup_);
|
||||
Blockly.utils.createSvgElement('rect',
|
||||
{'width': 32, 'height': 32, 'y': 77},
|
||||
clip);
|
||||
var zoomoutSvg = Blockly.utils.createSvgElement('image',
|
||||
{'width': Blockly.SPRITE.width,
|
||||
'height': Blockly.SPRITE.height, 'x': -64,
|
||||
'y': -15,
|
||||
'clip-path': 'url(#blocklyZoomoutClipPath' + rnd + ')'},
|
||||
this.svgGroup_);
|
||||
zoomoutSvg.setAttributeNS('http://www.w3.org/1999/xlink', 'xlink:href',
|
||||
workspace.options.pathToMedia + Blockly.SPRITE.url);
|
||||
/**
|
||||
* Zoom in control.
|
||||
* @type {SVGElement}
|
||||
*/
|
||||
var zoominSvg = Blockly.utils.createSvgElement(
|
||||
'image',
|
||||
{
|
||||
'width': this.WIDTH_,
|
||||
'height': this.WIDTH_,
|
||||
'y': 0
|
||||
},
|
||||
this.svgGroup_
|
||||
);
|
||||
zoominSvg.setAttributeNS(
|
||||
'http://www.w3.org/1999/xlink',
|
||||
'xlink:href',
|
||||
workspace.options.pathToMedia + this.ZOOM_IN_PATH_
|
||||
);
|
||||
|
||||
var clip = Blockly.utils.createSvgElement('clipPath',
|
||||
{'id': 'blocklyZoominClipPath' + rnd},
|
||||
this.svgGroup_);
|
||||
Blockly.utils.createSvgElement('rect',
|
||||
{'width': 32, 'height': 32, 'y': 43},
|
||||
clip);
|
||||
var zoominSvg = Blockly.utils.createSvgElement('image',
|
||||
{'width': Blockly.SPRITE.width,
|
||||
'height': Blockly.SPRITE.height,
|
||||
'x': -32,
|
||||
'y': -49,
|
||||
'clip-path': 'url(#blocklyZoominClipPath' + rnd + ')'},
|
||||
this.svgGroup_);
|
||||
zoominSvg.setAttributeNS('http://www.w3.org/1999/xlink', 'xlink:href',
|
||||
workspace.options.pathToMedia + Blockly.SPRITE.url);
|
||||
/**
|
||||
* Zoom out control.
|
||||
* @type {SVGElement}
|
||||
*/
|
||||
var zoomoutSvg = Blockly.utils.createSvgElement(
|
||||
'image',
|
||||
{
|
||||
'width': this.WIDTH_,
|
||||
'height': this.WIDTH_,
|
||||
'y': (this.WIDTH_ * 1) + (this.MARGIN_BETWEEN_ * 1)
|
||||
},
|
||||
this.svgGroup_
|
||||
);
|
||||
zoomoutSvg.setAttributeNS(
|
||||
'http://www.w3.org/1999/xlink',
|
||||
'xlink:href',
|
||||
workspace.options.pathToMedia + this.ZOOM_OUT_PATH_
|
||||
);
|
||||
|
||||
var clip = Blockly.utils.createSvgElement('clipPath',
|
||||
{'id': 'blocklyZoomresetClipPath' + rnd},
|
||||
this.svgGroup_);
|
||||
Blockly.utils.createSvgElement('rect',
|
||||
{'width': 32, 'height': 32},
|
||||
clip);
|
||||
var zoomresetSvg = Blockly.utils.createSvgElement('image',
|
||||
{'width': Blockly.SPRITE.width,
|
||||
'height': Blockly.SPRITE.height, 'y': -92,
|
||||
'clip-path': 'url(#blocklyZoomresetClipPath' + rnd + ')'},
|
||||
this.svgGroup_);
|
||||
zoomresetSvg.setAttributeNS('http://www.w3.org/1999/xlink', 'xlink:href',
|
||||
workspace.options.pathToMedia + Blockly.SPRITE.url);
|
||||
/**
|
||||
* Zoom reset control.
|
||||
* @type {SVGElement}
|
||||
*/
|
||||
var zoomresetSvg = Blockly.utils.createSvgElement(
|
||||
'image',
|
||||
{
|
||||
'width': this.WIDTH_,
|
||||
'height': this.WIDTH_,
|
||||
'y': (this.WIDTH_ * 2) + (this.MARGIN_BETWEEN_ * 2)
|
||||
},
|
||||
this.svgGroup_
|
||||
);
|
||||
zoomresetSvg.setAttributeNS(
|
||||
'http://www.w3.org/1999/xlink',
|
||||
'xlink:href',
|
||||
workspace.options.pathToMedia + this.ZOOM_RESET_PATH_
|
||||
);
|
||||
|
||||
// Attach event listeners.
|
||||
Blockly.bindEventWithChecks_(zoomresetSvg, 'mousedown', null, function(e) {
|
||||
workspace.markFocused();
|
||||
workspace.setScale(workspace.options.zoomOptions.startScale);
|
||||
workspace.scrollCenter();
|
||||
Blockly.Touch.clearTouchIdentifier(); // Don't block future drags.
|
||||
e.stopPropagation(); // Don't start a workspace scroll.
|
||||
e.preventDefault(); // Stop double-clicking from selecting text.
|
||||
});
|
||||
Blockly.bindEventWithChecks_(zoominSvg, 'mousedown', null, function(e) {
|
||||
workspace.markFocused();
|
||||
workspace.zoomCenter(1);
|
||||
|
@ -185,6 +210,14 @@ Blockly.ZoomControls.prototype.createDom = function() {
|
|||
e.stopPropagation(); // Don't start a workspace scroll.
|
||||
e.preventDefault(); // Stop double-clicking from selecting text.
|
||||
});
|
||||
Blockly.bindEventWithChecks_(zoomresetSvg, 'mousedown', null, function(e) {
|
||||
workspace.markFocused();
|
||||
workspace.setScale(workspace.options.zoomOptions.startScale);
|
||||
workspace.scrollCenter();
|
||||
Blockly.Touch.clearTouchIdentifier(); // Don't block future drags.
|
||||
e.stopPropagation(); // Don't start a workspace scroll.
|
||||
e.preventDefault(); // Stop double-clicking from selecting text.
|
||||
});
|
||||
|
||||
return this.svgGroup_;
|
||||
};
|
||||
|
|
1
media/zoom-in.svg
Normal file
1
media/zoom-in.svg
Normal file
|
@ -0,0 +1 @@
|
|||
<svg id="Layer_1" data-name="Layer 1" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 36 36"><defs><style>.cls-1{fill:#231f20;opacity:0.15;}.cls-2{fill:#fff;}.cls-3{opacity:0.75;}.cls-4{fill:none;stroke:#575e75;stroke-linecap:round;stroke-linejoin:round;stroke-width:1.5px;}</style></defs><title>zoom-in</title><circle class="cls-1" cx="18" cy="18" r="18"/><circle class="cls-2" cx="18" cy="18" r="16"/><g class="cls-3"><circle class="cls-4" cx="18" cy="18" r="7"/><line class="cls-4" x1="23" y1="23" x2="26" y2="26"/><line class="cls-4" x1="16" y1="18" x2="20" y2="18"/><line class="cls-4" x1="18" y1="16" x2="18" y2="20"/></g></svg>
|
After Width: | Height: | Size: 634 B |
1
media/zoom-out.svg
Normal file
1
media/zoom-out.svg
Normal file
|
@ -0,0 +1 @@
|
|||
<svg id="Layer_1" data-name="Layer 1" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 36 36"><defs><style>.cls-1{fill:#231f20;opacity:0.15;}.cls-2{fill:#fff;}.cls-3{opacity:0.75;}.cls-4{fill:none;stroke:#575e75;stroke-linecap:round;stroke-linejoin:round;stroke-width:1.5px;}</style></defs><title>zoom-out</title><circle class="cls-1" cx="18" cy="18" r="18"/><circle class="cls-2" cx="18" cy="18" r="16"/><g class="cls-3"><circle class="cls-4" cx="18" cy="18" r="7"/><line class="cls-4" x1="23" y1="23" x2="26" y2="26"/><line class="cls-4" x1="16" y1="18" x2="20" y2="18"/></g></svg>
|
After Width: | Height: | Size: 582 B |
1
media/zoom-reset.svg
Normal file
1
media/zoom-reset.svg
Normal file
|
@ -0,0 +1 @@
|
|||
<svg id="Layer_1" data-name="Layer 1" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 36 36"><defs><style>.cls-1{fill:#231f20;opacity:0.15;}.cls-2{fill:#fff;}.cls-3{opacity:0.75;}.cls-4{fill:#575e75;}</style></defs><title>zoom-reset</title><circle class="cls-1" cx="18" cy="18" r="18"/><circle class="cls-2" cx="18" cy="18" r="16"/><g class="cls-3"><rect class="cls-4" x="13" y="14" width="10" height="2" rx="1" ry="1"/><rect class="cls-4" x="13" y="20" width="10" height="2" rx="1" ry="1"/></g></svg>
|
After Width: | Height: | Size: 501 B |
|
@ -71,7 +71,6 @@
|
|||
toolbox: toolbox,
|
||||
toolboxPosition: side == 'top' || side == 'start' ? 'start' : 'end',
|
||||
horizontalLayout: side == 'top' || side == 'bottom',
|
||||
trashcan: true,
|
||||
sounds: soundsEnabled,
|
||||
zoom: {
|
||||
controls: true,
|
||||
|
@ -92,7 +91,7 @@
|
|||
dragShadowOpacity: 0.6
|
||||
}
|
||||
});
|
||||
|
||||
|
||||
if (sessionStorage) {
|
||||
// Restore previously displayed text.
|
||||
var text = sessionStorage.getItem('textarea');
|
||||
|
@ -101,7 +100,7 @@
|
|||
}
|
||||
taChange();
|
||||
}
|
||||
|
||||
|
||||
if (sessionStorage) {
|
||||
// Restore event logging state.
|
||||
var state = sessionStorage.getItem('logEvents');
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue