719 lines
18 KiB
Java
719 lines
18 KiB
Java
/**
|
||
* @fileOverview interval shapes
|
||
* @author dxq613@gmail.com
|
||
* @author sima.zhang1990@gmail.com
|
||
* @author huangtonger@aliyun.com
|
||
*/
|
||
var Util = require('../../util');
|
||
|
||
var Shape = require('./shape');
|
||
|
||
var PathUtil = require('../util/path');
|
||
|
||
var ShapeUtil = require('../util/shape');
|
||
|
||
var Global = require('../../global');
|
||
|
||
var G = require('../../renderer');
|
||
|
||
var GPathUtil = Util.PathUtil; // 获取柱状图的几个点
|
||
|
||
function getRectPoints(cfg, isPyramid) {
|
||
var x = cfg.x;
|
||
var y = cfg.y;
|
||
var y0 = cfg.y0; // 0 点的位置
|
||
|
||
var width = cfg.size; // 有3种情况,
|
||
// 1. y,x都不是数组
|
||
// 2. y是数组,x不是
|
||
// 3. x是数组,y不是
|
||
|
||
var ymin = y0;
|
||
var ymax = y;
|
||
|
||
if (Util.isArray(y)) {
|
||
ymax = y[1];
|
||
ymin = y[0];
|
||
}
|
||
|
||
var xmin;
|
||
var xmax;
|
||
|
||
if (Util.isArray(x)) {
|
||
xmin = x[0];
|
||
xmax = x[1];
|
||
} else {
|
||
xmin = x - width / 2;
|
||
xmax = x + width / 2;
|
||
}
|
||
|
||
var points = [];
|
||
points.push({
|
||
x: xmin,
|
||
y: ymin
|
||
}, {
|
||
x: xmin,
|
||
y: ymax
|
||
});
|
||
|
||
if (isPyramid) {
|
||
points.push({
|
||
x: xmax,
|
||
y: (ymax + ymin) / 2
|
||
});
|
||
} else {
|
||
points.push({
|
||
x: xmax,
|
||
y: ymax
|
||
}, {
|
||
x: xmax,
|
||
y: ymin
|
||
});
|
||
}
|
||
|
||
return points;
|
||
}
|
||
|
||
function getRectPath(points) {
|
||
var path = [];
|
||
|
||
for (var i = 0; i < points.length; i++) {
|
||
var point = points[i];
|
||
|
||
if (point) {
|
||
var action = i === 0 ? 'M' : 'L';
|
||
path.push([action, point.x, point.y]);
|
||
}
|
||
}
|
||
|
||
var first = points[0];
|
||
path.push(['L', first.x, first.y]);
|
||
path.push(['z']);
|
||
return path;
|
||
}
|
||
|
||
function getLinePoints(cfg) {
|
||
var x = cfg.x;
|
||
var y = cfg.y;
|
||
var y0 = cfg.y0; // 0 点的位置
|
||
|
||
var points = [];
|
||
|
||
if (Util.isArray(y)) {
|
||
Util.each(y, function (yItem, idx) {
|
||
points.push({
|
||
x: Util.isArray(x) ? x[idx] : x,
|
||
y: yItem
|
||
});
|
||
});
|
||
} else {
|
||
points.push({
|
||
x: x,
|
||
y: y
|
||
}, {
|
||
x: x,
|
||
y: y0
|
||
});
|
||
}
|
||
|
||
return points;
|
||
}
|
||
|
||
function getTickPoints(cfg) {
|
||
var x = cfg.x;
|
||
var y = Util.isArray(cfg.y) ? cfg.y[1] : cfg.y;
|
||
var y0 = Util.isArray(cfg.y) ? cfg.y[0] : cfg.y0;
|
||
var barWidth = cfg.size;
|
||
var points = [];
|
||
points.push({
|
||
x: x - barWidth / 2,
|
||
y: y
|
||
}, {
|
||
x: x + barWidth / 2,
|
||
y: y
|
||
}, {
|
||
x: x,
|
||
y: y
|
||
}, {
|
||
x: x,
|
||
y: y0
|
||
}, {
|
||
x: x - barWidth / 2,
|
||
y: y0
|
||
}, {
|
||
x: x + barWidth / 2,
|
||
y: y0
|
||
});
|
||
return points;
|
||
}
|
||
|
||
function getTickPath(points) {
|
||
var path = [];
|
||
path.push(['M', points[0].x, points[0].y], ['L', points[1].x, points[1].y], ['M', points[2].x, points[2].y], ['L', points[3].x, points[3].y], ['M', points[4].x, points[4].y], ['L', points[5].x, points[5].y]);
|
||
return path;
|
||
}
|
||
|
||
function getFillAttrs(cfg) {
|
||
var defaultAttrs = Global.shape.interval;
|
||
var attrs = Util.mix({}, defaultAttrs, cfg.style);
|
||
ShapeUtil.addFillAttrs(attrs, cfg);
|
||
|
||
if (cfg.color) {
|
||
attrs.stroke = attrs.stroke || cfg.color;
|
||
}
|
||
|
||
return attrs;
|
||
}
|
||
|
||
function getLineAttrs(cfg) {
|
||
var defaultAttrs = Global.shape.hollowInterval;
|
||
var attrs = Util.mix({}, defaultAttrs, cfg.style);
|
||
ShapeUtil.addStrokeAttrs(attrs, cfg);
|
||
return attrs;
|
||
}
|
||
|
||
function getFunnelPath(cfg, isFunnel) {
|
||
var path = [];
|
||
var points = cfg.points;
|
||
var nextPoints = cfg.nextPoints;
|
||
|
||
if (!Util.isNil(nextPoints)) {
|
||
path.push(['M', points[0].x, points[0].y], ['L', points[1].x, points[1].y], ['L', nextPoints[1].x, nextPoints[1].y], ['L', nextPoints[0].x, nextPoints[0].y], ['Z']);
|
||
} else if (isFunnel) {
|
||
path.push(['M', points[0].x, points[0].y], ['L', points[1].x, points[1].y], ['L', points[2].x, points[2].y], ['L', points[3].x, points[3].y], ['Z']);
|
||
} else {
|
||
path.push(['M', points[0].x, points[0].y], ['L', points[1].x, points[1].y], ['L', points[2].x, points[2].y], ['L', points[2].x, points[2].y], ['Z']);
|
||
}
|
||
|
||
return path;
|
||
}
|
||
|
||
function getThetaCfg(point, coord) {
|
||
var r = coord.getRadius();
|
||
var inner = coord.innerRadius;
|
||
var startAngle;
|
||
var endAngle;
|
||
var ir = r * inner;
|
||
var startPoint;
|
||
var endPoint;
|
||
|
||
if (!Util.isArray(point.x) && Util.isArray(point.y)) {
|
||
point.x = [point.x, point.x]; // 如果x是一个值,y是数组,将x转成数组
|
||
}
|
||
|
||
if (Util.isArray(point.x)) {
|
||
startPoint = {
|
||
x: point.x[0],
|
||
y: point.y[0]
|
||
};
|
||
endPoint = {
|
||
x: point.x[1],
|
||
y: point.y[1]
|
||
};
|
||
startAngle = PathUtil.getPointAngle(coord, startPoint);
|
||
endAngle = PathUtil.getPointAngle(coord, endPoint);
|
||
|
||
if (endAngle <= startAngle) {
|
||
// 考虑占比百分百的情形
|
||
endAngle = endAngle + Math.PI * 2;
|
||
}
|
||
} else {
|
||
endPoint = point;
|
||
startAngle = coord.startAngle;
|
||
endAngle = PathUtil.getPointAngle(coord, endPoint);
|
||
}
|
||
|
||
return {
|
||
r: r,
|
||
ir: ir,
|
||
startAngle: startAngle,
|
||
endAngle: endAngle
|
||
};
|
||
} // 获取选中时的样式,当前仅支持饼图
|
||
|
||
|
||
function _getSelectedCfg(type, cfg) {
|
||
var geom = cfg.geom;
|
||
var coord = geom.get('coord');
|
||
var point = cfg.point;
|
||
var r = 7.5;
|
||
var selectedCfg;
|
||
|
||
if (coord && coord.type === 'theta') {
|
||
var thetaCfg = getThetaCfg(point, coord);
|
||
var middleAngle = (thetaCfg.endAngle - thetaCfg.startAngle) / 2 + thetaCfg.startAngle;
|
||
var x = r * Math.cos(middleAngle);
|
||
var y = r * Math.sin(middleAngle);
|
||
selectedCfg = {
|
||
transform: [['t', x, y]]
|
||
};
|
||
}
|
||
|
||
return Util.mix({}, selectedCfg);
|
||
}
|
||
|
||
var Interval = Shape.registerFactory('interval', {
|
||
defaultShapeType: 'rect',
|
||
getActiveCfg: function getActiveCfg(type, cfg) {
|
||
if (!type || Util.inArray(['rect', 'funnel', 'pyramid'], type)) {
|
||
// 透明度降低 0.15
|
||
var fillOpacity = cfg.fillOpacity || cfg.opacity || 1;
|
||
return {
|
||
fillOpacity: fillOpacity - 0.15
|
||
};
|
||
}
|
||
|
||
var lineWidth = cfg.lineWidth || 0;
|
||
return {
|
||
lineWidth: lineWidth + 1
|
||
};
|
||
},
|
||
getDefaultPoints: function getDefaultPoints(pointInfo) {
|
||
return getRectPoints(pointInfo);
|
||
},
|
||
getSelectedCfg: function getSelectedCfg(type, cfg) {
|
||
return _getSelectedCfg(type, cfg);
|
||
}
|
||
}); // 默认柱状图
|
||
|
||
Shape.registerShape('interval', 'rect', {
|
||
draw: function draw(cfg, container) {
|
||
var attrs = getFillAttrs(cfg);
|
||
var path = getRectPath(cfg.points);
|
||
path = this.parsePath(path);
|
||
return container.addShape('path', {
|
||
attrs: Util.mix(attrs, {
|
||
path: path
|
||
})
|
||
});
|
||
},
|
||
getMarkerCfg: function getMarkerCfg(cfg) {
|
||
var rectCfg = getFillAttrs(cfg);
|
||
var isInCircle = cfg.isInCircle;
|
||
return Util.mix({
|
||
symbol: isInCircle ? 'circle' : 'square',
|
||
radius: isInCircle ? 4.5 : 4
|
||
}, rectCfg);
|
||
}
|
||
}); // 空心柱状图
|
||
|
||
Shape.registerShape('interval', 'hollowRect', {
|
||
draw: function draw(cfg, container) {
|
||
var attrs = getLineAttrs(cfg);
|
||
var path = getRectPath(cfg.points);
|
||
path = this.parsePath(path);
|
||
return container.addShape('path', {
|
||
attrs: Util.mix(attrs, {
|
||
path: path
|
||
})
|
||
});
|
||
},
|
||
getMarkerCfg: function getMarkerCfg(cfg) {
|
||
var rectCfg = getLineAttrs(cfg);
|
||
var isInCircle = cfg.isInCircle;
|
||
return Util.mix({
|
||
symbol: isInCircle ? 'circle' : 'square',
|
||
radius: isInCircle ? 4.5 : 4
|
||
}, rectCfg);
|
||
}
|
||
}); // 线形柱状图
|
||
|
||
Shape.registerShape('interval', 'line', {
|
||
getPoints: function getPoints(pointInfo) {
|
||
return getLinePoints(pointInfo);
|
||
},
|
||
draw: function draw(cfg, container) {
|
||
var attrs = getLineAttrs(cfg);
|
||
attrs.lineWidth = cfg.size || 1; // size 就是线的宽度
|
||
|
||
var path = getRectPath(cfg.points);
|
||
path = this.parsePath(path);
|
||
return container.addShape('path', {
|
||
attrs: Util.mix(attrs, {
|
||
path: path
|
||
})
|
||
});
|
||
},
|
||
getMarkerCfg: function getMarkerCfg(cfg) {
|
||
var lineCfg = getLineAttrs(cfg);
|
||
return Util.mix({
|
||
symbol: 'line',
|
||
radius: 5
|
||
}, lineCfg);
|
||
}
|
||
}); // 钉子形的柱状图
|
||
|
||
Shape.registerShape('interval', 'tick', {
|
||
getPoints: function getPoints(pointInfo) {
|
||
return getTickPoints(pointInfo);
|
||
},
|
||
draw: function draw(cfg, container) {
|
||
var attrs = getLineAttrs(cfg); // @2018-12-25 by blue.lb 经过测试发现size代表的是宽度,而style中的lineWidth才是设置线宽,放在interval暂时先特殊处理
|
||
|
||
if (!attrs.lineWidth) {
|
||
attrs.lineWidth = 2;
|
||
}
|
||
|
||
var path = getTickPath(cfg.points);
|
||
path = this.parsePath(path);
|
||
return container.addShape('path', {
|
||
attrs: Util.mix(attrs, {
|
||
path: path
|
||
})
|
||
});
|
||
},
|
||
getMarkerCfg: function getMarkerCfg(cfg) {
|
||
var lineCfg = getLineAttrs(cfg);
|
||
return Util.mix({
|
||
symbol: 'tick',
|
||
radius: 5
|
||
}, lineCfg);
|
||
}
|
||
}); // 漏斗图
|
||
|
||
Shape.registerShape('interval', 'funnel', {
|
||
getPoints: function getPoints(pointInfo) {
|
||
pointInfo.size = pointInfo.size * 2; // 漏斗图的 size 是柱状图的两倍
|
||
|
||
return getRectPoints(pointInfo);
|
||
},
|
||
draw: function draw(cfg, container) {
|
||
var attrs = getFillAttrs(cfg);
|
||
var path = getFunnelPath(cfg, true);
|
||
path = this.parsePath(path);
|
||
return container.addShape('path', {
|
||
attrs: Util.mix(attrs, {
|
||
path: path
|
||
})
|
||
});
|
||
},
|
||
getMarkerCfg: function getMarkerCfg(cfg) {
|
||
var funnelCfg = getFillAttrs(cfg);
|
||
return Util.mix({
|
||
symbol: 'square',
|
||
radius: 4
|
||
}, funnelCfg);
|
||
}
|
||
}); // 金字塔图
|
||
|
||
Shape.registerShape('interval', 'pyramid', {
|
||
getPoints: function getPoints(pointInfo) {
|
||
pointInfo.size = pointInfo.size * 2; // 漏斗图的 size 是柱状图的两倍
|
||
|
||
return getRectPoints(pointInfo, true);
|
||
},
|
||
draw: function draw(cfg, container) {
|
||
var attrs = getFillAttrs(cfg);
|
||
var path = getFunnelPath(cfg, false);
|
||
path = this.parsePath(path);
|
||
return container.addShape('path', {
|
||
attrs: Util.mix(attrs, {
|
||
path: path
|
||
})
|
||
});
|
||
},
|
||
getMarkerCfg: function getMarkerCfg(cfg) {
|
||
var funnelCfg = getFillAttrs(cfg);
|
||
return Util.mix({
|
||
symbol: 'square',
|
||
radius: 4
|
||
}, funnelCfg);
|
||
}
|
||
}); // 水波图
|
||
|
||
/**
|
||
* 用贝塞尔曲线模拟正弦波
|
||
* Using Bezier curves to fit sine wave.
|
||
* There is 4 control points for each curve of wave,
|
||
* which is at 1/4 wave length of the sine wave.
|
||
*
|
||
* The control points for a wave from (a) to (d) are a-b-c-d:
|
||
* c *----* d
|
||
* b *
|
||
* |
|
||
* ... a * ..................
|
||
*
|
||
* whose positions are a: (0, 0), b: (0.5, 0.5), c: (1, 1), d: (PI / 2, 1)
|
||
*
|
||
* @param {number} x x position of the left-most point (a)
|
||
* @param {number} stage 0-3, stating which part of the wave it is
|
||
* @param {number} waveLength wave length of the sine wave
|
||
* @param {number} amplitude wave amplitude
|
||
* @return {Array} 正弦片段曲线
|
||
*/
|
||
|
||
function getWaterWavePositions(x, stage, waveLength, amplitude) {
|
||
if (stage === 0) {
|
||
return [[x + 1 / 2 * waveLength / Math.PI / 2, amplitude / 2], [x + 1 / 2 * waveLength / Math.PI, amplitude], [x + waveLength / 4, amplitude]];
|
||
} else if (stage === 1) {
|
||
return [[x + 1 / 2 * waveLength / Math.PI / 2 * (Math.PI - 2), amplitude], [x + 1 / 2 * waveLength / Math.PI / 2 * (Math.PI - 1), amplitude / 2], [x + waveLength / 4, 0]];
|
||
} else if (stage === 2) {
|
||
return [[x + 1 / 2 * waveLength / Math.PI / 2, -amplitude / 2], [x + 1 / 2 * waveLength / Math.PI, -amplitude], [x + waveLength / 4, -amplitude]];
|
||
}
|
||
|
||
return [[x + 1 / 2 * waveLength / Math.PI / 2 * (Math.PI - 2), -amplitude], [x + 1 / 2 * waveLength / Math.PI / 2 * (Math.PI - 1), -amplitude / 2], [x + waveLength / 4, 0]];
|
||
}
|
||
/**
|
||
* 获取水波路径
|
||
* @param {number} radius 半径
|
||
* @param {number} waterLevel 水位
|
||
* @param {number} waveLength 波长
|
||
* @param {number} phase 相位
|
||
* @param {number} amplitude 震幅
|
||
* @param {number} cx 圆心x
|
||
* @param {number} cy 圆心y
|
||
* @return {Array} path 路径
|
||
* @reference http://gitlab.alipay-inc.com/datavis/g6/blob/1.2.0/src/graph/utils/path.js#L135
|
||
*/
|
||
|
||
|
||
function getWaterWavePath(radius, waterLevel, waveLength, phase, amplitude, cx, cy) {
|
||
var curves = Math.ceil(2 * radius / waveLength * 4) * 2;
|
||
var path = []; // map phase to [-Math.PI * 2, 0]
|
||
|
||
while (phase < -Math.PI * 2) {
|
||
phase += Math.PI * 2;
|
||
}
|
||
|
||
while (phase > 0) {
|
||
phase -= Math.PI * 2;
|
||
}
|
||
|
||
phase = phase / Math.PI / 2 * waveLength;
|
||
var left = cx - radius + phase - radius * 2;
|
||
/**
|
||
* top-left corner as start point
|
||
*
|
||
* draws this point
|
||
* |
|
||
* \|/
|
||
* ~~~~~~~~
|
||
* | |
|
||
* +------+
|
||
*/
|
||
|
||
path.push(['M', left, waterLevel]);
|
||
/**
|
||
* top wave
|
||
*
|
||
* ~~~~~~~~ <- draws this sine wave
|
||
* | |
|
||
* +------+
|
||
*/
|
||
|
||
var waveRight = 0;
|
||
|
||
for (var c = 0; c < curves; ++c) {
|
||
var stage = c % 4;
|
||
var pos = getWaterWavePositions(c * waveLength / 4, stage, waveLength, amplitude);
|
||
path.push(['C', pos[0][0] + left, -pos[0][1] + waterLevel, pos[1][0] + left, -pos[1][1] + waterLevel, pos[2][0] + left, -pos[2][1] + waterLevel]);
|
||
|
||
if (c === curves - 1) {
|
||
waveRight = pos[2][0];
|
||
}
|
||
}
|
||
/**
|
||
* top-right corner
|
||
*
|
||
* ~~~~~~~~
|
||
* 3. draws this line -> | | <- 1. draws this line
|
||
* +------+
|
||
* ^
|
||
* |
|
||
* 2. draws this line
|
||
*/
|
||
|
||
|
||
path.push(['L', waveRight + left, cy + radius]);
|
||
path.push(['L', left, cy + radius]);
|
||
path.push(['L', left, waterLevel]);
|
||
return path;
|
||
}
|
||
/**
|
||
* 添加水波
|
||
* @param {number} x 中心x
|
||
* @param {number} y 中心y
|
||
* @param {number} level 水位等级 0~1
|
||
* @param {number} waveCount 水波数
|
||
* @param {number} colors 色值
|
||
* @param {number} group 图组
|
||
* @param {number} clip 用于剪切的图形
|
||
* @param {number} radius 绘制图形的高度
|
||
*/
|
||
|
||
|
||
function addWaterWave(x, y, level, waveCount, colors, group, clip, radius) {
|
||
var bbox = clip.getBBox();
|
||
var width = bbox.maxX - bbox.minX;
|
||
var height = bbox.maxY - bbox.minY;
|
||
var duration = 5000;
|
||
var delayDiff = 300;
|
||
|
||
for (var i = 0; i < waveCount; i++) {
|
||
var wave = group.addShape('path', {
|
||
attrs: {
|
||
path: getWaterWavePath(radius, bbox.minY + height * level, width / 4, 0, width / 64, x, y),
|
||
fill: colors[i],
|
||
clip: clip
|
||
}
|
||
}); // FIXME wave animation error in svg
|
||
|
||
if (Global.renderer === 'canvas') {
|
||
wave.animate({
|
||
transform: [['t', width / 2, 0]],
|
||
repeat: true
|
||
}, duration - i * delayDiff);
|
||
}
|
||
}
|
||
}
|
||
|
||
Shape.registerShape('interval', 'liquid-fill-gauge', {
|
||
draw: function draw(cfg, container) {
|
||
var self = this;
|
||
var cy = 0.5;
|
||
var sumX = 0;
|
||
var minX = Infinity;
|
||
Util.each(cfg.points, function (p) {
|
||
if (p.x < minX) {
|
||
minX = p.x;
|
||
}
|
||
|
||
sumX += p.x;
|
||
});
|
||
var cx = sumX / cfg.points.length;
|
||
var cp = self.parsePoint({
|
||
x: cx,
|
||
y: cy
|
||
});
|
||
var minP = self.parsePoint({
|
||
x: minX,
|
||
y: 0.5
|
||
});
|
||
var xWidth = cp.x - minP.x;
|
||
var radius = Math.min(xWidth, minP.y);
|
||
var attrs = getFillAttrs(cfg);
|
||
var clipCircle = new G.Circle({
|
||
attrs: {
|
||
x: cp.x,
|
||
y: cp.y,
|
||
r: radius
|
||
}
|
||
});
|
||
addWaterWave(cp.x, cp.y, cfg.y / (2 * cp.y), 1, [attrs.fill], container, clipCircle, radius * 4);
|
||
return container.addShape('circle', {
|
||
attrs: Util.mix(getLineAttrs(cfg), {
|
||
x: cp.x,
|
||
y: cp.y,
|
||
r: radius + radius / 8
|
||
})
|
||
});
|
||
}
|
||
});
|
||
var pathMetaCache = {};
|
||
Shape.registerShape('interval', 'liquid-fill-path', {
|
||
draw: function draw(cfg, container) {
|
||
var self = this;
|
||
var attrs = Util.mix({}, getFillAttrs(cfg));
|
||
var path = cfg.shape[1];
|
||
var cy = 0.5;
|
||
var sumX = 0;
|
||
var minX = Infinity;
|
||
Util.each(cfg.points, function (p) {
|
||
if (p.x < minX) {
|
||
minX = p.x;
|
||
}
|
||
|
||
sumX += p.x;
|
||
});
|
||
var cx = sumX / cfg.points.length;
|
||
var cp = self.parsePoint({
|
||
x: cx,
|
||
y: cy
|
||
});
|
||
var minP = self.parsePoint({
|
||
x: minX,
|
||
y: 0.5
|
||
});
|
||
var xWidth = cp.x - minP.x;
|
||
var radius = Math.min(xWidth, minP.y);
|
||
var pathMeta;
|
||
|
||
if (pathMetaCache[path]) {
|
||
pathMeta = pathMetaCache[path];
|
||
} else {
|
||
var segments = GPathUtil.parsePathString(path);
|
||
pathMetaCache[path] = pathMeta = {
|
||
segments: segments
|
||
};
|
||
}
|
||
|
||
var transform = [];
|
||
|
||
if (attrs.rotate) {
|
||
transform.push(['r', attrs.rotate / 180 * Math.PI]);
|
||
delete attrs.rotate;
|
||
}
|
||
|
||
var shape = container.addShape('path', {
|
||
attrs: Util.mix(attrs, {
|
||
fillOpacity: 0,
|
||
path: pathMeta.segments
|
||
})
|
||
});
|
||
var bbox = Util.cloneDeep(shape.getBBox());
|
||
var rangeX = bbox.maxX - bbox.minX;
|
||
var rangeY = bbox.maxY - bbox.minY;
|
||
var range = Math.max(rangeX, rangeY);
|
||
var scale = radius * 2 / range;
|
||
shape.transform(transform.concat([['s', scale, scale]]));
|
||
var dw = scale * rangeX / 2; // (bbox.maxX - bbox.minX) / 2;
|
||
|
||
var dh = scale * rangeY / 2; // (bbox.maxY - bbox.minY) / 2;
|
||
|
||
shape.transform([['t', cp.x - dw, cp.y - dh]]);
|
||
addWaterWave(cp.x, cp.y, cfg.y / (2 * cp.y), 1, [attrs.fill], container, shape, minP.y * 4);
|
||
var keyShape = container.addShape('path', {
|
||
attrs: Util.mix(getLineAttrs(cfg), {
|
||
path: pathMeta.segments
|
||
})
|
||
});
|
||
keyShape.transform(transform.concat([['s', scale, scale], ['t', cp.x - dw, cp.y - dh]]));
|
||
return keyShape;
|
||
}
|
||
});
|
||
Shape.registerShape('interval', 'top-line', {
|
||
draw: function draw(cfg, container) {
|
||
var attrs = getFillAttrs(cfg);
|
||
var style = cfg.style || {};
|
||
var linePath = [['M', cfg.points[1].x, cfg.points[1].y], ['L', cfg.points[2].x, cfg.points[2].y]];
|
||
var lineAttrs = {
|
||
stroke: style.stroke || 'white',
|
||
lineWidth: style.lineWidth || 1,
|
||
path: this.parsePath(linePath)
|
||
};
|
||
var path = getRectPath(cfg.points);
|
||
path = this.parsePath(path);
|
||
delete attrs.stroke; // 不在柱子上绘制线
|
||
|
||
var rectShape = container.addShape('path', {
|
||
attrs: Util.mix(attrs, {
|
||
zIndex: 0,
|
||
path: path
|
||
})
|
||
});
|
||
container.addShape('path', {
|
||
zIndex: 1,
|
||
attrs: lineAttrs
|
||
});
|
||
return rectShape;
|
||
},
|
||
getMarkerCfg: function getMarkerCfg(cfg) {
|
||
var rectCfg = getFillAttrs(cfg);
|
||
var isInCircle = cfg.isInCircle;
|
||
return Util.mix({
|
||
symbol: isInCircle ? 'circle' : 'square',
|
||
radius: isInCircle ? 4.5 : 4
|
||
}, rectCfg);
|
||
}
|
||
});
|
||
module.exports = Interval; |