jmgraph 3.2.27 → 3.2.28
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/jmgraph.core.min.js +1 -1
- package/dist/jmgraph.core.min.js.map +1 -1
- package/dist/jmgraph.js +2661 -415
- package/dist/jmgraph.min.js +1 -1
- package/package.json +1 -1
- package/src/core/jmControl.js +827 -127
- package/src/core/jmEvents.js +154 -0
- package/src/core/jmFilter.js +38 -1
- package/src/core/jmGradient.js +47 -2
- package/src/core/jmGraph.js +51 -7
- package/src/core/jmLayer.js +34 -2
- package/src/core/jmList.js +167 -0
- package/src/core/jmObject.js +128 -8
- package/src/core/jmPath.js +43 -5
- package/src/core/jmProperty.js +181 -2
- package/src/core/jmShadow.js +36 -7
- package/src/core/jmUtils.js +149 -12
- package/src/lib/webgl/base.js +211 -83
- package/src/lib/webgl/core/buffer.js +43 -12
- package/src/lib/webgl/core/mapSize.js +16 -7
- package/src/lib/webgl/core/mapType.js +41 -22
- package/src/lib/webgl/core/program.js +94 -54
- package/src/lib/webgl/core/shader.js +20 -8
- package/src/lib/webgl/core/texture.js +55 -32
- package/src/lib/webgl/gradient.js +49 -17
- package/src/lib/webgl/index.js +173 -24
- package/src/lib/webgl/path.js +61 -12
- package/src/shapes/jmArc.js +48 -2
- package/src/shapes/jmArrow.js +35 -2
- package/src/shapes/jmArrowLine.js +33 -2
- package/src/shapes/jmBezier.js +50 -4
- package/src/shapes/jmCircle.js +35 -2
- package/src/shapes/jmEllipse.js +29 -3
- package/src/shapes/jmHArc.js +39 -2
- package/src/shapes/jmImage.js +49 -3
- package/src/shapes/jmLabel.js +41 -2
- package/src/shapes/jmLine.js +42 -2
- package/src/shapes/jmPolygon.js +42 -3
- package/src/shapes/jmPrismatic.js +34 -2
- package/src/shapes/jmRect.js +45 -3
- package/src/shapes/jmResize.js +42 -4
- package/src/shapes/jmStar.js +38 -4
package/src/core/jmControl.js
CHANGED
|
@@ -1,4 +1,22 @@
|
|
|
1
1
|
|
|
2
|
+
/**
|
|
3
|
+
* @fileoverview jmGraph 控件基类
|
|
4
|
+
*
|
|
5
|
+
* jmControl 是 jmGraph 库中所有可视化控件的基类,继承自 jmProperty。
|
|
6
|
+
* 提供了完整的控件生命周期管理:
|
|
7
|
+
* - 样式系统:支持填充、描边、阴影、渐变、滤镜等
|
|
8
|
+
* - 变换系统:支持平移、旋转、缩放
|
|
9
|
+
* - 事件系统:支持鼠标、键盘、触摸事件
|
|
10
|
+
* - 渲染系统:支持 Canvas 2D 和 WebGL 双渲染模式
|
|
11
|
+
* - 层级管理:支持 zIndex 排序和父子关系
|
|
12
|
+
* - 碰撞检测:支持点击测试和命中区域
|
|
13
|
+
*
|
|
14
|
+
* @module jmControl
|
|
15
|
+
* @extends jmProperty
|
|
16
|
+
* @author jmGraph Team
|
|
17
|
+
* @license MIT
|
|
18
|
+
*/
|
|
19
|
+
|
|
2
20
|
import {jmUtils} from "./jmUtils.js";
|
|
3
21
|
import {jmList} from "./jmList.js";
|
|
4
22
|
import {jmGradient} from "./jmGradient.js";
|
|
@@ -7,51 +25,164 @@ import {jmFilter} from "./jmFilter.js";
|
|
|
7
25
|
import {jmProperty} from "./jmProperty.js";
|
|
8
26
|
import WebglPath from "../lib/webgl/path.js";
|
|
9
27
|
|
|
28
|
+
/**
|
|
29
|
+
* 样式名称映射表
|
|
30
|
+
*
|
|
31
|
+
* 将简化的样式名称映射到 Canvas API 的标准属性名。
|
|
32
|
+
* 例如:'fill' -> 'fillStyle', 'stroke' -> 'strokeStyle'
|
|
33
|
+
*
|
|
34
|
+
* @constant {Object.<string, string>}
|
|
35
|
+
* @private
|
|
36
|
+
*/
|
|
10
37
|
const jmStyleMap = {
|
|
11
|
-
'fill':'fillStyle',
|
|
12
|
-
'fillImage':'fillImage',
|
|
13
|
-
'stroke':'strokeStyle',
|
|
14
|
-
'shadow.blur':'shadowBlur',
|
|
15
|
-
'shadow.x':'shadowOffsetX',
|
|
16
|
-
'shadow.y':'shadowOffsetY',
|
|
17
|
-
'shadow.color':'shadowColor',
|
|
18
|
-
'lineWidth' : 'lineWidth',
|
|
19
|
-
'miterLimit': 'miterLimit',
|
|
20
|
-
'fillStyle' : 'fillStyle',
|
|
21
|
-
'strokeStyle' : 'strokeStyle'
|
|
22
|
-
'font' : 'font',
|
|
23
|
-
'opacity' : 'globalAlpha',
|
|
24
|
-
'textAlign' : 'textAlign',
|
|
25
|
-
'textBaseline' : 'textBaseline',
|
|
26
|
-
'shadowBlur' : 'shadowBlur',
|
|
27
|
-
'shadowOffsetX' : 'shadowOffsetX',
|
|
28
|
-
'shadowOffsetY' : 'shadowOffsetY',
|
|
29
|
-
'shadowColor' : 'shadowColor',
|
|
30
|
-
'lineJoin': 'lineJoin',
|
|
31
|
-
'lineCap':'lineCap',
|
|
32
|
-
'lineDashOffset': 'lineDashOffset',
|
|
33
|
-
'globalCompositeOperation': 'globalCompositeOperation'
|
|
38
|
+
'fill':'fillStyle', // 填充颜色
|
|
39
|
+
'fillImage':'fillImage', // 填充图片
|
|
40
|
+
'stroke':'strokeStyle', // 描边颜色
|
|
41
|
+
'shadow.blur':'shadowBlur', // 阴影模糊度
|
|
42
|
+
'shadow.x':'shadowOffsetX', // 阴影X偏移
|
|
43
|
+
'shadow.y':'shadowOffsetY', // 阴影Y偏移
|
|
44
|
+
'shadow.color':'shadowColor', // 阴影颜色
|
|
45
|
+
'lineWidth' : 'lineWidth', // 线宽
|
|
46
|
+
'miterLimit': 'miterLimit', // 斜接限制
|
|
47
|
+
'fillStyle' : 'fillStyle', // 填充样式
|
|
48
|
+
'strokeStyle' : 'strokeStyle',// 描边样式
|
|
49
|
+
'font' : 'font', // 字体
|
|
50
|
+
'opacity' : 'globalAlpha', // 透明度
|
|
51
|
+
'textAlign' : 'textAlign', // 文本对齐
|
|
52
|
+
'textBaseline' : 'textBaseline', // 文本基线
|
|
53
|
+
'shadowBlur' : 'shadowBlur', // 阴影模糊
|
|
54
|
+
'shadowOffsetX' : 'shadowOffsetX', // 阴影X偏移
|
|
55
|
+
'shadowOffsetY' : 'shadowOffsetY', // 阴影Y偏移
|
|
56
|
+
'shadowColor' : 'shadowColor', // 阴影颜色
|
|
57
|
+
'lineJoin': 'lineJoin', // 线条连接样式
|
|
58
|
+
'lineCap':'lineCap', // 线条端点样式
|
|
59
|
+
'lineDashOffset': 'lineDashOffset', // 虚线偏移
|
|
60
|
+
'globalCompositeOperation': 'globalCompositeOperation' // 合成操作
|
|
34
61
|
};
|
|
35
62
|
|
|
63
|
+
/**
|
|
64
|
+
* jmGraph 控件基类
|
|
65
|
+
*
|
|
66
|
+
* jmControl 是所有可视化图形控件的基类,提供了完整的图形渲染和交互能力。
|
|
67
|
+
*
|
|
68
|
+
* **核心功能:**
|
|
69
|
+
*
|
|
70
|
+
* 1. **样式系统**
|
|
71
|
+
* - 支持填充色、描边色、渐变、图片填充
|
|
72
|
+
* - 支持阴影、滤镜、混合模式
|
|
73
|
+
* - 支持虚线、线宽、线帽等线条样式
|
|
74
|
+
*
|
|
75
|
+
* 2. **变换系统**
|
|
76
|
+
* - 支持 translate(平移)
|
|
77
|
+
* - 支持 rotation(旋转)
|
|
78
|
+
* - 支持 transform(矩阵变换)
|
|
79
|
+
*
|
|
80
|
+
* 3. **事件系统**
|
|
81
|
+
* - 鼠标事件:mousedown, mouseup, mousemove, click, dblclick
|
|
82
|
+
* - 触摸事件:touchstart, touchmove, touchend
|
|
83
|
+
* - 焦点事件:mouseover, mouseleave, touchover, touchleave
|
|
84
|
+
* - 自定义事件:支持任意事件类型
|
|
85
|
+
*
|
|
86
|
+
* 4. **渲染系统**
|
|
87
|
+
* - 自动选择 Canvas 2D 或 WebGL 渲染器
|
|
88
|
+
* - 支持脏矩形优化
|
|
89
|
+
* - 支持层级排序(zIndex)
|
|
90
|
+
*
|
|
91
|
+
* 5. **碰撞检测**
|
|
92
|
+
* - 支持点在多边形内判断
|
|
93
|
+
* - 支持自定义命中区域
|
|
94
|
+
* - 支持旋转后的碰撞检测
|
|
95
|
+
*
|
|
96
|
+
* @class jmControl
|
|
97
|
+
* @extends jmProperty
|
|
98
|
+
*
|
|
99
|
+
* @example
|
|
100
|
+
* // 创建自定义控件
|
|
101
|
+
* class MyShape extends jmControl {
|
|
102
|
+
* constructor(params) {
|
|
103
|
+
* super(params, 'myShape');
|
|
104
|
+
* }
|
|
105
|
+
*
|
|
106
|
+
* // 重写绘制方法
|
|
107
|
+
* draw() {
|
|
108
|
+
* // 自定义绘制逻辑
|
|
109
|
+
* }
|
|
110
|
+
* }
|
|
111
|
+
*
|
|
112
|
+
* // 使用控件
|
|
113
|
+
* const shape = new MyShape({
|
|
114
|
+
* position: { x: 100, y: 100 },
|
|
115
|
+
* width: 50,
|
|
116
|
+
* height: 50,
|
|
117
|
+
* style: {
|
|
118
|
+
* fill: 'red',
|
|
119
|
+
* stroke: 'black',
|
|
120
|
+
* lineWidth: 2
|
|
121
|
+
* }
|
|
122
|
+
* });
|
|
123
|
+
* graph.children.add(shape);
|
|
124
|
+
*/
|
|
36
125
|
export default class jmControl extends jmProperty {
|
|
37
126
|
|
|
127
|
+
/**
|
|
128
|
+
* 构造函数
|
|
129
|
+
*
|
|
130
|
+
* 创建一个新的控件实例。子类应该调用 super(params, 'typeName') 来设置类型名称。
|
|
131
|
+
*
|
|
132
|
+
* @constructor
|
|
133
|
+
* @param {Object} [params] - 控件初始化参数
|
|
134
|
+
* @param {Object} [params.style] - 样式对象,包含填充、描边等属性
|
|
135
|
+
* @param {number} [params.width=0] - 控件宽度
|
|
136
|
+
* @param {number} [params.height=0] - 控件高度
|
|
137
|
+
* @param {Object} [params.position] - 控件位置 {x, y}
|
|
138
|
+
* @param {jmGraph} [params.graph] - 所属画布实例
|
|
139
|
+
* @param {number} [params.zIndex=0] - 层级顺序
|
|
140
|
+
* @param {boolean} [params.interactive=false] - 是否响应交互事件
|
|
141
|
+
* @param {Object} [params.hitArea] - 自定义命中区域 {x, y, width, height}
|
|
142
|
+
* @param {boolean} [params.isRegular] - 是否为规则图形(WebGL优化)
|
|
143
|
+
* @param {boolean} [params.needCut] - 是否需要裁剪(WebGL)
|
|
144
|
+
* @param {string} [t] - 控件类型名称,默认使用类名
|
|
145
|
+
*
|
|
146
|
+
* @example
|
|
147
|
+
* // 创建矩形控件
|
|
148
|
+
* const rect = new jmControl({
|
|
149
|
+
* position: { x: 10, y: 10 },
|
|
150
|
+
* width: 100,
|
|
151
|
+
* height: 50,
|
|
152
|
+
* style: {
|
|
153
|
+
* fill: '#ff0000',
|
|
154
|
+
* stroke: '#000000',
|
|
155
|
+
* lineWidth: 2
|
|
156
|
+
* },
|
|
157
|
+
* interactive: true
|
|
158
|
+
* }, 'jmRect');
|
|
159
|
+
*/
|
|
38
160
|
constructor(params, t) {
|
|
39
161
|
params = params||{};
|
|
40
162
|
super(params);
|
|
163
|
+
// 设置控件类型标识
|
|
41
164
|
this.property('type', t || new.target.name);
|
|
165
|
+
// 初始化样式对象
|
|
42
166
|
this.style = params && params.style ? params.style : {};
|
|
167
|
+
// 设置尺寸
|
|
43
168
|
this.width = params.width || 0;
|
|
44
169
|
this.height = params.height || 0;
|
|
170
|
+
// 自定义命中区域(用于点击测试)
|
|
45
171
|
this.hitArea = params.hitArea || null;
|
|
46
172
|
|
|
173
|
+
// 设置位置
|
|
47
174
|
if(params.position) {
|
|
48
175
|
this.position = params.position;
|
|
49
176
|
}
|
|
50
177
|
|
|
178
|
+
// 关联画布
|
|
51
179
|
this.graph = params.graph || null;
|
|
180
|
+
// 层级顺序(用于排序)
|
|
52
181
|
this.zIndex = params.zIndex || 0;
|
|
182
|
+
// 是否响应交互事件
|
|
53
183
|
this.interactive = typeof params.interactive == 'undefined'? false : params.interactive;
|
|
54
184
|
|
|
185
|
+
// WebGL 模式下创建对应的渲染控制器
|
|
55
186
|
if(this.mode === 'webgl') {
|
|
56
187
|
this.webglControl = new WebglPath(this.graph, {
|
|
57
188
|
style: this.style,
|
|
@@ -61,17 +192,47 @@ export default class jmControl extends jmProperty {
|
|
|
61
192
|
});
|
|
62
193
|
}
|
|
63
194
|
|
|
195
|
+
// 执行初始化
|
|
64
196
|
this.initializing();
|
|
65
197
|
|
|
198
|
+
// 别名:on 等同于 bind
|
|
66
199
|
this.on = this.bind;
|
|
67
200
|
|
|
201
|
+
// 保存原始参数
|
|
68
202
|
this.option = params;
|
|
69
203
|
}
|
|
70
204
|
|
|
205
|
+
/**
|
|
206
|
+
* 控件类型标识
|
|
207
|
+
*
|
|
208
|
+
* 用于类型检查和调试,由构造函数自动设置。
|
|
209
|
+
*
|
|
210
|
+
* @type {string}
|
|
211
|
+
* @readonly
|
|
212
|
+
*
|
|
213
|
+
* @example
|
|
214
|
+
* console.log(rect.type); // 'jmRect'
|
|
215
|
+
* if(control.type === 'jmCircle') { ... }
|
|
216
|
+
*/
|
|
71
217
|
get type() {
|
|
72
218
|
return this.property('type');
|
|
73
219
|
}
|
|
74
220
|
|
|
221
|
+
/**
|
|
222
|
+
* 绘图上下文
|
|
223
|
+
*
|
|
224
|
+
* 获取当前控件的 Canvas 2D 或 WebGL 渲染上下文。
|
|
225
|
+
* 如果控件本身不是 jmGraph,会返回所属 graph 的上下文。
|
|
226
|
+
*
|
|
227
|
+
* @type {CanvasRenderingContext2D|WebGLRenderingContext}
|
|
228
|
+
* @readonly
|
|
229
|
+
*
|
|
230
|
+
* @example
|
|
231
|
+
* // 获取上下文并绘制
|
|
232
|
+
* const ctx = control.context;
|
|
233
|
+
* ctx.fillStyle = 'red';
|
|
234
|
+
* ctx.fillRect(0, 0, 100, 100);
|
|
235
|
+
*/
|
|
75
236
|
get context() {
|
|
76
237
|
let s = this.property('context');
|
|
77
238
|
if(s) return s;
|
|
@@ -86,6 +247,35 @@ export default class jmControl extends jmProperty {
|
|
|
86
247
|
return this.property('context', v);
|
|
87
248
|
}
|
|
88
249
|
|
|
250
|
+
/**
|
|
251
|
+
* 样式对象
|
|
252
|
+
*
|
|
253
|
+
* 控件的视觉样式配置,包括:
|
|
254
|
+
* - fill: 填充颜色或渐变
|
|
255
|
+
* - stroke: 描边颜色
|
|
256
|
+
* - lineWidth: 线宽
|
|
257
|
+
* - shadow: 阴影配置
|
|
258
|
+
* - font: 字体(文本控件)
|
|
259
|
+
* - opacity: 透明度
|
|
260
|
+
*
|
|
261
|
+
* 设置新样式会触发 needUpdate。
|
|
262
|
+
*
|
|
263
|
+
* @type {Object}
|
|
264
|
+
*
|
|
265
|
+
* @example
|
|
266
|
+
* // 设置样式
|
|
267
|
+
* control.style = {
|
|
268
|
+
* fill: '#ff0000',
|
|
269
|
+
* stroke: '#000000',
|
|
270
|
+
* lineWidth: 2,
|
|
271
|
+
* shadow: {
|
|
272
|
+
* blur: 10,
|
|
273
|
+
* x: 5,
|
|
274
|
+
* y: 5,
|
|
275
|
+
* color: 'rgba(0,0,0,0.5)'
|
|
276
|
+
* }
|
|
277
|
+
* };
|
|
278
|
+
*/
|
|
89
279
|
get style() {
|
|
90
280
|
let s = this.property('style');
|
|
91
281
|
if(!s) s = this.property('style', {});
|
|
@@ -96,6 +286,22 @@ export default class jmControl extends jmProperty {
|
|
|
96
286
|
return this.property('style', v);
|
|
97
287
|
}
|
|
98
288
|
|
|
289
|
+
/**
|
|
290
|
+
* 是否可见
|
|
291
|
+
*
|
|
292
|
+
* 控制控件是否参与渲染和事件响应。
|
|
293
|
+
* 不可见的控件不会被绘制,也不会响应鼠标/触摸事件。
|
|
294
|
+
*
|
|
295
|
+
* @type {boolean}
|
|
296
|
+
* @default true
|
|
297
|
+
*
|
|
298
|
+
* @example
|
|
299
|
+
* // 隐藏控件
|
|
300
|
+
* control.visible = false;
|
|
301
|
+
*
|
|
302
|
+
* // 显示控件
|
|
303
|
+
* control.visible = true;
|
|
304
|
+
*/
|
|
99
305
|
get visible() {
|
|
100
306
|
let s = this.property('visible');
|
|
101
307
|
if(typeof s == 'undefined') s = this.property('visible', true);
|
|
@@ -106,6 +312,22 @@ export default class jmControl extends jmProperty {
|
|
|
106
312
|
return this.property('visible', v);
|
|
107
313
|
}
|
|
108
314
|
|
|
315
|
+
/**
|
|
316
|
+
* 是否响应交互事件
|
|
317
|
+
*
|
|
318
|
+
* 设置为 true 时,控件会响应鼠标和触摸事件。
|
|
319
|
+
* 设置为 false 时,事件会穿透到下层控件。
|
|
320
|
+
*
|
|
321
|
+
* @type {boolean}
|
|
322
|
+
* @default false
|
|
323
|
+
*
|
|
324
|
+
* @example
|
|
325
|
+
* // 启用交互
|
|
326
|
+
* control.interactive = true;
|
|
327
|
+
* control.bind('click', (evt) => {
|
|
328
|
+
* console.log('clicked!');
|
|
329
|
+
* });
|
|
330
|
+
*/
|
|
109
331
|
get interactive() {
|
|
110
332
|
const s = this.property('interactive');
|
|
111
333
|
return s;
|
|
@@ -114,6 +336,23 @@ export default class jmControl extends jmProperty {
|
|
|
114
336
|
return this.property('interactive', v);
|
|
115
337
|
}
|
|
116
338
|
|
|
339
|
+
/**
|
|
340
|
+
* 自定义命中区域
|
|
341
|
+
*
|
|
342
|
+
* 用于点击测试的自定义区域,格式为 {x, y, width, height}。
|
|
343
|
+
* 如果设置,点击测试会使用此区域而非实际图形边界。
|
|
344
|
+
*
|
|
345
|
+
* @type {Object|null}
|
|
346
|
+
*
|
|
347
|
+
* @example
|
|
348
|
+
* // 设置更大的点击区域
|
|
349
|
+
* control.hitArea = {
|
|
350
|
+
* x: -10,
|
|
351
|
+
* y: -10,
|
|
352
|
+
* width: control.width + 20,
|
|
353
|
+
* height: control.height + 20
|
|
354
|
+
* };
|
|
355
|
+
*/
|
|
117
356
|
get hitArea() {
|
|
118
357
|
const s = this.property('hitArea');
|
|
119
358
|
return s;
|
|
@@ -122,6 +361,26 @@ export default class jmControl extends jmProperty {
|
|
|
122
361
|
return this.property('hitArea', v);
|
|
123
362
|
}
|
|
124
363
|
|
|
364
|
+
/**
|
|
365
|
+
* 子控件列表
|
|
366
|
+
*
|
|
367
|
+
* 当前控件的所有子控件。子控件会按 zIndex 排序后绘制。
|
|
368
|
+
* 添加子控件时会自动建立父子关系。
|
|
369
|
+
*
|
|
370
|
+
* @type {jmList}
|
|
371
|
+
*
|
|
372
|
+
* @example
|
|
373
|
+
* // 添加子控件
|
|
374
|
+
* parent.children.add(child);
|
|
375
|
+
*
|
|
376
|
+
* // 移除子控件
|
|
377
|
+
* parent.children.remove(child);
|
|
378
|
+
*
|
|
379
|
+
* // 遍历子控件
|
|
380
|
+
* parent.children.each((i, child) => {
|
|
381
|
+
* console.log(child);
|
|
382
|
+
* });
|
|
383
|
+
*/
|
|
125
384
|
get children() {
|
|
126
385
|
let s = this.property('children');
|
|
127
386
|
if(!s) s = this.property('children', new jmList());
|
|
@@ -132,6 +391,21 @@ export default class jmControl extends jmProperty {
|
|
|
132
391
|
return this.property('children', v);
|
|
133
392
|
}
|
|
134
393
|
|
|
394
|
+
/**
|
|
395
|
+
* 控件宽度
|
|
396
|
+
*
|
|
397
|
+
* 可以是具体数值或百分比字符串(如 '50%')。
|
|
398
|
+
* 百分比会相对于父容器宽度计算。
|
|
399
|
+
*
|
|
400
|
+
* @type {number|string}
|
|
401
|
+
*
|
|
402
|
+
* @example
|
|
403
|
+
* // 设置固定宽度
|
|
404
|
+
* control.width = 100;
|
|
405
|
+
*
|
|
406
|
+
* // 设置百分比宽度
|
|
407
|
+
* control.width = '50%';
|
|
408
|
+
*/
|
|
135
409
|
get width() {
|
|
136
410
|
let s = this.property('width');
|
|
137
411
|
if(typeof s == 'undefined') s = this.property('width', 0);
|
|
@@ -142,6 +416,21 @@ export default class jmControl extends jmProperty {
|
|
|
142
416
|
return this.property('width', v);
|
|
143
417
|
}
|
|
144
418
|
|
|
419
|
+
/**
|
|
420
|
+
* 控件高度
|
|
421
|
+
*
|
|
422
|
+
* 可以是具体数值或百分比字符串(如 '50%')。
|
|
423
|
+
* 百分比会相对于父容器高度计算。
|
|
424
|
+
*
|
|
425
|
+
* @type {number|string}
|
|
426
|
+
*
|
|
427
|
+
* @example
|
|
428
|
+
* // 设置固定高度
|
|
429
|
+
* control.height = 100;
|
|
430
|
+
*
|
|
431
|
+
* // 设置百分比高度
|
|
432
|
+
* control.height = '50%';
|
|
433
|
+
*/
|
|
145
434
|
get height() {
|
|
146
435
|
let s = this.property('height');
|
|
147
436
|
if(typeof s == 'undefined') s = this.property('height', 0);
|
|
@@ -152,6 +441,22 @@ export default class jmControl extends jmProperty {
|
|
|
152
441
|
return this.property('height', v);
|
|
153
442
|
}
|
|
154
443
|
|
|
444
|
+
/**
|
|
445
|
+
* 层级顺序
|
|
446
|
+
*
|
|
447
|
+
* 控制控件的绘制顺序,值越大越靠上。
|
|
448
|
+
* 设置 zIndex 会触发子控件重新排序。
|
|
449
|
+
*
|
|
450
|
+
* @type {number}
|
|
451
|
+
* @default 0
|
|
452
|
+
*
|
|
453
|
+
* @example
|
|
454
|
+
* // 将控件置于最上层
|
|
455
|
+
* control.zIndex = 100;
|
|
456
|
+
*
|
|
457
|
+
* // 将控件置于最下层
|
|
458
|
+
* control.zIndex = -1;
|
|
459
|
+
*/
|
|
155
460
|
get zIndex() {
|
|
156
461
|
let s = this.property('zIndex');
|
|
157
462
|
if(!s) s = this.property('zIndex', 0);
|
|
@@ -164,6 +469,21 @@ export default class jmControl extends jmProperty {
|
|
|
164
469
|
return v;
|
|
165
470
|
}
|
|
166
471
|
|
|
472
|
+
/**
|
|
473
|
+
* 鼠标样式
|
|
474
|
+
*
|
|
475
|
+
* 鼠标悬停在控件上时显示的光标样式。
|
|
476
|
+
* 常用值:'default', 'pointer', 'move', 'text', 'crosshair'
|
|
477
|
+
*
|
|
478
|
+
* @type {string}
|
|
479
|
+
*
|
|
480
|
+
* @example
|
|
481
|
+
* // 设置为手型指针
|
|
482
|
+
* control.cursor = 'pointer';
|
|
483
|
+
*
|
|
484
|
+
* // 设置为移动样式
|
|
485
|
+
* control.cursor = 'move';
|
|
486
|
+
*/
|
|
167
487
|
set cursor(cur) {
|
|
168
488
|
const graph = this.graph;
|
|
169
489
|
if(graph) {
|
|
@@ -177,18 +497,35 @@ export default class jmControl extends jmProperty {
|
|
|
177
497
|
}
|
|
178
498
|
}
|
|
179
499
|
|
|
500
|
+
/**
|
|
501
|
+
* 初始化控件
|
|
502
|
+
*
|
|
503
|
+
* 在构造函数末尾调用,用于设置子控件管理逻辑。
|
|
504
|
+
* 重写了 children 的 add、remove、sort、clear 方法,
|
|
505
|
+
* 实现自动的父子关系维护和脏标记传播。
|
|
506
|
+
*
|
|
507
|
+
* @method initializing
|
|
508
|
+
* @protected
|
|
509
|
+
*/
|
|
180
510
|
initializing() {
|
|
181
511
|
|
|
182
512
|
const self = this;
|
|
183
513
|
this.children = this.children || new jmList();
|
|
184
514
|
const oadd = this.children.add;
|
|
185
515
|
|
|
516
|
+
/**
|
|
517
|
+
* 重写 add 方法,自动建立父子关系
|
|
518
|
+
* @param {jmControl} obj - 要添加的子控件
|
|
519
|
+
* @returns {jmControl} 添加的子控件
|
|
520
|
+
*/
|
|
186
521
|
this.children.add = function(obj) {
|
|
187
522
|
if(typeof obj === 'object') {
|
|
523
|
+
// 如果对象已有父级,先从原父级移除
|
|
188
524
|
if(obj.parent && obj.parent != self && obj.parent.children) {
|
|
189
525
|
obj.parent.children.remove(obj);
|
|
190
526
|
}
|
|
191
527
|
obj.parent = self;
|
|
528
|
+
// 如果已存在,先移除再添加
|
|
192
529
|
if(this.contain(obj)) {
|
|
193
530
|
this.oremove(obj);
|
|
194
531
|
}
|
|
@@ -196,6 +533,7 @@ export default class jmControl extends jmProperty {
|
|
|
196
533
|
obj.emit('add', obj);
|
|
197
534
|
|
|
198
535
|
self.needUpdate = true;
|
|
536
|
+
// 传播 graph 引用
|
|
199
537
|
if(self.graph) obj.graph = self.graph;
|
|
200
538
|
this.sort();
|
|
201
539
|
return obj;
|
|
@@ -203,6 +541,10 @@ export default class jmControl extends jmProperty {
|
|
|
203
541
|
};
|
|
204
542
|
this.children.oremove= this.children.remove;
|
|
205
543
|
|
|
544
|
+
/**
|
|
545
|
+
* 重写 remove 方法,清理父子关系
|
|
546
|
+
* @param {jmControl} obj - 要移除的子控件
|
|
547
|
+
*/
|
|
206
548
|
this.children.remove = function(obj) {
|
|
207
549
|
if(typeof obj === 'object') {
|
|
208
550
|
obj.parent = null;
|
|
@@ -213,6 +555,9 @@ export default class jmControl extends jmProperty {
|
|
|
213
555
|
}
|
|
214
556
|
};
|
|
215
557
|
|
|
558
|
+
/**
|
|
559
|
+
* 按 zIndex 排序子控件
|
|
560
|
+
*/
|
|
216
561
|
this.children.sort = function() {
|
|
217
562
|
const levelItems = {};
|
|
218
563
|
this.each(function(i, obj) {
|
|
@@ -232,6 +577,10 @@ export default class jmControl extends jmProperty {
|
|
|
232
577
|
oadd.call(this, levelItems[index]);
|
|
233
578
|
}
|
|
234
579
|
}
|
|
580
|
+
|
|
581
|
+
/**
|
|
582
|
+
* 清空所有子控件
|
|
583
|
+
*/
|
|
235
584
|
this.children.clear = function() {
|
|
236
585
|
this.each(function(i,obj) {
|
|
237
586
|
this.remove(obj);
|
|
@@ -240,15 +589,55 @@ export default class jmControl extends jmProperty {
|
|
|
240
589
|
this.needUpdate = true;
|
|
241
590
|
}
|
|
242
591
|
|
|
592
|
+
/**
|
|
593
|
+
* 设置控件样式到绘图上下文
|
|
594
|
+
*
|
|
595
|
+
* 将样式对象应用到 Canvas 上下文,支持:
|
|
596
|
+
* - 基础样式:fill, stroke, lineWidth, opacity 等
|
|
597
|
+
* - 阴影效果:shadow.blur, shadow.x, shadow.y, shadow.color
|
|
598
|
+
* - 渐变填充:支持线性渐变和径向渐变
|
|
599
|
+
* - 变换效果:rotation(旋转)、translate(平移)、transform(矩阵变换)
|
|
600
|
+
* - 高级效果:lineDash(虚线)、filter(滤镜)、clipPath(裁剪)、mask(遮罩)
|
|
601
|
+
*
|
|
602
|
+
* @method setStyle
|
|
603
|
+
* @param {Object} [style] - 要应用的样式对象,默认使用 this.style
|
|
604
|
+
*
|
|
605
|
+
* @example
|
|
606
|
+
* // 应用样式
|
|
607
|
+
* control.setStyle({
|
|
608
|
+
* fill: '#ff0000',
|
|
609
|
+
* stroke: '#000000',
|
|
610
|
+
* lineWidth: 2,
|
|
611
|
+
* shadow: {
|
|
612
|
+
* blur: 10,
|
|
613
|
+
* x: 5,
|
|
614
|
+
* y: 5,
|
|
615
|
+
* color: 'rgba(0,0,0,0.5)'
|
|
616
|
+
* }
|
|
617
|
+
* });
|
|
618
|
+
*
|
|
619
|
+
* // 使用渐变
|
|
620
|
+
* control.setStyle({
|
|
621
|
+
* fill: 'linear-gradient(0,0,100,0,#ff0000,#0000ff)'
|
|
622
|
+
* });
|
|
623
|
+
*/
|
|
243
624
|
setStyle(style) {
|
|
244
625
|
if(!style) {
|
|
245
626
|
style = this.style;
|
|
246
627
|
}
|
|
247
628
|
if(!style) return;
|
|
248
629
|
|
|
630
|
+
/**
|
|
631
|
+
* 内部样式设置函数
|
|
632
|
+
* @param {*} styleValue - 样式值
|
|
633
|
+
* @param {string} name - 样式名称
|
|
634
|
+
* @param {string} [mpkey] - 映射键名
|
|
635
|
+
* @private
|
|
636
|
+
*/
|
|
249
637
|
const __setStyle = (style, name, mpkey) => {
|
|
250
638
|
if(style) {
|
|
251
639
|
let styleValue = style;
|
|
640
|
+
// 支持函数形式的样式值
|
|
252
641
|
if(typeof styleValue === 'function') {
|
|
253
642
|
try {
|
|
254
643
|
styleValue = styleValue.call(this);
|
|
@@ -261,12 +650,14 @@ export default class jmControl extends jmProperty {
|
|
|
261
650
|
let t = typeof styleValue;
|
|
262
651
|
let mpname = jmStyleMap[mpkey || name];
|
|
263
652
|
|
|
653
|
+
// 处理渐变
|
|
264
654
|
if((styleValue instanceof jmGradient) || (t == 'string' && styleValue.indexOf('-gradient') > -1)) {
|
|
265
655
|
if(t == 'string' && styleValue.indexOf('-gradient') > -1) {
|
|
266
656
|
styleValue = new jmGradient(styleValue);
|
|
267
657
|
}
|
|
268
658
|
__setStyle(styleValue.toGradient(this), mpname||name);
|
|
269
659
|
}
|
|
660
|
+
// 处理标准样式映射
|
|
270
661
|
else if(mpname) {
|
|
271
662
|
if(this.webglControl) {
|
|
272
663
|
this.webglControl.setStyle(mpname, styleValue);
|
|
@@ -278,8 +669,10 @@ export default class jmControl extends jmProperty {
|
|
|
278
669
|
this.context[mpname] = styleValue;
|
|
279
670
|
}
|
|
280
671
|
}
|
|
672
|
+
// 处理特殊样式
|
|
281
673
|
else {
|
|
282
674
|
switch(name) {
|
|
675
|
+
// 阴影样式
|
|
283
676
|
case 'shadow' : {
|
|
284
677
|
if(t == 'string') {
|
|
285
678
|
__setStyle(new jmShadow(styleValue), name);
|
|
@@ -290,9 +683,11 @@ export default class jmControl extends jmProperty {
|
|
|
290
683
|
}
|
|
291
684
|
break;
|
|
292
685
|
}
|
|
686
|
+
// 平移变换
|
|
293
687
|
case 'translate' : {
|
|
294
688
|
break;
|
|
295
689
|
}
|
|
690
|
+
// 旋转变换
|
|
296
691
|
case 'rotation' : {
|
|
297
692
|
if(typeof styleValue.angle === 'undefined' || isNaN(styleValue.angle)) break;
|
|
298
693
|
styleValue = this.getRotation(styleValue);
|
|
@@ -306,6 +701,7 @@ export default class jmControl extends jmProperty {
|
|
|
306
701
|
this.context.translate && this.context.translate(-this.__translateAbsolutePosition.x, -this.__translateAbsolutePosition.y);
|
|
307
702
|
break;
|
|
308
703
|
}
|
|
704
|
+
// 矩阵变换
|
|
309
705
|
case 'transform' : {
|
|
310
706
|
if(!this.context.transform) break;
|
|
311
707
|
if(Array.isArray(styleValue)) {
|
|
@@ -323,13 +719,19 @@ export default class jmControl extends jmProperty {
|
|
|
323
719
|
}
|
|
324
720
|
break;
|
|
325
721
|
}
|
|
722
|
+
// 鼠标样式
|
|
326
723
|
case 'cursor' : {
|
|
327
724
|
this.cursor = styleValue;
|
|
328
725
|
break;
|
|
329
726
|
}
|
|
330
727
|
// ===== 新增样式特性 =====
|
|
331
728
|
|
|
332
|
-
|
|
729
|
+
/**
|
|
730
|
+
* 虚线样式
|
|
731
|
+
* 支持数组格式 [5, 3, 2] 或字符串格式 "5,3,2"
|
|
732
|
+
* @example
|
|
733
|
+
* style: { lineDash: [5, 3] } // 5px实线,3px空白
|
|
734
|
+
*/
|
|
333
735
|
case 'lineDash' : {
|
|
334
736
|
if(!this.context.setLineDash) break;
|
|
335
737
|
let dash;
|
|
@@ -353,7 +755,14 @@ export default class jmControl extends jmProperty {
|
|
|
353
755
|
this.context.lineDashOffset = Number(styleValue) || 0;
|
|
354
756
|
break;
|
|
355
757
|
}
|
|
356
|
-
|
|
758
|
+
/**
|
|
759
|
+
* CSS滤镜效果
|
|
760
|
+
* 支持 blur, grayscale, sepia, brightness, contrast, saturate, hue-rotate, invert, opacity
|
|
761
|
+
* @example
|
|
762
|
+
* style: { filter: 'blur(5px) grayscale(50%)' }
|
|
763
|
+
* // 或使用对象
|
|
764
|
+
* style: { filter: { blur: 5, grayscale: 0.5 } }
|
|
765
|
+
*/
|
|
357
766
|
case 'filter' : {
|
|
358
767
|
if(this.context.filter === undefined) break;
|
|
359
768
|
if(styleValue instanceof jmFilter) {
|
|
@@ -367,13 +776,23 @@ export default class jmControl extends jmProperty {
|
|
|
367
776
|
}
|
|
368
777
|
break;
|
|
369
778
|
}
|
|
370
|
-
|
|
779
|
+
/**
|
|
780
|
+
* 混合模式
|
|
781
|
+
* 常用值:source-over, multiply, screen, overlay, darken, lighten
|
|
782
|
+
* @example
|
|
783
|
+
* style: { globalCompositeOperation: 'multiply' }
|
|
784
|
+
*/
|
|
371
785
|
case 'globalCompositeOperation' : {
|
|
372
786
|
if(!this.context.globalCompositeOperation) break;
|
|
373
787
|
this.context.globalCompositeOperation = styleValue;
|
|
374
788
|
break;
|
|
375
789
|
}
|
|
376
|
-
|
|
790
|
+
/**
|
|
791
|
+
* 裁剪路径
|
|
792
|
+
* 通过 canvas clip 实现裁剪效果
|
|
793
|
+
* @example
|
|
794
|
+
* style: { clipPath: clipShape } // clipShape 是一个图形控件
|
|
795
|
+
*/
|
|
377
796
|
case 'clipPath' : {
|
|
378
797
|
if(!this.context.clip) break;
|
|
379
798
|
// clipPath可以是一个图形控件实例
|
|
@@ -396,7 +815,12 @@ export default class jmControl extends jmProperty {
|
|
|
396
815
|
}
|
|
397
816
|
break;
|
|
398
817
|
}
|
|
399
|
-
|
|
818
|
+
/**
|
|
819
|
+
* 遮罩效果
|
|
820
|
+
* 通过 globalCompositeOperation + destination-in 实现
|
|
821
|
+
* @example
|
|
822
|
+
* style: { mask: maskShape } // maskShape 是一个图形控件
|
|
823
|
+
*/
|
|
400
824
|
case 'mask' : {
|
|
401
825
|
if(!this.context.globalCompositeOperation) break;
|
|
402
826
|
// mask是一个图形控件实例,在绘制前需要先应用mask
|
|
@@ -404,7 +828,7 @@ export default class jmControl extends jmProperty {
|
|
|
404
828
|
this.__mask = styleValue;
|
|
405
829
|
break;
|
|
406
830
|
}
|
|
407
|
-
//
|
|
831
|
+
// 阴影相关样式(WebGL兼容)
|
|
408
832
|
case 'shadowColor' : {
|
|
409
833
|
if(this.webglControl) {
|
|
410
834
|
this.webglControl.setStyle('shadowColor', styleValue);
|
|
@@ -446,21 +870,27 @@ export default class jmControl extends jmProperty {
|
|
|
446
870
|
}
|
|
447
871
|
}
|
|
448
872
|
|
|
873
|
+
// 应用平移变换
|
|
449
874
|
if(this.translate) {
|
|
450
875
|
__setStyle(this.translate, 'translate');
|
|
451
876
|
}
|
|
877
|
+
// 应用矩阵变换
|
|
452
878
|
if(this.transform) {
|
|
453
879
|
__setStyle(this.transform, 'transform');
|
|
454
880
|
}
|
|
881
|
+
// 遍历应用所有样式
|
|
455
882
|
for(let k in style) {
|
|
456
883
|
if(k === 'constructor') continue;
|
|
457
884
|
let t = typeof style[k];
|
|
885
|
+
// 自动转换渐变字符串
|
|
458
886
|
if(t == 'string' && style[k].indexOf('-gradient') > -1) {
|
|
459
887
|
style[k] = new jmGradient(style[k]);
|
|
460
888
|
}
|
|
889
|
+
// 自动转换阴影字符串
|
|
461
890
|
else if(t == 'string' && k == 'shadow') {
|
|
462
891
|
style[k] = new jmShadow(style[k]);
|
|
463
892
|
}
|
|
893
|
+
// 自动转换滤镜字符串
|
|
464
894
|
else if(t == 'string' && k == 'filter') {
|
|
465
895
|
style[k] = new jmFilter(style[k]);
|
|
466
896
|
}
|
|
@@ -469,13 +899,29 @@ export default class jmControl extends jmProperty {
|
|
|
469
899
|
}
|
|
470
900
|
|
|
471
901
|
/**
|
|
472
|
-
*
|
|
473
|
-
*
|
|
474
|
-
*
|
|
902
|
+
* 获取当前控件的边界矩形
|
|
903
|
+
*
|
|
904
|
+
* 通过分析控件的描点或位置加宽高得到边界矩形。
|
|
905
|
+
* 对于 jmGraph,边界为画布尺寸。
|
|
906
|
+
* 对于有 points 的控件,边界为所有点的最小包围矩形。
|
|
907
|
+
*
|
|
475
908
|
* @method getBounds
|
|
476
|
-
* @
|
|
477
|
-
* @
|
|
478
|
-
* @
|
|
909
|
+
* @param {boolean} [isReset=false] - 是否强制重新计算(忽略缓存)
|
|
910
|
+
* @returns {Object} 边界对象
|
|
911
|
+
* @returns {number} returns.left - 左边界 X 坐标
|
|
912
|
+
* @returns {number} returns.top - 上边界 Y 坐标
|
|
913
|
+
* @returns {number} returns.right - 右边界 X 坐标
|
|
914
|
+
* @returns {number} returns.bottom - 下边界 Y 坐标
|
|
915
|
+
* @returns {number} returns.width - 宽度
|
|
916
|
+
* @returns {number} returns.height - 高度
|
|
917
|
+
*
|
|
918
|
+
* @example
|
|
919
|
+
* // 获取边界
|
|
920
|
+
* const bounds = control.getBounds();
|
|
921
|
+
* console.log(`宽: ${bounds.width}, 高: ${bounds.height}`);
|
|
922
|
+
*
|
|
923
|
+
* // 强制重新计算
|
|
924
|
+
* const newBounds = control.getBounds(true);
|
|
479
925
|
*/
|
|
480
926
|
getBounds(isReset) {
|
|
481
927
|
//如果当次计算过,则不重复计算
|
|
@@ -498,6 +944,7 @@ export default class jmControl extends jmProperty {
|
|
|
498
944
|
rect.bottom = this.height;
|
|
499
945
|
}
|
|
500
946
|
}
|
|
947
|
+
// 根据 points 计算边界
|
|
501
948
|
else if(this.points && this.points.length > 0) {
|
|
502
949
|
for(const p of this.points) {
|
|
503
950
|
if(typeof rect.left === 'undefined' || rect.left > p.x) {
|
|
@@ -515,6 +962,7 @@ export default class jmControl extends jmProperty {
|
|
|
515
962
|
}
|
|
516
963
|
}
|
|
517
964
|
}
|
|
965
|
+
// 根据位置和尺寸计算边界
|
|
518
966
|
else if(this.getLocation) {
|
|
519
967
|
let p = this.getLocation();
|
|
520
968
|
if(p) {
|
|
@@ -524,10 +972,10 @@ export default class jmControl extends jmProperty {
|
|
|
524
972
|
rect.bottom = p.top + p.height;
|
|
525
973
|
}
|
|
526
974
|
}
|
|
527
|
-
if(
|
|
528
|
-
if(
|
|
529
|
-
if(
|
|
530
|
-
if(
|
|
975
|
+
if(rect.left === undefined) rect.left = 0;
|
|
976
|
+
if(rect.top === undefined) rect.top = 0;
|
|
977
|
+
if(rect.right === undefined) rect.right = 0;
|
|
978
|
+
if(rect.bottom === undefined) rect.bottom = 0;
|
|
531
979
|
rect.width = rect.right - rect.left;
|
|
532
980
|
rect.height = rect.bottom - rect.top;
|
|
533
981
|
|
|
@@ -535,7 +983,23 @@ export default class jmControl extends jmProperty {
|
|
|
535
983
|
}
|
|
536
984
|
|
|
537
985
|
/**
|
|
538
|
-
*
|
|
986
|
+
* 获取旋转后的边界矩形
|
|
987
|
+
*
|
|
988
|
+
* 计算控件旋转后的最小包围矩形。
|
|
989
|
+
* 当控件有旋转变换时,实际占据的空间会发生变化。
|
|
990
|
+
*
|
|
991
|
+
* @method getRotationBounds
|
|
992
|
+
* @param {Object} [rotation] - 旋转参数,默认使用 style.rotation
|
|
993
|
+
* @param {number} rotation.x - 旋转中心 X(相对于控件)
|
|
994
|
+
* @param {number} rotation.y - 旋转中心 Y(相对于控件)
|
|
995
|
+
* @param {number} rotation.angle - 旋转角度(弧度)
|
|
996
|
+
* @param {Object} [bounds] - 基础边界,默认使用 getBounds()
|
|
997
|
+
* @returns {Object} 旋转后的边界对象
|
|
998
|
+
*
|
|
999
|
+
* @example
|
|
1000
|
+
* // 获取旋转后的边界
|
|
1001
|
+
* const bounds = control.getRotationBounds();
|
|
1002
|
+
* console.log(`旋转后宽度: ${bounds.width}`);
|
|
539
1003
|
*/
|
|
540
1004
|
getRotationBounds(rotation=null) {
|
|
541
1005
|
rotation = rotation || this.getRotation();
|
|
@@ -602,11 +1066,26 @@ export default class jmControl extends jmProperty {
|
|
|
602
1066
|
}
|
|
603
1067
|
|
|
604
1068
|
/**
|
|
605
|
-
*
|
|
606
|
-
*
|
|
607
|
-
*
|
|
1069
|
+
* 获取当前控件的位置参数
|
|
1070
|
+
*
|
|
1071
|
+
* 解析百分比和 margin 参数,返回标准化的位置信息。
|
|
1072
|
+
* 支持百分比定位(如 '50%')和 margin 偏移。
|
|
1073
|
+
*
|
|
608
1074
|
* @method getLocation
|
|
609
|
-
* @
|
|
1075
|
+
* @returns {Object} 位置参数对象
|
|
1076
|
+
* @returns {number} returns.left - 左边距
|
|
1077
|
+
* @returns {number} returns.top - 上边距
|
|
1078
|
+
* @returns {number} returns.width - 宽度
|
|
1079
|
+
* @returns {number} returns.height - 高度
|
|
1080
|
+
* @returns {Object} [returns.position] - 位置对象 {x, y}
|
|
1081
|
+
* @returns {Object} [returns.center] - 中心点
|
|
1082
|
+
* @returns {Object} [returns.start] - 起点(线条类)
|
|
1083
|
+
* @returns {Object} [returns.end] - 终点(线条类)
|
|
1084
|
+
* @returns {number} [returns.radius] - 半径(圆形类)
|
|
1085
|
+
*
|
|
1086
|
+
* @example
|
|
1087
|
+
* const loc = control.getLocation();
|
|
1088
|
+
* console.log(`位置: (${loc.left}, ${loc.top})`);
|
|
610
1089
|
*/
|
|
611
1090
|
getLocation() {
|
|
612
1091
|
//如果已经计算过则直接返回
|
|
@@ -682,8 +1161,26 @@ export default class jmControl extends jmProperty {
|
|
|
682
1161
|
}
|
|
683
1162
|
|
|
684
1163
|
/**
|
|
685
|
-
*
|
|
686
|
-
*
|
|
1164
|
+
* 获取当前控件的旋转信息
|
|
1165
|
+
*
|
|
1166
|
+
* 解析旋转参数,支持百分比形式的旋转中心。
|
|
1167
|
+
* 如果控件本身没有旋转,会继承父级的旋转。
|
|
1168
|
+
*
|
|
1169
|
+
* @method getRotation
|
|
1170
|
+
* @param {Object} [rotation] - 旋转参数,默认使用 style.rotation
|
|
1171
|
+
* @param {Object} [bounds] - 基础边界
|
|
1172
|
+
* @returns {Object} 旋转信息
|
|
1173
|
+
* @returns {number} returns.x - 旋转中心 X(相对于控件)
|
|
1174
|
+
* @returns {number} returns.y - 旋转中心 Y(相对于控件)
|
|
1175
|
+
* @returns {number} returns.angle - 旋转角度(弧度)
|
|
1176
|
+
* @returns {Object} returns.bounds - 控件边界
|
|
1177
|
+
*
|
|
1178
|
+
* @example
|
|
1179
|
+
* // 获取旋转信息
|
|
1180
|
+
* const rot = control.getRotation();
|
|
1181
|
+
* if(rot.angle) {
|
|
1182
|
+
* console.log(`旋转角度: ${rot.angle} 弧度`);
|
|
1183
|
+
* }
|
|
687
1184
|
*/
|
|
688
1185
|
getRotation(rotation, bounds = null) {
|
|
689
1186
|
rotation = rotation || jmUtils.clone(this.style.rotation);
|
|
@@ -716,7 +1213,20 @@ export default class jmControl extends jmProperty {
|
|
|
716
1213
|
|
|
717
1214
|
}
|
|
718
1215
|
|
|
719
|
-
|
|
1216
|
+
/**
|
|
1217
|
+
* 计算位移偏移量
|
|
1218
|
+
*
|
|
1219
|
+
* 解析 translate 样式,支持百分比形式。
|
|
1220
|
+
*
|
|
1221
|
+
* @method getTranslate
|
|
1222
|
+
* @param {Object} [translate] - 平移参数,默认使用 style.translate
|
|
1223
|
+
* @param {Object} [bounds] - 参考边界
|
|
1224
|
+
* @returns {Object} 平移信息 {x, y}
|
|
1225
|
+
*
|
|
1226
|
+
* @example
|
|
1227
|
+
* const trans = control.getTranslate();
|
|
1228
|
+
* console.log(`平移: (${trans.x}, ${trans.y})`);
|
|
1229
|
+
*/
|
|
720
1230
|
getTranslate(translate, bounds = null) {
|
|
721
1231
|
translate = translate || this.style.translate;
|
|
722
1232
|
if(!translate) return {x: 0, y: 0};
|
|
@@ -738,9 +1248,15 @@ export default class jmControl extends jmProperty {
|
|
|
738
1248
|
|
|
739
1249
|
/**
|
|
740
1250
|
* 移除当前控件
|
|
741
|
-
*
|
|
742
|
-
*
|
|
743
|
-
*
|
|
1251
|
+
*
|
|
1252
|
+
* 从父控件的子控件列表中移除当前控件。
|
|
1253
|
+
* 移除后会触发 needUpdate 重绘。
|
|
1254
|
+
*
|
|
1255
|
+
* @method remove
|
|
1256
|
+
*
|
|
1257
|
+
* @example
|
|
1258
|
+
* // 移除控件
|
|
1259
|
+
* control.remove();
|
|
744
1260
|
*/
|
|
745
1261
|
remove() {
|
|
746
1262
|
if(this.parent) {
|
|
@@ -750,13 +1266,19 @@ export default class jmControl extends jmProperty {
|
|
|
750
1266
|
|
|
751
1267
|
/**
|
|
752
1268
|
* 对控件进行平移
|
|
1269
|
+
*
|
|
753
1270
|
* 遍历控件所有描点或位置,设置其偏移量。
|
|
754
|
-
*
|
|
1271
|
+
* 支持移动 position、center、start、end、points 等属性。
|
|
1272
|
+
*
|
|
755
1273
|
* @method offset
|
|
756
|
-
* @param {number} x
|
|
757
|
-
* @param {number} y
|
|
758
|
-
* @param {boolean} [trans]
|
|
759
|
-
* @param {
|
|
1274
|
+
* @param {number} x - X 轴偏移量
|
|
1275
|
+
* @param {number} y - Y 轴偏移量
|
|
1276
|
+
* @param {boolean} [trans=true] - 是否传递给监听者
|
|
1277
|
+
* @param {Object} [evt] - 如果是事件触发,传递 move 事件参数
|
|
1278
|
+
*
|
|
1279
|
+
* @example
|
|
1280
|
+
* // 向右移动 10px,向下移动 5px
|
|
1281
|
+
* control.offset(10, 5);
|
|
760
1282
|
*/
|
|
761
1283
|
offset(x, y, trans, evt) {
|
|
762
1284
|
trans = trans === false?false:true;
|
|
@@ -824,11 +1346,17 @@ export default class jmControl extends jmProperty {
|
|
|
824
1346
|
}
|
|
825
1347
|
|
|
826
1348
|
/**
|
|
827
|
-
*
|
|
828
|
-
*
|
|
829
|
-
*
|
|
1349
|
+
* 获取控件相对于画布的绝对边界
|
|
1350
|
+
*
|
|
1351
|
+
* 与 getBounds 不同的是:getBounds 获取的是相对于父容器的边界,
|
|
1352
|
+
* 而 getAbsoluteBounds 获取的是相对于画布的边界。
|
|
1353
|
+
*
|
|
830
1354
|
* @method getAbsoluteBounds
|
|
831
|
-
* @
|
|
1355
|
+
* @returns {Object} 绝对边界对象
|
|
1356
|
+
*
|
|
1357
|
+
* @example
|
|
1358
|
+
* const absBounds = control.getAbsoluteBounds();
|
|
1359
|
+
* console.log(`画布上的位置: (${absBounds.left}, ${absBounds.top})`);
|
|
832
1360
|
*/
|
|
833
1361
|
getAbsoluteBounds() {
|
|
834
1362
|
//当前控件的边界,
|
|
@@ -850,10 +1378,14 @@ export default class jmControl extends jmProperty {
|
|
|
850
1378
|
}
|
|
851
1379
|
|
|
852
1380
|
/**
|
|
853
|
-
*
|
|
1381
|
+
* 把当前控件内部坐标转为画布绝对坐标
|
|
854
1382
|
*
|
|
855
1383
|
* @method toAbsolutePoint
|
|
856
|
-
* @param {x
|
|
1384
|
+
* @param {Object} point - 内部坐标 {x, y}
|
|
1385
|
+
* @returns {Object} 绝对坐标
|
|
1386
|
+
*
|
|
1387
|
+
* @example
|
|
1388
|
+
* const absPoint = control.toAbsolutePoint({x: 10, y: 10});
|
|
857
1389
|
*/
|
|
858
1390
|
toAbsolutePoint(point) {
|
|
859
1391
|
if(point.x || point.y) {
|
|
@@ -866,8 +1398,14 @@ export default class jmControl extends jmProperty {
|
|
|
866
1398
|
}
|
|
867
1399
|
|
|
868
1400
|
/**
|
|
869
|
-
*
|
|
870
|
-
*
|
|
1401
|
+
* 把画布绝对坐标转为当前控件坐标系内
|
|
1402
|
+
*
|
|
1403
|
+
* @method toLocalPosition
|
|
1404
|
+
* @param {Object} point - 绝对坐标
|
|
1405
|
+
* @returns {Object|false} 相对坐标,如果无法转换返回 false
|
|
1406
|
+
*
|
|
1407
|
+
* @example
|
|
1408
|
+
* const localPoint = control.toLocalPosition({x: 100, y: 100});
|
|
871
1409
|
*/
|
|
872
1410
|
toLocalPosition(point) {
|
|
873
1411
|
|
|
@@ -881,9 +1419,21 @@ export default class jmControl extends jmProperty {
|
|
|
881
1419
|
|
|
882
1420
|
/**
|
|
883
1421
|
* 画控件前初始化
|
|
884
|
-
*
|
|
1422
|
+
*
|
|
1423
|
+
* 执行 beginPath 开始控件的绘制路径。
|
|
1424
|
+
* 重置位置信息缓存,确保使用最新的位置数据。
|
|
885
1425
|
*
|
|
886
1426
|
* @method beginDraw
|
|
1427
|
+
* @protected
|
|
1428
|
+
*
|
|
1429
|
+
* @example
|
|
1430
|
+
* // 子类重写时需要调用父类方法
|
|
1431
|
+
* class MyShape extends jmControl {
|
|
1432
|
+
* beginDraw() {
|
|
1433
|
+
* super.beginDraw();
|
|
1434
|
+
* // 自定义初始化逻辑
|
|
1435
|
+
* }
|
|
1436
|
+
* }
|
|
887
1437
|
*/
|
|
888
1438
|
beginDraw() {
|
|
889
1439
|
this.getLocation(true);//重置位置信息
|
|
@@ -893,8 +1443,18 @@ export default class jmControl extends jmProperty {
|
|
|
893
1443
|
|
|
894
1444
|
/**
|
|
895
1445
|
* 结束控件绘制
|
|
896
|
-
*
|
|
1446
|
+
*
|
|
1447
|
+
* 根据样式执行 fill 或 stroke 操作。
|
|
1448
|
+
* 如果设置了 close 样式,会先闭合路径。
|
|
1449
|
+
*
|
|
897
1450
|
* @method endDraw
|
|
1451
|
+
* @protected
|
|
1452
|
+
*
|
|
1453
|
+
* @example
|
|
1454
|
+
* // 绘制流程
|
|
1455
|
+
* control.beginDraw();
|
|
1456
|
+
* control.draw();
|
|
1457
|
+
* control.endDraw();
|
|
898
1458
|
*/
|
|
899
1459
|
endDraw() {
|
|
900
1460
|
//如果当前为封闭路径
|
|
@@ -931,10 +1491,24 @@ export default class jmControl extends jmProperty {
|
|
|
931
1491
|
}
|
|
932
1492
|
|
|
933
1493
|
/**
|
|
934
|
-
*
|
|
935
|
-
*
|
|
1494
|
+
* 绘制控件路径
|
|
1495
|
+
*
|
|
1496
|
+
* 在画布上绘制控件的路径点。
|
|
1497
|
+
* 子类应该重写此方法实现自定义绘制逻辑。
|
|
936
1498
|
*
|
|
937
1499
|
* @method draw
|
|
1500
|
+
* @protected
|
|
1501
|
+
*
|
|
1502
|
+
* @example
|
|
1503
|
+
* // 子类重写绘制方法
|
|
1504
|
+
* class MyShape extends jmControl {
|
|
1505
|
+
* draw() {
|
|
1506
|
+
* const ctx = this.context;
|
|
1507
|
+
* ctx.moveTo(0, 0);
|
|
1508
|
+
* ctx.lineTo(100, 100);
|
|
1509
|
+
* // ... 更多绘制逻辑
|
|
1510
|
+
* }
|
|
1511
|
+
* }
|
|
938
1512
|
*/
|
|
939
1513
|
draw() {
|
|
940
1514
|
if(this.points && this.points.length > 0) {
|
|
@@ -962,10 +1536,23 @@ export default class jmControl extends jmProperty {
|
|
|
962
1536
|
}
|
|
963
1537
|
|
|
964
1538
|
/**
|
|
965
|
-
*
|
|
966
|
-
*
|
|
967
|
-
*
|
|
1539
|
+
* 绘制当前控件及其子控件
|
|
1540
|
+
*
|
|
1541
|
+
* 协调控件的绘制流程:
|
|
1542
|
+
* 1. 检查可见性
|
|
1543
|
+
* 2. 初始化点数据
|
|
1544
|
+
* 3. 计算边界
|
|
1545
|
+
* 4. 应用样式
|
|
1546
|
+
* 5. 绘制自身
|
|
1547
|
+
* 6. 绘制子控件
|
|
1548
|
+
* 7. 触发事件
|
|
1549
|
+
*
|
|
968
1550
|
* @method paint
|
|
1551
|
+
* @param {boolean} [v] - 是否可见,false 时跳过绘制
|
|
1552
|
+
*
|
|
1553
|
+
* @example
|
|
1554
|
+
* // 手动触发重绘
|
|
1555
|
+
* control.paint();
|
|
969
1556
|
*/
|
|
970
1557
|
paint(v) {
|
|
971
1558
|
if(v !== false && this.visible !== false) {
|
|
@@ -1040,23 +1627,50 @@ export default class jmControl extends jmProperty {
|
|
|
1040
1627
|
}
|
|
1041
1628
|
|
|
1042
1629
|
/**
|
|
1043
|
-
*
|
|
1044
|
-
*
|
|
1045
|
-
*
|
|
1630
|
+
* 获取指定事件的监听器集合
|
|
1631
|
+
*
|
|
1632
|
+
* 返回绑定到指定事件名称的所有事件处理函数。
|
|
1633
|
+
*
|
|
1046
1634
|
* @method getEvent
|
|
1047
|
-
* @param {string} name
|
|
1048
|
-
* @
|
|
1635
|
+
* @param {string} name - 事件名称(如 'click', 'mousedown')
|
|
1636
|
+
* @returns {jmList|null} 事件处理函数集合,不存在则返回 null
|
|
1637
|
+
*
|
|
1638
|
+
* @example
|
|
1639
|
+
* const handlers = control.getEvent('click');
|
|
1640
|
+
* if(handlers) {
|
|
1641
|
+
* console.log(`有 ${handlers.count()} 个点击事件处理器`);
|
|
1642
|
+
* }
|
|
1049
1643
|
*/
|
|
1050
1644
|
getEvent(name) {
|
|
1051
1645
|
return this.__events?this.__events[name]:null;
|
|
1052
1646
|
}
|
|
1053
1647
|
|
|
1054
1648
|
/**
|
|
1055
|
-
*
|
|
1056
|
-
*
|
|
1649
|
+
* 绑定控件事件
|
|
1650
|
+
*
|
|
1651
|
+
* 为控件添加事件监听器。支持同时绑定多个事件(用空格分隔)。
|
|
1652
|
+
* 同一个处理函数不会被重复添加。
|
|
1653
|
+
*
|
|
1057
1654
|
* @method bind
|
|
1058
|
-
* @param {string} name
|
|
1059
|
-
* @param {
|
|
1655
|
+
* @param {string} name - 事件名称,多个事件用空格分隔
|
|
1656
|
+
* @param {Function} handle - 事件处理函数
|
|
1657
|
+
* @returns {void}
|
|
1658
|
+
*
|
|
1659
|
+
* @example
|
|
1660
|
+
* // 绑定单个事件
|
|
1661
|
+
* control.bind('click', (evt) => {
|
|
1662
|
+
* console.log('被点击了', evt);
|
|
1663
|
+
* });
|
|
1664
|
+
*
|
|
1665
|
+
* // 绑定多个事件
|
|
1666
|
+
* control.bind('mousedown mouseup', (evt) => {
|
|
1667
|
+
* console.log('鼠标事件', evt);
|
|
1668
|
+
* });
|
|
1669
|
+
*
|
|
1670
|
+
* // 使用 on 别名
|
|
1671
|
+
* control.on('mousemove', (evt) => {
|
|
1672
|
+
* console.log('鼠标移动', evt.position);
|
|
1673
|
+
* });
|
|
1060
1674
|
*/
|
|
1061
1675
|
bind(name, handle) {
|
|
1062
1676
|
if(name && name.indexOf(' ') > -1) {
|
|
@@ -1083,11 +1697,23 @@ export default class jmControl extends jmProperty {
|
|
|
1083
1697
|
}
|
|
1084
1698
|
|
|
1085
1699
|
/**
|
|
1086
|
-
*
|
|
1087
|
-
*
|
|
1088
|
-
*
|
|
1089
|
-
*
|
|
1090
|
-
* @
|
|
1700
|
+
* 移除控件事件
|
|
1701
|
+
*
|
|
1702
|
+
* 移除已绑定的事件处理函数。如果不指定处理函数,则移除该事件的所有处理函数。
|
|
1703
|
+
*
|
|
1704
|
+
* @method unbind
|
|
1705
|
+
* @param {string} name - 事件名称,多个事件用空格分隔
|
|
1706
|
+
* @param {Function} [handle] - 要移除的事件处理函数,不指定则移除所有
|
|
1707
|
+
*
|
|
1708
|
+
* @example
|
|
1709
|
+
* // 移除特定处理函数
|
|
1710
|
+
* control.unbind('click', myHandler);
|
|
1711
|
+
*
|
|
1712
|
+
* // 移除所有点击事件
|
|
1713
|
+
* control.unbind('click');
|
|
1714
|
+
*
|
|
1715
|
+
* // 移除多个事件
|
|
1716
|
+
* control.unbind('mousedown mouseup');
|
|
1091
1717
|
*/
|
|
1092
1718
|
unbind(name, handle) {
|
|
1093
1719
|
if(name && name.indexOf(' ') > -1) {
|
|
@@ -1106,12 +1732,22 @@ export default class jmControl extends jmProperty {
|
|
|
1106
1732
|
|
|
1107
1733
|
|
|
1108
1734
|
/**
|
|
1109
|
-
*
|
|
1735
|
+
* 触发事件
|
|
1736
|
+
*
|
|
1737
|
+
* 执行指定事件的所有监听器。
|
|
1738
|
+
* 支持传递多个参数给事件处理函数。
|
|
1110
1739
|
*
|
|
1111
1740
|
* @method emit
|
|
1112
|
-
* @
|
|
1113
|
-
* @param {
|
|
1114
|
-
* @
|
|
1741
|
+
* @param {string} name - 事件名称
|
|
1742
|
+
* @param {...*} args - 传递给事件处理函数的参数
|
|
1743
|
+
* @returns {jmControl} 返回 this 以支持链式调用
|
|
1744
|
+
*
|
|
1745
|
+
* @example
|
|
1746
|
+
* // 触发自定义事件
|
|
1747
|
+
* control.emit('customEvent', { data: 'value' });
|
|
1748
|
+
*
|
|
1749
|
+
* // 触发带多个参数的事件
|
|
1750
|
+
* control.emit('dataChange', oldValue, newValue);
|
|
1115
1751
|
*/
|
|
1116
1752
|
emit(...args) {
|
|
1117
1753
|
// 避免每帧 args.slice(1) 分配临时数组
|
|
@@ -1127,15 +1763,24 @@ export default class jmControl extends jmProperty {
|
|
|
1127
1763
|
}
|
|
1128
1764
|
|
|
1129
1765
|
/**
|
|
1130
|
-
*
|
|
1131
|
-
*
|
|
1766
|
+
* 执行事件处理函数
|
|
1767
|
+
*
|
|
1768
|
+
* 内部方法,用于执行指定事件的所有监听器。
|
|
1769
|
+
* 如果任一处理函数返回 false,会设置 args.cancel = true。
|
|
1770
|
+
*
|
|
1132
1771
|
* @method runEventHandle
|
|
1133
|
-
* @param {string}
|
|
1134
|
-
* @param {
|
|
1772
|
+
* @param {string} name - 事件名称
|
|
1773
|
+
* @param {Array|Object} args - 事件参数
|
|
1774
|
+
* @returns {boolean} 是否被取消
|
|
1775
|
+
* @protected
|
|
1135
1776
|
*/
|
|
1136
1777
|
runEventHandle(name, args) {
|
|
1137
1778
|
let events = this.getEvent(name);
|
|
1138
1779
|
if(events) {
|
|
1780
|
+
|
|
1781
|
+
if(name === 'mousemove' && this.type == 'jmResize') {
|
|
1782
|
+
console.log('resize mousemove', args, events);
|
|
1783
|
+
}
|
|
1139
1784
|
var self = this;
|
|
1140
1785
|
if(!Array.isArray(args)) args = [args];
|
|
1141
1786
|
events.each(function(i, handle) {
|
|
@@ -1149,25 +1794,35 @@ export default class jmControl extends jmProperty {
|
|
|
1149
1794
|
}
|
|
1150
1795
|
|
|
1151
1796
|
/**
|
|
1152
|
-
*
|
|
1153
|
-
*
|
|
1797
|
+
* 检查坐标是否落在当前控件区域中
|
|
1798
|
+
*
|
|
1799
|
+
* 用于点击测试和碰撞检测。
|
|
1800
|
+
* 支持旋转后的碰撞检测,以及自定义命中区域。
|
|
1801
|
+
*
|
|
1154
1802
|
* @method checkPoint
|
|
1155
|
-
* @param {
|
|
1156
|
-
* @param {number}
|
|
1157
|
-
* @
|
|
1803
|
+
* @param {Object} p - 要检测的点坐标
|
|
1804
|
+
* @param {number} p.x - X 坐标
|
|
1805
|
+
* @param {number} p.y - Y 坐标
|
|
1806
|
+
* @param {number} [pad] - 容差范围,默认使用 lineWidth 或 1
|
|
1807
|
+
* @returns {boolean} 点是否在控件区域内
|
|
1808
|
+
*
|
|
1809
|
+
* @example
|
|
1810
|
+
* // 检查点击位置
|
|
1811
|
+
* graph.bind('click', (evt) => {
|
|
1812
|
+
* if(control.checkPoint(evt.position)) {
|
|
1813
|
+
* console.log('点击了控件');
|
|
1814
|
+
* }
|
|
1815
|
+
* });
|
|
1158
1816
|
*/
|
|
1159
1817
|
checkPoint(p, pad) {
|
|
1160
1818
|
//jmGraph 需要判断dom位置
|
|
1161
1819
|
if(this.type == 'jmGraph') {
|
|
1162
1820
|
//获取dom位置
|
|
1163
|
-
|
|
1164
|
-
|
|
1165
|
-
const right = position.left + this.width;
|
|
1166
|
-
const bottom = position.top + this.height;
|
|
1167
|
-
if(p.x > right || p.x < position.left) {
|
|
1821
|
+
const position = this.getPosition();
|
|
1822
|
+
if(p.pageX > position.right || p.pageX < position.left) {
|
|
1168
1823
|
return false;
|
|
1169
1824
|
}
|
|
1170
|
-
if(p.
|
|
1825
|
+
if(p.pageY > position.bottom || p.pageY < position.top) {
|
|
1171
1826
|
return false;
|
|
1172
1827
|
}
|
|
1173
1828
|
return true;
|
|
@@ -1254,15 +1909,23 @@ export default class jmControl extends jmProperty {
|
|
|
1254
1909
|
|
|
1255
1910
|
|
|
1256
1911
|
/**
|
|
1257
|
-
*
|
|
1258
|
-
*
|
|
1912
|
+
* 触发控件事件并执行事件冒泡
|
|
1913
|
+
*
|
|
1914
|
+
* 组合事件参数,按控件层级关系执行事件冒泡。
|
|
1915
|
+
* 事件从最上层的子控件开始触发,向上冒泡到父控件。
|
|
1916
|
+
*
|
|
1259
1917
|
* @method raiseEvent
|
|
1260
|
-
* @param {string} name 事件名称
|
|
1261
|
-
* @param {
|
|
1262
|
-
* @
|
|
1918
|
+
* @param {string} name - 事件名称
|
|
1919
|
+
* @param {Object} args - 原生事件对象
|
|
1920
|
+
* @returns {boolean} 如果事件被阻止冒泡则返回 false,否则返回 true
|
|
1921
|
+
*
|
|
1922
|
+
* @example
|
|
1923
|
+
* // 通常由框架内部调用,用户一般不需要直接调用
|
|
1924
|
+
* // 框架会自动处理鼠标/触摸事件
|
|
1263
1925
|
*/
|
|
1264
1926
|
raiseEvent(name, args) {
|
|
1265
1927
|
if(this.visible === false) return ;//如果不显示则不响应事件
|
|
1928
|
+
|
|
1266
1929
|
if(!args.position) {
|
|
1267
1930
|
const graph = this.graph;
|
|
1268
1931
|
args.isWXMiniApp = graph.isWXMiniApp;
|
|
@@ -1310,6 +1973,10 @@ export default class jmControl extends jmProperty {
|
|
|
1310
1973
|
|
|
1311
1974
|
// 是否在当前控件内操作
|
|
1312
1975
|
const inpos = this.interactive !== false && this.checkPoint(args.position);
|
|
1976
|
+
|
|
1977
|
+
if(name === 'mousemove' && this.type == 'jmGraph' && !inpos) {
|
|
1978
|
+
console.log('mousemove out', args.position, abounds);
|
|
1979
|
+
}
|
|
1313
1980
|
|
|
1314
1981
|
//事件发生在边界内或健盘事件发生在画布中才触发
|
|
1315
1982
|
if(inpos) {
|
|
@@ -1340,9 +2007,14 @@ export default class jmControl extends jmProperty {
|
|
|
1340
2007
|
}
|
|
1341
2008
|
|
|
1342
2009
|
/**
|
|
1343
|
-
*
|
|
1344
|
-
*
|
|
1345
|
-
*
|
|
2010
|
+
* 执行事件并进行冒泡
|
|
2011
|
+
*
|
|
2012
|
+
* 内部方法,用于执行事件处理并添加到事件路径。
|
|
2013
|
+
*
|
|
2014
|
+
* @method runEventAndPopEvent
|
|
2015
|
+
* @param {string} name - 事件名称
|
|
2016
|
+
* @param {Object} args - 事件参数
|
|
2017
|
+
* @protected
|
|
1346
2018
|
*/
|
|
1347
2019
|
runEventAndPopEvent(name, args) {
|
|
1348
2020
|
|
|
@@ -1368,23 +2040,38 @@ export default class jmControl extends jmProperty {
|
|
|
1368
2040
|
|
|
1369
2041
|
/**
|
|
1370
2042
|
* 清空控件指定事件
|
|
1371
|
-
*
|
|
2043
|
+
*
|
|
2044
|
+
* 移除指定事件名称下的所有事件处理函数。
|
|
2045
|
+
*
|
|
1372
2046
|
* @method clearEvents
|
|
1373
|
-
* @param {string} name 需要清除的事件名称
|
|
2047
|
+
* @param {string} name - 需要清除的事件名称
|
|
2048
|
+
*
|
|
2049
|
+
* @example
|
|
2050
|
+
* // 清除所有点击事件
|
|
2051
|
+
* control.clearEvents('click');
|
|
1374
2052
|
*/
|
|
1375
2053
|
clearEvents(name) {
|
|
1376
|
-
var eventCollection = this.getEvent(name)
|
|
2054
|
+
var eventCollection = this.getEvent(name);
|
|
1377
2055
|
if(eventCollection) {
|
|
1378
|
-
eventCollection.clear;
|
|
2056
|
+
eventCollection.clear();
|
|
1379
2057
|
}
|
|
1380
2058
|
}
|
|
1381
2059
|
|
|
1382
2060
|
/**
|
|
1383
|
-
*
|
|
1384
|
-
*
|
|
1385
|
-
*
|
|
1386
|
-
*
|
|
1387
|
-
* @
|
|
2061
|
+
* 查找指定类型的父级控件
|
|
2062
|
+
*
|
|
2063
|
+
* 沿着父级链向上查找,直到找到指定类型的控件或到达最顶级。
|
|
2064
|
+
*
|
|
2065
|
+
* @method findParent
|
|
2066
|
+
* @param {string|Function} type - 类型名称(字符串)或类构造函数
|
|
2067
|
+
* @returns {jmControl|null} 找到的父级控件实例,未找到返回 null
|
|
2068
|
+
*
|
|
2069
|
+
* @example
|
|
2070
|
+
* // 查找 jmGraph 实例
|
|
2071
|
+
* const graph = control.findParent('jmGraph');
|
|
2072
|
+
*
|
|
2073
|
+
* // 查找特定类的实例
|
|
2074
|
+
* const parent = control.findParent(MyCustomControl);
|
|
1388
2075
|
*/
|
|
1389
2076
|
findParent(type) {
|
|
1390
2077
|
//如果为类型名称,则返回名称相同的类型对象
|
|
@@ -1402,12 +2089,26 @@ export default class jmControl extends jmProperty {
|
|
|
1402
2089
|
}
|
|
1403
2090
|
|
|
1404
2091
|
/**
|
|
1405
|
-
*
|
|
1406
|
-
*
|
|
1407
|
-
*
|
|
2092
|
+
* 设置控件是否可拖动
|
|
2093
|
+
*
|
|
2094
|
+
* 启用或禁用控件的拖动功能。
|
|
2095
|
+
* 拖动时会触发 movestart、move、moveend 事件。
|
|
2096
|
+
*
|
|
1408
2097
|
* @method canMove
|
|
1409
|
-
* @param {boolean} m true
|
|
1410
|
-
* @param {jmGraph} [graph]
|
|
2098
|
+
* @param {boolean} m - true 启用拖动,false 禁用拖动
|
|
2099
|
+
* @param {jmGraph} [graph] - 画布实例,如果控件已添加到画布可省略
|
|
2100
|
+
* @returns {jmControl} 返回 this 以支持链式调用
|
|
2101
|
+
*
|
|
2102
|
+
* @example
|
|
2103
|
+
* // 启用拖动
|
|
2104
|
+
* control.canMove(true);
|
|
2105
|
+
*
|
|
2106
|
+
* // 禁用拖动
|
|
2107
|
+
* control.canMove(false);
|
|
2108
|
+
*
|
|
2109
|
+
* // 监听拖动事件
|
|
2110
|
+
* control.on('movestart', (evt) => console.log('开始拖动'));
|
|
2111
|
+
* control.on('moveend', (evt) => console.log('结束拖动'));
|
|
1411
2112
|
*/
|
|
1412
2113
|
canMove(m, graph) {
|
|
1413
2114
|
if(!this.__mvMonitor) {
|
|
@@ -1433,7 +2134,6 @@ export default class jmControl extends jmProperty {
|
|
|
1433
2134
|
//if(evt.path && evt.path.indexOf(_this)>-1) {
|
|
1434
2135
|
// _this.cursor('move');
|
|
1435
2136
|
//}
|
|
1436
|
-
|
|
1437
2137
|
if(_this.__mvMonitor.mouseDown) {
|
|
1438
2138
|
_this.parent.bounds = null;
|
|
1439
2139
|
//let parentbounds = _this.parent.getAbsoluteBounds();
|
|
@@ -1467,7 +2167,7 @@ export default class jmControl extends jmProperty {
|
|
|
1467
2167
|
_this.offset(offsetx, offsety, true, evt);
|
|
1468
2168
|
if(offsetx) _this.__mvMonitor.curposition.x = evt.position.offsetX;
|
|
1469
2169
|
if(offsety) _this.__mvMonitor.curposition.y = evt.position.offsetY;
|
|
1470
|
-
//console.log(offsetx + '.' + offsety);
|
|
2170
|
+
//console.log('mouse move',offsetx + '.' + offsety);
|
|
1471
2171
|
}
|
|
1472
2172
|
return false;
|
|
1473
2173
|
}
|