Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
7 changes: 5 additions & 2 deletions src/svg/Painter.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
* @module zrender/svg/Painter
*/

import {createElement} from './core';
import {createElement, normalizeColor} from './core';
import * as util from '../core/util';
import Path from '../graphic/Path';
import ZRImage from '../graphic/Image';
Expand Down Expand Up @@ -194,7 +194,10 @@ class SVGPainter implements PainterBase {
bgNode.setAttribute('x', 0 as any);
bgNode.setAttribute('y', 0 as any);
bgNode.setAttribute('id', 0 as any);
bgNode.style.fill = backgroundColor;
const { color, opacity } = normalizeColor(backgroundColor);
bgNode.setAttribute('fill', color);
bgNode.setAttribute('fill-opacity', opacity as any);

this._backgroundRoot.appendChild(bgNode);
this._backgroundNode = bgNode;
}
Expand Down
22 changes: 21 additions & 1 deletion src/svg/core.ts
Original file line number Diff line number Diff line change
@@ -1,3 +1,23 @@
import { parse } from '../tool/color';

export function createElement(name: string) {
return document.createElementNS('http://www.w3.org/2000/svg', name);
}
}

export function normalizeColor(color: string): { color: string, opacity: number } {
let opacity;
if (!color || color === 'transparent') {
color = 'none';
}
else if (color.indexOf('rgba') > -1) {
const arr = parse(color);
if (arr) {
color = 'rgb(' + arr[0] + ',' + arr[1] + ',' + arr[2] + ')';
opacity = arr[3];
}
}
return {
color,
opacity: opacity == null ? 1 : opacity
};
}
33 changes: 23 additions & 10 deletions src/svg/graphic.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
// 1. shadow
// 2. Image: sx, sy, sw, sh

import {createElement} from './core';
import {createElement, normalizeColor} from './core';
import { PathRebuilder } from '../core/PathProxy';
import * as matrix from '../core/matrix';
import Path, { PathStyleProps } from '../graphic/Path';
Expand Down Expand Up @@ -92,30 +92,35 @@ function bindStyle(svgEl: SVGElement, style: AllStyleOption, el?: Path | TSpan |
}

if (pathHasFill(style)) {
let fill = style.fill;
fill = fill === 'transparent' ? NONE : fill;
attr(svgEl, 'fill', fill as string);
const fill = normalizeColor(style.fill as string);
attr(svgEl, 'fill', fill.color);
attr(svgEl,
'fill-opacity',
(style.fillOpacity != null ? style.fillOpacity * opacity : opacity) + ''
(style.fillOpacity != null
? style.fillOpacity * fill.opacity * opacity
: fill.opacity * opacity
) + ''
);
}
else {
attr(svgEl, 'fill', NONE);
}

if (pathHasStroke(style)) {
let stroke = style.stroke;
stroke = stroke === 'transparent' ? NONE : stroke;
attr(svgEl, 'stroke', stroke as string);
const stroke = normalizeColor(style.stroke as string);
attr(svgEl, 'stroke', stroke.color);
const strokeWidth = style.lineWidth;
const strokeScale = style.strokeNoScale
? (el as Path).getLineScale()
: 1;
attr(svgEl, 'stroke-width', (strokeScale ? strokeWidth / strokeScale : 0) + '');
// stroke then fill for text; fill then stroke for others
attr(svgEl, 'paint-order', style.strokeFirst ? 'stroke' : 'fill');
attr(svgEl, 'stroke-opacity', (style.strokeOpacity != null ? style.strokeOpacity * opacity : opacity) + '');
attr(svgEl, 'stroke-opacity', (
style.strokeOpacity != null
? style.strokeOpacity * stroke.opacity * opacity
: stroke.opacity * opacity
) + '');
let lineDash = style.lineDash && strokeWidth > 0 && normalizeLineDash(style.lineDash, strokeWidth);
if (lineDash) {
let lineDashOffset = style.lineDashOffset;
Expand Down Expand Up @@ -169,7 +174,14 @@ class SVGPathRebuilder implements PathRebuilder {
arc(cx: number, cy: number, r: number, startAngle: number, endAngle: number, anticlockwise: boolean) {
this.ellipse(cx, cy, r, r, 0, startAngle, endAngle, anticlockwise);
}
ellipse(cx: number, cy: number, rx: number, ry: number, psi: number, startAngle: number, endAngle: number, anticlockwise: boolean) {
ellipse(
cx: number, cy: number,
rx: number, ry: number,
psi: number,
startAngle: number,
endAngle: number,
anticlockwise: boolean
) {

const firstCmd = this._d.length === 0;

Expand Down Expand Up @@ -237,6 +249,7 @@ class SVGPathRebuilder implements PathRebuilder {
this._add('L', x + w, y + h);
this._add('L', x, y + h);
this._add('L', x, y);
this._add('Z');
}
closePath() {
// Not use Z as first command
Expand Down
24 changes: 15 additions & 9 deletions src/svg/helper/ClippathManager.ts
Original file line number Diff line number Diff line change
Expand Up @@ -44,8 +44,11 @@ export default class ClippathManager extends Definable {

markAllUnused() {
super.markAllUnused();
for (let key in this._refGroups) {
this.markDomUnused(this._refGroups[key]);
const refGroups = this._refGroups;
for (let key in refGroups) {
if (refGroups.hasOwnProperty(key)) {
this.markDomUnused(refGroups[key]);
}
}
this._keyDuplicateCount = {};
}
Expand Down Expand Up @@ -163,13 +166,16 @@ export default class ClippathManager extends Definable {
super.removeUnused();

const newRefGroupsMap: Dictionary<SVGElement> = {};
for (let key in this._refGroups) {
const group = this._refGroups[key];
if (!this.isDomUnused(group)) {
newRefGroupsMap[key] = group;
}
else if (group.parentNode) {
group.parentNode.removeChild(group);
const refGroups = this._refGroups;
for (let key in refGroups) {
if (refGroups.hasOwnProperty(key)) {
const group = refGroups[key];
if (!this.isDomUnused(group)) {
newRefGroupsMap[key] = group;
}
else if (group.parentNode) {
group.parentNode.removeChild(group);
}
}
}
this._refGroups = newRefGroupsMap;
Expand Down
16 changes: 10 additions & 6 deletions src/svg/helper/ShadowManager.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ import Definable from './Definable';
import Displayable from '../../graphic/Displayable';
import { PathStyleProps } from '../../graphic/Path';
import { Dictionary } from '../../core/types';
import { normalizeColor } from '../core';

type DisplayableExtended = Displayable & {
_shadowDom: SVGElement
Expand Down Expand Up @@ -35,7 +36,7 @@ export default class ShadowManager extends Definable {
if (!shadowDom) {
shadowDom = this.createElement('filter') as SVGFilterElement;
shadowDom.setAttribute('id', 'zr' + this._zrId + '-shadow-' + this.nextId++);
const domChild = this.createElement('feDropShadow')
const domChild = this.createElement('feDropShadow');
shadowDom.appendChild(domChild);
this.addDom(shadowDom);
}
Expand Down Expand Up @@ -98,11 +99,12 @@ export default class ShadowManager extends Definable {
let offsetX = style.shadowOffsetX || 0;
let offsetY = style.shadowOffsetY || 0;
let blur = style.shadowBlur;
let color = style.shadowColor;
const normalizedColor = normalizeColor(style.shadowColor);

domChild.setAttribute('dx', offsetX / scaleX + '');
domChild.setAttribute('dy', offsetY / scaleY + '');
domChild.setAttribute('flood-color', color);
domChild.setAttribute('flood-color', normalizedColor.color);
domChild.setAttribute('flood-opacity', normalizedColor.opacity + '');

// Divide by two here so that it looks the same as in canvas
// See: https://html.spec.whatwg.org/multipage/canvas.html#dom-context-2d-shadowblur
Expand Down Expand Up @@ -134,9 +136,11 @@ export default class ShadowManager extends Definable {
let shadowDomsPool = this._shadowDomPool;

// let currentUsedShadow = 0;
for (let key in this._shadowDomMap) {
const dom = this._shadowDomMap[key];
shadowDomsPool.push(dom);
const shadowDomMap = this._shadowDomMap;
for (let key in shadowDomMap) {
if (shadowDomMap.hasOwnProperty(key)) {
shadowDomsPool.push(shadowDomMap[key]);
}
// currentUsedShadow++;
}

Expand Down