diff --git a/core/trashcan.ts b/core/trashcan.ts
index 08211bac9dd..e658977a0dc 100644
--- a/core/trashcan.ts
+++ b/core/trashcan.ts
@@ -14,6 +14,7 @@
// Unused import preserved for side-effects. Remove if unneeded.
import * as browserEvents from './browser_events.js';
import {ComponentManager} from './component_manager.js';
+import * as Css from './css.js';
import {DeleteArea} from './delete_area.js';
import type {Abstract} from './events/events_abstract.js';
import './events/events_trashcan_open.js';
@@ -28,7 +29,6 @@ import type {UiMetrics} from './metrics_manager.js';
import * as uiPosition from './positionable_helpers.js';
import * as registry from './registry.js';
import type * as blocks from './serialization/blocks.js';
-import {SPRITE} from './sprites.js';
import * as dom from './utils/dom.js';
import {Rect} from './utils/rect.js';
import {Size} from './utils/size.js';
@@ -150,61 +150,21 @@ export class Trashcan
*/
this.svgGroup = dom.createSvgElement(Svg.G, {'class': 'blocklyTrash'});
- let clip;
- const rnd = String(Math.random()).substring(2);
- clip = dom.createSvgElement(
- Svg.CLIPPATH,
- {'id': 'blocklyTrashBodyClipPath' + rnd},
+ this.svgLid = dom.createSvgElement(
+ Svg.G,
+ {'class': 'blocklyTrashLid'},
this.svgGroup,
);
- dom.createSvgElement(
- Svg.RECT,
- {'width': WIDTH, 'height': BODY_HEIGHT, 'y': LID_HEIGHT},
- clip,
- );
+ this.svgLid.innerHTML = ``;
const body = dom.createSvgElement(
- Svg.IMAGE,
- {
- 'width': SPRITE.width,
- 'x': -SPRITE_LEFT,
- 'height': SPRITE.height,
- 'y': -SPRITE_TOP,
- 'clip-path': 'url(#blocklyTrashBodyClipPath' + rnd + ')',
- },
+ Svg.G,
+ {'class': 'blocklyTrashBody'},
this.svgGroup,
);
- body.setAttributeNS(
- dom.XLINK_NS,
- 'xlink:href',
- this.workspace.options.pathToMedia + SPRITE.url,
- );
-
- clip = dom.createSvgElement(
- Svg.CLIPPATH,
- {'id': 'blocklyTrashLidClipPath' + rnd},
- this.svgGroup,
- );
- dom.createSvgElement(
- Svg.RECT,
- {'width': WIDTH, 'height': LID_HEIGHT},
- clip,
- );
- this.svgLid = dom.createSvgElement(
- Svg.IMAGE,
- {
- 'width': SPRITE.width,
- 'x': -SPRITE_LEFT,
- 'height': SPRITE.height,
- 'y': -SPRITE_TOP,
- 'clip-path': 'url(#blocklyTrashLidClipPath' + rnd + ')',
- },
- this.svgGroup,
- );
- this.svgLid.setAttributeNS(
- dom.XLINK_NS,
- 'xlink:href',
- this.workspace.options.pathToMedia + SPRITE.url,
- );
+ body.innerHTML = `
+
+
+ `;
// bindEventWithChecks_ quashes events too aggressively. See:
// https://groups.google.com/forum/#!topic/blockly/QF4yB9Wx00s
@@ -475,12 +435,6 @@ export class Trashcan
this.setLidAngle(this.lidOpen * MAX_LID_ANGLE);
- // Linear interpolation between min and max.
- const opacity = OPACITY_MIN + this.lidOpen * (OPACITY_MAX - OPACITY_MIN);
- if (this.svgGroup) {
- this.svgGroup.style.opacity = `${opacity}`;
- }
-
if (this.lidOpen > this.minOpenness && this.lidOpen < 1) {
this.lidTask = setTimeout(
this.animateLid.bind(this),
@@ -717,14 +671,19 @@ const ANIMATION_LENGTH = 80;
/** The number of frames in the animation. */
const ANIMATION_FRAMES = 4;
-/** The minimum (resting) opacity of the trashcan and lid. */
-const OPACITY_MIN = 0.4;
-
-/** The maximum (hovered) opacity of the trashcan and lid. */
-const OPACITY_MAX = 0.8;
-
/**
* The maximum angle the trashcan lid can opens to. At the end of the open
* animation the lid will be open to this angle.
*/
const MAX_LID_ANGLE = 45;
+
+Css.register(`
+.blocklyTrash {
+ fill: #888;
+ opacity: 0.4;
+ transition: opacity .08s linear;
+}
+.blocklyTrash:hover {
+ opacity: 0.8;
+}
+`);
diff --git a/core/zoom_controls.ts b/core/zoom_controls.ts
index 4f14b73bed6..f7646992144 100644
--- a/core/zoom_controls.ts
+++ b/core/zoom_controls.ts
@@ -22,7 +22,6 @@ import * as eventUtils from './events/utils.js';
import type {IPositionable} from './interfaces/i_positionable.js';
import type {UiMetrics} from './metrics_manager.js';
import * as uiPosition from './positionable_helpers.js';
-import {SPRITE} from './sprites.js';
import * as Touch from './touch.js';
import * as dom from './utils/dom.js';
import {Rect} from './utils/rect.js';
@@ -102,13 +101,12 @@ export class ZoomControls implements IPositionable {
// Each filter/pattern needs a unique ID for the case of multiple Blockly
// instances on a page. Browser behaviour becomes undefined otherwise.
// https://neil.fraser.name/news/2015/11/01/
- const rnd = String(Math.random()).substring(2);
- this.createZoomOutSvg(rnd);
- this.createZoomInSvg(rnd);
+ this.createZoomOutSvg();
+ this.createZoomInSvg();
if (this.workspace.isMovable()) {
// If we zoom to the center and the workspace isn't movable we could
// loose blocks at the edges of the workspace.
- this.createZoomResetSvg(rnd);
+ this.createZoomResetSvg();
}
return this.svgGroup;
}
@@ -238,12 +236,8 @@ export class ZoomControls implements IPositionable {
/**
* Create the zoom in icon and its event handler.
- *
- * @param rnd The random string to use as a suffix in the clip path's ID.
- * These IDs must be unique in case there are multiple Blockly instances
- * on the same page.
*/
- private createZoomOutSvg(rnd: string) {
+ private createZoomOutSvg() {
/* This markup will be generated and added to the .svgGroup:
@@ -259,35 +253,10 @@ export class ZoomControls implements IPositionable {
{'class': 'blocklyZoom blocklyZoomOut'},
this.svgGroup,
);
- const clip = dom.createSvgElement(
- Svg.CLIPPATH,
- {'id': 'blocklyZoomoutClipPath' + rnd},
- this.zoomOutGroup,
- );
- dom.createSvgElement(
- Svg.RECT,
- {
- 'width': 32,
- 'height': 32,
- },
- clip,
- );
- const zoomoutSvg = dom.createSvgElement(
- Svg.IMAGE,
- {
- 'width': SPRITE.width,
- 'height': SPRITE.height,
- 'x': -64,
- 'y': -92,
- 'clip-path': 'url(#blocklyZoomoutClipPath' + rnd + ')',
- },
- this.zoomOutGroup,
- );
- zoomoutSvg.setAttributeNS(
- dom.XLINK_NS,
- 'xlink:href',
- this.workspace.options.pathToMedia + SPRITE.url,
- );
+ this.zoomOutGroup.innerHTML = `
+
+
+`;
// Attach listener.
this.boundEvents.push(
@@ -302,12 +271,8 @@ export class ZoomControls implements IPositionable {
/**
* Create the zoom out icon and its event handler.
- *
- * @param rnd The random string to use as a suffix in the clip path's ID.
- * These IDs must be unique in case there are multiple Blockly instances
- * on the same page.
*/
- private createZoomInSvg(rnd: string) {
+ private createZoomInSvg() {
/* This markup will be generated and added to the .svgGroup:
@@ -323,35 +288,11 @@ export class ZoomControls implements IPositionable {
{'class': 'blocklyZoom blocklyZoomIn'},
this.svgGroup,
);
- const clip = dom.createSvgElement(
- Svg.CLIPPATH,
- {'id': 'blocklyZoominClipPath' + rnd},
- this.zoomInGroup,
- );
- dom.createSvgElement(
- Svg.RECT,
- {
- 'width': 32,
- 'height': 32,
- },
- clip,
- );
- const zoominSvg = dom.createSvgElement(
- Svg.IMAGE,
- {
- 'width': SPRITE.width,
- 'height': SPRITE.height,
- 'x': -32,
- 'y': -92,
- 'clip-path': 'url(#blocklyZoominClipPath' + rnd + ')',
- },
- this.zoomInGroup,
- );
- zoominSvg.setAttributeNS(
- dom.XLINK_NS,
- 'xlink:href',
- this.workspace.options.pathToMedia + SPRITE.url,
- );
+ this.zoomInGroup.innerHTML = `
+
+
+
+`;
// Attach listener.
this.boundEvents.push(
@@ -383,12 +324,8 @@ export class ZoomControls implements IPositionable {
/**
* Create the zoom reset icon and its event handler.
- *
- * @param rnd The random string to use as a suffix in the clip path's ID.
- * These IDs must be unique in case there are multiple Blockly instances
- * on the same page.
*/
- private createZoomResetSvg(rnd: string) {
+ private createZoomResetSvg() {
/* This markup will be generated and added to the .svgGroup:
@@ -404,27 +341,14 @@ export class ZoomControls implements IPositionable {
{'class': 'blocklyZoom blocklyZoomReset'},
this.svgGroup,
);
- const clip = dom.createSvgElement(
- Svg.CLIPPATH,
- {'id': 'blocklyZoomresetClipPath' + rnd},
- this.zoomResetGroup,
- );
- dom.createSvgElement(Svg.RECT, {'width': 32, 'height': 32}, clip);
- const zoomresetSvg = dom.createSvgElement(
- Svg.IMAGE,
- {
- 'width': SPRITE.width,
- 'height': SPRITE.height,
- 'y': -92,
- 'clip-path': 'url(#blocklyZoomresetClipPath' + rnd + ')',
- },
- this.zoomResetGroup,
- );
- zoomresetSvg.setAttributeNS(
- dom.XLINK_NS,
- 'xlink:href',
- this.workspace.options.pathToMedia + SPRITE.url,
- );
+ this.zoomResetGroup.innerHTML = `
+
+
+
+
+
+
+`;
// Attach event listeners.
this.boundEvents.push(
@@ -479,15 +403,29 @@ export class ZoomControls implements IPositionable {
/** CSS for zoom controls. See css.js for use. */
Css.register(`
-.blocklyZoom>image, .blocklyZoom>svg>image {
+.blocklyZoom {
opacity: .4;
+ pointer-events: bounding-box;
}
-.blocklyZoom>image:hover, .blocklyZoom>svg>image:hover {
+.blocklyZoom:hover {
opacity: .6;
}
-.blocklyZoom>image:active, .blocklyZoom>svg>image:active {
+.blocklyZoom:active {
opacity: .8;
}
+
+.blocklyZoom>* {
+ fill:#fff;
+ fill-opacity:0.005;
+ stroke:#888;
+ stroke-width:2;
+ stroke-linecap:round;
+}
+.blocklyZoom>circle.center {
+ fill: #888;
+ fill-opacity: 1;
+ stroke-width: 0;
+}
`);