jmgraph 3.2.20 → 3.2.21
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/README.md +137 -4
- package/dist/jmgraph.core.min.js +1 -1
- package/dist/jmgraph.core.min.js.map +1 -1
- package/dist/jmgraph.js +976 -827
- package/dist/jmgraph.min.js +1 -1
- package/index.js +13 -26
- package/package.json +1 -1
- package/src/core/jmControl.js +199 -30
- package/src/core/jmFilter.js +150 -0
- package/src/core/jmGraph.js +16 -265
- package/src/core/jmUtils.js +46 -37
- package/src/lib/webgl/base.js +10 -36
- package/src/lib/webgl/gradient.js +16 -3
- package/src/lib/webgl/index.js +5 -4
- package/src/lib/webgl/path.js +156 -33
- package/src/shapes/jmLabel.js +1 -62
- package/src/shapes/jmRect.js +107 -29
package/src/core/jmGraph.js
CHANGED
|
@@ -3,10 +3,10 @@ import {jmList} from "./jmList.js";
|
|
|
3
3
|
import {jmProperty} from './jmProperty.js';
|
|
4
4
|
import {jmShadow} from "./jmShadow.js";
|
|
5
5
|
import {jmGradient} from "./jmGradient.js";
|
|
6
|
+
import {jmFilter} from "./jmFilter.js";
|
|
6
7
|
import {jmEvents} from "./jmEvents.js";
|
|
7
8
|
import {jmControl} from "./jmControl.js";
|
|
8
9
|
import {jmPath} from "./jmPath.js";
|
|
9
|
-
import {jmLayer} from "./jmLayer.js";
|
|
10
10
|
|
|
11
11
|
/**
|
|
12
12
|
* jmGraph画图类库
|
|
@@ -286,9 +286,7 @@ export default class jmGraph extends jmControl {
|
|
|
286
286
|
if(shape) {
|
|
287
287
|
if(!args) args = {};
|
|
288
288
|
args.graph = this;
|
|
289
|
-
|
|
290
|
-
// 添加到活动图层
|
|
291
|
-
this.addShapeToLayer(obj);
|
|
289
|
+
const obj = new shape(args);
|
|
292
290
|
return obj;
|
|
293
291
|
}
|
|
294
292
|
}
|
|
@@ -611,232 +609,6 @@ export default class jmGraph extends jmControl {
|
|
|
611
609
|
return this; // 支持链式调用
|
|
612
610
|
}
|
|
613
611
|
|
|
614
|
-
/**
|
|
615
|
-
* 初始化图层系统
|
|
616
|
-
* 创建图层管理的基础结构,包括默认图层
|
|
617
|
-
*
|
|
618
|
-
* @method initLayers
|
|
619
|
-
* @private
|
|
620
|
-
*/
|
|
621
|
-
initLayers() {
|
|
622
|
-
if(!this.layers) {
|
|
623
|
-
this.layers = new jmList();
|
|
624
|
-
// 创建默认图层
|
|
625
|
-
const defaultLayer = this.createLayer('Default Layer');
|
|
626
|
-
this.activeLayer = defaultLayer;
|
|
627
|
-
}
|
|
628
|
-
}
|
|
629
|
-
|
|
630
|
-
/**
|
|
631
|
-
* 创建新图层
|
|
632
|
-
* 图层用于组织和管理图形对象,支持可见性和锁定控制
|
|
633
|
-
*
|
|
634
|
-
* @method createLayer
|
|
635
|
-
* @param {string} name 图层名称(必须唯一)
|
|
636
|
-
* @param {object} [options] 图层选项
|
|
637
|
-
* @param {boolean} [options.visible=true] 图层是否可见
|
|
638
|
-
* @param {boolean} [options.locked=false] 图层是否锁定(锁定后不可交互)
|
|
639
|
-
* @return {jmLayer} 新创建的图层
|
|
640
|
-
*/
|
|
641
|
-
createLayer(name, options = {}) {
|
|
642
|
-
// 参数验证
|
|
643
|
-
if(!name || typeof name !== 'string') {
|
|
644
|
-
console.warn('jmGraph: createLayer - 图层名称必须是非空字符串');
|
|
645
|
-
name = `Layer_${Date.now()}`;
|
|
646
|
-
}
|
|
647
|
-
|
|
648
|
-
this.initLayers();
|
|
649
|
-
|
|
650
|
-
// 检查图层名称是否已存在
|
|
651
|
-
const existingLayer = this.getLayer(name);
|
|
652
|
-
if(existingLayer) {
|
|
653
|
-
console.warn(`jmGraph: 图层 "${name}" 已存在,将返回现有图层`);
|
|
654
|
-
return existingLayer;
|
|
655
|
-
}
|
|
656
|
-
|
|
657
|
-
const layer = new jmLayer({
|
|
658
|
-
name: name,
|
|
659
|
-
graph: this,
|
|
660
|
-
...options
|
|
661
|
-
});
|
|
662
|
-
|
|
663
|
-
this.layers.add(layer);
|
|
664
|
-
this.children.add(layer);
|
|
665
|
-
this.needUpdate = true;
|
|
666
|
-
return layer;
|
|
667
|
-
}
|
|
668
|
-
|
|
669
|
-
/**
|
|
670
|
-
* 获取所有图层
|
|
671
|
-
*
|
|
672
|
-
* @method getLayers
|
|
673
|
-
* @return {jmList} 图层列表
|
|
674
|
-
*/
|
|
675
|
-
getLayers() {
|
|
676
|
-
this.initLayers();
|
|
677
|
-
return this.layers;
|
|
678
|
-
}
|
|
679
|
-
|
|
680
|
-
/**
|
|
681
|
-
* 根据名称获取图层
|
|
682
|
-
*
|
|
683
|
-
* @method getLayer
|
|
684
|
-
* @param {string} name 图层名称
|
|
685
|
-
* @return {jmLayer|null} 图层对象,如果不存在则返回null
|
|
686
|
-
*/
|
|
687
|
-
getLayer(name) {
|
|
688
|
-
this.initLayers();
|
|
689
|
-
|
|
690
|
-
if(!name) return null;
|
|
691
|
-
|
|
692
|
-
let result = null;
|
|
693
|
-
this.layers.each((i, layer) => {
|
|
694
|
-
if(layer.name === name) {
|
|
695
|
-
result = layer;
|
|
696
|
-
return false; // 找到后停止遍历
|
|
697
|
-
}
|
|
698
|
-
});
|
|
699
|
-
return result;
|
|
700
|
-
}
|
|
701
|
-
|
|
702
|
-
/**
|
|
703
|
-
* 设置活动图层
|
|
704
|
-
* 新创建的图形将自动添加到活动图层
|
|
705
|
-
*
|
|
706
|
-
* @method setActiveLayer
|
|
707
|
-
* @param {string|jmLayer} layer 图层名称或图层对象
|
|
708
|
-
* @return {jmGraph} 返回当前实例,支持链式调用
|
|
709
|
-
*/
|
|
710
|
-
setActiveLayer(layer) {
|
|
711
|
-
this.initLayers();
|
|
712
|
-
|
|
713
|
-
// 支持传入图层名称或图层对象
|
|
714
|
-
if(typeof layer === 'string') {
|
|
715
|
-
layer = this.getLayer(layer);
|
|
716
|
-
}
|
|
717
|
-
|
|
718
|
-
if(!layer || !(layer instanceof jmLayer)) {
|
|
719
|
-
console.warn('jmGraph: setActiveLayer - 无效的图层');
|
|
720
|
-
return this;
|
|
721
|
-
}
|
|
722
|
-
|
|
723
|
-
this.activeLayer = layer;
|
|
724
|
-
return this;
|
|
725
|
-
}
|
|
726
|
-
|
|
727
|
-
/**
|
|
728
|
-
* 获取当前活动图层
|
|
729
|
-
* 活动图层是新创建图形的默认容器
|
|
730
|
-
*
|
|
731
|
-
* @method getActiveLayer
|
|
732
|
-
* @return {jmLayer} 当前活动图层
|
|
733
|
-
*/
|
|
734
|
-
getActiveLayer() {
|
|
735
|
-
this.initLayers();
|
|
736
|
-
return this.activeLayer;
|
|
737
|
-
}
|
|
738
|
-
|
|
739
|
-
/**
|
|
740
|
-
* 移除图层
|
|
741
|
-
* 删除指定图层及其包含的所有图形
|
|
742
|
-
* 注意:默认图层不可删除
|
|
743
|
-
*
|
|
744
|
-
* @method removeLayer
|
|
745
|
-
* @param {string|jmLayer} layer 图层名称或图层对象
|
|
746
|
-
* @return {boolean} 是否成功删除
|
|
747
|
-
*/
|
|
748
|
-
removeLayer(layer) {
|
|
749
|
-
this.initLayers();
|
|
750
|
-
|
|
751
|
-
// 支持传入图层名称或图层对象
|
|
752
|
-
if(typeof layer === 'string') {
|
|
753
|
-
layer = this.getLayer(layer);
|
|
754
|
-
}
|
|
755
|
-
|
|
756
|
-
if(!layer) {
|
|
757
|
-
console.warn('jmGraph: removeLayer - 图层不存在');
|
|
758
|
-
return false;
|
|
759
|
-
}
|
|
760
|
-
|
|
761
|
-
// 禁止删除默认图层
|
|
762
|
-
if(layer.name === 'Default Layer') {
|
|
763
|
-
console.warn('jmGraph: 不能删除默认图层');
|
|
764
|
-
return false;
|
|
765
|
-
}
|
|
766
|
-
|
|
767
|
-
// 如果删除的是当前活动图层,切换到默认图层
|
|
768
|
-
if(this.activeLayer === layer) {
|
|
769
|
-
this.activeLayer = this.getLayer('Default Layer');
|
|
770
|
-
}
|
|
771
|
-
|
|
772
|
-
this.layers.remove(layer);
|
|
773
|
-
this.children.remove(layer);
|
|
774
|
-
this.needUpdate = true;
|
|
775
|
-
return true;
|
|
776
|
-
}
|
|
777
|
-
|
|
778
|
-
/**
|
|
779
|
-
* 将形状添加到指定图层
|
|
780
|
-
* 如果未指定图层,则添加到当前活动图层
|
|
781
|
-
*
|
|
782
|
-
* @method addShapeToLayer
|
|
783
|
-
* @param {jmControl} shape 要添加的形状对象
|
|
784
|
-
* @param {string|jmLayer} [layer] 图层名称或图层对象,默认为当前活动图层
|
|
785
|
-
* @return {jmGraph} 返回当前实例,支持链式调用
|
|
786
|
-
*/
|
|
787
|
-
addShapeToLayer(shape, layer) {
|
|
788
|
-
this.initLayers();
|
|
789
|
-
|
|
790
|
-
// 参数验证
|
|
791
|
-
if(!shape) {
|
|
792
|
-
console.warn('jmGraph: addShapeToLayer - 无效的形状对象');
|
|
793
|
-
return this;
|
|
794
|
-
}
|
|
795
|
-
|
|
796
|
-
// 确定目标图层
|
|
797
|
-
if(!layer) {
|
|
798
|
-
layer = this.activeLayer;
|
|
799
|
-
} else if(typeof layer === 'string') {
|
|
800
|
-
layer = this.getLayer(layer);
|
|
801
|
-
}
|
|
802
|
-
|
|
803
|
-
if(!layer) {
|
|
804
|
-
console.warn('jmGraph: addShapeToLayer - 图层不存在');
|
|
805
|
-
return this;
|
|
806
|
-
}
|
|
807
|
-
|
|
808
|
-
layer.children.add(shape);
|
|
809
|
-
this.needUpdate = true;
|
|
810
|
-
return this;
|
|
811
|
-
}
|
|
812
|
-
|
|
813
|
-
/**
|
|
814
|
-
* 从图层中移除形状
|
|
815
|
-
*
|
|
816
|
-
* @method removeShapeFromLayer
|
|
817
|
-
* @param {jmControl} shape 要移除的形状对象
|
|
818
|
-
* @return {jmGraph} 返回当前实例,支持链式调用
|
|
819
|
-
*/
|
|
820
|
-
removeShapeFromLayer(shape) {
|
|
821
|
-
if(!shape) {
|
|
822
|
-
console.warn('jmGraph: removeShapeFromLayer - 无效的形状对象');
|
|
823
|
-
return this;
|
|
824
|
-
}
|
|
825
|
-
|
|
826
|
-
// 从所有图层中查找并移除
|
|
827
|
-
if(this.layers) {
|
|
828
|
-
this.layers.each((i, layer) => {
|
|
829
|
-
if(layer.children.contains(shape)) {
|
|
830
|
-
layer.children.remove(shape);
|
|
831
|
-
this.needUpdate = true;
|
|
832
|
-
return false; // 找到后停止遍历
|
|
833
|
-
}
|
|
834
|
-
});
|
|
835
|
-
}
|
|
836
|
-
|
|
837
|
-
return this;
|
|
838
|
-
}
|
|
839
|
-
|
|
840
612
|
/**
|
|
841
613
|
* 保存为base64图形数据
|
|
842
614
|
*
|
|
@@ -903,48 +675,27 @@ export default class jmGraph extends jmControl {
|
|
|
903
675
|
}
|
|
904
676
|
|
|
905
677
|
/**
|
|
906
|
-
*
|
|
907
|
-
*
|
|
908
|
-
*
|
|
678
|
+
* 遍历所有形状,生成SVG标记
|
|
679
|
+
*
|
|
909
680
|
* @method toSVG
|
|
910
681
|
* @return {string} SVG字符串
|
|
911
682
|
*/
|
|
912
683
|
toSVG() {
|
|
913
684
|
// SVG头部,包含命名空间和画布尺寸
|
|
914
685
|
let svg = `<svg width="${this.width}" height="${this.height}" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 ${this.width} ${this.height}">`;
|
|
915
|
-
|
|
686
|
+
|
|
916
687
|
// 添加背景色(如果有)
|
|
917
688
|
if(this.style && this.style.fill) {
|
|
918
689
|
svg += `<rect width="100%" height="100%" fill="${this.style.fill}"/>`;
|
|
919
690
|
}
|
|
920
|
-
|
|
921
|
-
//
|
|
922
|
-
|
|
923
|
-
|
|
924
|
-
|
|
925
|
-
|
|
926
|
-
|
|
927
|
-
|
|
928
|
-
// 遍历图层中的所有形状
|
|
929
|
-
layer.children.each((j, shape) => {
|
|
930
|
-
if(shape.toSVG) {
|
|
931
|
-
svg += shape.toSVG();
|
|
932
|
-
}
|
|
933
|
-
});
|
|
934
|
-
|
|
935
|
-
svg += '</g>';
|
|
936
|
-
}
|
|
937
|
-
});
|
|
938
|
-
}
|
|
939
|
-
else {
|
|
940
|
-
// 遍历直接添加的形状(兼容没有图层系统的情况)
|
|
941
|
-
this.children.each((i, shape) => {
|
|
942
|
-
if(shape.toSVG) {
|
|
943
|
-
svg += shape.toSVG();
|
|
944
|
-
}
|
|
945
|
-
});
|
|
946
|
-
}
|
|
947
|
-
|
|
691
|
+
|
|
692
|
+
// 遍历所有直接添加的形状
|
|
693
|
+
this.children.each((i, shape) => {
|
|
694
|
+
if(shape.toSVG) {
|
|
695
|
+
svg += shape.toSVG();
|
|
696
|
+
}
|
|
697
|
+
});
|
|
698
|
+
|
|
948
699
|
svg += '</svg>';
|
|
949
700
|
return svg;
|
|
950
701
|
}
|
|
@@ -1010,15 +761,15 @@ export default class jmGraph extends jmControl {
|
|
|
1010
761
|
}
|
|
1011
762
|
}
|
|
1012
763
|
|
|
1013
|
-
export {
|
|
1014
|
-
jmGraph,
|
|
764
|
+
export {
|
|
765
|
+
jmGraph,
|
|
1015
766
|
jmUtils,
|
|
1016
767
|
jmList,
|
|
1017
768
|
jmProperty,
|
|
1018
769
|
jmShadow,
|
|
1019
770
|
jmGradient,
|
|
771
|
+
jmFilter,
|
|
1020
772
|
jmEvents,
|
|
1021
773
|
jmControl,
|
|
1022
774
|
jmPath,
|
|
1023
|
-
jmLayer,
|
|
1024
775
|
};
|
package/src/core/jmUtils.js
CHANGED
|
@@ -165,66 +165,75 @@ export default class jmUtils {
|
|
|
165
165
|
* @param {function} copyHandler 复制对象回调,如果返回undefined,就走后面的逻辑,否则到这里中止
|
|
166
166
|
* @return {object} 参数source的拷贝对象
|
|
167
167
|
*/
|
|
168
|
-
static clone(source, target, deep = false, copyHandler = null, deepIndex = 0) {
|
|
168
|
+
static clone(source, target, deep = false, copyHandler = null, deepIndex = 0, cloned = null) {
|
|
169
169
|
// 如果有指定回调,则用回调处理,否则走后面的复制逻辑
|
|
170
170
|
if(typeof copyHandler === 'function') {
|
|
171
171
|
const obj = copyHandler(source, deep, deepIndex);
|
|
172
172
|
if(obj) return obj;
|
|
173
173
|
}
|
|
174
|
-
|
|
174
|
+
|
|
175
|
+
// 首次调用时初始化克隆映射表(用于处理循环引用)
|
|
176
|
+
if(!cloned) cloned = new WeakMap();
|
|
175
177
|
|
|
176
178
|
if(typeof target === 'boolean') {
|
|
177
179
|
deep = target;
|
|
178
180
|
target = undefined;
|
|
179
181
|
}
|
|
180
182
|
|
|
181
|
-
//
|
|
182
|
-
if(
|
|
183
|
-
return target;
|
|
183
|
+
// 非对象直接返回
|
|
184
|
+
if(!source || typeof source !== 'object') {
|
|
185
|
+
return typeof target !== 'undefined' ? target : source;
|
|
184
186
|
}
|
|
185
187
|
|
|
186
|
-
|
|
187
|
-
|
|
188
|
+
// 如果source已经被克隆过,直接返回之前的克隆对象,打破循环引用
|
|
189
|
+
if(cloned.has(source)) return cloned.get(source);
|
|
188
190
|
|
|
191
|
+
// 数组处理
|
|
192
|
+
if(Array.isArray(source)) {
|
|
189
193
|
//如果为当前泛型,则直接new
|
|
190
194
|
if(this.isType(source, jmList)) {
|
|
191
195
|
return new jmList(source);
|
|
192
196
|
}
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
dest.push(this.clone(source[i], target[i], deep, copyHandler, deepIndex));
|
|
199
|
-
}
|
|
200
|
-
return dest;
|
|
201
|
-
}
|
|
202
|
-
return source.slice(0);
|
|
203
|
-
}
|
|
204
|
-
|
|
205
|
-
if(source.__proto__) target.__proto__ = source.__proto__;
|
|
206
|
-
|
|
207
|
-
for(let k in source) {
|
|
208
|
-
if(k === 'constructor') continue;
|
|
209
|
-
const v = source[k];
|
|
210
|
-
// 不复制页面元素和class对象
|
|
211
|
-
if(v && (v.tagName || v.getContext)) {
|
|
212
|
-
target[k] = v;
|
|
213
|
-
continue;
|
|
214
|
-
}
|
|
215
|
-
|
|
216
|
-
// 如果不是对象和空,则采用target的属性
|
|
217
|
-
if(typeof target[k] === 'object' || typeof target[k] === 'undefined') {
|
|
218
|
-
target[k] = this.clone(v, target[k], deep, copyHandler, deepIndex);
|
|
197
|
+
if(deep) {
|
|
198
|
+
let dest = [];
|
|
199
|
+
cloned.set(source, dest);
|
|
200
|
+
for(let i = 0; i < source.length; i++) {
|
|
201
|
+
dest.push(this.clone(source[i], undefined, deep, copyHandler, deepIndex + 1, cloned));
|
|
219
202
|
}
|
|
203
|
+
return dest;
|
|
220
204
|
}
|
|
221
|
-
return
|
|
205
|
+
return source.slice(0);
|
|
222
206
|
}
|
|
223
|
-
|
|
224
|
-
|
|
207
|
+
|
|
208
|
+
// 不复制页面元素和class对象(如jmControl实例等复杂对象保持引用)
|
|
209
|
+
if(source.tagName || source.getContext || source.emit) {
|
|
210
|
+
return source;
|
|
225
211
|
}
|
|
226
212
|
|
|
227
|
-
|
|
213
|
+
// 普通对象处理
|
|
214
|
+
target = target || {};
|
|
215
|
+
cloned.set(source, target);
|
|
216
|
+
|
|
217
|
+
// 保持原型链一致
|
|
218
|
+
if(source.__proto__) target.__proto__ = source.__proto__;
|
|
219
|
+
|
|
220
|
+
// 遍历自身可枚举属性(字符串键 + Symbol键),避免触发原型链上宿主对象的getter
|
|
221
|
+
const keys = Object.keys(source).concat(Object.getOwnPropertySymbols(source));
|
|
222
|
+
for(const k of keys) {
|
|
223
|
+
if(k === 'constructor') continue;
|
|
224
|
+
const v = source[k];
|
|
225
|
+
// 不复制页面元素和class对象
|
|
226
|
+
if(v && (v.tagName || v.getContext || v.emit)) {
|
|
227
|
+
target[k] = v;
|
|
228
|
+
continue;
|
|
229
|
+
}
|
|
230
|
+
|
|
231
|
+
// 如果不是对象和空,则采用target的属性
|
|
232
|
+
if(typeof target[k] === 'object' || typeof target[k] === 'undefined') {
|
|
233
|
+
target[k] = this.clone(v, target[k], deep, copyHandler, deepIndex + 1, cloned);
|
|
234
|
+
}
|
|
235
|
+
}
|
|
236
|
+
return target;
|
|
228
237
|
}
|
|
229
238
|
|
|
230
239
|
/**
|
package/src/lib/webgl/base.js
CHANGED
|
@@ -265,7 +265,6 @@ class WeblBase {
|
|
|
265
265
|
|
|
266
266
|
// 创建程序
|
|
267
267
|
createProgram(vertexSrc, fragmentSrc) {
|
|
268
|
-
this.context.lineWidth(1);
|
|
269
268
|
return createProgram(this.context, vertexSrc, fragmentSrc);
|
|
270
269
|
}
|
|
271
270
|
|
|
@@ -378,7 +377,9 @@ class WeblBase {
|
|
|
378
377
|
// polygonIndices 顶点索引,
|
|
379
378
|
earCutPointsToTriangles(points) {
|
|
380
379
|
this.earCutCache = this.earCutCache || (this.earCutCache = {});
|
|
381
|
-
|
|
380
|
+
// 快速缓存 key:用长度和首尾点坐标
|
|
381
|
+
const len = points.length;
|
|
382
|
+
const key = len + '_' + points[0].x + '_' + points[0].y + '_' + points[len-1].x + '_' + points[len-1].y;
|
|
382
383
|
if (this.earCutCache[key]) return this.earCutCache[key];
|
|
383
384
|
|
|
384
385
|
const ps = this.earCutPoints(points);// 切割得到3角色顶点索引,
|
|
@@ -473,31 +474,11 @@ class WeblBase {
|
|
|
473
474
|
|
|
474
475
|
this.textureContext.fillStyle = fillStyle;
|
|
475
476
|
|
|
476
|
-
|
|
477
|
+
// 规则图形用 fillRect,比 beginPath/lineTo/fill 快
|
|
477
478
|
if(!points || !points.length) {
|
|
478
|
-
|
|
479
|
-
|
|
480
|
-
|
|
481
|
-
y: bounds.top
|
|
482
|
-
});
|
|
483
|
-
points.push({
|
|
484
|
-
x: bounds.left + bounds.width,
|
|
485
|
-
y: bounds.top
|
|
486
|
-
});
|
|
487
|
-
points.push({
|
|
488
|
-
x: bounds.left + bounds.width,
|
|
489
|
-
y: bounds.top + bounds.height
|
|
490
|
-
});
|
|
491
|
-
points.push({
|
|
492
|
-
x: bounds.left,
|
|
493
|
-
y: bounds.top + bounds.height
|
|
494
|
-
});
|
|
495
|
-
points.push({
|
|
496
|
-
x: bounds.left,
|
|
497
|
-
y: bounds.top
|
|
498
|
-
});
|
|
499
|
-
}
|
|
500
|
-
if(points && points.length) {
|
|
479
|
+
this.textureContext.fillRect(0, 0, bounds.width, bounds.height);
|
|
480
|
+
} else {
|
|
481
|
+
this.textureContext.beginPath();
|
|
501
482
|
for(const p of points) {
|
|
502
483
|
//移至当前坐标
|
|
503
484
|
if(p.m) {
|
|
@@ -506,17 +487,10 @@ class WeblBase {
|
|
|
506
487
|
else {
|
|
507
488
|
this.textureContext.lineTo(p.x - bounds.left, p.y - bounds.top);
|
|
508
489
|
}
|
|
509
|
-
}
|
|
510
|
-
|
|
511
|
-
|
|
512
|
-
this.textureContext.moveTo(0, 0);
|
|
513
|
-
this.textureContext.lineTo(bounds.width, 0);
|
|
514
|
-
this.textureContext.lineTo(bounds.width, bounds.height);
|
|
515
|
-
this.textureContext.lineTo(0, bounds.height);
|
|
516
|
-
this.textureContext.lineTo(0, 0);
|
|
490
|
+
}
|
|
491
|
+
this.textureContext.closePath();
|
|
492
|
+
this.textureContext.fill();
|
|
517
493
|
}
|
|
518
|
-
this.textureContext.closePath();
|
|
519
|
-
this.textureContext.fill();
|
|
520
494
|
|
|
521
495
|
const data = this.textureContext.getImageData(0, 0, canvas.width, canvas.height);
|
|
522
496
|
return {
|
|
@@ -53,8 +53,14 @@ class WebglGradient {
|
|
|
53
53
|
|
|
54
54
|
// 转为渐变为纹理
|
|
55
55
|
toImageData(control, bounds, points=null) {
|
|
56
|
-
//
|
|
57
|
-
|
|
56
|
+
// 缓存基于渐变参数(不含 bounds,因为同一个渐变只是位置不同时纹理相同)
|
|
57
|
+
const gradientKey = this.toString();
|
|
58
|
+
if(this.__cachedData && this.__cacheKey === gradientKey &&
|
|
59
|
+
this.__cachedData.data && this.__cachedData.data.width === Math.ceil(bounds.width) &&
|
|
60
|
+
this.__cachedData.data.data && this.__cachedData.data.data.height === Math.ceil(bounds.height)) {
|
|
61
|
+
return this.__cachedData;
|
|
62
|
+
}
|
|
63
|
+
|
|
58
64
|
if(!control.textureContext) {
|
|
59
65
|
return null;
|
|
60
66
|
}
|
|
@@ -72,11 +78,18 @@ class WebglGradient {
|
|
|
72
78
|
|
|
73
79
|
const data = control.toFillTexture(gradient, bounds, points);
|
|
74
80
|
|
|
75
|
-
|
|
81
|
+
this.__cachedData = data;
|
|
82
|
+
this.__cacheKey = gradientKey;
|
|
76
83
|
|
|
77
84
|
return data;
|
|
78
85
|
}
|
|
79
86
|
|
|
87
|
+
// 当渐变参数变化时使缓存失效
|
|
88
|
+
invalidateCache() {
|
|
89
|
+
this.__cachedData = null;
|
|
90
|
+
this.__cacheKey = null;
|
|
91
|
+
}
|
|
92
|
+
|
|
80
93
|
// 根据绘制图形的坐标计算出对应点的颜色
|
|
81
94
|
/*
|
|
82
95
|
toPointColors(points) {
|
package/src/lib/webgl/index.js
CHANGED
|
@@ -105,12 +105,13 @@ class webgl {
|
|
|
105
105
|
// 由具体的绘制方法处理
|
|
106
106
|
}
|
|
107
107
|
|
|
108
|
-
//
|
|
108
|
+
// 测量文本宽度(复用纹理 canvas 的 context)
|
|
109
109
|
measureText(text) {
|
|
110
|
-
|
|
110
|
+
const ctx = this.base.textureContext;
|
|
111
|
+
if(ctx && ctx.measureText) return ctx.measureText(text);
|
|
111
112
|
const canvas = document.createElement('canvas');
|
|
112
|
-
const
|
|
113
|
-
return
|
|
113
|
+
const ctx2 = canvas.getContext('2d');
|
|
114
|
+
return ctx2.measureText(text);
|
|
114
115
|
}
|
|
115
116
|
|
|
116
117
|
// 创建线性渐变
|