790 lines
19 KiB
Java
790 lines
19 KiB
Java
|
|
var Util = require('../../util');
|
|||
|
|
|
|||
|
|
var _require = require('../../util/format'),
|
|||
|
|
parseRadius = _require.parseRadius;
|
|||
|
|
|
|||
|
|
var Marker = require('../../shapes/marker');
|
|||
|
|
|
|||
|
|
var Defs = require('./defs');
|
|||
|
|
|
|||
|
|
var SHAPE_TO_TAGS = {
|
|||
|
|
rect: 'path',
|
|||
|
|
circle: 'circle',
|
|||
|
|
line: 'line',
|
|||
|
|
path: 'path',
|
|||
|
|
marker: 'path',
|
|||
|
|
text: 'text',
|
|||
|
|
polygon: 'polygon',
|
|||
|
|
image: 'image',
|
|||
|
|
ellipse: 'ellipse',
|
|||
|
|
dom: 'foreignObject',
|
|||
|
|
fan: 'path',
|
|||
|
|
group: 'g'
|
|||
|
|
};
|
|||
|
|
var LETTER_SPACING = 0.3;
|
|||
|
|
var SVG_ATTR_MAP = {
|
|||
|
|
opacity: 'opacity',
|
|||
|
|
fillStyle: 'fill',
|
|||
|
|
strokeOpacity: 'stroke-opacity',
|
|||
|
|
fillOpacity: 'fill-opacity',
|
|||
|
|
strokeStyle: 'stroke',
|
|||
|
|
x: 'x',
|
|||
|
|
y: 'y',
|
|||
|
|
r: 'r',
|
|||
|
|
rx: 'rx',
|
|||
|
|
ry: 'ry',
|
|||
|
|
width: 'width',
|
|||
|
|
height: 'height',
|
|||
|
|
x1: 'x1',
|
|||
|
|
x2: 'x2',
|
|||
|
|
y1: 'y1',
|
|||
|
|
y2: 'y2',
|
|||
|
|
lineCap: 'stroke-linecap',
|
|||
|
|
lineJoin: 'stroke-linejoin',
|
|||
|
|
lineWidth: 'stroke-width',
|
|||
|
|
lineDash: 'stroke-dasharray',
|
|||
|
|
lineDashOffset: 'stroke-dashoffset',
|
|||
|
|
miterLimit: 'stroke-miterlimit',
|
|||
|
|
font: 'font',
|
|||
|
|
fontSize: 'font-size',
|
|||
|
|
fontStyle: 'font-style',
|
|||
|
|
fontVariant: 'font-variant',
|
|||
|
|
fontWeight: 'font-weight',
|
|||
|
|
fontFamily: 'font-family',
|
|||
|
|
startArrow: 'marker-start',
|
|||
|
|
endArrow: 'marker-end',
|
|||
|
|
path: 'd',
|
|||
|
|
"class": 'class',
|
|||
|
|
id: 'id',
|
|||
|
|
style: 'style',
|
|||
|
|
preserveAspectRatio: 'preserveAspectRatio'
|
|||
|
|
};
|
|||
|
|
var BASELINE_MAP = {
|
|||
|
|
top: 'before-edge',
|
|||
|
|
middle: 'central',
|
|||
|
|
bottom: 'after-edge',
|
|||
|
|
alphabetic: 'baseline',
|
|||
|
|
hanging: 'hanging'
|
|||
|
|
};
|
|||
|
|
var ANCHOR_MAP = {
|
|||
|
|
left: 'left',
|
|||
|
|
start: 'left',
|
|||
|
|
center: 'middle',
|
|||
|
|
right: 'end',
|
|||
|
|
end: 'end'
|
|||
|
|
};
|
|||
|
|
|
|||
|
|
var Painter = /*#__PURE__*/function () {
|
|||
|
|
function Painter(dom) {
|
|||
|
|
if (!dom) {
|
|||
|
|
return null;
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
var svgId = Util.uniqueId('canvas_');
|
|||
|
|
var canvasDom = Util.createDom("<svg id=\"" + svgId + "\"></svg>");
|
|||
|
|
dom.appendChild(canvasDom);
|
|||
|
|
this.type = 'svg';
|
|||
|
|
this.canvas = canvasDom;
|
|||
|
|
this.context = new Defs(canvasDom);
|
|||
|
|
this.toDraw = false;
|
|||
|
|
return this;
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
var _proto = Painter.prototype;
|
|||
|
|
|
|||
|
|
_proto.draw = function draw(model) {
|
|||
|
|
var self = this;
|
|||
|
|
|
|||
|
|
function drawInner() {
|
|||
|
|
self.animateHandler = Util.requestAnimationFrame(function () {
|
|||
|
|
self.animateHandler = undefined;
|
|||
|
|
|
|||
|
|
if (self.toDraw) {
|
|||
|
|
drawInner();
|
|||
|
|
}
|
|||
|
|
});
|
|||
|
|
|
|||
|
|
try {
|
|||
|
|
self._drawChildren(model);
|
|||
|
|
} catch (ev) {
|
|||
|
|
// 绘制时异常,中断重绘
|
|||
|
|
console.warn('error in draw canvas, detail as:');
|
|||
|
|
console.warn(ev);
|
|||
|
|
} finally {
|
|||
|
|
self.toDraw = false;
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
if (self.animateHandler) {
|
|||
|
|
self.toDraw = true;
|
|||
|
|
} else {
|
|||
|
|
drawInner();
|
|||
|
|
}
|
|||
|
|
};
|
|||
|
|
|
|||
|
|
_proto.drawSync = function drawSync(model) {
|
|||
|
|
this._drawChildren(model);
|
|||
|
|
};
|
|||
|
|
|
|||
|
|
_proto._drawGroup = function _drawGroup(model, index) {
|
|||
|
|
var cfg = model._cfg;
|
|||
|
|
|
|||
|
|
if (cfg.removed || cfg.destroyed) {
|
|||
|
|
return;
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
if (cfg.tobeRemoved) {
|
|||
|
|
Util.each(cfg.tobeRemoved, function (item) {
|
|||
|
|
if (item.parentNode) {
|
|||
|
|
item.parentNode.removeChild(item);
|
|||
|
|
}
|
|||
|
|
});
|
|||
|
|
cfg.tobeRemoved = [];
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
this._drawShape(model, index);
|
|||
|
|
|
|||
|
|
if (cfg.children && cfg.children.length > 0) {
|
|||
|
|
this._drawChildren(model);
|
|||
|
|
}
|
|||
|
|
};
|
|||
|
|
|
|||
|
|
_proto._drawChildren = function _drawChildren(parent) {
|
|||
|
|
var self = this;
|
|||
|
|
var children = parent._cfg.children;
|
|||
|
|
var shape; // 防止在画children的时候,父group已经被destroy
|
|||
|
|
|
|||
|
|
if (!children) {
|
|||
|
|
return;
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
for (var i = 0; i < children.length; i++) {
|
|||
|
|
shape = children[i];
|
|||
|
|
|
|||
|
|
if (shape.isGroup) {
|
|||
|
|
self._drawGroup(shape, i);
|
|||
|
|
} else {
|
|||
|
|
self._drawShape(shape, i);
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
};
|
|||
|
|
|
|||
|
|
_proto._drawShape = function _drawShape(model, index) {
|
|||
|
|
var self = this;
|
|||
|
|
var attrs = model._attrs;
|
|||
|
|
var cfg = model._cfg;
|
|||
|
|
var el = cfg.el; // 删除
|
|||
|
|
|
|||
|
|
if (cfg.removed || cfg.destroyed) {
|
|||
|
|
if (el) {
|
|||
|
|
el.parentNode.removeChild(cfg.el);
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
return;
|
|||
|
|
} // 新增节点
|
|||
|
|
|
|||
|
|
|
|||
|
|
if (!el && cfg.parent) {
|
|||
|
|
self._createDom(model, index);
|
|||
|
|
|
|||
|
|
self._updateShape(model);
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
el = cfg.el;
|
|||
|
|
|
|||
|
|
if (cfg.visible === false) {
|
|||
|
|
el.setAttribute('visibility', 'hidden');
|
|||
|
|
return;
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
if (cfg.visible && el.hasAttribute('visibility')) {
|
|||
|
|
el.removeAttribute('visibility');
|
|||
|
|
} // 更新
|
|||
|
|
|
|||
|
|
|
|||
|
|
if (cfg.hasUpdate) {
|
|||
|
|
self._updateShape(model);
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
if (attrs.clip && attrs.clip._cfg.hasUpdate) {
|
|||
|
|
self._updateShape(attrs.clip);
|
|||
|
|
}
|
|||
|
|
};
|
|||
|
|
|
|||
|
|
_proto._updateShape = function _updateShape(model) {
|
|||
|
|
var self = this;
|
|||
|
|
var attrs = model._attrs;
|
|||
|
|
var formerAttrs = model._cfg.attrs;
|
|||
|
|
|
|||
|
|
if (!formerAttrs) {
|
|||
|
|
return;
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
if (!model._cfg.el) {
|
|||
|
|
self._createDom(model);
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
if ('clip' in attrs) {
|
|||
|
|
this._setClip(model, attrs.clip);
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
if ('shadowOffsetX' in attrs || 'shadowOffsetY' in attrs || 'shadowBlur' in attrs || 'shadowColor' in attrs) {
|
|||
|
|
this._setShadow(model);
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
if (model.type === 'text') {
|
|||
|
|
self._updateText(model);
|
|||
|
|
|
|||
|
|
return;
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
if (model.type === 'fan') {
|
|||
|
|
self._updateFan(model);
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
if (model.type === 'marker') {
|
|||
|
|
model._cfg.el.setAttribute('d', self._assembleMarker(attrs));
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
if (model.type === 'rect') {
|
|||
|
|
model._cfg.el.setAttribute('d', self._assembleRect(attrs));
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
for (var key in attrs) {
|
|||
|
|
if (attrs[key] !== formerAttrs[key]) {
|
|||
|
|
self._setAttribute(model, key, attrs[key]);
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
model._cfg.attrs = Util.deepMix({}, model._attrs);
|
|||
|
|
model._cfg.hasUpdate = false;
|
|||
|
|
};
|
|||
|
|
|
|||
|
|
_proto._setAttribute = function _setAttribute(model, name, value) {
|
|||
|
|
var type = model.type;
|
|||
|
|
var attrs = model._attrs;
|
|||
|
|
var el = model._cfg.el;
|
|||
|
|
var defs = this.context; // 计算marker路径
|
|||
|
|
|
|||
|
|
if ((type === 'marker' || type === 'rect') && ~['x', 'y', 'radius', 'r'].indexOf(name)) {
|
|||
|
|
return;
|
|||
|
|
} // 圆和椭圆不是x, y, 是cx, cy。 marker的x,y 用于计算marker的路径,不需要写到dom
|
|||
|
|
|
|||
|
|
|
|||
|
|
if (~['circle', 'ellipse'].indexOf(type) && ~['x', 'y'].indexOf(name)) {
|
|||
|
|
el.setAttribute('c' + name, parseInt(value, 10));
|
|||
|
|
return;
|
|||
|
|
} // 多边形
|
|||
|
|
|
|||
|
|
|
|||
|
|
if (type === 'polygon' && name === 'points') {
|
|||
|
|
if (!value || value.length === 0) {
|
|||
|
|
value = '';
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
if (Util.isArray(value)) {
|
|||
|
|
value = value.map(function (point) {
|
|||
|
|
return point[0] + ',' + point[1];
|
|||
|
|
});
|
|||
|
|
value = value.join(' ');
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
el.setAttribute('points', value);
|
|||
|
|
return;
|
|||
|
|
} // 设置path
|
|||
|
|
|
|||
|
|
|
|||
|
|
if (name === 'path' && Util.isArray(value)) {
|
|||
|
|
el.setAttribute('d', this._formatPath(value));
|
|||
|
|
return;
|
|||
|
|
} // 设置图片
|
|||
|
|
|
|||
|
|
|
|||
|
|
if (name === 'img') {
|
|||
|
|
this._setImage(model, value);
|
|||
|
|
|
|||
|
|
return;
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
if (name === 'transform') {
|
|||
|
|
if (!value) {
|
|||
|
|
el.removeAttribute('transform');
|
|||
|
|
return;
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
this._setTransform(model);
|
|||
|
|
|
|||
|
|
return;
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
if (name === 'rotate') {
|
|||
|
|
if (!value) {
|
|||
|
|
el.removeAttribute('transform');
|
|||
|
|
return;
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
this._setTransform(model);
|
|||
|
|
|
|||
|
|
return;
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
if (name === 'matrix') {
|
|||
|
|
this._setTransform(model);
|
|||
|
|
|
|||
|
|
return;
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
if (name === 'fillStyle' || name === 'strokeStyle') {
|
|||
|
|
this._setColor(model, name, value);
|
|||
|
|
|
|||
|
|
return;
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
if (name === 'clip') {
|
|||
|
|
return;
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
if (~name.indexOf('Arrow')) {
|
|||
|
|
name = SVG_ATTR_MAP[name];
|
|||
|
|
|
|||
|
|
if (!value) {
|
|||
|
|
model._cfg[name] = null;
|
|||
|
|
el.removeAttribute(name);
|
|||
|
|
} else {
|
|||
|
|
var id = null;
|
|||
|
|
|
|||
|
|
if (typeof value === 'boolean') {
|
|||
|
|
id = defs.getDefaultArrow(attrs, name);
|
|||
|
|
} else {
|
|||
|
|
id = defs.addArrow(attrs, name);
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
el.setAttribute(name, "url(#" + id + ")");
|
|||
|
|
model._cfg[name] = id;
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
return;
|
|||
|
|
} // foreignObject
|
|||
|
|
|
|||
|
|
|
|||
|
|
if (name === 'html') {
|
|||
|
|
if (typeof value === 'string') {
|
|||
|
|
el.innerHTML = value;
|
|||
|
|
} else {
|
|||
|
|
el.innerHTML = '';
|
|||
|
|
el.appendChild(value);
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
if (SVG_ATTR_MAP[name]) {
|
|||
|
|
el.setAttribute(SVG_ATTR_MAP[name], value);
|
|||
|
|
}
|
|||
|
|
};
|
|||
|
|
|
|||
|
|
_proto._createDom = function _createDom(model, index) {
|
|||
|
|
var type = SHAPE_TO_TAGS[model.type];
|
|||
|
|
var attrs = model._attrs;
|
|||
|
|
var parent = model._cfg.parent;
|
|||
|
|
|
|||
|
|
if (!type) {
|
|||
|
|
throw new Error('the type' + model.type + 'is not supported by svg');
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
var shape = document.createElementNS('http://www.w3.org/2000/svg', type);
|
|||
|
|
|
|||
|
|
if (model._cfg.id) {
|
|||
|
|
shape.id = model._cfg.id;
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
model._cfg.el = shape;
|
|||
|
|
|
|||
|
|
if (parent) {
|
|||
|
|
var parentNode = parent._cfg.el;
|
|||
|
|
|
|||
|
|
if (typeof index === 'undefined') {
|
|||
|
|
parentNode.appendChild(shape);
|
|||
|
|
} else {
|
|||
|
|
var childNodes = parent._cfg.el.childNodes; // svg下天然有defs作为子节点,svg下子元素index需要+1
|
|||
|
|
|
|||
|
|
if (parentNode.tagName === 'svg') {
|
|||
|
|
index += 1;
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
if (childNodes.length <= index) {
|
|||
|
|
parentNode.appendChild(shape);
|
|||
|
|
} else {
|
|||
|
|
parentNode.insertBefore(shape, childNodes[index]);
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
model._cfg.attrs = {};
|
|||
|
|
|
|||
|
|
if (model.type === 'text') {
|
|||
|
|
shape.setAttribute('paint-order', 'stroke');
|
|||
|
|
shape.setAttribute('style', 'stroke-linecap:butt; stroke-linejoin:miter;');
|
|||
|
|
} else {
|
|||
|
|
if (!attrs.stroke && !attrs.strokeStyle) {
|
|||
|
|
shape.setAttribute('stroke', 'none');
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
if (!attrs.fill && !attrs.fillStyle) {
|
|||
|
|
shape.setAttribute('fill', 'none');
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
return shape;
|
|||
|
|
};
|
|||
|
|
|
|||
|
|
_proto._assembleMarker = function _assembleMarker(attrs) {
|
|||
|
|
var r = attrs.r;
|
|||
|
|
|
|||
|
|
if (typeof attrs.r === 'undefined') {
|
|||
|
|
r = attrs.radius;
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
if (isNaN(Number(attrs.x)) || isNaN(Number(attrs.y)) || isNaN(Number(r))) {
|
|||
|
|
return '';
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
var d = '';
|
|||
|
|
|
|||
|
|
if (typeof attrs.symbol === 'function') {
|
|||
|
|
d = attrs.symbol(attrs.x, attrs.y, r);
|
|||
|
|
} else {
|
|||
|
|
d = Marker.Symbols[attrs.symbol || 'circle'](attrs.x, attrs.y, r);
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
if (Util.isArray(d)) {
|
|||
|
|
d = d.map(function (path) {
|
|||
|
|
return path.join(' ');
|
|||
|
|
}).join('');
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
return d;
|
|||
|
|
};
|
|||
|
|
|
|||
|
|
_proto._assembleRect = function _assembleRect(attrs) {
|
|||
|
|
var x = attrs.x;
|
|||
|
|
var y = attrs.y;
|
|||
|
|
var w = attrs.width;
|
|||
|
|
var h = attrs.height;
|
|||
|
|
var radius = attrs.radius;
|
|||
|
|
|
|||
|
|
if (!radius) {
|
|||
|
|
return "M " + x + "," + y + " l " + w + ",0 l 0," + h + " l" + -w + " 0 z";
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
var r = parseRadius(radius);
|
|||
|
|
|
|||
|
|
if (Util.isArray(radius)) {
|
|||
|
|
if (radius.length === 1) {
|
|||
|
|
r.r1 = r.r2 = r.r3 = r.r4 = radius[0];
|
|||
|
|
} else if (radius.length === 2) {
|
|||
|
|
r.r1 = r.r3 = radius[0];
|
|||
|
|
r.r2 = r.r4 = radius[1];
|
|||
|
|
} else if (radius.length === 3) {
|
|||
|
|
r.r1 = radius[0];
|
|||
|
|
r.r2 = r.r4 = radius[1];
|
|||
|
|
r.r3 = radius[2];
|
|||
|
|
} else {
|
|||
|
|
r.r1 = radius[0];
|
|||
|
|
r.r2 = radius[1];
|
|||
|
|
r.r3 = radius[2];
|
|||
|
|
r.r4 = radius[3];
|
|||
|
|
}
|
|||
|
|
} else {
|
|||
|
|
r.r1 = r.r2 = r.r3 = r.r4 = radius;
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
var d = [["M " + (x + r.r1) + "," + y], ["l " + (w - r.r1 - r.r2) + ",0"], ["a " + r.r2 + "," + r.r2 + ",0,0,1," + r.r2 + "," + r.r2], ["l 0," + (h - r.r2 - r.r3)], ["a " + r.r3 + "," + r.r3 + ",0,0,1," + -r.r3 + "," + r.r3], ["l " + (r.r3 + r.r4 - w) + ",0"], ["a " + r.r4 + "," + r.r4 + ",0,0,1," + -r.r4 + "," + -r.r4], ["l 0," + (r.r4 + r.r1 - h)], ["a " + r.r1 + "," + r.r1 + ",0,0,1," + r.r1 + "," + -r.r1], ['z']];
|
|||
|
|
return d.join(' ');
|
|||
|
|
};
|
|||
|
|
|
|||
|
|
_proto._formatPath = function _formatPath(value) {
|
|||
|
|
value = value.map(function (path) {
|
|||
|
|
return path.join(' ');
|
|||
|
|
}).join('');
|
|||
|
|
|
|||
|
|
if (~value.indexOf('NaN')) {
|
|||
|
|
return '';
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
return value;
|
|||
|
|
};
|
|||
|
|
|
|||
|
|
_proto._setTransform = function _setTransform(model) {
|
|||
|
|
var matrix = model._attrs.matrix;
|
|||
|
|
var el = model._cfg.el;
|
|||
|
|
var transform = [];
|
|||
|
|
|
|||
|
|
for (var i = 0; i < 9; i += 3) {
|
|||
|
|
transform.push(matrix[i] + ',' + matrix[i + 1]);
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
transform = transform.join(',');
|
|||
|
|
|
|||
|
|
if (transform.indexOf('NaN') === -1) {
|
|||
|
|
el.setAttribute('transform', "matrix(" + transform + ")");
|
|||
|
|
} else {
|
|||
|
|
console.warn('invalid matrix:', matrix);
|
|||
|
|
}
|
|||
|
|
};
|
|||
|
|
|
|||
|
|
_proto._setImage = function _setImage(model, img) {
|
|||
|
|
var attrs = model._attrs;
|
|||
|
|
var el = model._cfg.el;
|
|||
|
|
|
|||
|
|
if (Util.isString(img)) {
|
|||
|
|
el.setAttribute('href', img);
|
|||
|
|
} else if (img instanceof Image) {
|
|||
|
|
if (!attrs.width) {
|
|||
|
|
el.setAttribute('width', img.width);
|
|||
|
|
model._attrs.width = img.width;
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
if (!attrs.height) {
|
|||
|
|
el.setAttribute('height', img.height);
|
|||
|
|
model._attrs.height = img.height;
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
el.setAttribute('href', img.src);
|
|||
|
|
} else if (img instanceof HTMLElement && Util.isString(img.nodeName) && img.nodeName.toUpperCase() === 'CANVAS') {
|
|||
|
|
el.setAttribute('href', img.toDataURL());
|
|||
|
|
} else if (img instanceof ImageData) {
|
|||
|
|
var canvas = document.createElement('canvas');
|
|||
|
|
canvas.setAttribute('width', img.width);
|
|||
|
|
canvas.setAttribute('height', img.height);
|
|||
|
|
canvas.getContext('2d').putImageData(img, 0, 0);
|
|||
|
|
|
|||
|
|
if (!attrs.width) {
|
|||
|
|
el.setAttribute('width', img.width);
|
|||
|
|
model._attrs.width = img.width;
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
if (!attrs.height) {
|
|||
|
|
el.setAttribute('height', img.height);
|
|||
|
|
model._attrs.height = img.height;
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
el.setAttribute('href', canvas.toDataURL());
|
|||
|
|
}
|
|||
|
|
};
|
|||
|
|
|
|||
|
|
_proto._updateFan = function _updateFan(model) {
|
|||
|
|
function getPoint(angle, radius, center) {
|
|||
|
|
return {
|
|||
|
|
x: radius * Math.cos(angle) + center.x,
|
|||
|
|
y: radius * Math.sin(angle) + center.y
|
|||
|
|
};
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
var attrs = model._attrs;
|
|||
|
|
var cfg = model._cfg;
|
|||
|
|
var center = {
|
|||
|
|
x: attrs.x,
|
|||
|
|
y: attrs.y
|
|||
|
|
};
|
|||
|
|
var d = [];
|
|||
|
|
var startAngle = attrs.startAngle;
|
|||
|
|
var endAngle = attrs.endAngle;
|
|||
|
|
|
|||
|
|
if (Util.isNumberEqual(endAngle - startAngle, Math.PI * 2)) {
|
|||
|
|
endAngle -= 0.00001;
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
var outerStart = getPoint(startAngle, attrs.re, center);
|
|||
|
|
var outerEnd = getPoint(endAngle, attrs.re, center);
|
|||
|
|
var fa = endAngle > startAngle ? 1 : 0;
|
|||
|
|
var fs = Math.abs(endAngle - startAngle) > Math.PI ? 1 : 0;
|
|||
|
|
var rs = attrs.rs;
|
|||
|
|
var re = attrs.re;
|
|||
|
|
var innerStart = getPoint(startAngle, attrs.rs, center);
|
|||
|
|
var innerEnd = getPoint(endAngle, attrs.rs, center);
|
|||
|
|
|
|||
|
|
if (attrs.rs > 0) {
|
|||
|
|
d.push("M " + outerEnd.x + "," + outerEnd.y);
|
|||
|
|
d.push("L " + innerEnd.x + "," + innerEnd.y);
|
|||
|
|
d.push("A " + rs + "," + rs + ",0," + fs + "," + (fa === 1 ? 0 : 1) + "," + innerStart.x + "," + innerStart.y);
|
|||
|
|
d.push("L " + outerStart.x + " " + outerStart.y);
|
|||
|
|
} else {
|
|||
|
|
d.push("M " + center.x + "," + center.y);
|
|||
|
|
d.push("L " + outerStart.x + "," + outerStart.y);
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
d.push("A " + re + "," + re + ",0," + fs + "," + fa + "," + outerEnd.x + "," + outerEnd.y);
|
|||
|
|
|
|||
|
|
if (attrs.rs > 0) {
|
|||
|
|
d.push("L " + innerEnd.x + "," + innerEnd.y);
|
|||
|
|
} else {
|
|||
|
|
d.push('Z');
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
cfg.el.setAttribute('d', d.join(' '));
|
|||
|
|
};
|
|||
|
|
|
|||
|
|
_proto._updateText = function _updateText(model) {
|
|||
|
|
var self = this;
|
|||
|
|
var attrs = model._attrs;
|
|||
|
|
var formerAttrs = model._cfg.attrs;
|
|||
|
|
var el = model._cfg.el;
|
|||
|
|
|
|||
|
|
this._setFont(model);
|
|||
|
|
|
|||
|
|
for (var attr in attrs) {
|
|||
|
|
if (attrs[attr] !== formerAttrs[attr]) {
|
|||
|
|
if (attr === 'text') {
|
|||
|
|
self._setText(model, "" + attrs[attr]);
|
|||
|
|
|
|||
|
|
continue;
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
if (attr === 'fillStyle' || attr === 'strokeStyle') {
|
|||
|
|
this._setColor(model, attr, attrs[attr]);
|
|||
|
|
|
|||
|
|
continue;
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
if (attr === 'matrix') {
|
|||
|
|
this._setTransform(model);
|
|||
|
|
|
|||
|
|
continue;
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
if (SVG_ATTR_MAP[attr]) {
|
|||
|
|
el.setAttribute(SVG_ATTR_MAP[attr], attrs[attr]);
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
model._cfg.attrs = Object.assign({}, model._attrs);
|
|||
|
|
model._cfg.hasUpdate = false;
|
|||
|
|
};
|
|||
|
|
|
|||
|
|
_proto._setFont = function _setFont(model) {
|
|||
|
|
var el = model.get('el');
|
|||
|
|
var attrs = model._attrs;
|
|||
|
|
var fontSize = attrs.fontSize;
|
|||
|
|
el.setAttribute('alignment-baseline', BASELINE_MAP[attrs.textBaseline] || 'baseline');
|
|||
|
|
el.setAttribute('text-anchor', ANCHOR_MAP[attrs.textAlign] || 'left');
|
|||
|
|
|
|||
|
|
if (fontSize && +fontSize < 12) {
|
|||
|
|
// 小于 12 像素的文本进行 scale 处理
|
|||
|
|
attrs.matrix = [1, 0, 0, 0, 1, 0, 0, 0, 1];
|
|||
|
|
model.transform([['t', -attrs.x, -attrs.y], ['s', +fontSize / 12, +fontSize / 12], ['t', attrs.x, attrs.y]]);
|
|||
|
|
}
|
|||
|
|
};
|
|||
|
|
|
|||
|
|
_proto._setText = function _setText(model, text) {
|
|||
|
|
var el = model._cfg.el;
|
|||
|
|
var baseline = model._attrs.textBaseline || 'bottom';
|
|||
|
|
|
|||
|
|
if (!text) {
|
|||
|
|
el.innerHTML = '';
|
|||
|
|
} else if (~text.indexOf('\n')) {
|
|||
|
|
var x = model._attrs.x;
|
|||
|
|
var textArr = text.split('\n');
|
|||
|
|
var textLen = textArr.length - 1;
|
|||
|
|
var arr = '';
|
|||
|
|
Util.each(textArr, function (segment, i) {
|
|||
|
|
if (i === 0) {
|
|||
|
|
if (baseline === 'alphabetic') {
|
|||
|
|
arr += "<tspan x=\"" + x + "\" dy=\"" + -textLen + "em\">" + segment + "</tspan>";
|
|||
|
|
} else if (baseline === 'top') {
|
|||
|
|
arr += "<tspan x=\"" + x + "\" dy=\"0.9em\">" + segment + "</tspan>";
|
|||
|
|
} else if (baseline === 'middle') {
|
|||
|
|
arr += "<tspan x=\"" + x + "\" dy=\"" + -(textLen - 1) / 2 + "em\">" + segment + "</tspan>";
|
|||
|
|
} else if (baseline === 'bottom') {
|
|||
|
|
arr += "<tspan x=\"" + x + "\" dy=\"-" + (textLen + LETTER_SPACING) + "em\">" + segment + "</tspan>";
|
|||
|
|
} else if (baseline === 'hanging') {
|
|||
|
|
arr += "<tspan x=\"" + x + "\" dy=\"" + (-(textLen - 1) - LETTER_SPACING) + "em\">" + segment + "</tspan>";
|
|||
|
|
}
|
|||
|
|
} else {
|
|||
|
|
arr += "<tspan x=\"" + x + "\" dy=\"1em\">" + segment + "</tspan>";
|
|||
|
|
}
|
|||
|
|
});
|
|||
|
|
el.innerHTML = arr;
|
|||
|
|
} else {
|
|||
|
|
el.innerHTML = text;
|
|||
|
|
}
|
|||
|
|
};
|
|||
|
|
|
|||
|
|
_proto._setClip = function _setClip(model, value) {
|
|||
|
|
var el = model._cfg.el;
|
|||
|
|
|
|||
|
|
if (!value) {
|
|||
|
|
el.removeAttribute('clip-path');
|
|||
|
|
return;
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
if (!el.hasAttribute('clip-path')) {
|
|||
|
|
this._createDom(value);
|
|||
|
|
|
|||
|
|
this._updateShape(value);
|
|||
|
|
|
|||
|
|
var id = this.context.addClip(value);
|
|||
|
|
el.setAttribute('clip-path', "url(#" + id + ")");
|
|||
|
|
} else if (value._cfg.hasUpdate) {
|
|||
|
|
this._updateShape(value);
|
|||
|
|
}
|
|||
|
|
};
|
|||
|
|
|
|||
|
|
_proto._setColor = function _setColor(model, name, value) {
|
|||
|
|
var el = model._cfg.el;
|
|||
|
|
var defs = this.context;
|
|||
|
|
|
|||
|
|
if (!value) {
|
|||
|
|
el.setAttribute(SVG_ATTR_MAP[name], 'none');
|
|||
|
|
return;
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
value = value.trim();
|
|||
|
|
|
|||
|
|
if (/^[r,R,L,l]{1}[\s]*\(/.test(value)) {
|
|||
|
|
var id = defs.find('gradient', value);
|
|||
|
|
|
|||
|
|
if (!id) {
|
|||
|
|
id = defs.addGradient(value);
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
el.setAttribute(SVG_ATTR_MAP[name], "url(#" + id + ")");
|
|||
|
|
} else if (/^[p,P]{1}[\s]*\(/.test(value)) {
|
|||
|
|
var _id = defs.find('pattern', value);
|
|||
|
|
|
|||
|
|
if (!_id) {
|
|||
|
|
_id = defs.addPattern(value);
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
el.setAttribute(SVG_ATTR_MAP[name], "url(#" + _id + ")");
|
|||
|
|
} else {
|
|||
|
|
el.setAttribute(SVG_ATTR_MAP[name], value);
|
|||
|
|
}
|
|||
|
|
};
|
|||
|
|
|
|||
|
|
_proto._setShadow = function _setShadow(model) {
|
|||
|
|
var el = model._cfg.el;
|
|||
|
|
var attrs = model._attrs;
|
|||
|
|
var cfg = {
|
|||
|
|
dx: attrs.shadowOffsetX,
|
|||
|
|
dy: attrs.shadowOffsetY,
|
|||
|
|
blur: attrs.shadowBlur,
|
|||
|
|
color: attrs.shadowColor
|
|||
|
|
};
|
|||
|
|
|
|||
|
|
if (!cfg.dx && !cfg.dy && !cfg.blur && !cfg.color) {
|
|||
|
|
el.removeAttribute('filter');
|
|||
|
|
} else {
|
|||
|
|
var id = this.context.find('filter', cfg);
|
|||
|
|
|
|||
|
|
if (!id) {
|
|||
|
|
id = this.context.addShadow(cfg, this);
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
el.setAttribute('filter', "url(#" + id + ")");
|
|||
|
|
}
|
|||
|
|
};
|
|||
|
|
|
|||
|
|
return Painter;
|
|||
|
|
}();
|
|||
|
|
|
|||
|
|
module.exports = Painter;
|