jmgraph 3.2.16 → 3.2.18

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.
Files changed (77) hide show
  1. package/LICENSE +21 -21
  2. package/README.md +251 -428
  3. package/build/gulpfile.js +142 -142
  4. package/build/package-lock.json +10666 -0
  5. package/build/package.json +71 -71
  6. package/dev.js +9 -9
  7. package/dist/jmgraph.core.min.js +1 -1
  8. package/dist/jmgraph.core.min.js.map +1 -1
  9. package/dist/jmgraph.js +3500 -2668
  10. package/dist/jmgraph.min.js +1 -1
  11. package/example/ball.html +216 -216
  12. package/example/base.html +111 -111
  13. package/example/canvas.html +53 -53
  14. package/example/cell.html +283 -283
  15. package/example/controls/arc.html +128 -128
  16. package/example/controls/arrowline.html +77 -77
  17. package/example/controls/bezier.html +298 -298
  18. package/example/controls/img.html +96 -96
  19. package/example/controls/label.html +86 -86
  20. package/example/controls/line.html +172 -172
  21. package/example/controls/prismatic.html +62 -62
  22. package/example/controls/rect.html +63 -63
  23. package/example/controls/resize.html +111 -111
  24. package/example/controls/test.html +359 -359
  25. package/example/es.html +69 -69
  26. package/example/es5module.html +62 -63
  27. package/example/heartarc.html +115 -115
  28. package/example/index.html +46 -46
  29. package/example/js/require.js +4 -4
  30. package/example/love/img/bling/bling.tps +265 -265
  31. package/example/love/img/bling.json +87 -87
  32. package/example/love/img/bling.tps +295 -295
  33. package/example/love/img/love.json +95 -95
  34. package/example/love/img/love.tps +315 -315
  35. package/example/love/img/qq/qq.tps +399 -399
  36. package/example/love/img/qq.json +242 -242
  37. package/example/love/index.html +40 -40
  38. package/example/love/js/game.js +558 -558
  39. package/example/music.html +210 -210
  40. package/example/node/test.js +137 -137
  41. package/example/pdf.html +186 -186
  42. package/example/progress.html +172 -172
  43. package/example/pso.html +147 -147
  44. package/example/sort.html +804 -815
  45. package/example/tweenjs.html +83 -83
  46. package/example/webgl.html +278 -278
  47. package/example/xfj/index.html +331 -331
  48. package/example/xfj/shake.js +48 -48
  49. package/example/xfj/testori.html +75 -75
  50. package/index.js +99 -99
  51. package/package.json +58 -56
  52. package/src/core/jmControl.js +1376 -1531
  53. package/src/core/jmEvents.js +240 -281
  54. package/src/core/jmGradient.js +231 -231
  55. package/src/core/jmGraph.js +569 -569
  56. package/src/core/jmList.js +92 -157
  57. package/src/core/jmObject.js +83 -103
  58. package/src/core/jmPath.js +35 -35
  59. package/src/core/jmProperty.js +71 -110
  60. package/src/core/jmShadow.js +65 -65
  61. package/src/core/jmUtils.js +906 -919
  62. package/src/lib/earcut.js +680 -680
  63. package/src/lib/earcut.md +73 -73
  64. package/src/lib/webgl/base.js +522 -452
  65. package/src/lib/webgl/core/buffer.js +48 -48
  66. package/src/lib/webgl/core/mapSize.js +40 -40
  67. package/src/lib/webgl/core/mapType.js +43 -43
  68. package/src/lib/webgl/core/program.js +138 -138
  69. package/src/lib/webgl/core/shader.js +13 -13
  70. package/src/lib/webgl/core/texture.js +60 -60
  71. package/src/lib/webgl/gradient.js +168 -168
  72. package/src/lib/webgl/index.js +137 -11
  73. package/src/lib/webgl/path.js +568 -561
  74. package/src/shapes/jmArrowLine.js +36 -36
  75. package/src/shapes/jmImage.js +244 -244
  76. package/src/shapes/jmLabel.js +271 -271
  77. package/src/shapes/jmResize.js +332 -330
@@ -1,569 +1,569 @@
1
- import {jmUtils} from "./jmUtils.js";
2
- import {jmList} from "./jmList.js";
3
- import {jmProperty} from './jmProperty.js';
4
- import {jmShadow} from "./jmShadow.js";
5
- import {jmGradient} from "./jmGradient.js";
6
- import {jmEvents} from "./jmEvents.js";
7
- import {jmControl} from "./jmControl.js";
8
- import {jmPath} from "./jmPath.js";
9
-
10
- /**
11
- * jmGraph画图类库
12
- * 对canvas画图api进行二次封装,使其更易调用,省去很多重复的工作。
13
- *
14
- * @module jmGraph
15
- * @class jmGraph
16
- * @extends jmControl
17
- * @param {element} canvas 标签canvas
18
- * @param {object} option 参数:{width:宽,height:高}
19
- * @param {function} callback 初始化后的回调
20
- */
21
- export default class jmGraph extends jmControl {
22
-
23
- constructor(canvas, option, callback) {
24
- if(typeof option == 'function') {
25
- callback = option;
26
- option = {};
27
- }
28
-
29
- option = option || {};
30
- //option.mode = '2d'; // webgl | 2d 暂不支持webgl
31
- option.interactive = true;
32
- option.isRegular = true;// 规则的
33
-
34
- super(option, 'jmGraph');
35
-
36
- this.option = option || {};
37
-
38
- this.devicePixelRatio = 1; // 根据屏幕的缩放倍数
39
-
40
- /**
41
- * 工具类
42
- * @property utils/util
43
- * @type {jmUtils}
44
- */
45
- this.util = this.utils = jmUtils;
46
- // 模式 webgl | 2d
47
- this.mode = option.mode || '2d';
48
-
49
- //如果是小程序
50
- if(typeof wx != 'undefined' && wx.canIUse && wx.canIUse('canvas')) {
51
- if(typeof canvas === 'string') canvas = wx.createSelectorQuery().select('#' + canvas);
52
- this.isWXMiniApp = true;// 微信小程序平台
53
- this.container = canvas;
54
- }
55
- else {
56
- if(typeof canvas === 'string' && typeof document != 'undefined') {
57
- canvas = document.getElementById(canvas);
58
- }
59
- else if(canvas.length) {
60
- canvas = canvas[0];
61
- }
62
-
63
- if(!canvas.getContext && typeof document != 'undefined') {
64
- this.container = canvas;
65
- let cn = document.createElement('canvas');
66
- canvas.appendChild(cn);
67
- cn.width = canvas.offsetWidth||canvas.clientWidth;
68
- cn.height = canvas.offsetHeight||canvas.clientHeight;
69
- canvas = cn;
70
- }
71
- else {
72
- this.container = canvas.parentElement;
73
- }
74
- }
75
- this.canvas = canvas;
76
- this.context = canvas.getContext(this.mode);
77
-
78
- this.textureCanvas = option.textureCanvas || null;
79
-
80
- // webgl模式
81
- if(this.mode === 'webgl') {
82
-
83
- this.context.enable(this.context.BLEND);// 开启混合功能:(注意,它不可和gl.DEPTH_TEST一起使用)
84
- this.context.blendFunc(this.context.SRC_ALPHA, this.context.ONE_MINUS_SRC_ALPHA); // 指定混合函数:
85
- // webglcontextlost webglcontextrestored
86
- jmUtils.bindEvent(canvas, 'webglcontextlost', (e)=> {
87
- console.log('canvas webglcontextlost', e);
88
- this.emit('webglcontextlost', e);
89
- });
90
- jmUtils.bindEvent(canvas, 'webglcontextrestored', (e)=> {
91
- console.log('canvas webglcontextrestored', e);
92
- this.emit('webglcontextrestored', e);
93
- });
94
- }
95
- this.__init(callback);
96
- }
97
-
98
- /**
99
- * 初始化画布
100
- * @method init
101
- */
102
- __init(callback) {
103
- /**
104
- * 当前所有图形类型
105
- * @property shapes
106
- * @type {object}
107
- */
108
- this.shapes = Object.assign({
109
- "path": jmPath,
110
- }, this.option.shapes);
111
-
112
- /**
113
- * 画控件前初始化
114
- * 为了解决一像素线条问题
115
- */
116
- this.on('beginDraw', function() {
117
- this.context.translate && this.context.translate(0.5, 0.5);
118
- });
119
- /**
120
- * 结束控件绘制 为了解决一像素线条问题
121
- */
122
- this.on('endDraw', function() {
123
- this.context.translate && this.context.translate(-0.5, -0.5);
124
- });
125
-
126
- // devicePixelRatio初始化
127
- let dpr = typeof window != 'undefined' && window.devicePixelRatio > 1? window.devicePixelRatio : 1;
128
- if(this.isWXMiniApp) {
129
- dpr = wx.getWindowInfo().pixelRatio || 1;
130
- }
131
- this.devicePixelRatio = dpr;
132
- // 为了解决锯齿问题,先放大canvas再缩放
133
- this.dprScaleSize = this.devicePixelRatio > 1? this.devicePixelRatio : 2;
134
-
135
- if(this.option.width > 0) this.width = this.option.width;
136
- if(this.option.height > 0) this.height = this.option.height;
137
- this.resize();
138
-
139
- //绑定事件
140
- this.eventHandler = new jmEvents(this, this.canvas.canvas || this.canvas);
141
-
142
- //如果指定了自动刷新
143
- if(this.option.autoRefresh) {
144
- this.autoRefresh();
145
- }
146
-
147
- if(callback) callback(this);
148
- }
149
-
150
- // 重置canvas大小,并判断高清屏,画图先放大二倍
151
- resize(w, h) {
152
- if(!this.canvas) return;
153
-
154
- this.__normalSize = this.__normalSize || { width: 0, height: 0};
155
- w = w || this.__normalSize.width || this.width, h = h || this.__normalSize.height || this.height;
156
-
157
- if(w) this.__normalSize.width = w;
158
- if(h) this.__normalSize.height = h;
159
-
160
- this.css('width', w + "px");
161
- this.css('height', h + "px");
162
- if(this.mode === '2d') {
163
- this.canvas.height = h * this.dprScaleSize;
164
- this.canvas.width = w * this.dprScaleSize;
165
- if(this.dprScaleSize !== 1) this.context.scale && this.context.scale(this.dprScaleSize, this.dprScaleSize);
166
- }
167
- else {
168
- this.canvas.width = w;
169
- this.canvas.height = h;
170
- }
171
-
172
- this.context.viewport && this.context.viewport(0, 0, w, h);
173
- this.needUpdate = true;
174
- }
175
-
176
- /**
177
- * 宽度
178
- * @property width
179
- * @type {number}
180
- */
181
- get width() {
182
- if(this.__normalSize && this.__normalSize.width) return this.__normalSize.width;
183
- if(this.canvas) return this.canvas.width;
184
- return 0;
185
- }
186
- set width(v) {
187
- this.needUpdate = true;
188
- if(this.canvas) {
189
- this.resize(v);
190
- }
191
- return v;
192
- }
193
-
194
- /**
195
- * 高度
196
- * @property height
197
- * @type {number}
198
- */
199
- get height() {
200
- if(this.__normalSize && this.__normalSize.height) return this.__normalSize.height;
201
- if(this.canvas) return this.canvas.height;
202
- return 0;
203
- }
204
- set height(v) {
205
- this.needUpdate = true;
206
- if(this.canvas) {
207
- this.resize(0, v);
208
- }
209
- return v;
210
- }
211
-
212
- /**
213
- * 创建jmGraph的静态对象
214
- *
215
- * @method create
216
- * @return {jmGraph} jmGraph实例对象
217
- */
218
- static create(...args) {
219
- return new jmGraph(...args);
220
- }
221
-
222
- /**
223
- * 获取当前画布在浏览器中的绝对定位
224
- *
225
- * @method getPosition
226
- * @return {postion} 返回定位坐标
227
- */
228
- getPosition() {
229
- const p = this.isWXMiniApp? {
230
- left: 0,
231
- top: 0
232
- } :jmUtils.getElementPosition(this.canvas.canvas || this.canvas);
233
-
234
- p.width = this.width;
235
- p.height = this.height;
236
- p.right = p.left + p.width;
237
- p.bottom = p.top + p.height;
238
- return p;
239
- }
240
-
241
- /**
242
- * 注册图形类型,图形类型必需有统一的构造函数。参数为画布句柄和参数对象。
243
- *
244
- * @method registerShape
245
- * @param {string} name 控件图形名称
246
- * @param {class} shape 图形控件类型
247
- */
248
- registerShape(name, shape) {
249
- this.shapes[name] = shape;
250
- }
251
-
252
- /**
253
- * 从已注册的图形类创建图形
254
- * 简单直观创建对象
255
- *
256
- * @method createShape
257
- * @param {string} shape 注册控件的名称 也可以直接是控件类型
258
- * @param {object} args 实例化控件的参数
259
- * @return {object} 已实例化控件的对象
260
- */
261
- createShape(shape, args) {
262
- if(typeof shape === 'string') {
263
- shape = this.shapes[shape];
264
- }
265
- if(shape) {
266
- if(!args) args = {};
267
- args.graph = this;
268
- let obj = new shape(args);
269
- return obj;
270
- }
271
- }
272
-
273
- /**
274
- * 生成阴影对象
275
- *
276
- * @method createShadow
277
- * @param {number} x x偏移量
278
- * @param {number} y y偏移量
279
- * @param {number} blur 模糊值
280
- * @param {string} color 颜色
281
- * @return {jmShadow} 阴影对象
282
- */
283
- createShadow(x, y, blur, color) {
284
- const sh = new jmShadow(x, y, blur, color);
285
- return sh;
286
- }
287
-
288
- /**
289
- * 生成线性渐变对象
290
- *
291
- * @method createLinearGradient
292
- * @param {number} x1 线性渐变起始点X坐标
293
- * @param {number} y1 线性渐变起始点Y坐标
294
- * @param {number} x2 线性渐变结束点X坐标
295
- * @param {number} y2 线性渐变结束点Y坐标
296
- * @return {jmGradient} 线性渐变对象
297
- */
298
- createLinearGradient(x1, y1, x2, y2, stops=[]) {
299
- const gradient = new jmGradient({
300
- type:'linear',
301
- x1: x1,
302
- y1: y1,
303
- x2: x2,
304
- y2: y2,
305
- stops
306
- });
307
- return gradient;
308
- }
309
-
310
- /**
311
- * 生成放射渐变对象
312
- *
313
- * @method createRadialGradient
314
- * @param {number} x1 放射渐变小圆中心X坐标
315
- * @param {number} y1 放射渐变小圆中心Y坐标
316
- * @param {number} r1 放射渐变小圆半径
317
- * @param {number} x2 放射渐变大圆中心X坐标
318
- * @param {number} y2 放射渐变大圆中心Y坐标
319
- * @param {number} r2 放射渐变大圆半径
320
- * @return {jmGradient} 放射渐变对象
321
- */
322
- createRadialGradient(x1, y1, r1, x2, y2, r2, stops=[]) {
323
- const gradient = new jmGradient({
324
- type:'radial',
325
- x1: x1,
326
- y1: y1,
327
- r1: r1,
328
- x2: x2,
329
- y2: y2,
330
- r2: r2,
331
- stops
332
- });
333
- return gradient;
334
- }
335
-
336
- /**
337
- * 重新刷新整个画板
338
- * 以加入动画事件触发延时10毫秒刷新,保存最尽的调用只刷新一次,加强性能的效果。
339
- *
340
- * @method refresh
341
- */
342
- refresh() {
343
- //加入动画,触发redraw,会导致多次refresh只redraw一次
344
- /*this.animate(function() {
345
- return false;
346
- },100,'jmgraph_refresh');*/
347
- this.redraw();
348
- }
349
-
350
- /**
351
- * 重新刷新整个画板
352
- * 此方法直接重画,与refresh效果类似
353
- *
354
- * @method redraw
355
- * @param {number} [w] 清除画布的宽度
356
- * @param {number} [h] 清除画布的高度
357
- */
358
- redraw(w, h) {
359
- this.clear(w||this.width, h||this.height);
360
- this.paint();
361
- }
362
-
363
- /**
364
- * 清除画布
365
- *
366
- * @method clear
367
- * @param {number} [w] 清除画布的宽度
368
- * @param {number} [h] 清除画布的高度
369
- */
370
- clear(w, h) {
371
- if(!w || !h) {
372
- w = this.width;
373
- h = this.height;
374
- /*if(this.scaleSize) {
375
- w = w / this.scaleSize.x;
376
- h = h / this.scaleSize.y;
377
- }*/
378
- }
379
-
380
- if(this.context.clearRect) {
381
- if(this.style && this.style.fill) {
382
- this.points = [
383
- {x:0, y:0},
384
- {x:w, y:0},
385
- {x:w, y:h},
386
- {x:0, y:h}
387
- ];
388
- this.style.close = true;// 封闭填充
389
- }
390
-
391
- this.context.clearRect(0, 0, w, h);
392
- }
393
- else if(this.mode === 'webgl' && this.context.clear) {
394
- const color = this.style && this.style.fill? this.utils.hexToRGBA(this.style.fill): {
395
- r: 0,
396
- g: 0,
397
- b: 0,
398
- a: 0
399
- };
400
- this.context.clearColor(color.r, color.g, color.b, color.a); // 设置清空颜色缓冲时的颜色值
401
- this.context.clear(this.context.COLOR_BUFFER_BIT); // 清空颜色缓冲区,也就是清空画布
402
- }
403
- }
404
-
405
- /**
406
- * 设置画布样式,此处只是设置其css样式
407
- *
408
- * @method css
409
- * @param {string} name 样式名
410
- * @param {string} value 样式值
411
- */
412
- css(name, value) {
413
- if(this.canvas && this.canvas.style) {
414
- if(typeof value != 'undefined') this.canvas.style[name] = value;
415
- return this.canvas.style[name];
416
- }
417
- }
418
-
419
- /**
420
- * 生成路径对象
421
- *
422
- * @method createPath
423
- * @param {array} points 路径中的描点集合
424
- * @param {style} style 当前路径的样式
425
- * @return {jmPath} 路径对象jmPath
426
- */
427
- createPath(points, style, option={}) {
428
- const path = this.createShape('path',{
429
- points: points,
430
- style: style,
431
- ...option
432
- });
433
- return path;
434
- }
435
-
436
- /**
437
- * 生成直线
438
- *
439
- * @method createLine
440
- * @param {point} start 直线的起点
441
- * @param {point} end 直线的终点
442
- * @param {style} 直线的样式
443
- * @return {jmLine} 直线对象
444
- */
445
- createLine(start, end, style) {
446
- const line = this.createShape('line', {
447
- start: start,
448
- end: end,
449
- style: style
450
- });
451
- return line;
452
- }
453
-
454
- /**
455
- * 缩小整个画布按比例0.9
456
- *
457
- * @method zoomOut
458
- */
459
- zoomOut() {
460
- this.scale(0.9 ,0.9);
461
- }
462
-
463
- /**
464
- * 放大 每次增大0.1的比例
465
- *
466
- * @method zoomIn
467
- */
468
- zoomIn() {
469
- this.scale(1.1 ,1.1);
470
- }
471
-
472
- /**
473
- * 大小复原
474
- *
475
- * @method zoomActual
476
- */
477
- zoomActual() {
478
- if(this.scaleSize) {
479
- this.scale(1 / this.scaleSize.x ,1 / this.scaleSize.y);
480
- }
481
- else {
482
- this.scale(1 ,1);
483
- }
484
- }
485
-
486
- /**
487
- * 放大缩小画布
488
- *
489
- * @method scale
490
- * @param {number} dx 缩放X轴比例
491
- * @param {number} dy 缩放Y轴比例
492
- */
493
- scale(dx, dy) {
494
- if(!this.normalSize) {
495
- this.normalSize = {
496
- width: this.canvas.width,
497
- height: this.canvas.height
498
- };
499
- }
500
-
501
- //this.context.scale && this.context.scale(dx,dy);
502
- if(!this.scaleSize) {
503
- this.scaleSize = {x: 1,y: 1};
504
- }
505
- else {
506
- this.scaleSize = {x: dx * this.scaleSize.x, y: dy * this.scaleSize.y};
507
- }
508
- this.canvas.style && (this.canvas.style.transform = `scale(${this.scaleSize.x}, ${this.scaleSize.y})`);
509
- }
510
-
511
- /**
512
- * 保存为base64图形数据
513
- *
514
- * @method toDataURL
515
- * @return {string} 当前画布图的base64字符串
516
- */
517
- toDataURL() {
518
- let data = this.canvas.toDataURL?this.canvas.toDataURL():'';
519
- return data;
520
- }
521
-
522
- /**
523
- * 自动刷新画版
524
- * @param {function} callback 执行回调
525
- */
526
- autoRefresh(callback) {
527
- if(this.___isAutoRefreshing) return;
528
- const self = this;
529
- this.___isAutoRefreshing = true;
530
-
531
- const refreshStartTime = Date.now();
532
- function update() {
533
- if(self.destroyed) {
534
- self.___isAutoRefreshing = false;
535
- return;// 已销毁
536
- }
537
- if(self.needUpdate) self.redraw();
538
-
539
- const time = Date.now() - refreshStartTime;
540
- // 触发刷新事件
541
- self.emit('update', time);
542
-
543
- self.__requestAnimationFrameFunHandler && self.cancelAnimationFrame(self.__requestAnimationFrameFunHandler);
544
- self.__requestAnimationFrameFunHandler = self.requestAnimationFrame(update);
545
- if(callback) callback();
546
- }
547
- self.__requestAnimationFrameFunHandler && this.cancelAnimationFrame(self.__requestAnimationFrameFunHandler);
548
- self.__requestAnimationFrameFunHandler = this.requestAnimationFrame(update);
549
- return this;
550
- }
551
-
552
- // 销毁当前对象
553
- destroy() {
554
- this.eventHandler.destroy();
555
- this.destroyed = true;// 标记已销毁
556
- }
557
- }
558
-
559
- export {
560
- jmGraph,
561
- jmUtils,
562
- jmList,
563
- jmProperty,
564
- jmShadow,
565
- jmGradient,
566
- jmEvents,
567
- jmControl,
568
- jmPath,
569
- };
1
+ import {jmUtils} from "./jmUtils.js";
2
+ import {jmList} from "./jmList.js";
3
+ import {jmProperty} from './jmProperty.js';
4
+ import {jmShadow} from "./jmShadow.js";
5
+ import {jmGradient} from "./jmGradient.js";
6
+ import {jmEvents} from "./jmEvents.js";
7
+ import {jmControl} from "./jmControl.js";
8
+ import {jmPath} from "./jmPath.js";
9
+
10
+ /**
11
+ * jmGraph画图类库
12
+ * 对canvas画图api进行二次封装,使其更易调用,省去很多重复的工作。
13
+ *
14
+ * @module jmGraph
15
+ * @class jmGraph
16
+ * @extends jmControl
17
+ * @param {element} canvas 标签canvas
18
+ * @param {object} option 参数:{width:宽,height:高}
19
+ * @param {function} callback 初始化后的回调
20
+ */
21
+ export default class jmGraph extends jmControl {
22
+
23
+ constructor(canvas, option, callback) {
24
+ if(typeof option == 'function') {
25
+ callback = option;
26
+ option = {};
27
+ }
28
+
29
+ option = option || {};
30
+ //option.mode = '2d'; // webgl | 2d 暂不支持webgl
31
+ option.interactive = true;
32
+ option.isRegular = true;// 规则的
33
+
34
+ super(option, 'jmGraph');
35
+
36
+ this.option = option || {};
37
+
38
+ this.devicePixelRatio = 1; // 根据屏幕的缩放倍数
39
+
40
+ /**
41
+ * 工具类
42
+ * @property utils/util
43
+ * @type {jmUtils}
44
+ */
45
+ this.util = this.utils = jmUtils;
46
+ // 模式 webgl | 2d
47
+ this.mode = option.mode || '2d';
48
+
49
+ //如果是小程序
50
+ if(typeof wx != 'undefined' && wx.canIUse && wx.canIUse('canvas')) {
51
+ if(typeof canvas === 'string') canvas = wx.createSelectorQuery().select('#' + canvas);
52
+ this.isWXMiniApp = true;// 微信小程序平台
53
+ this.container = canvas;
54
+ }
55
+ else {
56
+ if(typeof canvas === 'string' && typeof document != 'undefined') {
57
+ canvas = document.getElementById(canvas);
58
+ }
59
+ else if(canvas.length) {
60
+ canvas = canvas[0];
61
+ }
62
+
63
+ if(!canvas.getContext && typeof document != 'undefined') {
64
+ this.container = canvas;
65
+ let cn = document.createElement('canvas');
66
+ canvas.appendChild(cn);
67
+ cn.width = canvas.offsetWidth||canvas.clientWidth;
68
+ cn.height = canvas.offsetHeight||canvas.clientHeight;
69
+ canvas = cn;
70
+ }
71
+ else {
72
+ this.container = canvas.parentElement;
73
+ }
74
+ }
75
+ this.canvas = canvas;
76
+ this.context = canvas.getContext(this.mode);
77
+
78
+ this.textureCanvas = option.textureCanvas || null;
79
+
80
+ // webgl模式
81
+ if(this.mode === 'webgl') {
82
+
83
+ this.context.enable(this.context.BLEND);// 开启混合功能:(注意,它不可和gl.DEPTH_TEST一起使用)
84
+ this.context.blendFunc(this.context.SRC_ALPHA, this.context.ONE_MINUS_SRC_ALPHA); // 指定混合函数:
85
+ // webglcontextlost webglcontextrestored
86
+ jmUtils.bindEvent(canvas, 'webglcontextlost', (e)=> {
87
+ console.log('canvas webglcontextlost', e);
88
+ this.emit('webglcontextlost', e);
89
+ });
90
+ jmUtils.bindEvent(canvas, 'webglcontextrestored', (e)=> {
91
+ console.log('canvas webglcontextrestored', e);
92
+ this.emit('webglcontextrestored', e);
93
+ });
94
+ }
95
+ this.__init(callback);
96
+ }
97
+
98
+ /**
99
+ * 初始化画布
100
+ * @method init
101
+ */
102
+ __init(callback) {
103
+ /**
104
+ * 当前所有图形类型
105
+ * @property shapes
106
+ * @type {object}
107
+ */
108
+ this.shapes = Object.assign({
109
+ "path": jmPath,
110
+ }, this.option.shapes);
111
+
112
+ /**
113
+ * 画控件前初始化
114
+ * 为了解决一像素线条问题
115
+ */
116
+ this.on('beginDraw', function() {
117
+ this.context.translate && this.context.translate(0.5, 0.5);
118
+ });
119
+ /**
120
+ * 结束控件绘制 为了解决一像素线条问题
121
+ */
122
+ this.on('endDraw', function() {
123
+ this.context.translate && this.context.translate(-0.5, -0.5);
124
+ });
125
+
126
+ // devicePixelRatio初始化
127
+ let dpr = typeof window != 'undefined' && window.devicePixelRatio > 1? window.devicePixelRatio : 1;
128
+ if(this.isWXMiniApp) {
129
+ dpr = wx.getWindowInfo().pixelRatio || 1;
130
+ }
131
+ this.devicePixelRatio = dpr;
132
+ // 为了解决锯齿问题,先放大canvas再缩放
133
+ this.dprScaleSize = this.devicePixelRatio > 1? this.devicePixelRatio : 2;
134
+
135
+ if(this.option.width > 0) this.width = this.option.width;
136
+ if(this.option.height > 0) this.height = this.option.height;
137
+ this.resize();
138
+
139
+ //绑定事件
140
+ this.eventHandler = new jmEvents(this, this.canvas.canvas || this.canvas);
141
+
142
+ //如果指定了自动刷新
143
+ if(this.option.autoRefresh) {
144
+ this.autoRefresh();
145
+ }
146
+
147
+ if(callback) callback(this);
148
+ }
149
+
150
+ // 重置canvas大小,并判断高清屏,画图先放大二倍
151
+ resize(w, h) {
152
+ if(!this.canvas) return;
153
+
154
+ this.__normalSize = this.__normalSize || { width: 0, height: 0};
155
+ w = w || this.__normalSize.width || this.width, h = h || this.__normalSize.height || this.height;
156
+
157
+ if(w) this.__normalSize.width = w;
158
+ if(h) this.__normalSize.height = h;
159
+
160
+ this.css('width', w + "px");
161
+ this.css('height', h + "px");
162
+ if(this.mode === '2d') {
163
+ this.canvas.height = h * this.dprScaleSize;
164
+ this.canvas.width = w * this.dprScaleSize;
165
+ if(this.dprScaleSize !== 1) this.context.scale && this.context.scale(this.dprScaleSize, this.dprScaleSize);
166
+ }
167
+ else {
168
+ this.canvas.width = w;
169
+ this.canvas.height = h;
170
+ }
171
+
172
+ this.context.viewport && this.context.viewport(0, 0, w, h);
173
+ this.needUpdate = true;
174
+ }
175
+
176
+ /**
177
+ * 宽度
178
+ * @property width
179
+ * @type {number}
180
+ */
181
+ get width() {
182
+ if(this.__normalSize && this.__normalSize.width) return this.__normalSize.width;
183
+ if(this.canvas) return this.canvas.width;
184
+ return 0;
185
+ }
186
+ set width(v) {
187
+ this.needUpdate = true;
188
+ if(this.canvas) {
189
+ this.resize(v);
190
+ }
191
+ return v;
192
+ }
193
+
194
+ /**
195
+ * 高度
196
+ * @property height
197
+ * @type {number}
198
+ */
199
+ get height() {
200
+ if(this.__normalSize && this.__normalSize.height) return this.__normalSize.height;
201
+ if(this.canvas) return this.canvas.height;
202
+ return 0;
203
+ }
204
+ set height(v) {
205
+ this.needUpdate = true;
206
+ if(this.canvas) {
207
+ this.resize(0, v);
208
+ }
209
+ return v;
210
+ }
211
+
212
+ /**
213
+ * 创建jmGraph的静态对象
214
+ *
215
+ * @method create
216
+ * @return {jmGraph} jmGraph实例对象
217
+ */
218
+ static create(...args) {
219
+ return new jmGraph(...args);
220
+ }
221
+
222
+ /**
223
+ * 获取当前画布在浏览器中的绝对定位
224
+ *
225
+ * @method getPosition
226
+ * @return {postion} 返回定位坐标
227
+ */
228
+ getPosition() {
229
+ const p = this.isWXMiniApp? {
230
+ left: 0,
231
+ top: 0
232
+ } :jmUtils.getElementPosition(this.canvas.canvas || this.canvas);
233
+
234
+ p.width = this.width;
235
+ p.height = this.height;
236
+ p.right = p.left + p.width;
237
+ p.bottom = p.top + p.height;
238
+ return p;
239
+ }
240
+
241
+ /**
242
+ * 注册图形类型,图形类型必需有统一的构造函数。参数为画布句柄和参数对象。
243
+ *
244
+ * @method registerShape
245
+ * @param {string} name 控件图形名称
246
+ * @param {class} shape 图形控件类型
247
+ */
248
+ registerShape(name, shape) {
249
+ this.shapes[name] = shape;
250
+ }
251
+
252
+ /**
253
+ * 从已注册的图形类创建图形
254
+ * 简单直观创建对象
255
+ *
256
+ * @method createShape
257
+ * @param {string} shape 注册控件的名称 也可以直接是控件类型
258
+ * @param {object} args 实例化控件的参数
259
+ * @return {object} 已实例化控件的对象
260
+ */
261
+ createShape(shape, args) {
262
+ if(typeof shape === 'string') {
263
+ shape = this.shapes[shape];
264
+ }
265
+ if(shape) {
266
+ if(!args) args = {};
267
+ args.graph = this;
268
+ let obj = new shape(args);
269
+ return obj;
270
+ }
271
+ }
272
+
273
+ /**
274
+ * 生成阴影对象
275
+ *
276
+ * @method createShadow
277
+ * @param {number} x x偏移量
278
+ * @param {number} y y偏移量
279
+ * @param {number} blur 模糊值
280
+ * @param {string} color 颜色
281
+ * @return {jmShadow} 阴影对象
282
+ */
283
+ createShadow(x, y, blur, color) {
284
+ const sh = new jmShadow(x, y, blur, color);
285
+ return sh;
286
+ }
287
+
288
+ /**
289
+ * 生成线性渐变对象
290
+ *
291
+ * @method createLinearGradient
292
+ * @param {number} x1 线性渐变起始点X坐标
293
+ * @param {number} y1 线性渐变起始点Y坐标
294
+ * @param {number} x2 线性渐变结束点X坐标
295
+ * @param {number} y2 线性渐变结束点Y坐标
296
+ * @return {jmGradient} 线性渐变对象
297
+ */
298
+ createLinearGradient(x1, y1, x2, y2, stops=[]) {
299
+ const gradient = new jmGradient({
300
+ type:'linear',
301
+ x1: x1,
302
+ y1: y1,
303
+ x2: x2,
304
+ y2: y2,
305
+ stops
306
+ });
307
+ return gradient;
308
+ }
309
+
310
+ /**
311
+ * 生成放射渐变对象
312
+ *
313
+ * @method createRadialGradient
314
+ * @param {number} x1 放射渐变小圆中心X坐标
315
+ * @param {number} y1 放射渐变小圆中心Y坐标
316
+ * @param {number} r1 放射渐变小圆半径
317
+ * @param {number} x2 放射渐变大圆中心X坐标
318
+ * @param {number} y2 放射渐变大圆中心Y坐标
319
+ * @param {number} r2 放射渐变大圆半径
320
+ * @return {jmGradient} 放射渐变对象
321
+ */
322
+ createRadialGradient(x1, y1, r1, x2, y2, r2, stops=[]) {
323
+ const gradient = new jmGradient({
324
+ type:'radial',
325
+ x1: x1,
326
+ y1: y1,
327
+ r1: r1,
328
+ x2: x2,
329
+ y2: y2,
330
+ r2: r2,
331
+ stops
332
+ });
333
+ return gradient;
334
+ }
335
+
336
+ /**
337
+ * 重新刷新整个画板
338
+ * 以加入动画事件触发延时10毫秒刷新,保存最尽的调用只刷新一次,加强性能的效果。
339
+ *
340
+ * @method refresh
341
+ */
342
+ refresh() {
343
+ //加入动画,触发redraw,会导致多次refresh只redraw一次
344
+ /*this.animate(function() {
345
+ return false;
346
+ },100,'jmgraph_refresh');*/
347
+ this.redraw();
348
+ }
349
+
350
+ /**
351
+ * 重新刷新整个画板
352
+ * 此方法直接重画,与refresh效果类似
353
+ *
354
+ * @method redraw
355
+ * @param {number} [w] 清除画布的宽度
356
+ * @param {number} [h] 清除画布的高度
357
+ */
358
+ redraw(w, h) {
359
+ this.clear(w||this.width, h||this.height);
360
+ this.paint();
361
+ }
362
+
363
+ /**
364
+ * 清除画布
365
+ *
366
+ * @method clear
367
+ * @param {number} [w] 清除画布的宽度
368
+ * @param {number} [h] 清除画布的高度
369
+ */
370
+ clear(w, h) {
371
+ if(!w || !h) {
372
+ w = this.width;
373
+ h = this.height;
374
+ /*if(this.scaleSize) {
375
+ w = w / this.scaleSize.x;
376
+ h = h / this.scaleSize.y;
377
+ }*/
378
+ }
379
+
380
+ if(this.context.clearRect) {
381
+ if(this.style && this.style.fill) {
382
+ this.points = [
383
+ {x:0, y:0},
384
+ {x:w, y:0},
385
+ {x:w, y:h},
386
+ {x:0, y:h}
387
+ ];
388
+ this.style.close = true;// 封闭填充
389
+ }
390
+
391
+ this.context.clearRect(0, 0, w, h);
392
+ }
393
+ else if(this.mode === 'webgl' && this.context.clear) {
394
+ const color = this.style && this.style.fill? this.utils.hexToRGBA(this.style.fill): {
395
+ r: 0,
396
+ g: 0,
397
+ b: 0,
398
+ a: 0
399
+ };
400
+ this.context.clearColor(color.r, color.g, color.b, color.a); // 设置清空颜色缓冲时的颜色值
401
+ this.context.clear(this.context.COLOR_BUFFER_BIT); // 清空颜色缓冲区,也就是清空画布
402
+ }
403
+ }
404
+
405
+ /**
406
+ * 设置画布样式,此处只是设置其css样式
407
+ *
408
+ * @method css
409
+ * @param {string} name 样式名
410
+ * @param {string} value 样式值
411
+ */
412
+ css(name, value) {
413
+ if(this.canvas && this.canvas.style) {
414
+ if(typeof value != 'undefined') this.canvas.style[name] = value;
415
+ return this.canvas.style[name];
416
+ }
417
+ }
418
+
419
+ /**
420
+ * 生成路径对象
421
+ *
422
+ * @method createPath
423
+ * @param {array} points 路径中的描点集合
424
+ * @param {style} style 当前路径的样式
425
+ * @return {jmPath} 路径对象jmPath
426
+ */
427
+ createPath(points, style, option={}) {
428
+ const path = this.createShape('path',{
429
+ points: points,
430
+ style: style,
431
+ ...option
432
+ });
433
+ return path;
434
+ }
435
+
436
+ /**
437
+ * 生成直线
438
+ *
439
+ * @method createLine
440
+ * @param {point} start 直线的起点
441
+ * @param {point} end 直线的终点
442
+ * @param {style} 直线的样式
443
+ * @return {jmLine} 直线对象
444
+ */
445
+ createLine(start, end, style) {
446
+ const line = this.createShape('line', {
447
+ start: start,
448
+ end: end,
449
+ style: style
450
+ });
451
+ return line;
452
+ }
453
+
454
+ /**
455
+ * 缩小整个画布按比例0.9
456
+ *
457
+ * @method zoomOut
458
+ */
459
+ zoomOut() {
460
+ this.scale(0.9 ,0.9);
461
+ }
462
+
463
+ /**
464
+ * 放大 每次增大0.1的比例
465
+ *
466
+ * @method zoomIn
467
+ */
468
+ zoomIn() {
469
+ this.scale(1.1 ,1.1);
470
+ }
471
+
472
+ /**
473
+ * 大小复原
474
+ *
475
+ * @method zoomActual
476
+ */
477
+ zoomActual() {
478
+ if(this.scaleSize) {
479
+ this.scale(1 / this.scaleSize.x ,1 / this.scaleSize.y);
480
+ }
481
+ else {
482
+ this.scale(1 ,1);
483
+ }
484
+ }
485
+
486
+ /**
487
+ * 放大缩小画布
488
+ *
489
+ * @method scale
490
+ * @param {number} dx 缩放X轴比例
491
+ * @param {number} dy 缩放Y轴比例
492
+ */
493
+ scale(dx, dy) {
494
+ if(!this.normalSize) {
495
+ this.normalSize = {
496
+ width: this.canvas.width,
497
+ height: this.canvas.height
498
+ };
499
+ }
500
+
501
+ //this.context.scale && this.context.scale(dx,dy);
502
+ if(!this.scaleSize) {
503
+ this.scaleSize = {x: 1,y: 1};
504
+ }
505
+ else {
506
+ this.scaleSize = {x: dx * this.scaleSize.x, y: dy * this.scaleSize.y};
507
+ }
508
+ this.canvas.style && (this.canvas.style.transform = `scale(${this.scaleSize.x}, ${this.scaleSize.y})`);
509
+ }
510
+
511
+ /**
512
+ * 保存为base64图形数据
513
+ *
514
+ * @method toDataURL
515
+ * @return {string} 当前画布图的base64字符串
516
+ */
517
+ toDataURL() {
518
+ let data = this.canvas.toDataURL?this.canvas.toDataURL():'';
519
+ return data;
520
+ }
521
+
522
+ /**
523
+ * 自动刷新画版
524
+ * @param {function} callback 执行回调
525
+ */
526
+ autoRefresh(callback) {
527
+ if(this.___isAutoRefreshing) return;
528
+ const self = this;
529
+ this.___isAutoRefreshing = true;
530
+
531
+ const refreshStartTime = Date.now();
532
+ function update() {
533
+ if(self.destroyed) {
534
+ self.___isAutoRefreshing = false;
535
+ return;// 已销毁
536
+ }
537
+ if(self.needUpdate) self.redraw();
538
+
539
+ const time = Date.now() - refreshStartTime;
540
+ // 触发刷新事件
541
+ self.emit('update', time);
542
+
543
+ self.__requestAnimationFrameFunHandler && self.cancelAnimationFrame(self.__requestAnimationFrameFunHandler);
544
+ self.__requestAnimationFrameFunHandler = self.requestAnimationFrame(update);
545
+ if(callback) callback();
546
+ }
547
+ self.__requestAnimationFrameFunHandler && this.cancelAnimationFrame(self.__requestAnimationFrameFunHandler);
548
+ self.__requestAnimationFrameFunHandler = this.requestAnimationFrame(update);
549
+ return this;
550
+ }
551
+
552
+ // 销毁当前对象
553
+ destroy() {
554
+ this.eventHandler.destroy();
555
+ this.destroyed = true;// 标记已销毁
556
+ }
557
+ }
558
+
559
+ export {
560
+ jmGraph,
561
+ jmUtils,
562
+ jmList,
563
+ jmProperty,
564
+ jmShadow,
565
+ jmGradient,
566
+ jmEvents,
567
+ jmControl,
568
+ jmPath,
569
+ };