static/js/dncp/util/shape/MarkLine.js
/**
* zrender
*
* @author Kener (@Kener-林峰, kener.linfeng@gmail.com)
* Yi Shen(https://github.com/pissang)
*
* shape类:标线
*/
/**
* @typedef {Object} IMarkLineStyle
* @property {number} xStart 起点x坐标
* @property {number} yStart 起点y坐标
* @property {number} xEnd 终止点x坐标
* @property {number} yEnd 终止点y坐标
* @property {number} cpX1 控制点x坐标,可以使用updatePoints自动根据curveness计算
* @property {number} cpY1 控制点y坐标,可以使用updatePoints自动根据curveness计算
* @property {number} curveness 曲度
* @property {Array.<string>} symbol
* @property {Array.<number>} symbolRotate
*/
define(function (require) {
var Base = require('zrender/shape/Base');
var IconShape = require('./Icon');
var LineShape = require('zrender/shape/Line');
var lineInstance = new LineShape({});
var CurveShape = require('zrender/shape/BezierCurve');
var curveInstance = new CurveShape({});
var area = require('zrender/tool/area');
var dashedLineTo = require('zrender/shape/util/dashedLineTo');
var zrUtil = require('zrender/tool/util');
var curveTool = require('zrender/tool/curve');
function MarkLine(options) {
Base.call(this, options);
if (this.style.curveness > 0) {
this.updatePoints(this.style);
}
if (this.highlightStyle.curveness > 0) {
this.updatePoints(this.highlightStyle);
}
}
MarkLine.prototype = {
type : 'mark-line',
/**
* 画刷
* @param ctx 画布句柄
* @param isHighlight 是否为高亮状态
* @param updateCallback 让painter更新视图,base.brush没用,需要的话重载brush
*/
brush : function (ctx, isHighlight) {
var style = this.style;
if (isHighlight) {
// 根据style扩展默认高亮样式
style = this.getHighlightStyle(
style,
this.highlightStyle || {}
);
}
ctx.save();
this.setContext(ctx, style);
// 设置transform
this.setTransform(ctx);
ctx.save();
ctx.beginPath();
this.buildPath(ctx, style);
ctx.stroke();
ctx.restore();
this.brushSymbol(ctx, style, 0);
this.brushSymbol(ctx, style, 1);
this.drawText(ctx, style, this.style);
ctx.restore();
},
/**
* 创建线条路径
* @param {Context2D} ctx Canvas 2D上下文
* @param {Object} style 样式
*/
buildPath : function (ctx, style) {
var lineType = style.lineType || 'solid';
ctx.moveTo(style.xStart, style.yStart);
if (style.curveness > 0) {
// FIXME Bezier 在少部分浏览器上暂时不支持虚线
var lineDash = null;
switch (lineType) {
case 'dashed':
lineDash = [5, 5];
break;
case'dotted':
lineDash = [1, 1];
break;
}
if (lineDash && ctx.setLineDash) {
ctx.setLineDash(lineDash);
}
ctx.quadraticCurveTo(
style.cpX1, style.cpY1, style.xEnd, style.yEnd
);
}
else {
if (lineType == 'solid') {
ctx.lineTo(style.xEnd, style.yEnd);
}
else {
var dashLength = (style.lineWidth || 1)
* (style.lineType == 'dashed' ? 5 : 1);
dashedLineTo(
ctx, style.xStart, style.yStart,
style.xEnd, style.yEnd, dashLength
);
}
}
},
/**
* Update cpX1 and cpY1 according to curveniss
* @param {Object} style
*/
updatePoints: function (style) {
var curveness = style.curveness || 0;
var inv = 1;
var x0 = style.xStart;
var y0 = style.yStart;
var x2 = style.xEnd;
var y2 = style.yEnd;
var x1 = (x0 + x2) / 2 - inv * (y0 - y2) * curveness;
var y1 =(y0 + y2) / 2 - inv * (x2 - x0) * curveness;
style.cpX1 = x1;
style.cpY1 = y1;
},
/**
* 标线始末标注
*/
brushSymbol : function (ctx, style, idx) {
if (style.symbol[idx] == 'none') {
return;
}
ctx.save();
ctx.beginPath();
ctx.lineWidth = style.symbolBorder;
ctx.strokeStyle = style.symbolBorderColor;
// symbol
var symbol = style.symbol[idx].replace('empty', '')
.toLowerCase();
if (style.symbol[idx].match('empty')) {
ctx.fillStyle = '#fff'; //'rgba(0, 0, 0, 0)';
}
// symbolRotate
var x0 = style.xStart;
var y0 = style.yStart;
var x2 = style.xEnd;
var y2 = style.yEnd;
var x = idx === 0 ? x0 : x2;
var y = idx === 0 ? y0 : y2;
var curveness = style.curveness || 0;
var rotate = style.symbolRotate[idx] != null ? (style.symbolRotate[idx] - 0) : 0;
rotate = rotate / 180 * Math.PI;
if (symbol == 'arrow' && rotate === 0) {
if (curveness === 0) {
var sign = idx === 0 ? -1 : 1;
rotate = Math.PI / 2 + Math.atan2(
sign * (y2 - y0), sign * (x2 - x0)
);
}
else {
var x1 = style.cpX1;
var y1 = style.cpY1;
var quadraticDerivativeAt = curveTool.quadraticDerivativeAt;
var dx = quadraticDerivativeAt(x0, x1, x2, idx);
var dy = quadraticDerivativeAt(y0, y1, y2, idx);
rotate = Math.PI / 2 + Math.atan2(dy, dx);
}
}
ctx.translate(x, y);
if (rotate !== 0) {
ctx.rotate(rotate);
}
// symbolSize
var symbolSize = style.symbolSize[idx];
IconShape.prototype.buildPath(ctx, {
x: -symbolSize,
y: -symbolSize,
width: symbolSize * 2,
height: symbolSize * 2,
iconType: symbol
});
ctx.closePath();
ctx.fill();
ctx.stroke();
ctx.restore();
},
/**
* 返回矩形区域,用于局部刷新和文字定位
* @param {Object} style
*/
getRect : function (style) {
style.curveness > 0 ? curveInstance.getRect(style)
: lineInstance.getRect(style);
return style.__rect;
},
isCover : function (x, y) {
var originPos = this.transformCoordToLocal(x, y);
x = originPos[0];
y = originPos[1];
// 快速预判并保留判断矩形
if (this.isCoverRect(x, y)) {
// 矩形内
return this.style.curveness > 0
? area.isInside(curveInstance, this.style, x, y)
: area.isInside(lineInstance, this.style, x, y);
}
return false;
}
};
zrUtil.inherits(MarkLine, Base);
return MarkLine;
});