// Symbol factory
define(function(require) {
'use strict';
var graphic = require('./graphic');
var BoundingRect = require('zrender/core/BoundingRect');
/**
* Triangle shape
* @inner
*/
var Triangle = graphic.extendShape({
type: 'triangle',
shape: {
cx: 0,
cy: 0,
width: 0,
height: 0
},
buildPath: function (path, shape) {
var cx = shape.cx;
var cy = shape.cy;
var width = shape.width / 2;
var height = shape.height / 2;
path.moveTo(cx, cy - height);
path.lineTo(cx + width, cy + height);
path.lineTo(cx - width, cy + height);
path.closePath();
}
});
/**
* Diamond shape
* @inner
*/
var Diamond = graphic.extendShape({
type: 'diamond',
shape: {
cx: 0,
cy: 0,
width: 0,
height: 0
},
buildPath: function (path, shape) {
var cx = shape.cx;
var cy = shape.cy;
var width = shape.width / 2;
var height = shape.height / 2;
path.moveTo(cx, cy - height);
path.lineTo(cx + width, cy);
path.lineTo(cx, cy + height);
path.lineTo(cx - width, cy);
path.closePath();
}
});
/**
* Pin shape
* @inner
*/
var Pin = graphic.extendShape({
type: 'pin',
shape: {
// x, y on the cusp
x: 0,
y: 0,
width: 0,
height: 0
},
buildPath: function (path, shape) {
var x = shape.x;
var y = shape.y;
var w = shape.width / 5 * 3;
// Height must be larger than width
var h = Math.max(w, shape.height);
var r = w / 2;
// Dist on y with tangent point and circle center
var dy = r * r / (h - r);
var cy = y - h + r + dy;
var angle = Math.asin(dy / r);
// Dist on x with tangent point and circle center
var dx = Math.cos(angle) * r;
var tanX = Math.sin(angle);
var tanY = Math.cos(angle);
path.arc(
x, cy, r,
Math.PI - angle,
Math.PI * 2 + angle
);
var cpLen = r * 0.6;
var cpLen2 = r * 0.7;
path.bezierCurveTo(
x + dx - tanX * cpLen, cy + dy + tanY * cpLen,
x, y - cpLen2,
x, y
);
path.bezierCurveTo(
x, y - cpLen2,
x - dx + tanX * cpLen, cy + dy + tanY * cpLen,
x - dx, cy + dy
);
path.closePath();
}
});
/**
* Arrow shape
* @inner
*/
var Arrow = graphic.extendShape({
type: 'arrow',
shape: {
x: 0,
y: 0,
width: 0,
height: 0
},
buildPath: function (ctx, shape) {
var height = shape.height;
var width = shape.width;
var x = shape.x;
var y = shape.y;
var dx = width / 3 * 2;
ctx.moveTo(x, y);
ctx.lineTo(x + dx, y + height);
ctx.lineTo(x, y + height / 4 * 3);
ctx.lineTo(x - dx, y + height);
ctx.lineTo(x, y);
ctx.closePath();
}
});
/**
* Map of path contructors
* @type {Object.<string, module:zrender/graphic/Path>}
*/
var symbolCtors = {
line: graphic.Line,
rect: graphic.Rect,
roundRect: graphic.Rect,
square: graphic.Rect,
circle: graphic.Circle,
diamond: Diamond,
pin: Pin,
arrow: Arrow,
triangle: Triangle
};
var symbolShapeMakers = {
line: function (x, y, w, h, shape) {
// FIXME
shape.x1 = x;
shape.y1 = y + h / 2;
shape.x2 = x + w;
shape.y2 = y + h / 2;
},
rect: function (x, y, w, h, shape) {
shape.x = x;
shape.y = y;
shape.width = w;
shape.height = h;
},
roundRect: function (x, y, w, h, shape) {
shape.x = x;
shape.y = y;
shape.width = w;
shape.height = h;
shape.r = Math.min(w, h) / 4;
},
square: function (x, y, w, h, shape) {
var size = Math.min(w, h);
shape.x = x;
shape.y = y;
shape.width = size;
shape.height = size;
},
circle: function (x, y, w, h, shape) {
// Put circle in the center of square
shape.cx = x + w / 2;
shape.cy = y + h / 2;
shape.r = Math.min(w, h) / 2;
},
diamond: function (x, y, w, h, shape) {
shape.cx = x + w / 2;
shape.cy = y + h / 2;
shape.width = w;
shape.height = h;
},
pin: function (x, y, w, h, shape) {
shape.x = x + w / 2;
shape.y = y + h / 2;
shape.width = w;
shape.height = h;
},
arrow: function (x, y, w, h, shape) {
shape.x = x + w / 2;
shape.y = y + h / 2;
shape.width = w;
shape.height = h;
},
triangle: function (x, y, w, h, shape) {
shape.cx = x + w / 2;
shape.cy = y + h / 2;
shape.width = w;
shape.height = h;
}
};
var symbolBuildProxies = {};
for (var name in symbolCtors) {
symbolBuildProxies[name] = new symbolCtors[name]();
}
var Symbol = graphic.extendShape({
type: 'symbol',
shape: {
symbolType: '',
x: 0,
y: 0,
width: 0,
height: 0
},
beforeBrush: function () {
var style = this.style;
var shape = this.shape;
// FIXME
if (shape.symbolType === 'pin' && style.textPosition === 'inside') {
style.textPosition = ['50%', '40%'];
style.textAlign = 'center';
style.textVerticalAlign = 'middle';
}
},
buildPath: function (ctx, shape) {
var symbolType = shape.symbolType;
var proxySymbol = symbolBuildProxies[symbolType];
if (shape.symbolType !== 'none') {
if (!proxySymbol) {
// Default rect
symbolType = 'rect';
proxySymbol = symbolBuildProxies[symbolType];
}
symbolShapeMakers[symbolType](
shape.x, shape.y, shape.width, shape.height, proxySymbol.shape
);
proxySymbol.buildPath(ctx, proxySymbol.shape);
}
}
});
// Provide setColor helper method to avoid determine if set the fill or stroke outside
var symbolPathSetColor = function (color) {
if (this.type !== 'image') {
var symbolStyle = this.style;
var symbolShape = this.shape;
if (symbolShape && symbolShape.symbolType === 'line') {
symbolStyle.stroke = color;
}
else if (this.__isEmptyBrush) {
symbolStyle.stroke = color;
symbolStyle.fill = '#fff';
}
else {
// FIXME 判断图形默认是填充还是描边,使用 onlyStroke ?
symbolStyle.fill && (symbolStyle.fill = color);
symbolStyle.stroke && (symbolStyle.stroke = color);
}
this.dirty();
}
};
var symbolUtil = {
/**
* Create a symbol element with given symbol configuration: shape, x, y, width, height, color
* @param {string} symbolType
* @param {number} x
* @param {number} y
* @param {number} w
* @param {number} h
* @param {string} color
*/
createSymbol: function (symbolType, x, y, w, h, color) {
var isEmpty = symbolType.indexOf('empty') === 0;
if (isEmpty) {
symbolType = symbolType.substr(5, 1).toLowerCase() + symbolType.substr(6);
}
var symbolPath;
if (symbolType.indexOf('image://') === 0) {
symbolPath = new graphic.Image({
style: {
image: symbolType.slice(8),
x: x,
y: y,
width: w,
height: h
}
});
}
else if (symbolType.indexOf('path://') === 0) {
symbolPath = graphic.makePath(symbolType.slice(7), {}, new BoundingRect(x, y, w, h));
}
else {
symbolPath = new Symbol({
shape: {
symbolType: symbolType,
x: x,
y: y,
width: w,
height: h
}
});
}
symbolPath.__isEmptyBrush = isEmpty;
symbolPath.setColor = symbolPathSetColor;
symbolPath.setColor(color);
return symbolPath;
}
};
return symbolUtil;
}); |