UNPKG

14.1 kBJavaScriptView Raw
1import { __extends } from "tslib";
2import Displayable, { DEFAULT_COMMON_STYLE, DEFAULT_COMMON_ANIMATION_PROPS } from './Displayable.js';
3import PathProxy from '../core/PathProxy.js';
4import * as pathContain from '../contain/path.js';
5import { defaults, keys, extend, clone, isString, createObject } from '../core/util.js';
6import { lum } from '../tool/color.js';
7import { DARK_LABEL_COLOR, LIGHT_LABEL_COLOR, DARK_MODE_THRESHOLD, LIGHTER_LABEL_COLOR } from '../config.js';
8import { REDRAW_BIT, SHAPE_CHANGED_BIT, STYLE_CHANGED_BIT } from './constants.js';
9import { TRANSFORMABLE_PROPS } from '../core/Transformable.js';
10export 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);
23export 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};
35var pathCopyParams = TRANSFORMABLE_PROPS.concat(['invisible',
36 'culling', 'z', 'z2', 'zlevel', 'parent'
37]);
38var 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));
398export default Path;