1 | import { __extends } from "tslib";
|
2 | import Displayable, { DEFAULT_COMMON_STYLE, DEFAULT_COMMON_ANIMATION_PROPS } from './Displayable.js';
|
3 | import PathProxy from '../core/PathProxy.js';
|
4 | import * as pathContain from '../contain/path.js';
|
5 | import { defaults, keys, extend, clone, isString, createObject } from '../core/util.js';
|
6 | import { lum } from '../tool/color.js';
|
7 | import { DARK_LABEL_COLOR, LIGHT_LABEL_COLOR, DARK_MODE_THRESHOLD, LIGHTER_LABEL_COLOR } from '../config.js';
|
8 | import { REDRAW_BIT, SHAPE_CHANGED_BIT, STYLE_CHANGED_BIT } from './constants.js';
|
9 | import { TRANSFORMABLE_PROPS } from '../core/Transformable.js';
|
10 | export var DEFAULT_PATH_STYLE = defaults({
|
11 | fill: '#000',
|
12 | stroke: null,
|
13 | strokePercent: 1,
|
14 | fillOpacity: 1,
|
15 | strokeOpacity: 1,
|
16 | lineDashOffset: 0,
|
17 | lineWidth: 1,
|
18 | lineCap: 'butt',
|
19 | miterLimit: 10,
|
20 | strokeNoScale: false,
|
21 | strokeFirst: false
|
22 | }, DEFAULT_COMMON_STYLE);
|
23 | export var DEFAULT_PATH_ANIMATION_PROPS = {
|
24 | style: defaults({
|
25 | fill: true,
|
26 | stroke: true,
|
27 | strokePercent: true,
|
28 | fillOpacity: true,
|
29 | strokeOpacity: true,
|
30 | lineDashOffset: true,
|
31 | lineWidth: true,
|
32 | miterLimit: true
|
33 | }, DEFAULT_COMMON_ANIMATION_PROPS.style)
|
34 | };
|
35 | var pathCopyParams = TRANSFORMABLE_PROPS.concat(['invisible',
|
36 | 'culling', 'z', 'z2', 'zlevel', 'parent'
|
37 | ]);
|
38 | var Path = (function (_super) {
|
39 | __extends(Path, _super);
|
40 | function Path(opts) {
|
41 | return _super.call(this, opts) || this;
|
42 | }
|
43 | Path.prototype.update = function () {
|
44 | var _this = this;
|
45 | _super.prototype.update.call(this);
|
46 | var style = this.style;
|
47 | if (style.decal) {
|
48 | var decalEl = this._decalEl = this._decalEl || new Path();
|
49 | if (decalEl.buildPath === Path.prototype.buildPath) {
|
50 | decalEl.buildPath = function (ctx) {
|
51 | _this.buildPath(ctx, _this.shape);
|
52 | };
|
53 | }
|
54 | decalEl.silent = true;
|
55 | var decalElStyle = decalEl.style;
|
56 | for (var key in style) {
|
57 | if (decalElStyle[key] !== style[key]) {
|
58 | decalElStyle[key] = style[key];
|
59 | }
|
60 | }
|
61 | decalElStyle.fill = style.fill ? style.decal : null;
|
62 | decalElStyle.decal = null;
|
63 | decalElStyle.shadowColor = null;
|
64 | style.strokeFirst && (decalElStyle.stroke = null);
|
65 | for (var i = 0; i < pathCopyParams.length; ++i) {
|
66 | decalEl[pathCopyParams[i]] = this[pathCopyParams[i]];
|
67 | }
|
68 | decalEl.__dirty |= REDRAW_BIT;
|
69 | }
|
70 | else if (this._decalEl) {
|
71 | this._decalEl = null;
|
72 | }
|
73 | };
|
74 | Path.prototype.getDecalElement = function () {
|
75 | return this._decalEl;
|
76 | };
|
77 | Path.prototype._init = function (props) {
|
78 | var keysArr = keys(props);
|
79 | this.shape = this.getDefaultShape();
|
80 | var defaultStyle = this.getDefaultStyle();
|
81 | if (defaultStyle) {
|
82 | this.useStyle(defaultStyle);
|
83 | }
|
84 | for (var i = 0; i < keysArr.length; i++) {
|
85 | var key = keysArr[i];
|
86 | var value = props[key];
|
87 | if (key === 'style') {
|
88 | if (!this.style) {
|
89 | this.useStyle(value);
|
90 | }
|
91 | else {
|
92 | extend(this.style, value);
|
93 | }
|
94 | }
|
95 | else if (key === 'shape') {
|
96 | extend(this.shape, value);
|
97 | }
|
98 | else {
|
99 | _super.prototype.attrKV.call(this, key, value);
|
100 | }
|
101 | }
|
102 | if (!this.style) {
|
103 | this.useStyle({});
|
104 | }
|
105 | };
|
106 | Path.prototype.getDefaultStyle = function () {
|
107 | return null;
|
108 | };
|
109 | Path.prototype.getDefaultShape = function () {
|
110 | return {};
|
111 | };
|
112 | Path.prototype.canBeInsideText = function () {
|
113 | return this.hasFill();
|
114 | };
|
115 | Path.prototype.getInsideTextFill = function () {
|
116 | var pathFill = this.style.fill;
|
117 | if (pathFill !== 'none') {
|
118 | if (isString(pathFill)) {
|
119 | var fillLum = lum(pathFill, 0);
|
120 | if (fillLum > 0.5) {
|
121 | return DARK_LABEL_COLOR;
|
122 | }
|
123 | else if (fillLum > 0.2) {
|
124 | return LIGHTER_LABEL_COLOR;
|
125 | }
|
126 | return LIGHT_LABEL_COLOR;
|
127 | }
|
128 | else if (pathFill) {
|
129 | return LIGHT_LABEL_COLOR;
|
130 | }
|
131 | }
|
132 | return DARK_LABEL_COLOR;
|
133 | };
|
134 | Path.prototype.getInsideTextStroke = function (textFill) {
|
135 | var pathFill = this.style.fill;
|
136 | if (isString(pathFill)) {
|
137 | var zr = this.__zr;
|
138 | var isDarkMode = !!(zr && zr.isDarkMode());
|
139 | var isDarkLabel = lum(textFill, 0) < DARK_MODE_THRESHOLD;
|
140 | if (isDarkMode === isDarkLabel) {
|
141 | return pathFill;
|
142 | }
|
143 | }
|
144 | };
|
145 | Path.prototype.buildPath = function (ctx, shapeCfg, inBatch) { };
|
146 | Path.prototype.pathUpdated = function () {
|
147 | this.__dirty &= ~SHAPE_CHANGED_BIT;
|
148 | };
|
149 | Path.prototype.getUpdatedPathProxy = function (inBatch) {
|
150 | !this.path && this.createPathProxy();
|
151 | this.path.beginPath();
|
152 | this.buildPath(this.path, this.shape, inBatch);
|
153 | return this.path;
|
154 | };
|
155 | Path.prototype.createPathProxy = function () {
|
156 | this.path = new PathProxy(false);
|
157 | };
|
158 | Path.prototype.hasStroke = function () {
|
159 | var style = this.style;
|
160 | var stroke = style.stroke;
|
161 | return !(stroke == null || stroke === 'none' || !(style.lineWidth > 0));
|
162 | };
|
163 | Path.prototype.hasFill = function () {
|
164 | var style = this.style;
|
165 | var fill = style.fill;
|
166 | return fill != null && fill !== 'none';
|
167 | };
|
168 | Path.prototype.getBoundingRect = function () {
|
169 | var rect = this._rect;
|
170 | var style = this.style;
|
171 | var needsUpdateRect = !rect;
|
172 | if (needsUpdateRect) {
|
173 | var firstInvoke = false;
|
174 | if (!this.path) {
|
175 | firstInvoke = true;
|
176 | this.createPathProxy();
|
177 | }
|
178 | var path = this.path;
|
179 | if (firstInvoke || (this.__dirty & SHAPE_CHANGED_BIT)) {
|
180 | path.beginPath();
|
181 | this.buildPath(path, this.shape, false);
|
182 | this.pathUpdated();
|
183 | }
|
184 | rect = path.getBoundingRect();
|
185 | }
|
186 | this._rect = rect;
|
187 | if (this.hasStroke() && this.path && this.path.len() > 0) {
|
188 | var rectStroke = this._rectStroke || (this._rectStroke = rect.clone());
|
189 | if (this.__dirty || needsUpdateRect) {
|
190 | rectStroke.copy(rect);
|
191 | var lineScale = style.strokeNoScale ? this.getLineScale() : 1;
|
192 | var w = style.lineWidth;
|
193 | if (!this.hasFill()) {
|
194 | var strokeContainThreshold = this.strokeContainThreshold;
|
195 | w = Math.max(w, strokeContainThreshold == null ? 4 : strokeContainThreshold);
|
196 | }
|
197 | if (lineScale > 1e-10) {
|
198 | rectStroke.width += w / lineScale;
|
199 | rectStroke.height += w / lineScale;
|
200 | rectStroke.x -= w / lineScale / 2;
|
201 | rectStroke.y -= w / lineScale / 2;
|
202 | }
|
203 | }
|
204 | return rectStroke;
|
205 | }
|
206 | return rect;
|
207 | };
|
208 | Path.prototype.contain = function (x, y) {
|
209 | var localPos = this.transformCoordToLocal(x, y);
|
210 | var rect = this.getBoundingRect();
|
211 | var style = this.style;
|
212 | x = localPos[0];
|
213 | y = localPos[1];
|
214 | if (rect.contain(x, y)) {
|
215 | var pathProxy = this.path;
|
216 | if (this.hasStroke()) {
|
217 | var lineWidth = style.lineWidth;
|
218 | var lineScale = style.strokeNoScale ? this.getLineScale() : 1;
|
219 | if (lineScale > 1e-10) {
|
220 | if (!this.hasFill()) {
|
221 | lineWidth = Math.max(lineWidth, this.strokeContainThreshold);
|
222 | }
|
223 | if (pathContain.containStroke(pathProxy, lineWidth / lineScale, x, y)) {
|
224 | return true;
|
225 | }
|
226 | }
|
227 | }
|
228 | if (this.hasFill()) {
|
229 | return pathContain.contain(pathProxy, x, y);
|
230 | }
|
231 | }
|
232 | return false;
|
233 | };
|
234 | Path.prototype.dirtyShape = function () {
|
235 | this.__dirty |= SHAPE_CHANGED_BIT;
|
236 | if (this._rect) {
|
237 | this._rect = null;
|
238 | }
|
239 | if (this._decalEl) {
|
240 | this._decalEl.dirtyShape();
|
241 | }
|
242 | this.markRedraw();
|
243 | };
|
244 | Path.prototype.dirty = function () {
|
245 | this.dirtyStyle();
|
246 | this.dirtyShape();
|
247 | };
|
248 | Path.prototype.animateShape = function (loop) {
|
249 | return this.animate('shape', loop);
|
250 | };
|
251 | Path.prototype.updateDuringAnimation = function (targetKey) {
|
252 | if (targetKey === 'style') {
|
253 | this.dirtyStyle();
|
254 | }
|
255 | else if (targetKey === 'shape') {
|
256 | this.dirtyShape();
|
257 | }
|
258 | else {
|
259 | this.markRedraw();
|
260 | }
|
261 | };
|
262 | Path.prototype.attrKV = function (key, value) {
|
263 | if (key === 'shape') {
|
264 | this.setShape(value);
|
265 | }
|
266 | else {
|
267 | _super.prototype.attrKV.call(this, key, value);
|
268 | }
|
269 | };
|
270 | Path.prototype.setShape = function (keyOrObj, value) {
|
271 | var shape = this.shape;
|
272 | if (!shape) {
|
273 | shape = this.shape = {};
|
274 | }
|
275 | if (typeof keyOrObj === 'string') {
|
276 | shape[keyOrObj] = value;
|
277 | }
|
278 | else {
|
279 | extend(shape, keyOrObj);
|
280 | }
|
281 | this.dirtyShape();
|
282 | return this;
|
283 | };
|
284 | Path.prototype.shapeChanged = function () {
|
285 | return !!(this.__dirty & SHAPE_CHANGED_BIT);
|
286 | };
|
287 | Path.prototype.createStyle = function (obj) {
|
288 | return createObject(DEFAULT_PATH_STYLE, obj);
|
289 | };
|
290 | Path.prototype._innerSaveToNormal = function (toState) {
|
291 | _super.prototype._innerSaveToNormal.call(this, toState);
|
292 | var normalState = this._normalState;
|
293 | if (toState.shape && !normalState.shape) {
|
294 | normalState.shape = extend({}, this.shape);
|
295 | }
|
296 | };
|
297 | Path.prototype._applyStateObj = function (stateName, state, normalState, keepCurrentStates, transition, animationCfg) {
|
298 | _super.prototype._applyStateObj.call(this, stateName, state, normalState, keepCurrentStates, transition, animationCfg);
|
299 | var needsRestoreToNormal = !(state && keepCurrentStates);
|
300 | var targetShape;
|
301 | if (state && state.shape) {
|
302 | if (transition) {
|
303 | if (keepCurrentStates) {
|
304 | targetShape = state.shape;
|
305 | }
|
306 | else {
|
307 | targetShape = extend({}, normalState.shape);
|
308 | extend(targetShape, state.shape);
|
309 | }
|
310 | }
|
311 | else {
|
312 | targetShape = extend({}, keepCurrentStates ? this.shape : normalState.shape);
|
313 | extend(targetShape, state.shape);
|
314 | }
|
315 | }
|
316 | else if (needsRestoreToNormal) {
|
317 | targetShape = normalState.shape;
|
318 | }
|
319 | if (targetShape) {
|
320 | if (transition) {
|
321 | this.shape = extend({}, this.shape);
|
322 | var targetShapePrimaryProps = {};
|
323 | var shapeKeys = keys(targetShape);
|
324 | for (var i = 0; i < shapeKeys.length; i++) {
|
325 | var key = shapeKeys[i];
|
326 | if (typeof targetShape[key] === 'object') {
|
327 | this.shape[key] = targetShape[key];
|
328 | }
|
329 | else {
|
330 | targetShapePrimaryProps[key] = targetShape[key];
|
331 | }
|
332 | }
|
333 | this._transitionState(stateName, {
|
334 | shape: targetShapePrimaryProps
|
335 | }, animationCfg);
|
336 | }
|
337 | else {
|
338 | this.shape = targetShape;
|
339 | this.dirtyShape();
|
340 | }
|
341 | }
|
342 | };
|
343 | Path.prototype._mergeStates = function (states) {
|
344 | var mergedState = _super.prototype._mergeStates.call(this, states);
|
345 | var mergedShape;
|
346 | for (var i = 0; i < states.length; i++) {
|
347 | var state = states[i];
|
348 | if (state.shape) {
|
349 | mergedShape = mergedShape || {};
|
350 | this._mergeStyle(mergedShape, state.shape);
|
351 | }
|
352 | }
|
353 | if (mergedShape) {
|
354 | mergedState.shape = mergedShape;
|
355 | }
|
356 | return mergedState;
|
357 | };
|
358 | Path.prototype.getAnimationStyleProps = function () {
|
359 | return DEFAULT_PATH_ANIMATION_PROPS;
|
360 | };
|
361 | Path.prototype.isZeroArea = function () {
|
362 | return false;
|
363 | };
|
364 | Path.extend = function (defaultProps) {
|
365 | var Sub = (function (_super) {
|
366 | __extends(Sub, _super);
|
367 | function Sub(opts) {
|
368 | var _this = _super.call(this, opts) || this;
|
369 | defaultProps.init && defaultProps.init.call(_this, opts);
|
370 | return _this;
|
371 | }
|
372 | Sub.prototype.getDefaultStyle = function () {
|
373 | return clone(defaultProps.style);
|
374 | };
|
375 | Sub.prototype.getDefaultShape = function () {
|
376 | return clone(defaultProps.shape);
|
377 | };
|
378 | return Sub;
|
379 | }(Path));
|
380 | for (var key in defaultProps) {
|
381 | if (typeof defaultProps[key] === 'function') {
|
382 | Sub.prototype[key] = defaultProps[key];
|
383 | }
|
384 | }
|
385 | return Sub;
|
386 | };
|
387 | Path.initDefaultProps = (function () {
|
388 | var pathProto = Path.prototype;
|
389 | pathProto.type = 'path';
|
390 | pathProto.strokeContainThreshold = 5;
|
391 | pathProto.segmentIgnoreThreshold = 0;
|
392 | pathProto.subPixelOptimize = false;
|
393 | pathProto.autoBatch = false;
|
394 | pathProto.__dirty = REDRAW_BIT | STYLE_CHANGED_BIT | SHAPE_CHANGED_BIT;
|
395 | })();
|
396 | return Path;
|
397 | }(Displayable));
|
398 | export default Path;
|