393 lines
9.3 KiB
Java
393 lines
9.3 KiB
Java
|
|
/**
|
|||
|
|
* @fileOverview line shapes
|
|||
|
|
* @author dxq613@gmail.com
|
|||
|
|
* @author sima.zhang1990@gmail.com
|
|||
|
|
* @author huangtonger@aliyun.com
|
|||
|
|
*/
|
|||
|
|
var Util = require('../../util');
|
|||
|
|
|
|||
|
|
var PathUtil = require('../util/path');
|
|||
|
|
|
|||
|
|
var ShapeUtil = require('../util/shape');
|
|||
|
|
|
|||
|
|
var Shape = require('./shape');
|
|||
|
|
|
|||
|
|
var Global = require('../../global');
|
|||
|
|
|
|||
|
|
var DOT_ARR = [1, 1];
|
|||
|
|
var DASH_ARR = [5.5, 1];
|
|||
|
|
|
|||
|
|
function getAttrs(cfg) {
|
|||
|
|
var defaultCfg = Global.shape.line;
|
|||
|
|
var lineAttrs = Util.mix({}, defaultCfg, cfg.style);
|
|||
|
|
ShapeUtil.addStrokeAttrs(lineAttrs, cfg);
|
|||
|
|
|
|||
|
|
if (cfg.size) {
|
|||
|
|
lineAttrs.lineWidth = cfg.size;
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
return lineAttrs;
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
function getMarkerAttrs(cfg) {
|
|||
|
|
var defaultCfg = Global.shape.line;
|
|||
|
|
var lineAttrs = Util.mix({
|
|||
|
|
lineWidth: 2,
|
|||
|
|
radius: 6
|
|||
|
|
}, defaultCfg, cfg.style);
|
|||
|
|
ShapeUtil.addStrokeAttrs(lineAttrs, cfg);
|
|||
|
|
return lineAttrs;
|
|||
|
|
} // 获取带有上下区间的 path
|
|||
|
|
|
|||
|
|
|
|||
|
|
function getRangePath(points, smooth, isInCircle, cfg) {
|
|||
|
|
var topPoints = [];
|
|||
|
|
var isStack = cfg.isStack;
|
|||
|
|
var bottomPoints = [];
|
|||
|
|
|
|||
|
|
for (var i = 0; i < points.length; i++) {
|
|||
|
|
var point = points[i];
|
|||
|
|
var tmp = ShapeUtil.splitPoints(point);
|
|||
|
|
bottomPoints.push(tmp[0]);
|
|||
|
|
topPoints.push(tmp[1]);
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
var topPath = getSinglePath(topPoints, smooth, isInCircle, cfg);
|
|||
|
|
var bottomPath = getSinglePath(bottomPoints, smooth, isInCircle, cfg);
|
|||
|
|
|
|||
|
|
if (isStack) {
|
|||
|
|
return topPath;
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
return topPath.concat(bottomPath);
|
|||
|
|
} // 单条 path
|
|||
|
|
|
|||
|
|
|
|||
|
|
function getSinglePath(points, smooth, isInCircle, cfg) {
|
|||
|
|
var path;
|
|||
|
|
|
|||
|
|
if (!smooth) {
|
|||
|
|
path = PathUtil.getLinePath(points, false);
|
|||
|
|
|
|||
|
|
if (isInCircle) {
|
|||
|
|
path.push(['Z']);
|
|||
|
|
}
|
|||
|
|
} else {
|
|||
|
|
// 直角坐标系下绘制曲线时限制最大值、最小值
|
|||
|
|
var constraint = cfg.constraint;
|
|||
|
|
|
|||
|
|
if (isInCircle && points.length) {
|
|||
|
|
points.push({
|
|||
|
|
x: points[0].x,
|
|||
|
|
y: points[0].y
|
|||
|
|
});
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
path = PathUtil.getSplinePath(points, false, constraint);
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
return path;
|
|||
|
|
} // get line path
|
|||
|
|
|
|||
|
|
|
|||
|
|
function getPath(cfg, smooth) {
|
|||
|
|
var path;
|
|||
|
|
var points = cfg.points;
|
|||
|
|
var isInCircle = cfg.isInCircle;
|
|||
|
|
var first = points[0];
|
|||
|
|
|
|||
|
|
if (Util.isArray(first.y)) {
|
|||
|
|
path = getRangePath(points, smooth, isInCircle, cfg);
|
|||
|
|
} else {
|
|||
|
|
path = getSinglePath(points, smooth, isInCircle, cfg);
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
return path;
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
function _interpPoints(points, fn) {
|
|||
|
|
var tmpPoints = [];
|
|||
|
|
Util.each(points, function (point, index) {
|
|||
|
|
var nextPoint = points[index + 1];
|
|||
|
|
tmpPoints.push(point);
|
|||
|
|
|
|||
|
|
if (nextPoint) {
|
|||
|
|
tmpPoints = tmpPoints.concat(fn(point, nextPoint));
|
|||
|
|
}
|
|||
|
|
});
|
|||
|
|
return tmpPoints;
|
|||
|
|
} // 插值的图形path,不考虑null
|
|||
|
|
|
|||
|
|
|
|||
|
|
function _getInterPath(points) {
|
|||
|
|
var path = [];
|
|||
|
|
Util.each(points, function (point, index) {
|
|||
|
|
var subPath = index === 0 ? ['M', point.x, point.y] : ['L', point.x, point.y];
|
|||
|
|
path.push(subPath);
|
|||
|
|
});
|
|||
|
|
return path;
|
|||
|
|
} // 插值的图形
|
|||
|
|
|
|||
|
|
|
|||
|
|
function _getInterPointShapeCfg(cfg, fn) {
|
|||
|
|
var points = _interpPoints(cfg.points, fn);
|
|||
|
|
|
|||
|
|
return _getInterPath(points);
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
function _markerFn(x, y, r) {
|
|||
|
|
return [['M', x - r, y], ['L', x + r, y]];
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
function _smoothMarkerFn(x, y, r) {
|
|||
|
|
return [['M', x - r, y], ['A', r / 2, r / 2, 0, 1, 1, x, y], ['A', r / 2, r / 2, 0, 1, 0, x + r, y]];
|
|||
|
|
} // get marker cfg
|
|||
|
|
|
|||
|
|
|
|||
|
|
function _getMarkerCfg(cfg, smooth) {
|
|||
|
|
return Util.mix({
|
|||
|
|
symbol: smooth ? _smoothMarkerFn : _markerFn
|
|||
|
|
}, getMarkerAttrs(cfg));
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
function _getInterMarkerCfg(cfg, fn) {
|
|||
|
|
return Util.mix({
|
|||
|
|
symbol: fn
|
|||
|
|
}, getMarkerAttrs(cfg));
|
|||
|
|
} // 当只有一个数据时绘制点
|
|||
|
|
|
|||
|
|
|
|||
|
|
function drawPointShape(shapeObj, cfg, container) {
|
|||
|
|
var point = cfg.points[0];
|
|||
|
|
return container.addShape('circle', {
|
|||
|
|
attrs: Util.mix({
|
|||
|
|
x: point.x,
|
|||
|
|
y: point.y,
|
|||
|
|
r: 2,
|
|||
|
|
fill: cfg.color
|
|||
|
|
}, cfg.style)
|
|||
|
|
});
|
|||
|
|
} // regist line geom
|
|||
|
|
|
|||
|
|
|
|||
|
|
var Line = Shape.registerFactory('line', {
|
|||
|
|
// 默认的shape
|
|||
|
|
defaultShapeType: 'line',
|
|||
|
|
|
|||
|
|
/* getMarkerCfg(type, cfg) {
|
|||
|
|
const lineObj = Line[type] || Line.line;
|
|||
|
|
return lineObj.getMarkerCfg(cfg);
|
|||
|
|
}, */
|
|||
|
|
getActiveCfg: function getActiveCfg(type, cfg) {
|
|||
|
|
var lineWidth = cfg.lineWidth || 0;
|
|||
|
|
return {
|
|||
|
|
lineWidth: lineWidth + 1
|
|||
|
|
};
|
|||
|
|
},
|
|||
|
|
// 计算点 如果存在多个点,分割成单个的点, 不考虑多个x对应一个y的情况
|
|||
|
|
getDefaultPoints: function getDefaultPoints(pointInfo) {
|
|||
|
|
return ShapeUtil.splitPoints(pointInfo);
|
|||
|
|
},
|
|||
|
|
drawShape: function drawShape(type, cfg, container) {
|
|||
|
|
var shape = this.getShape(type);
|
|||
|
|
var gShape;
|
|||
|
|
|
|||
|
|
if (cfg.points.length === 1 && Global.showSinglePoint) {
|
|||
|
|
gShape = drawPointShape(this, cfg, container);
|
|||
|
|
} else {
|
|||
|
|
gShape = shape.draw(cfg, container);
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
if (gShape) {
|
|||
|
|
gShape.set('origin', cfg.origin);
|
|||
|
|
gShape._id = cfg.splitedIndex ? cfg._id + cfg.splitedIndex : cfg._id;
|
|||
|
|
gShape.name = this.name;
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
return gShape;
|
|||
|
|
}
|
|||
|
|
}); // draw line shape
|
|||
|
|
|
|||
|
|
Shape.registerShape('line', 'line', {
|
|||
|
|
draw: function draw(cfg, container) {
|
|||
|
|
var attrs = getAttrs(cfg);
|
|||
|
|
var path = getPath(cfg, false);
|
|||
|
|
return container.addShape('path', {
|
|||
|
|
attrs: Util.mix(attrs, {
|
|||
|
|
path: path
|
|||
|
|
})
|
|||
|
|
});
|
|||
|
|
},
|
|||
|
|
getMarkerCfg: function getMarkerCfg(cfg) {
|
|||
|
|
return _getMarkerCfg(cfg);
|
|||
|
|
}
|
|||
|
|
}); // 点线 ···
|
|||
|
|
|
|||
|
|
Shape.registerShape('line', 'dot', {
|
|||
|
|
draw: function draw(cfg, container) {
|
|||
|
|
var attrs = getAttrs(cfg);
|
|||
|
|
var path = getPath(cfg, false);
|
|||
|
|
return container.addShape('path', {
|
|||
|
|
attrs: Util.mix(attrs, {
|
|||
|
|
path: path,
|
|||
|
|
lineDash: DOT_ARR
|
|||
|
|
})
|
|||
|
|
});
|
|||
|
|
},
|
|||
|
|
getMarkerCfg: function getMarkerCfg(cfg) {
|
|||
|
|
var tmp = _getMarkerCfg(cfg, false);
|
|||
|
|
|
|||
|
|
tmp.lineDash = DOT_ARR;
|
|||
|
|
return tmp;
|
|||
|
|
}
|
|||
|
|
}); // 断线 - - -
|
|||
|
|
|
|||
|
|
Shape.registerShape('line', 'dash', {
|
|||
|
|
draw: function draw(cfg, container) {
|
|||
|
|
var attrs = getAttrs(cfg);
|
|||
|
|
var path = getPath(cfg, false);
|
|||
|
|
return container.addShape('path', {
|
|||
|
|
attrs: Util.mix({
|
|||
|
|
path: path,
|
|||
|
|
lineDash: DASH_ARR
|
|||
|
|
}, attrs)
|
|||
|
|
});
|
|||
|
|
},
|
|||
|
|
getMarkerCfg: function getMarkerCfg(cfg) {
|
|||
|
|
var tmp = _getMarkerCfg(cfg, false);
|
|||
|
|
|
|||
|
|
tmp.lineDash = tmp.lineDash || DASH_ARR;
|
|||
|
|
return tmp;
|
|||
|
|
}
|
|||
|
|
}); // draw smooth line shape
|
|||
|
|
|
|||
|
|
Shape.registerShape('line', 'smooth', {
|
|||
|
|
draw: function draw(cfg, container) {
|
|||
|
|
var attrs = getAttrs(cfg);
|
|||
|
|
var coord = this._coord; // 曲线的限制
|
|||
|
|
|
|||
|
|
cfg.constraint = [[coord.start.x, coord.end.y], [coord.end.x, coord.start.y]];
|
|||
|
|
var path = getPath(cfg, true);
|
|||
|
|
return container.addShape('path', {
|
|||
|
|
attrs: Util.mix(attrs, {
|
|||
|
|
path: path
|
|||
|
|
})
|
|||
|
|
});
|
|||
|
|
},
|
|||
|
|
getMarkerCfg: function getMarkerCfg(cfg) {
|
|||
|
|
return _getMarkerCfg(cfg, true);
|
|||
|
|
}
|
|||
|
|
});
|
|||
|
|
Shape.registerShape('line', 'hv', {
|
|||
|
|
draw: function draw(cfg, container) {
|
|||
|
|
var attrs = getAttrs(cfg);
|
|||
|
|
|
|||
|
|
var path = _getInterPointShapeCfg(cfg, function (point, nextPoint) {
|
|||
|
|
var tmp = [];
|
|||
|
|
tmp.push({
|
|||
|
|
x: nextPoint.x,
|
|||
|
|
y: point.y
|
|||
|
|
});
|
|||
|
|
return tmp;
|
|||
|
|
});
|
|||
|
|
|
|||
|
|
return container.addShape('path', {
|
|||
|
|
attrs: Util.mix(attrs, {
|
|||
|
|
path: path
|
|||
|
|
})
|
|||
|
|
});
|
|||
|
|
},
|
|||
|
|
getMarkerCfg: function getMarkerCfg(cfg) {
|
|||
|
|
return _getInterMarkerCfg(cfg, function (x, y, r) {
|
|||
|
|
return [['M', x - r - 1, y - 2.5], ['L', x, y - 2.5], ['L', x, y + 2.5], ['L', x + r + 1, y + 2.5]];
|
|||
|
|
});
|
|||
|
|
}
|
|||
|
|
});
|
|||
|
|
Shape.registerShape('line', 'vh', {
|
|||
|
|
draw: function draw(cfg, container) {
|
|||
|
|
var attrs = getAttrs(cfg);
|
|||
|
|
|
|||
|
|
var path = _getInterPointShapeCfg(cfg, function (point, nextPoint) {
|
|||
|
|
var tmp = [];
|
|||
|
|
tmp.push({
|
|||
|
|
x: point.x,
|
|||
|
|
y: nextPoint.y
|
|||
|
|
});
|
|||
|
|
return tmp;
|
|||
|
|
});
|
|||
|
|
|
|||
|
|
return container.addShape('path', {
|
|||
|
|
attrs: Util.mix(attrs, {
|
|||
|
|
path: path
|
|||
|
|
})
|
|||
|
|
});
|
|||
|
|
},
|
|||
|
|
getMarkerCfg: function getMarkerCfg(cfg) {
|
|||
|
|
return _getInterMarkerCfg(cfg, function (x, y, r) {
|
|||
|
|
return [['M', x - r - 1, y + 2.5], ['L', x, y + 2.5], ['L', x, y - 2.5], ['L', x + r + 1, y - 2.5]];
|
|||
|
|
});
|
|||
|
|
}
|
|||
|
|
});
|
|||
|
|
Shape.registerShape('line', 'hvh', {
|
|||
|
|
draw: function draw(cfg, container) {
|
|||
|
|
var attrs = getAttrs(cfg);
|
|||
|
|
|
|||
|
|
var path = _getInterPointShapeCfg(cfg, function (point, nextPoint) {
|
|||
|
|
var tmp = [];
|
|||
|
|
var middlex = (nextPoint.x - point.x) / 2 + point.x;
|
|||
|
|
tmp.push({
|
|||
|
|
x: middlex,
|
|||
|
|
y: point.y
|
|||
|
|
});
|
|||
|
|
tmp.push({
|
|||
|
|
x: middlex,
|
|||
|
|
y: nextPoint.y
|
|||
|
|
});
|
|||
|
|
return tmp;
|
|||
|
|
});
|
|||
|
|
|
|||
|
|
return container.addShape('path', {
|
|||
|
|
attrs: Util.mix(attrs, {
|
|||
|
|
path: path
|
|||
|
|
})
|
|||
|
|
});
|
|||
|
|
},
|
|||
|
|
getMarkerCfg: function getMarkerCfg(cfg) {
|
|||
|
|
return _getInterMarkerCfg(cfg, function (x, y, r) {
|
|||
|
|
return [['M', x - (r + 1), y + 2.5], ['L', x - r / 2, y + 2.5], ['L', x - r / 2, y - 2.5], ['L', x + r / 2, y - 2.5], ['L', x + r / 2, y + 2.5], ['L', x + r + 1, y + 2.5]];
|
|||
|
|
});
|
|||
|
|
}
|
|||
|
|
});
|
|||
|
|
Shape.registerShape('line', 'vhv', {
|
|||
|
|
draw: function draw(cfg, container) {
|
|||
|
|
var attrs = getAttrs(cfg);
|
|||
|
|
|
|||
|
|
var path = _getInterPointShapeCfg(cfg, function (point, nextPoint) {
|
|||
|
|
var tmp = [];
|
|||
|
|
var middley = (nextPoint.y - point.y) / 2 + point.y;
|
|||
|
|
tmp.push({
|
|||
|
|
x: point.x,
|
|||
|
|
y: middley
|
|||
|
|
});
|
|||
|
|
tmp.push({
|
|||
|
|
x: nextPoint.x,
|
|||
|
|
y: middley
|
|||
|
|
});
|
|||
|
|
return tmp;
|
|||
|
|
});
|
|||
|
|
|
|||
|
|
return container.addShape('path', {
|
|||
|
|
attrs: Util.mix(attrs, {
|
|||
|
|
path: path
|
|||
|
|
})
|
|||
|
|
});
|
|||
|
|
},
|
|||
|
|
getMarkerCfg: function getMarkerCfg(cfg) {
|
|||
|
|
return _getInterMarkerCfg(cfg, function (x, y) {
|
|||
|
|
// 宽 13px,高 8px
|
|||
|
|
return [['M', x - 5, y + 2.5], ['L', x - 5, y], ['L', x, y], ['L', x, y - 3], ['L', x, y + 3], ['L', x + 6.5, y + 3]];
|
|||
|
|
});
|
|||
|
|
}
|
|||
|
|
});
|
|||
|
|
Line.spline = Line.smooth;
|
|||
|
|
module.exports = Line;
|