You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@echarts.apache.org by sh...@apache.org on 2020/06/02 06:24:50 UTC
[incubator-echarts] branch label-enhancement updated: feat: add
minTurnAngle in labelLine
This is an automated email from the ASF dual-hosted git repository.
shenyi pushed a commit to branch label-enhancement
in repository https://gitbox.apache.org/repos/asf/incubator-echarts.git
The following commit(s) were added to refs/heads/label-enhancement by this push:
new d8b1f1c feat: add minTurnAngle in labelLine
d8b1f1c is described below
commit d8b1f1cc5e27b89cfaed54dd88a93809ea989479
Author: pissang <bm...@gmail.com>
AuthorDate: Tue Jun 2 14:24:08 2020 +0800
feat: add minTurnAngle in labelLine
---
src/chart/pie/PieSeries.ts | 1 +
src/chart/pie/PieView.ts | 2 +-
src/chart/pie/labelLayout.ts | 10 ++++-
src/label/LabelManager.ts | 3 +-
src/label/labelGuideHelper.ts | 91 +++++++++++++++++++++++++++++++++++++++----
src/util/types.ts | 3 ++
6 files changed, 99 insertions(+), 11 deletions(-)
diff --git a/src/chart/pie/PieSeries.ts b/src/chart/pie/PieSeries.ts
index 8e86ed9..e5c398b 100644
--- a/src/chart/pie/PieSeries.ts
+++ b/src/chart/pie/PieSeries.ts
@@ -272,6 +272,7 @@ class PieSeriesModel extends SeriesModel<PieSeriesOption> {
// 引导线两段中的第二段长度
length2: 15,
smooth: false,
+ minTurnAngle: 100,
lineStyle: {
// color: 各异,
width: 1,
diff --git a/src/chart/pie/PieView.ts b/src/chart/pie/PieView.ts
index f52c6f7..6241d52 100644
--- a/src/chart/pie/PieView.ts
+++ b/src/chart/pie/PieView.ts
@@ -224,7 +224,7 @@ class PiePiece extends graphic.Sector {
let smooth = labelLineModel.get('smooth');
if (smooth && smooth === true) {
- smooth = 0.4;
+ smooth = 0.3;
}
labelLine.setShape({
smooth: smooth as number
diff --git a/src/chart/pie/labelLayout.ts b/src/chart/pie/labelLayout.ts
index ec057ec..693008d 100644
--- a/src/chart/pie/labelLayout.ts
+++ b/src/chart/pie/labelLayout.ts
@@ -26,6 +26,7 @@ import { Sector, Polyline } from '../../util/graphic';
import ZRText from 'zrender/src/graphic/Text';
import { RectLike } from 'zrender/src/core/BoundingRect';
import { each } from 'zrender/src/core/util';
+import { limitTurnAngle } from '../../label/labelGuideHelper';
const RADIAN = Math.PI / 180;
@@ -37,6 +38,7 @@ interface LabelLayout {
position: PieSeriesOption['label']['position'],
len: number
len2: number
+ minTurnAngle: number
linePoints: VectorArray[]
textAlign: HorizontalAlign
rotation: number,
@@ -411,6 +413,7 @@ export default function (
position: labelPosition,
len: labelLineLen,
len2: labelLineLen2,
+ minTurnAngle: labelLineModel.get('minTurnAngle'),
linePoints: linePoints,
textAlign: textAlign,
rotation: labelRotate,
@@ -463,11 +466,14 @@ export default function (
}
}
if (labelLine) {
- labelLine.setShape({ points: layout.linePoints });
- if (notShowLabel) {
+ if (notShowLabel || !layout.linePoints) {
each(labelLine.states, setNotShow);
labelLine.ignore = true;
}
+ else {
+ limitTurnAngle(layout.linePoints, layout.minTurnAngle);
+ labelLine.setShape({ points: layout.linePoints });
+ }
}
}
}
\ No newline at end of file
diff --git a/src/label/LabelManager.ts b/src/label/LabelManager.ts
index 3cbdef5..d3cdfc5 100644
--- a/src/label/LabelManager.ts
+++ b/src/label/LabelManager.ts
@@ -397,7 +397,8 @@ class LabelManager {
label,
globalRect,
label.__hostTarget,
- labelItem.hostRect
+ labelItem.hostRect,
+ labelItem.seriesModel.getModel(['labelLine'])
);
}
}
diff --git a/src/label/labelGuideHelper.ts b/src/label/labelGuideHelper.ts
index da4848b..ddeba60 100644
--- a/src/label/labelGuideHelper.ts
+++ b/src/label/labelGuideHelper.ts
@@ -27,6 +27,8 @@ import { RectLike } from 'zrender/src/core/BoundingRect';
import { normalizeRadian } from 'zrender/src/contain/util';
import { cubicProjectPoint, quadraticProjectPoint } from 'zrender/src/core/curve';
import Element from 'zrender/src/Element';
+import { LabelGuideLineOption } from '../util/types';
+import Model from '../model/Model';
const PI2 = Math.PI * 2;
const CMD = PathProxy.CMD;
@@ -144,7 +146,9 @@ function projectPointToArc(
}
}
-function projectPointToLine(x1: number, y1: number, x2: number, y2: number, x: number, y: number, out: number[]) {
+function projectPointToLine(
+ x1: number, y1: number, x2: number, y2: number, x: number, y: number, out: number[], limitToEnds: boolean
+) {
const dx = x - x1;
const dy = y - y1;
@@ -157,7 +161,11 @@ function projectPointToLine(x1: number, y1: number, x2: number, y2: number, x: n
// dot product
const projectedLen = dx * dx1 + dy * dy1;
- const t = Math.min(Math.max(projectedLen / lineLen, 0), 1);
+ let t = projectedLen / lineLen;
+ if (limitToEnds) {
+ t = Math.min(Math.max(t, 0), 1);
+ }
+ t *= lineLen;
const ox = out[0] = x1 + t * dx1;
const oy = out[1] = y1 + t * dy1;
@@ -234,7 +242,7 @@ function nearestPointOnPath(pt: Point, path: PathProxy, out: Point) {
yi = y0;
break;
case CMD.L:
- d = projectPointToLine(xi, yi, data[i], data[i + 1], x, y, tmpPt);
+ d = projectPointToLine(xi, yi, data[i], data[i + 1], x, y, tmpPt, true);
xi = data[i++];
yi = data[i++];
break;
@@ -293,7 +301,7 @@ function nearestPointOnPath(pt: Point, path: PathProxy, out: Point) {
d = projectPointToRect(x0, y0, width, height, x, y, tmpPt);
break;
case CMD.Z:
- d = projectPointToLine(xi, yi, x0, y0, x, y, tmpPt);
+ d = projectPointToLine(xi, yi, x0, y0, x, y, tmpPt, true);
xi = x0;
yi = y0;
@@ -309,15 +317,26 @@ function nearestPointOnPath(pt: Point, path: PathProxy, out: Point) {
return minDist;
}
+// Temporal varible for intermediate usage.
const pt0 = new Point();
const pt1 = new Point();
const pt2 = new Point();
const dir = new Point();
+const dir2 = new Point();
+
+/**
+ * Calculate a proper guide line based on the label position and graphic element definition
+ * @param label
+ * @param labelRect
+ * @param target
+ * @param targetRect
+ */
export function updateLabelGuideLine(
label: ZRText,
labelRect: RectLike,
target: Element,
- targetRect: RectLike
+ targetRect: RectLike,
+ labelLineModel: Model<LabelGuideLineOption>
) {
if (!target) {
return;
@@ -356,11 +375,69 @@ export function updateLabelGuideLine(
// TODO pt2 is in the path
if (dist < minDist) {
minDist = dist;
- pt0.toArray(points[0]);
+ pt2.toArray(points[0]);
pt1.toArray(points[1]);
- pt2.toArray(points[2]);
+ pt0.toArray(points[2]);
}
}
+ limitTurnAngle(points, labelLineModel.get('minTurnAngle'));
+
labelLine.setShape({ points });
+}
+
+// Temporal variable for the limitTurnAngle function
+const tmpArr: number[] = [];
+const tmpProjPoint = new Point();
+/**
+ * Reduce the line segment attached to the label to limit the turn angle between two segments.
+ * @param linePoints
+ * @param minTurnAngle Radian of minimum turn angle. 0 - 180
+ */
+export function limitTurnAngle(linePoints: number[][], minTurnAngle: number) {
+ if (!(minTurnAngle < 180 && minTurnAngle > 0)) {
+ return;
+ }
+ minTurnAngle = minTurnAngle / 180 * Math.PI;
+ // The line points can be
+ // /pt1----pt2 (label)
+ // /
+ // pt0/
+ pt0.fromArray(linePoints[0]);
+ pt1.fromArray(linePoints[1]);
+ pt2.fromArray(linePoints[2]);
+
+ Point.sub(dir, pt0, pt1);
+ Point.sub(dir2, pt2, pt1);
+
+ const len1 = dir.len();
+ const len2 = dir2.len();
+ if (len1 < 1e-3 || len2 < 1e-3) {
+ return;
+ }
+
+ dir.scale(1 / len1);
+ dir2.scale(1 / len2);
+
+ const angleCos = dir.dot(dir2);
+ const minTurnAngleCos = Math.cos(minTurnAngle);
+ if (minTurnAngleCos < angleCos) { // Smaller than minTurnAngle
+ // Calculate project point of pt0 on pt1-pt2
+ const d = projectPointToLine(pt1.x, pt1.y, pt2.x, pt2.y, pt0.x, pt0.y, tmpArr, false);
+ tmpProjPoint.fromArray(tmpArr);
+ // Calculate new projected length with limited minTurnAngle and get the new connect point
+ tmpProjPoint.scaleAndAdd(dir2, d / Math.tan(Math.PI - minTurnAngle));
+ // Limit the new calculated connect point between pt1 and pt2.
+ const t = pt2.x !== pt1.x
+ ? (tmpProjPoint.x - pt1.x) / (pt2.x - pt1.x)
+ : (tmpProjPoint.y - pt1.y) / (pt2.y - pt1.y);
+ if (t < 0) {
+ Point.copy(tmpProjPoint, pt1);
+ }
+ else if (t > 1) {
+ Point.copy(tmpProjPoint, pt2);
+ }
+
+ tmpProjPoint.toArray(linePoints[1]);
+ }
}
\ No newline at end of file
diff --git a/src/util/types.ts b/src/util/types.ts
index f0eaac1..96a82ad 100644
--- a/src/util/types.ts
+++ b/src/util/types.ts
@@ -804,6 +804,7 @@ export interface LabelGuideLineOption {
length?: number
length2?: number
smooth?: boolean | number
+ minTurnAngle?: number,
lineStyle?: LineStyleOption
}
@@ -1132,6 +1133,8 @@ export interface SeriesOption extends
*/
labelLayout?: LabelLayoutOption | LabelLayoutOptionCallback
+ labelLine?: LabelGuideLineOption
+
/**
* Animation config for state transition.
*/
---------------------------------------------------------------------
To unsubscribe, e-mail: commits-unsubscribe@echarts.apache.org
For additional commands, e-mail: commits-help@echarts.apache.org