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.
- package/LICENSE +21 -21
- package/README.md +251 -428
- package/build/gulpfile.js +142 -142
- package/build/package-lock.json +10666 -0
- package/build/package.json +71 -71
- package/dev.js +9 -9
- package/dist/jmgraph.core.min.js +1 -1
- package/dist/jmgraph.core.min.js.map +1 -1
- package/dist/jmgraph.js +3500 -2668
- package/dist/jmgraph.min.js +1 -1
- package/example/ball.html +216 -216
- package/example/base.html +111 -111
- package/example/canvas.html +53 -53
- package/example/cell.html +283 -283
- package/example/controls/arc.html +128 -128
- package/example/controls/arrowline.html +77 -77
- package/example/controls/bezier.html +298 -298
- package/example/controls/img.html +96 -96
- package/example/controls/label.html +86 -86
- package/example/controls/line.html +172 -172
- package/example/controls/prismatic.html +62 -62
- package/example/controls/rect.html +63 -63
- package/example/controls/resize.html +111 -111
- package/example/controls/test.html +359 -359
- package/example/es.html +69 -69
- package/example/es5module.html +62 -63
- package/example/heartarc.html +115 -115
- package/example/index.html +46 -46
- package/example/js/require.js +4 -4
- package/example/love/img/bling/bling.tps +265 -265
- package/example/love/img/bling.json +87 -87
- package/example/love/img/bling.tps +295 -295
- package/example/love/img/love.json +95 -95
- package/example/love/img/love.tps +315 -315
- package/example/love/img/qq/qq.tps +399 -399
- package/example/love/img/qq.json +242 -242
- package/example/love/index.html +40 -40
- package/example/love/js/game.js +558 -558
- package/example/music.html +210 -210
- package/example/node/test.js +137 -137
- package/example/pdf.html +186 -186
- package/example/progress.html +172 -172
- package/example/pso.html +147 -147
- package/example/sort.html +804 -815
- package/example/tweenjs.html +83 -83
- package/example/webgl.html +278 -278
- package/example/xfj/index.html +331 -331
- package/example/xfj/shake.js +48 -48
- package/example/xfj/testori.html +75 -75
- package/index.js +99 -99
- package/package.json +58 -56
- package/src/core/jmControl.js +1376 -1531
- package/src/core/jmEvents.js +240 -281
- package/src/core/jmGradient.js +231 -231
- package/src/core/jmGraph.js +569 -569
- package/src/core/jmList.js +92 -157
- package/src/core/jmObject.js +83 -103
- package/src/core/jmPath.js +35 -35
- package/src/core/jmProperty.js +71 -110
- package/src/core/jmShadow.js +65 -65
- package/src/core/jmUtils.js +906 -919
- package/src/lib/earcut.js +680 -680
- package/src/lib/earcut.md +73 -73
- package/src/lib/webgl/base.js +522 -452
- package/src/lib/webgl/core/buffer.js +48 -48
- package/src/lib/webgl/core/mapSize.js +40 -40
- package/src/lib/webgl/core/mapType.js +43 -43
- package/src/lib/webgl/core/program.js +138 -138
- package/src/lib/webgl/core/shader.js +13 -13
- package/src/lib/webgl/core/texture.js +60 -60
- package/src/lib/webgl/gradient.js +168 -168
- package/src/lib/webgl/index.js +137 -11
- package/src/lib/webgl/path.js +568 -561
- package/src/shapes/jmArrowLine.js +36 -36
- package/src/shapes/jmImage.js +244 -244
- package/src/shapes/jmLabel.js +271 -271
- package/src/shapes/jmResize.js +332 -330
package/src/core/jmUtils.js
CHANGED
|
@@ -1,920 +1,907 @@
|
|
|
1
|
-
|
|
2
|
-
import { jmList } from './jmList.js';
|
|
3
|
-
|
|
4
|
-
const colorKeywords = {
|
|
5
|
-
aliceblue: "#f0f8ff",
|
|
6
|
-
antiquewhite: "#faebd7",
|
|
7
|
-
aqua: "#00ffff",
|
|
8
|
-
aquamarine: "#7fffd4",
|
|
9
|
-
azure: "#f0ffff",
|
|
10
|
-
beige: "#f5f5dc",
|
|
11
|
-
bisque: "#ffe4c4",
|
|
12
|
-
black: "#000000",
|
|
13
|
-
blanchedalmond: "#ffebcd",
|
|
14
|
-
blue: "#0000ff",
|
|
15
|
-
blueviolet: "#8a2be2",
|
|
16
|
-
brown: "#a52a2a",
|
|
17
|
-
burlywood: "#deb887",
|
|
18
|
-
cadetblue: "#5f9ea0",
|
|
19
|
-
chartreuse: "#7fff00",
|
|
20
|
-
chocolate: "#d2691e",
|
|
21
|
-
coral: "#ff7f50",
|
|
22
|
-
cornflowerblue: "#6495ed",
|
|
23
|
-
cornsilk: "#fff8dc",
|
|
24
|
-
crimson: "#dc143c",
|
|
25
|
-
cyan: "#00ffff",
|
|
26
|
-
darkblue: "#00008b",
|
|
27
|
-
darkcyan: "#008b8b",
|
|
28
|
-
darkgoldenrod: "#b8860b",
|
|
29
|
-
darkgray: "#a9a9a9",
|
|
30
|
-
darkgreen: "#006400",
|
|
31
|
-
darkkhaki: "#bdb76b",
|
|
32
|
-
darkmagenta: "#8b008b",
|
|
33
|
-
darkolivegreen: "#556b2f",
|
|
34
|
-
darkorange: "#ff8c00",
|
|
35
|
-
darkorchid: "#9932cc",
|
|
36
|
-
darkred: "#8b0000",
|
|
37
|
-
darksalmon: "#e9967a",
|
|
38
|
-
darkseagreen: "#8fbc8f",
|
|
39
|
-
darkslateblue: "#483d8b",
|
|
40
|
-
darkslategray: "#2f4f4f",
|
|
41
|
-
darkturquoise: "#00ced1",
|
|
42
|
-
darkviolet: "#9400d3",
|
|
43
|
-
deeppink: "#ff1493",
|
|
44
|
-
deepskyblue: "#00bfff",
|
|
45
|
-
dimgray: "#696969",
|
|
46
|
-
dodgerblue: "#1e90ff",
|
|
47
|
-
firebrick: "#b22222",
|
|
48
|
-
floralwhite: "#fffaf0",
|
|
49
|
-
forestgreen: "#228b22",
|
|
50
|
-
fuchsia: "#ff00ff",
|
|
51
|
-
gainsboro: "#dcdcdc",
|
|
52
|
-
ghostwhite: "#f8f8ff",
|
|
53
|
-
gold: "#ffd700",
|
|
54
|
-
goldenrod: "#daa520",
|
|
55
|
-
gray: "#808080",
|
|
56
|
-
green: "#008000",
|
|
57
|
-
greenyellow: "#adff2f",
|
|
58
|
-
grey: "#808080",
|
|
59
|
-
honeydew: "#f0fff0",
|
|
60
|
-
hotpink: "#ff69b4",
|
|
61
|
-
indianred: "#cd5c5c",
|
|
62
|
-
indigo: "#4b0082",
|
|
63
|
-
ivory: "#fffff0",
|
|
64
|
-
khaki: "#f0e68c",
|
|
65
|
-
lavender: "#e6e6fa",
|
|
66
|
-
lavenderblush: "#fff0f5",
|
|
67
|
-
lawngreen: "#7cfc00",
|
|
68
|
-
lemonchiffon: "#fffacd",
|
|
69
|
-
lightblue: "#add8e6",
|
|
70
|
-
lightcoral: "#f08080",
|
|
71
|
-
lightcyan: "#e0ffff",
|
|
72
|
-
lightgoldenrodyellow: "#fafad2",
|
|
73
|
-
lightgrey: "#d3d3d3",
|
|
74
|
-
lightgreen: "#90ee90",
|
|
75
|
-
lightpink: "#ffb6c1",
|
|
76
|
-
lightsalmon: "#ffa07a",
|
|
77
|
-
lightseagreen: "#20b2aa",
|
|
78
|
-
lightskyblue: "#87cefa",
|
|
79
|
-
lightslategray: "#778899",
|
|
80
|
-
lightsteelblue: "#b0c4de",
|
|
81
|
-
lightyellow: "#ffffe0",
|
|
82
|
-
lime: "#00ff00",
|
|
83
|
-
limegreen: "#32cd32",
|
|
84
|
-
linen: "#faf0e6",
|
|
85
|
-
magenta: "#ff00ff",
|
|
86
|
-
maroon: "#800000",
|
|
87
|
-
mediumaquamarine: "#66cdaa",
|
|
88
|
-
mediumblue: "#0000cd",
|
|
89
|
-
mediumorchid: "#ba55d3",
|
|
90
|
-
mediumpurple: "#9370d8",
|
|
91
|
-
mediumseagreen: "#3cb371",
|
|
92
|
-
mediumslateblue: "#7b68ee",
|
|
93
|
-
mediumspringgreen: "#00fa9a",
|
|
94
|
-
mediumturquoise: "#48d1cc",
|
|
95
|
-
mediumvioletred: "#c71585",
|
|
96
|
-
midnightblue: "#191970",
|
|
97
|
-
mintcream: "#f5fffa",
|
|
98
|
-
mistyrose: "#ffe4e1",
|
|
99
|
-
moccasin: "#ffe4b5",
|
|
100
|
-
navajowhite: "#ffdead",
|
|
101
|
-
navy: "#000080",
|
|
102
|
-
oldlace: "#fdf5e6",
|
|
103
|
-
olive: "#808000",
|
|
104
|
-
olivedrab: "#6b8e23",
|
|
105
|
-
orange: "#ffa500",
|
|
106
|
-
orangered: "#ff4500",
|
|
107
|
-
orchid: "#da70d6",
|
|
108
|
-
palegoldenrod: "#eee8aa",
|
|
109
|
-
palegreen: "#98fb98",
|
|
110
|
-
paleturquoise: "#afeeee",
|
|
111
|
-
palevioletred: "#d87093",
|
|
112
|
-
papayawhip: "#ffefd5",
|
|
113
|
-
peachpuff: "#ffdab9",
|
|
114
|
-
peru: "#cd853f",
|
|
115
|
-
pink: "#ffc0cb",
|
|
116
|
-
plum: "#dda0dd",
|
|
117
|
-
powderblue: "#b0e0e6",
|
|
118
|
-
purple: "#800080",
|
|
119
|
-
red: "#ff0000",
|
|
120
|
-
rosybrown: "#bc8f8f",
|
|
121
|
-
royalblue: "#4169e1",
|
|
122
|
-
saddlebrown: "#8b4513",
|
|
123
|
-
salmon: "#fa8072",
|
|
124
|
-
sandybrown: "#f4a460",
|
|
125
|
-
seagreen: "#2e8b57",
|
|
126
|
-
seashell: "#fff5ee",
|
|
127
|
-
sienna: "#a0522d",
|
|
128
|
-
silver: "#c0c0c0",
|
|
129
|
-
skyblue: "#87ceeb",
|
|
130
|
-
slateblue: "#6a5acd",
|
|
131
|
-
slategray: "#708090",
|
|
132
|
-
snow: "#fffafa",
|
|
133
|
-
springgreen: "#00ff7f",
|
|
134
|
-
steelblue: "#4682b4",
|
|
135
|
-
tan: "#d2b48c",
|
|
136
|
-
teal: "#008080",
|
|
137
|
-
thistle: "#d8bfd8",
|
|
138
|
-
tomato: "#ff6347",
|
|
139
|
-
turquoise: "#40e0d0",
|
|
140
|
-
violet: "#ee82ee",
|
|
141
|
-
wheat: "#f5deb3",
|
|
142
|
-
white: "#ffffff",
|
|
143
|
-
whitesmoke: "#f5f5f5",
|
|
144
|
-
yellow: "#ffff00",
|
|
145
|
-
yellowgreen: "#9acd32",
|
|
146
|
-
transparent: "rgba(0,0,0,0)"
|
|
147
|
-
};
|
|
148
|
-
|
|
149
|
-
/**
|
|
150
|
-
* 画图基础对象
|
|
151
|
-
* 当前库的工具类
|
|
152
|
-
*
|
|
153
|
-
* @class jmUtils
|
|
154
|
-
* @static
|
|
155
|
-
*/
|
|
156
|
-
export default class jmUtils {
|
|
157
|
-
/**
|
|
158
|
-
* 复制一个对象
|
|
159
|
-
*
|
|
160
|
-
* @method clone
|
|
161
|
-
* @static
|
|
162
|
-
* @param {object} source 被复制的对象
|
|
163
|
-
* @param {object} target 可选,如果指定就表示复制给这个对象,如果为boolean它就是deep参数
|
|
164
|
-
* @param {boolean} deep 是否深度复制,如果为true,数组内的每个对象都会被复制
|
|
165
|
-
* @param {function} copyHandler 复制对象回调,如果返回undefined,就走后面的逻辑,否则到这里中止
|
|
166
|
-
* @return {object} 参数source的拷贝对象
|
|
167
|
-
*/
|
|
168
|
-
static clone(source, target, deep = false, copyHandler = null, deepIndex = 0) {
|
|
169
|
-
// 如果有指定回调,则用回调处理,否则走后面的复制逻辑
|
|
170
|
-
if(typeof copyHandler === 'function') {
|
|
171
|
-
const obj = copyHandler(source, deep, deepIndex);
|
|
172
|
-
if(obj) return obj;
|
|
173
|
-
}
|
|
174
|
-
deepIndex++; // 每执行一次,需要判断最大拷贝深度
|
|
175
|
-
|
|
176
|
-
if(typeof target === 'boolean') {
|
|
177
|
-
deep = target;
|
|
178
|
-
target = undefined;
|
|
179
|
-
}
|
|
180
|
-
|
|
181
|
-
// 超过100拷贝深度,直接返回
|
|
182
|
-
if(deepIndex > 100) {
|
|
183
|
-
return target;
|
|
184
|
-
}
|
|
185
|
-
|
|
186
|
-
if(source && typeof source === 'object') {
|
|
187
|
-
target = target || {};
|
|
188
|
-
|
|
189
|
-
//如果为当前泛型,则直接new
|
|
190
|
-
if(this.isType(source, jmList)) {
|
|
191
|
-
return new jmList(source);
|
|
192
|
-
}
|
|
193
|
-
else if(Array.isArray(source)) {
|
|
194
|
-
//如果是深度复,则拷贝每个对象
|
|
195
|
-
if(deep) {
|
|
196
|
-
let dest = [];
|
|
197
|
-
for(let i=0; i<source.length; i++) {
|
|
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);
|
|
219
|
-
}
|
|
220
|
-
}
|
|
221
|
-
return target;
|
|
222
|
-
}
|
|
223
|
-
else if(typeof target != 'undefined') {
|
|
224
|
-
return target;
|
|
225
|
-
}
|
|
226
|
-
|
|
227
|
-
return source;
|
|
228
|
-
}
|
|
229
|
-
|
|
230
|
-
/**
|
|
231
|
-
* 绑定事件到html对象
|
|
232
|
-
*
|
|
233
|
-
* @method bindEvent
|
|
234
|
-
* @static
|
|
235
|
-
* @param {element} html元素对象
|
|
236
|
-
* @param {string} name 事件名称
|
|
237
|
-
* @param {function} fun 事件委托
|
|
238
|
-
* @returns {name, fun, target} 返回当前绑定
|
|
239
|
-
*/
|
|
240
|
-
static bindEvent(target, name, fun, opt) {
|
|
241
|
-
if(name && name.indexOf && name.indexOf(' ') != -1) {
|
|
242
|
-
let ns = name.split(' ');
|
|
243
|
-
for(let i=0;i<ns.length;i++) {
|
|
244
|
-
this.bindEvent(target, ns[i], fun, opt);
|
|
245
|
-
}
|
|
246
|
-
}
|
|
247
|
-
if(target.attachEvent) {
|
|
248
|
-
target.attachEvent("on"+name, fun, opt);
|
|
249
|
-
}
|
|
250
|
-
else if(target.addEventListener) {
|
|
251
|
-
target.addEventListener(name, fun, opt);
|
|
252
|
-
}
|
|
253
|
-
return {
|
|
254
|
-
name,
|
|
255
|
-
target,
|
|
256
|
-
fun
|
|
257
|
-
};
|
|
258
|
-
}
|
|
259
|
-
|
|
260
|
-
/**
|
|
261
|
-
* 从对象中移除事件到
|
|
262
|
-
*
|
|
263
|
-
* @method removeEvent
|
|
264
|
-
* @static
|
|
265
|
-
* @param {element} html元素对象
|
|
266
|
-
* @param {string} name 事件名称
|
|
267
|
-
* @param {function} fun 事件委托
|
|
268
|
-
*/
|
|
269
|
-
static removeEvent(target, name, fun) {
|
|
270
|
-
if(target.removeEventListener) {
|
|
271
|
-
return target.removeEventListener(name, fun, false);
|
|
272
|
-
}
|
|
273
|
-
else if(target.detachEvent) {
|
|
274
|
-
target.detachEvent('on' + name, fun);
|
|
275
|
-
return true;
|
|
276
|
-
}
|
|
277
|
-
else {
|
|
278
|
-
target['on' + name] = null;
|
|
279
|
-
}
|
|
280
|
-
}
|
|
281
|
-
|
|
282
|
-
/**
|
|
283
|
-
* 获取元素的绝对定位
|
|
284
|
-
*
|
|
285
|
-
* @method getElementPosition
|
|
286
|
-
* @static
|
|
287
|
-
* @param {element} el 目标元素对象
|
|
288
|
-
* @return {position} 位置对象(top,left)
|
|
289
|
-
*/
|
|
290
|
-
static getElementPosition(el) {
|
|
291
|
-
let pos = {"top": 0, "left": 0};
|
|
292
|
-
if(!el) return pos;
|
|
293
|
-
|
|
294
|
-
if (el.offsetParent) {
|
|
295
|
-
while (el.offsetParent) {
|
|
296
|
-
pos.top += el.offsetTop;
|
|
297
|
-
pos.left += el.offsetLeft;
|
|
298
|
-
el = el.offsetParent;
|
|
299
|
-
}
|
|
300
|
-
}
|
|
301
|
-
else if(el.x) {
|
|
302
|
-
pos.left += el.x;
|
|
303
|
-
}
|
|
304
|
-
else if(el.x){
|
|
305
|
-
pos.top += el.y;
|
|
306
|
-
}
|
|
307
|
-
return pos;
|
|
308
|
-
}
|
|
309
|
-
/**
|
|
310
|
-
* 获取元素事件触发的位置
|
|
311
|
-
*
|
|
312
|
-
* @method getEventPosition
|
|
313
|
-
* @static
|
|
314
|
-
* @param {eventArg} evt 当前触发事件的参数
|
|
315
|
-
* @param {point} [scale] 当前画布的缩放比例
|
|
316
|
-
* @return {point} 事件触发的位置
|
|
317
|
-
*/
|
|
318
|
-
static getEventPosition (evt, scale) {
|
|
319
|
-
evt = evt || event;
|
|
320
|
-
const isWXMiniApp = evt.isWXMiniApp;
|
|
321
|
-
let isTouch = false;
|
|
322
|
-
let touches = evt.changedTouches || evt.targetTouches || evt.touches;
|
|
323
|
-
let target = evt.target || evt.srcElement;
|
|
324
|
-
if(touches && touches.length) {
|
|
325
|
-
evt = touches[0];//兼容touch事件
|
|
326
|
-
if(!evt.target) evt.target = target;
|
|
327
|
-
isTouch = true;
|
|
328
|
-
}
|
|
329
|
-
let px = evt.pageX || evt.x;
|
|
330
|
-
if(typeof px == 'undefined') px = evt.clientX + (document.documentElement.scrollLeft || document.body.scrollLeft);
|
|
331
|
-
let py = evt.pageY || evt.y;
|
|
332
|
-
if(typeof py == 'undefined') py = evt.clientY + (document.documentElement.scrollTop || document.body.scrollTop);
|
|
333
|
-
|
|
334
|
-
let ox = evt.offsetX;
|
|
335
|
-
let oy = evt.offsetY;
|
|
336
|
-
if(typeof ox === 'undefined' && typeof oy === 'undefined') {
|
|
337
|
-
// 小程序下取x,y就是它的相对坐标
|
|
338
|
-
if(isWXMiniApp) {
|
|
339
|
-
ox = evt.x;
|
|
340
|
-
oy = evt.y;
|
|
341
|
-
}
|
|
342
|
-
else {
|
|
343
|
-
let p = this.getElementPosition(target);
|
|
344
|
-
ox= px - p.left;
|
|
345
|
-
oy = py - p.top;
|
|
346
|
-
}
|
|
347
|
-
}
|
|
348
|
-
if(scale) {
|
|
349
|
-
if(scale.x) ox = ox / scale.x;
|
|
350
|
-
if(scale.y) oy = oy / scale.y;
|
|
351
|
-
}
|
|
352
|
-
|
|
353
|
-
return {
|
|
354
|
-
pageX: px,
|
|
355
|
-
pageY: py,
|
|
356
|
-
clientX: evt.clientX,
|
|
357
|
-
clientY: evt.clientY,
|
|
358
|
-
//相对于容器偏移量
|
|
359
|
-
offsetX: ox,
|
|
360
|
-
offsetY: oy,
|
|
361
|
-
layerX: evt.layerX,
|
|
362
|
-
layerY: evt.layerY,
|
|
363
|
-
screenX: evt.screenX,
|
|
364
|
-
screenY: evt.screenY,
|
|
365
|
-
x: ox,
|
|
366
|
-
y: oy,
|
|
367
|
-
isTouch: isTouch,
|
|
368
|
-
touches,
|
|
369
|
-
isWXMiniApp
|
|
370
|
-
};
|
|
371
|
-
}
|
|
372
|
-
|
|
373
|
-
/**
|
|
374
|
-
* 检 查对象是否为指定的类型,不包括继承
|
|
375
|
-
*
|
|
376
|
-
* @method isType
|
|
377
|
-
* @static
|
|
378
|
-
* @param {object} target 需要判断类型的对象
|
|
379
|
-
* @param {class} type 对象类型
|
|
380
|
-
* @return {boolean} 返回对象是否为指定类型
|
|
381
|
-
*/
|
|
382
|
-
static isType(target, type) {
|
|
383
|
-
if(!target || typeof target !== 'object') return false;
|
|
384
|
-
if(target.constructor === type) return true;
|
|
385
|
-
/*if(target.__baseType) {
|
|
386
|
-
return jmUtils.isType(target.__baseType.prototype,type);
|
|
387
|
-
}*/
|
|
388
|
-
|
|
389
|
-
//return target instanceof type;
|
|
390
|
-
return false;
|
|
391
|
-
}
|
|
392
|
-
/**
|
|
393
|
-
* 判断点是否在多边形内
|
|
394
|
-
* 如果一个点在多边形内部,任意角度做射线肯定会与多边形要么有一个交点,要么有与多边形边界线重叠。
|
|
395
|
-
* 如果一个点在多边形外部,任意角度做射线要么与多边形有一个交点,要么有两个交点,要么没有交点,要么有与多边形边界线重叠。
|
|
396
|
-
* 利用上面的结论,我们只要判断这个点与多边形的交点个数,就可以判断出点与多边形的位置关系了。
|
|
397
|
-
*
|
|
398
|
-
* @method pointInPolygon
|
|
399
|
-
* @static
|
|
400
|
-
* @param {point} pt 坐标对象
|
|
401
|
-
* @param {array} polygon 多边型角坐标对象数组
|
|
402
|
-
* @param {number} offset 判断可偏移值
|
|
403
|
-
* @return {integer} 0= 不在图形内和线上,1=在边上,2=在图形内部
|
|
404
|
-
*/
|
|
405
|
-
static pointInPolygon(pt, polygon, offset) {
|
|
406
|
-
offset = offset || 1;
|
|
407
|
-
offset = offset / 2;
|
|
408
|
-
|
|
409
|
-
|
|
410
|
-
|
|
411
|
-
|
|
412
|
-
if(n == 1) {
|
|
413
|
-
return Math.abs(polygon[0].x - pt.x) <= offset && Math.abs(polygon[0].y - pt.y) <= offset;
|
|
414
|
-
}
|
|
415
|
-
|
|
416
|
-
|
|
417
|
-
|
|
418
|
-
|
|
419
|
-
|
|
420
|
-
|
|
421
|
-
|
|
422
|
-
|
|
423
|
-
|
|
424
|
-
|
|
425
|
-
|
|
426
|
-
|
|
427
|
-
|
|
428
|
-
|
|
429
|
-
|
|
430
|
-
|
|
431
|
-
|
|
432
|
-
|
|
433
|
-
|
|
434
|
-
|
|
435
|
-
|
|
436
|
-
|
|
437
|
-
|
|
438
|
-
|
|
439
|
-
|
|
440
|
-
|
|
441
|
-
|
|
442
|
-
|
|
443
|
-
|
|
444
|
-
|
|
445
|
-
|
|
446
|
-
|
|
447
|
-
|
|
448
|
-
|
|
449
|
-
|
|
450
|
-
|
|
451
|
-
|
|
452
|
-
|
|
453
|
-
|
|
454
|
-
return
|
|
455
|
-
}
|
|
456
|
-
|
|
457
|
-
|
|
458
|
-
|
|
459
|
-
|
|
460
|
-
|
|
461
|
-
|
|
462
|
-
|
|
463
|
-
|
|
464
|
-
|
|
465
|
-
|
|
466
|
-
|
|
467
|
-
|
|
468
|
-
|
|
469
|
-
|
|
470
|
-
|
|
471
|
-
|
|
472
|
-
|
|
473
|
-
|
|
474
|
-
|
|
475
|
-
|
|
476
|
-
|
|
477
|
-
|
|
478
|
-
|
|
479
|
-
|
|
480
|
-
|
|
481
|
-
|
|
482
|
-
|
|
483
|
-
|
|
484
|
-
|
|
485
|
-
|
|
486
|
-
|
|
487
|
-
|
|
488
|
-
|
|
489
|
-
|
|
490
|
-
|
|
491
|
-
|
|
492
|
-
|
|
493
|
-
|
|
494
|
-
|
|
495
|
-
|
|
496
|
-
|
|
497
|
-
|
|
498
|
-
|
|
499
|
-
|
|
500
|
-
|
|
501
|
-
|
|
502
|
-
|
|
503
|
-
|
|
504
|
-
|
|
505
|
-
|
|
506
|
-
|
|
507
|
-
|
|
508
|
-
|
|
509
|
-
|
|
510
|
-
|
|
511
|
-
|
|
512
|
-
|
|
513
|
-
|
|
514
|
-
|
|
515
|
-
|
|
516
|
-
|
|
517
|
-
|
|
518
|
-
|
|
519
|
-
|
|
520
|
-
|
|
521
|
-
|
|
522
|
-
|
|
523
|
-
|
|
524
|
-
|
|
525
|
-
|
|
526
|
-
|
|
527
|
-
|
|
528
|
-
|
|
529
|
-
|
|
530
|
-
|
|
531
|
-
|
|
532
|
-
|
|
533
|
-
|
|
534
|
-
|
|
535
|
-
|
|
536
|
-
|
|
537
|
-
|
|
538
|
-
|
|
539
|
-
|
|
540
|
-
|
|
541
|
-
|
|
542
|
-
|
|
543
|
-
|
|
544
|
-
|
|
545
|
-
|
|
546
|
-
|
|
547
|
-
|
|
548
|
-
|
|
549
|
-
|
|
550
|
-
|
|
551
|
-
|
|
552
|
-
|
|
553
|
-
|
|
554
|
-
|
|
555
|
-
|
|
556
|
-
|
|
557
|
-
|
|
558
|
-
|
|
559
|
-
|
|
560
|
-
|
|
561
|
-
|
|
562
|
-
|
|
563
|
-
|
|
564
|
-
|
|
565
|
-
|
|
566
|
-
|
|
567
|
-
|
|
568
|
-
|
|
569
|
-
|
|
570
|
-
|
|
571
|
-
|
|
572
|
-
|
|
573
|
-
|
|
574
|
-
|
|
575
|
-
|
|
576
|
-
|
|
577
|
-
|
|
578
|
-
|
|
579
|
-
|
|
580
|
-
|
|
581
|
-
|
|
582
|
-
|
|
583
|
-
|
|
584
|
-
|
|
585
|
-
|
|
586
|
-
|
|
587
|
-
|
|
588
|
-
|
|
589
|
-
|
|
590
|
-
|
|
591
|
-
|
|
592
|
-
|
|
593
|
-
|
|
594
|
-
|
|
595
|
-
return
|
|
596
|
-
|
|
597
|
-
|
|
598
|
-
|
|
599
|
-
|
|
600
|
-
|
|
601
|
-
|
|
602
|
-
|
|
603
|
-
|
|
604
|
-
|
|
605
|
-
|
|
606
|
-
|
|
607
|
-
|
|
608
|
-
|
|
609
|
-
|
|
610
|
-
|
|
611
|
-
|
|
612
|
-
|
|
613
|
-
|
|
614
|
-
|
|
615
|
-
|
|
616
|
-
|
|
617
|
-
|
|
618
|
-
|
|
619
|
-
|
|
620
|
-
|
|
621
|
-
|
|
622
|
-
|
|
623
|
-
|
|
624
|
-
|
|
625
|
-
|
|
626
|
-
|
|
627
|
-
|
|
628
|
-
|
|
629
|
-
|
|
630
|
-
|
|
631
|
-
|
|
632
|
-
|
|
633
|
-
|
|
634
|
-
|
|
635
|
-
|
|
636
|
-
|
|
637
|
-
|
|
638
|
-
|
|
639
|
-
|
|
640
|
-
|
|
641
|
-
|
|
642
|
-
|
|
643
|
-
|
|
644
|
-
|
|
645
|
-
|
|
646
|
-
|
|
647
|
-
|
|
648
|
-
|
|
649
|
-
|
|
650
|
-
|
|
651
|
-
|
|
652
|
-
|
|
653
|
-
|
|
654
|
-
|
|
655
|
-
|
|
656
|
-
|
|
657
|
-
|
|
658
|
-
|
|
659
|
-
|
|
660
|
-
|
|
661
|
-
|
|
662
|
-
|
|
663
|
-
|
|
664
|
-
|
|
665
|
-
|
|
666
|
-
|
|
667
|
-
|
|
668
|
-
return source;
|
|
669
|
-
}
|
|
670
|
-
|
|
671
|
-
/**
|
|
672
|
-
*
|
|
673
|
-
*
|
|
674
|
-
* @method
|
|
675
|
-
* @static
|
|
676
|
-
* @param {string}
|
|
677
|
-
* @
|
|
678
|
-
|
|
679
|
-
|
|
680
|
-
|
|
681
|
-
|
|
682
|
-
|
|
683
|
-
|
|
684
|
-
|
|
685
|
-
|
|
686
|
-
|
|
687
|
-
|
|
688
|
-
|
|
689
|
-
*
|
|
690
|
-
*
|
|
691
|
-
|
|
692
|
-
|
|
693
|
-
|
|
694
|
-
|
|
695
|
-
|
|
696
|
-
|
|
697
|
-
|
|
698
|
-
|
|
699
|
-
|
|
700
|
-
|
|
701
|
-
|
|
702
|
-
|
|
703
|
-
|
|
704
|
-
|
|
705
|
-
|
|
706
|
-
|
|
707
|
-
|
|
708
|
-
|
|
709
|
-
|
|
710
|
-
|
|
711
|
-
|
|
712
|
-
|
|
713
|
-
|
|
714
|
-
|
|
715
|
-
|
|
716
|
-
|
|
717
|
-
|
|
718
|
-
|
|
719
|
-
|
|
720
|
-
|
|
721
|
-
|
|
722
|
-
|
|
723
|
-
|
|
724
|
-
|
|
725
|
-
|
|
726
|
-
|
|
727
|
-
|
|
728
|
-
|
|
729
|
-
|
|
730
|
-
|
|
731
|
-
|
|
732
|
-
|
|
733
|
-
|
|
734
|
-
|
|
735
|
-
|
|
736
|
-
|
|
737
|
-
|
|
738
|
-
|
|
739
|
-
|
|
740
|
-
|
|
741
|
-
|
|
742
|
-
|
|
743
|
-
|
|
744
|
-
|
|
745
|
-
|
|
746
|
-
|
|
747
|
-
|
|
748
|
-
|
|
749
|
-
|
|
750
|
-
|
|
751
|
-
|
|
752
|
-
|
|
753
|
-
|
|
754
|
-
|
|
755
|
-
|
|
756
|
-
|
|
757
|
-
|
|
758
|
-
|
|
759
|
-
|
|
760
|
-
|
|
761
|
-
|
|
762
|
-
|
|
763
|
-
}
|
|
764
|
-
return
|
|
765
|
-
|
|
766
|
-
|
|
767
|
-
|
|
768
|
-
|
|
769
|
-
|
|
770
|
-
|
|
771
|
-
|
|
772
|
-
if(
|
|
773
|
-
|
|
774
|
-
|
|
775
|
-
|
|
776
|
-
|
|
777
|
-
|
|
778
|
-
|
|
779
|
-
|
|
780
|
-
|
|
781
|
-
|
|
782
|
-
|
|
783
|
-
|
|
784
|
-
|
|
785
|
-
|
|
786
|
-
|
|
787
|
-
|
|
788
|
-
}
|
|
789
|
-
|
|
790
|
-
|
|
791
|
-
|
|
792
|
-
|
|
793
|
-
|
|
794
|
-
|
|
795
|
-
|
|
796
|
-
|
|
797
|
-
|
|
798
|
-
|
|
799
|
-
|
|
800
|
-
|
|
801
|
-
|
|
802
|
-
|
|
803
|
-
|
|
804
|
-
|
|
805
|
-
|
|
806
|
-
|
|
807
|
-
|
|
808
|
-
|
|
809
|
-
|
|
810
|
-
|
|
811
|
-
|
|
812
|
-
|
|
813
|
-
|
|
814
|
-
|
|
815
|
-
|
|
816
|
-
|
|
817
|
-
|
|
818
|
-
|
|
819
|
-
color.r = this.hexToNumber(color.r||0);
|
|
820
|
-
color.g = this.hexToNumber(color.g||0);
|
|
821
|
-
color.b = this.hexToNumber(color.b||0);
|
|
822
|
-
|
|
823
|
-
|
|
824
|
-
|
|
825
|
-
|
|
826
|
-
|
|
827
|
-
|
|
828
|
-
|
|
829
|
-
|
|
830
|
-
color
|
|
831
|
-
|
|
832
|
-
|
|
833
|
-
|
|
834
|
-
|
|
835
|
-
|
|
836
|
-
|
|
837
|
-
|
|
838
|
-
|
|
839
|
-
|
|
840
|
-
|
|
841
|
-
|
|
842
|
-
|
|
843
|
-
|
|
844
|
-
|
|
845
|
-
|
|
846
|
-
|
|
847
|
-
|
|
848
|
-
|
|
849
|
-
|
|
850
|
-
|
|
851
|
-
|
|
852
|
-
|
|
853
|
-
|
|
854
|
-
|
|
855
|
-
|
|
856
|
-
|
|
857
|
-
|
|
858
|
-
|
|
859
|
-
|
|
860
|
-
|
|
861
|
-
|
|
862
|
-
|
|
863
|
-
|
|
864
|
-
|
|
865
|
-
|
|
866
|
-
|
|
867
|
-
|
|
868
|
-
|
|
869
|
-
|
|
870
|
-
|
|
871
|
-
|
|
872
|
-
|
|
873
|
-
|
|
874
|
-
|
|
875
|
-
|
|
876
|
-
|
|
877
|
-
|
|
878
|
-
|
|
879
|
-
|
|
880
|
-
|
|
881
|
-
if(typeof r === '
|
|
882
|
-
|
|
883
|
-
|
|
884
|
-
|
|
885
|
-
|
|
886
|
-
|
|
887
|
-
|
|
888
|
-
|
|
889
|
-
|
|
890
|
-
|
|
891
|
-
|
|
892
|
-
|
|
893
|
-
|
|
894
|
-
|
|
895
|
-
|
|
896
|
-
|
|
897
|
-
|
|
898
|
-
|
|
899
|
-
|
|
900
|
-
|
|
901
|
-
|
|
902
|
-
|
|
903
|
-
|
|
904
|
-
|
|
905
|
-
|
|
906
|
-
|
|
907
|
-
}
|
|
908
|
-
return r;
|
|
909
|
-
}
|
|
910
|
-
// window.requestAnimationFrame() 告诉浏览器——你希望执行一个动画,并且要求浏览器在下次重绘之前调用指定的回调函数更新动画。该方法需要传入一个回调函数作为参数,该回调函数会在浏览器下一次重绘之前执行
|
|
911
|
-
static requestAnimationFrame(callback, win) {
|
|
912
|
-
let fun = win && win.requestAnimationFrame? win.requestAnimationFrame: (typeof window !== 'undefined' && window.requestAnimationFrame? window.requestAnimationFrame: setTimeout);
|
|
913
|
-
return fun(callback, 20);
|
|
914
|
-
}
|
|
915
|
-
static cancelAnimationFrame(handler, win) {
|
|
916
|
-
let fun = win && win.cancelAnimationFrame? win.cancelAnimationFrame: (typeof window !== 'undefined' && window.cancelAnimationFrame? window.cancelAnimationFrame: clearTimeout);
|
|
917
|
-
return fun(handler);
|
|
918
|
-
}
|
|
919
|
-
}
|
|
1
|
+
|
|
2
|
+
import { jmList } from './jmList.js';
|
|
3
|
+
|
|
4
|
+
const colorKeywords = {
|
|
5
|
+
aliceblue: "#f0f8ff",
|
|
6
|
+
antiquewhite: "#faebd7",
|
|
7
|
+
aqua: "#00ffff",
|
|
8
|
+
aquamarine: "#7fffd4",
|
|
9
|
+
azure: "#f0ffff",
|
|
10
|
+
beige: "#f5f5dc",
|
|
11
|
+
bisque: "#ffe4c4",
|
|
12
|
+
black: "#000000",
|
|
13
|
+
blanchedalmond: "#ffebcd",
|
|
14
|
+
blue: "#0000ff",
|
|
15
|
+
blueviolet: "#8a2be2",
|
|
16
|
+
brown: "#a52a2a",
|
|
17
|
+
burlywood: "#deb887",
|
|
18
|
+
cadetblue: "#5f9ea0",
|
|
19
|
+
chartreuse: "#7fff00",
|
|
20
|
+
chocolate: "#d2691e",
|
|
21
|
+
coral: "#ff7f50",
|
|
22
|
+
cornflowerblue: "#6495ed",
|
|
23
|
+
cornsilk: "#fff8dc",
|
|
24
|
+
crimson: "#dc143c",
|
|
25
|
+
cyan: "#00ffff",
|
|
26
|
+
darkblue: "#00008b",
|
|
27
|
+
darkcyan: "#008b8b",
|
|
28
|
+
darkgoldenrod: "#b8860b",
|
|
29
|
+
darkgray: "#a9a9a9",
|
|
30
|
+
darkgreen: "#006400",
|
|
31
|
+
darkkhaki: "#bdb76b",
|
|
32
|
+
darkmagenta: "#8b008b",
|
|
33
|
+
darkolivegreen: "#556b2f",
|
|
34
|
+
darkorange: "#ff8c00",
|
|
35
|
+
darkorchid: "#9932cc",
|
|
36
|
+
darkred: "#8b0000",
|
|
37
|
+
darksalmon: "#e9967a",
|
|
38
|
+
darkseagreen: "#8fbc8f",
|
|
39
|
+
darkslateblue: "#483d8b",
|
|
40
|
+
darkslategray: "#2f4f4f",
|
|
41
|
+
darkturquoise: "#00ced1",
|
|
42
|
+
darkviolet: "#9400d3",
|
|
43
|
+
deeppink: "#ff1493",
|
|
44
|
+
deepskyblue: "#00bfff",
|
|
45
|
+
dimgray: "#696969",
|
|
46
|
+
dodgerblue: "#1e90ff",
|
|
47
|
+
firebrick: "#b22222",
|
|
48
|
+
floralwhite: "#fffaf0",
|
|
49
|
+
forestgreen: "#228b22",
|
|
50
|
+
fuchsia: "#ff00ff",
|
|
51
|
+
gainsboro: "#dcdcdc",
|
|
52
|
+
ghostwhite: "#f8f8ff",
|
|
53
|
+
gold: "#ffd700",
|
|
54
|
+
goldenrod: "#daa520",
|
|
55
|
+
gray: "#808080",
|
|
56
|
+
green: "#008000",
|
|
57
|
+
greenyellow: "#adff2f",
|
|
58
|
+
grey: "#808080",
|
|
59
|
+
honeydew: "#f0fff0",
|
|
60
|
+
hotpink: "#ff69b4",
|
|
61
|
+
indianred: "#cd5c5c",
|
|
62
|
+
indigo: "#4b0082",
|
|
63
|
+
ivory: "#fffff0",
|
|
64
|
+
khaki: "#f0e68c",
|
|
65
|
+
lavender: "#e6e6fa",
|
|
66
|
+
lavenderblush: "#fff0f5",
|
|
67
|
+
lawngreen: "#7cfc00",
|
|
68
|
+
lemonchiffon: "#fffacd",
|
|
69
|
+
lightblue: "#add8e6",
|
|
70
|
+
lightcoral: "#f08080",
|
|
71
|
+
lightcyan: "#e0ffff",
|
|
72
|
+
lightgoldenrodyellow: "#fafad2",
|
|
73
|
+
lightgrey: "#d3d3d3",
|
|
74
|
+
lightgreen: "#90ee90",
|
|
75
|
+
lightpink: "#ffb6c1",
|
|
76
|
+
lightsalmon: "#ffa07a",
|
|
77
|
+
lightseagreen: "#20b2aa",
|
|
78
|
+
lightskyblue: "#87cefa",
|
|
79
|
+
lightslategray: "#778899",
|
|
80
|
+
lightsteelblue: "#b0c4de",
|
|
81
|
+
lightyellow: "#ffffe0",
|
|
82
|
+
lime: "#00ff00",
|
|
83
|
+
limegreen: "#32cd32",
|
|
84
|
+
linen: "#faf0e6",
|
|
85
|
+
magenta: "#ff00ff",
|
|
86
|
+
maroon: "#800000",
|
|
87
|
+
mediumaquamarine: "#66cdaa",
|
|
88
|
+
mediumblue: "#0000cd",
|
|
89
|
+
mediumorchid: "#ba55d3",
|
|
90
|
+
mediumpurple: "#9370d8",
|
|
91
|
+
mediumseagreen: "#3cb371",
|
|
92
|
+
mediumslateblue: "#7b68ee",
|
|
93
|
+
mediumspringgreen: "#00fa9a",
|
|
94
|
+
mediumturquoise: "#48d1cc",
|
|
95
|
+
mediumvioletred: "#c71585",
|
|
96
|
+
midnightblue: "#191970",
|
|
97
|
+
mintcream: "#f5fffa",
|
|
98
|
+
mistyrose: "#ffe4e1",
|
|
99
|
+
moccasin: "#ffe4b5",
|
|
100
|
+
navajowhite: "#ffdead",
|
|
101
|
+
navy: "#000080",
|
|
102
|
+
oldlace: "#fdf5e6",
|
|
103
|
+
olive: "#808000",
|
|
104
|
+
olivedrab: "#6b8e23",
|
|
105
|
+
orange: "#ffa500",
|
|
106
|
+
orangered: "#ff4500",
|
|
107
|
+
orchid: "#da70d6",
|
|
108
|
+
palegoldenrod: "#eee8aa",
|
|
109
|
+
palegreen: "#98fb98",
|
|
110
|
+
paleturquoise: "#afeeee",
|
|
111
|
+
palevioletred: "#d87093",
|
|
112
|
+
papayawhip: "#ffefd5",
|
|
113
|
+
peachpuff: "#ffdab9",
|
|
114
|
+
peru: "#cd853f",
|
|
115
|
+
pink: "#ffc0cb",
|
|
116
|
+
plum: "#dda0dd",
|
|
117
|
+
powderblue: "#b0e0e6",
|
|
118
|
+
purple: "#800080",
|
|
119
|
+
red: "#ff0000",
|
|
120
|
+
rosybrown: "#bc8f8f",
|
|
121
|
+
royalblue: "#4169e1",
|
|
122
|
+
saddlebrown: "#8b4513",
|
|
123
|
+
salmon: "#fa8072",
|
|
124
|
+
sandybrown: "#f4a460",
|
|
125
|
+
seagreen: "#2e8b57",
|
|
126
|
+
seashell: "#fff5ee",
|
|
127
|
+
sienna: "#a0522d",
|
|
128
|
+
silver: "#c0c0c0",
|
|
129
|
+
skyblue: "#87ceeb",
|
|
130
|
+
slateblue: "#6a5acd",
|
|
131
|
+
slategray: "#708090",
|
|
132
|
+
snow: "#fffafa",
|
|
133
|
+
springgreen: "#00ff7f",
|
|
134
|
+
steelblue: "#4682b4",
|
|
135
|
+
tan: "#d2b48c",
|
|
136
|
+
teal: "#008080",
|
|
137
|
+
thistle: "#d8bfd8",
|
|
138
|
+
tomato: "#ff6347",
|
|
139
|
+
turquoise: "#40e0d0",
|
|
140
|
+
violet: "#ee82ee",
|
|
141
|
+
wheat: "#f5deb3",
|
|
142
|
+
white: "#ffffff",
|
|
143
|
+
whitesmoke: "#f5f5f5",
|
|
144
|
+
yellow: "#ffff00",
|
|
145
|
+
yellowgreen: "#9acd32",
|
|
146
|
+
transparent: "rgba(0,0,0,0)"
|
|
147
|
+
};
|
|
148
|
+
|
|
149
|
+
/**
|
|
150
|
+
* 画图基础对象
|
|
151
|
+
* 当前库的工具类
|
|
152
|
+
*
|
|
153
|
+
* @class jmUtils
|
|
154
|
+
* @static
|
|
155
|
+
*/
|
|
156
|
+
export default class jmUtils {
|
|
157
|
+
/**
|
|
158
|
+
* 复制一个对象
|
|
159
|
+
*
|
|
160
|
+
* @method clone
|
|
161
|
+
* @static
|
|
162
|
+
* @param {object} source 被复制的对象
|
|
163
|
+
* @param {object} target 可选,如果指定就表示复制给这个对象,如果为boolean它就是deep参数
|
|
164
|
+
* @param {boolean} deep 是否深度复制,如果为true,数组内的每个对象都会被复制
|
|
165
|
+
* @param {function} copyHandler 复制对象回调,如果返回undefined,就走后面的逻辑,否则到这里中止
|
|
166
|
+
* @return {object} 参数source的拷贝对象
|
|
167
|
+
*/
|
|
168
|
+
static clone(source, target, deep = false, copyHandler = null, deepIndex = 0) {
|
|
169
|
+
// 如果有指定回调,则用回调处理,否则走后面的复制逻辑
|
|
170
|
+
if(typeof copyHandler === 'function') {
|
|
171
|
+
const obj = copyHandler(source, deep, deepIndex);
|
|
172
|
+
if(obj) return obj;
|
|
173
|
+
}
|
|
174
|
+
deepIndex++; // 每执行一次,需要判断最大拷贝深度
|
|
175
|
+
|
|
176
|
+
if(typeof target === 'boolean') {
|
|
177
|
+
deep = target;
|
|
178
|
+
target = undefined;
|
|
179
|
+
}
|
|
180
|
+
|
|
181
|
+
// 超过100拷贝深度,直接返回
|
|
182
|
+
if(deepIndex > 100) {
|
|
183
|
+
return target;
|
|
184
|
+
}
|
|
185
|
+
|
|
186
|
+
if(source && typeof source === 'object') {
|
|
187
|
+
target = target || {};
|
|
188
|
+
|
|
189
|
+
//如果为当前泛型,则直接new
|
|
190
|
+
if(this.isType(source, jmList)) {
|
|
191
|
+
return new jmList(source);
|
|
192
|
+
}
|
|
193
|
+
else if(Array.isArray(source)) {
|
|
194
|
+
//如果是深度复,则拷贝每个对象
|
|
195
|
+
if(deep) {
|
|
196
|
+
let dest = [];
|
|
197
|
+
for(let i=0; i<source.length; i++) {
|
|
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);
|
|
219
|
+
}
|
|
220
|
+
}
|
|
221
|
+
return target;
|
|
222
|
+
}
|
|
223
|
+
else if(typeof target != 'undefined') {
|
|
224
|
+
return target;
|
|
225
|
+
}
|
|
226
|
+
|
|
227
|
+
return source;
|
|
228
|
+
}
|
|
229
|
+
|
|
230
|
+
/**
|
|
231
|
+
* 绑定事件到html对象
|
|
232
|
+
*
|
|
233
|
+
* @method bindEvent
|
|
234
|
+
* @static
|
|
235
|
+
* @param {element} html元素对象
|
|
236
|
+
* @param {string} name 事件名称
|
|
237
|
+
* @param {function} fun 事件委托
|
|
238
|
+
* @returns {name, fun, target} 返回当前绑定
|
|
239
|
+
*/
|
|
240
|
+
static bindEvent(target, name, fun, opt) {
|
|
241
|
+
if(name && name.indexOf && name.indexOf(' ') != -1) {
|
|
242
|
+
let ns = name.split(' ');
|
|
243
|
+
for(let i=0;i<ns.length;i++) {
|
|
244
|
+
this.bindEvent(target, ns[i], fun, opt);
|
|
245
|
+
}
|
|
246
|
+
}
|
|
247
|
+
if(target.attachEvent) {
|
|
248
|
+
target.attachEvent("on"+name, fun, opt);
|
|
249
|
+
}
|
|
250
|
+
else if(target.addEventListener) {
|
|
251
|
+
target.addEventListener(name, fun, opt);
|
|
252
|
+
}
|
|
253
|
+
return {
|
|
254
|
+
name,
|
|
255
|
+
target,
|
|
256
|
+
fun
|
|
257
|
+
};
|
|
258
|
+
}
|
|
259
|
+
|
|
260
|
+
/**
|
|
261
|
+
* 从对象中移除事件到
|
|
262
|
+
*
|
|
263
|
+
* @method removeEvent
|
|
264
|
+
* @static
|
|
265
|
+
* @param {element} html元素对象
|
|
266
|
+
* @param {string} name 事件名称
|
|
267
|
+
* @param {function} fun 事件委托
|
|
268
|
+
*/
|
|
269
|
+
static removeEvent(target, name, fun) {
|
|
270
|
+
if(target.removeEventListener) {
|
|
271
|
+
return target.removeEventListener(name, fun, false);
|
|
272
|
+
}
|
|
273
|
+
else if(target.detachEvent) {
|
|
274
|
+
target.detachEvent('on' + name, fun);
|
|
275
|
+
return true;
|
|
276
|
+
}
|
|
277
|
+
else {
|
|
278
|
+
target['on' + name] = null;
|
|
279
|
+
}
|
|
280
|
+
}
|
|
281
|
+
|
|
282
|
+
/**
|
|
283
|
+
* 获取元素的绝对定位
|
|
284
|
+
*
|
|
285
|
+
* @method getElementPosition
|
|
286
|
+
* @static
|
|
287
|
+
* @param {element} el 目标元素对象
|
|
288
|
+
* @return {position} 位置对象(top,left)
|
|
289
|
+
*/
|
|
290
|
+
static getElementPosition(el) {
|
|
291
|
+
let pos = {"top": 0, "left": 0};
|
|
292
|
+
if(!el) return pos;
|
|
293
|
+
|
|
294
|
+
if (el.offsetParent) {
|
|
295
|
+
while (el.offsetParent) {
|
|
296
|
+
pos.top += el.offsetTop;
|
|
297
|
+
pos.left += el.offsetLeft;
|
|
298
|
+
el = el.offsetParent;
|
|
299
|
+
}
|
|
300
|
+
}
|
|
301
|
+
else if(el.x) {
|
|
302
|
+
pos.left += el.x;
|
|
303
|
+
}
|
|
304
|
+
else if(el.x){
|
|
305
|
+
pos.top += el.y;
|
|
306
|
+
}
|
|
307
|
+
return pos;
|
|
308
|
+
}
|
|
309
|
+
/**
|
|
310
|
+
* 获取元素事件触发的位置
|
|
311
|
+
*
|
|
312
|
+
* @method getEventPosition
|
|
313
|
+
* @static
|
|
314
|
+
* @param {eventArg} evt 当前触发事件的参数
|
|
315
|
+
* @param {point} [scale] 当前画布的缩放比例
|
|
316
|
+
* @return {point} 事件触发的位置
|
|
317
|
+
*/
|
|
318
|
+
static getEventPosition (evt, scale) {
|
|
319
|
+
evt = evt || event;
|
|
320
|
+
const isWXMiniApp = evt.isWXMiniApp;
|
|
321
|
+
let isTouch = false;
|
|
322
|
+
let touches = evt.changedTouches || evt.targetTouches || evt.touches;
|
|
323
|
+
let target = evt.target || evt.srcElement;
|
|
324
|
+
if(touches && touches.length) {
|
|
325
|
+
evt = touches[0];//兼容touch事件
|
|
326
|
+
if(!evt.target) evt.target = target;
|
|
327
|
+
isTouch = true;
|
|
328
|
+
}
|
|
329
|
+
let px = evt.pageX || evt.x;
|
|
330
|
+
if(typeof px == 'undefined') px = evt.clientX + (document.documentElement.scrollLeft || document.body.scrollLeft);
|
|
331
|
+
let py = evt.pageY || evt.y;
|
|
332
|
+
if(typeof py == 'undefined') py = evt.clientY + (document.documentElement.scrollTop || document.body.scrollTop);
|
|
333
|
+
|
|
334
|
+
let ox = evt.offsetX;
|
|
335
|
+
let oy = evt.offsetY;
|
|
336
|
+
if(typeof ox === 'undefined' && typeof oy === 'undefined') {
|
|
337
|
+
// 小程序下取x,y就是它的相对坐标
|
|
338
|
+
if(isWXMiniApp) {
|
|
339
|
+
ox = evt.x;
|
|
340
|
+
oy = evt.y;
|
|
341
|
+
}
|
|
342
|
+
else {
|
|
343
|
+
let p = this.getElementPosition(target);
|
|
344
|
+
ox= px - p.left;
|
|
345
|
+
oy = py - p.top;
|
|
346
|
+
}
|
|
347
|
+
}
|
|
348
|
+
if(scale) {
|
|
349
|
+
if(scale.x) ox = ox / scale.x;
|
|
350
|
+
if(scale.y) oy = oy / scale.y;
|
|
351
|
+
}
|
|
352
|
+
|
|
353
|
+
return {
|
|
354
|
+
pageX: px,
|
|
355
|
+
pageY: py,
|
|
356
|
+
clientX: evt.clientX,
|
|
357
|
+
clientY: evt.clientY,
|
|
358
|
+
//相对于容器偏移量
|
|
359
|
+
offsetX: ox,
|
|
360
|
+
offsetY: oy,
|
|
361
|
+
layerX: evt.layerX,
|
|
362
|
+
layerY: evt.layerY,
|
|
363
|
+
screenX: evt.screenX,
|
|
364
|
+
screenY: evt.screenY,
|
|
365
|
+
x: ox,
|
|
366
|
+
y: oy,
|
|
367
|
+
isTouch: isTouch,
|
|
368
|
+
touches,
|
|
369
|
+
isWXMiniApp
|
|
370
|
+
};
|
|
371
|
+
}
|
|
372
|
+
|
|
373
|
+
/**
|
|
374
|
+
* 检 查对象是否为指定的类型,不包括继承
|
|
375
|
+
*
|
|
376
|
+
* @method isType
|
|
377
|
+
* @static
|
|
378
|
+
* @param {object} target 需要判断类型的对象
|
|
379
|
+
* @param {class} type 对象类型
|
|
380
|
+
* @return {boolean} 返回对象是否为指定类型
|
|
381
|
+
*/
|
|
382
|
+
static isType(target, type) {
|
|
383
|
+
if(!target || typeof target !== 'object') return false;
|
|
384
|
+
if(target.constructor === type) return true;
|
|
385
|
+
/*if(target.__baseType) {
|
|
386
|
+
return jmUtils.isType(target.__baseType.prototype,type);
|
|
387
|
+
}*/
|
|
388
|
+
|
|
389
|
+
//return target instanceof type;
|
|
390
|
+
return false;
|
|
391
|
+
}
|
|
392
|
+
/**
|
|
393
|
+
* 判断点是否在多边形内
|
|
394
|
+
* 如果一个点在多边形内部,任意角度做射线肯定会与多边形要么有一个交点,要么有与多边形边界线重叠。
|
|
395
|
+
* 如果一个点在多边形外部,任意角度做射线要么与多边形有一个交点,要么有两个交点,要么没有交点,要么有与多边形边界线重叠。
|
|
396
|
+
* 利用上面的结论,我们只要判断这个点与多边形的交点个数,就可以判断出点与多边形的位置关系了。
|
|
397
|
+
*
|
|
398
|
+
* @method pointInPolygon
|
|
399
|
+
* @static
|
|
400
|
+
* @param {point} pt 坐标对象
|
|
401
|
+
* @param {array} polygon 多边型角坐标对象数组
|
|
402
|
+
* @param {number} offset 判断可偏移值
|
|
403
|
+
* @return {integer} 0= 不在图形内和线上,1=在边上,2=在图形内部
|
|
404
|
+
*/
|
|
405
|
+
static pointInPolygon(pt, polygon, offset) {
|
|
406
|
+
offset = offset || 1;
|
|
407
|
+
offset = offset / 2;
|
|
408
|
+
const n = polygon.length;
|
|
409
|
+
|
|
410
|
+
if(!polygon || n == 0) return 0;
|
|
411
|
+
|
|
412
|
+
if(n == 1) {
|
|
413
|
+
return Math.abs(polygon[0].x - pt.x) <= offset && Math.abs(polygon[0].y - pt.y) <= offset ? 1 : 0;
|
|
414
|
+
}
|
|
415
|
+
|
|
416
|
+
if(n == 2) {
|
|
417
|
+
return this.pointOnLine(pt, polygon[0], polygon[1], offset);
|
|
418
|
+
}
|
|
419
|
+
|
|
420
|
+
for (let i = 0; i < n; i++) {
|
|
421
|
+
if (Math.abs(polygon[i].x - pt.x) <= offset &&
|
|
422
|
+
Math.abs(polygon[i].y - pt.y) <= offset) {
|
|
423
|
+
return 1;
|
|
424
|
+
}
|
|
425
|
+
}
|
|
426
|
+
|
|
427
|
+
return this.rayCasting(pt, polygon, offset);
|
|
428
|
+
}
|
|
429
|
+
|
|
430
|
+
static pointOnLine(pt, p1, p2, offset) {
|
|
431
|
+
const minX = Math.min(p1.x, p2.x);
|
|
432
|
+
const maxX = Math.max(p1.x, p2.x);
|
|
433
|
+
const minY = Math.min(p1.y, p2.y);
|
|
434
|
+
const maxY = Math.max(p1.y, p2.y);
|
|
435
|
+
|
|
436
|
+
if (minX - pt.x > offset || pt.x - maxX > offset) {
|
|
437
|
+
return 0;
|
|
438
|
+
}
|
|
439
|
+
if (minY - pt.y > offset || pt.y - maxY > offset) {
|
|
440
|
+
return 0;
|
|
441
|
+
}
|
|
442
|
+
|
|
443
|
+
if (p1.x == p2.x) {
|
|
444
|
+
return Math.abs(p1.x - pt.x) <= offset &&
|
|
445
|
+
(pt.y - p1.y) * (pt.y - p2.y) <= 0 ? 1 : 0;
|
|
446
|
+
}
|
|
447
|
+
|
|
448
|
+
if (p1.y == p2.y) {
|
|
449
|
+
return Math.abs(p1.y - pt.y) <= offset &&
|
|
450
|
+
(pt.x - p1.x) * (pt.x - p2.x) <= 0 ? 1 : 0;
|
|
451
|
+
}
|
|
452
|
+
|
|
453
|
+
if (Math.abs(p1.x - pt.x) < offset && Math.abs(p1.y - pt.y) < offset) {
|
|
454
|
+
return 1;
|
|
455
|
+
}
|
|
456
|
+
if (Math.abs(p2.x - pt.x) < offset && Math.abs(p2.y - pt.y) < offset) {
|
|
457
|
+
return 1;
|
|
458
|
+
}
|
|
459
|
+
|
|
460
|
+
if (pt.y != p1.y && pt.y != p2.y) {
|
|
461
|
+
const f = (p2.x - p1.x) / (p2.y - p1.y) * (pt.y - p1.y);
|
|
462
|
+
const ff = (pt.y - p1.y) / Math.sqrt(f * f + (pt.y - p1.y) * (pt.y - p1.y));
|
|
463
|
+
const l = ff * (pt.x - p1.x - f);
|
|
464
|
+
|
|
465
|
+
return Math.abs(l) <= offset ? 1 : 0;
|
|
466
|
+
}
|
|
467
|
+
return 0;
|
|
468
|
+
}
|
|
469
|
+
|
|
470
|
+
static rayCasting(pt, polygon, offset) {
|
|
471
|
+
const n = polygon.length;
|
|
472
|
+
let inside = false;
|
|
473
|
+
const testY = pt.y;
|
|
474
|
+
const testX = pt.x;
|
|
475
|
+
|
|
476
|
+
for (let i = 0, j = n - 1; i < n; j = i++) {
|
|
477
|
+
const yi = polygon[i].y;
|
|
478
|
+
const yj = polygon[j].y;
|
|
479
|
+
const xi = polygon[i].x;
|
|
480
|
+
const xj = polygon[j].x;
|
|
481
|
+
|
|
482
|
+
const intersect = ((yi > testY) !== (yj > testY)) &&
|
|
483
|
+
(testX < (xj - xi) * (testY - yi) / (yj - yi) + xi);
|
|
484
|
+
|
|
485
|
+
if (intersect) {
|
|
486
|
+
inside = !inside;
|
|
487
|
+
}
|
|
488
|
+
}
|
|
489
|
+
|
|
490
|
+
return inside ? 2 : 0;
|
|
491
|
+
}
|
|
492
|
+
|
|
493
|
+
/**
|
|
494
|
+
* @method judge 判断点是否在多边形中
|
|
495
|
+
* @param {point} dot {{x,y}} 需要判断的点
|
|
496
|
+
* @param {array} coordinates {{x,y}} 多边形点坐标的数组,为保证图形能够闭合,起点和终点必须相等。
|
|
497
|
+
* 比如三角形需要四个点表示,第一个点和最后一个点必须相同。
|
|
498
|
+
* @param {number} 是否为实心 1= 是
|
|
499
|
+
* @returns {boolean} 结果 true=在形状内
|
|
500
|
+
*/
|
|
501
|
+
/*static judge(dot,coordinates,noneZeroMode) {
|
|
502
|
+
// 默认启动none zero mode
|
|
503
|
+
noneZeroMode=noneZeroMode||1;
|
|
504
|
+
var x = dot.x,y=dot.y;
|
|
505
|
+
var crossNum = 0;
|
|
506
|
+
// 点在线段的左侧数目
|
|
507
|
+
var leftCount = 0;
|
|
508
|
+
// 点在线段的右侧数目
|
|
509
|
+
var rightCount = 0;
|
|
510
|
+
for(var i=0;i<coordinates.length-1;i++){
|
|
511
|
+
var start = coordinates[i];
|
|
512
|
+
var end = coordinates[i+1];
|
|
513
|
+
|
|
514
|
+
// 起点、终点斜率不存在的情况
|
|
515
|
+
if(start.x===end.x) {
|
|
516
|
+
// 因为射线向右水平,此处说明不相交
|
|
517
|
+
if(x>start.x) continue;
|
|
518
|
+
|
|
519
|
+
// 从左侧贯穿
|
|
520
|
+
if((end.y>start.y&&y>=start.y && y<=end.y)){
|
|
521
|
+
leftCount++;
|
|
522
|
+
crossNum++;
|
|
523
|
+
}
|
|
524
|
+
// 从右侧贯穿
|
|
525
|
+
if((end.y<start.y&&y>=end.y && y<=start.y)) {
|
|
526
|
+
rightCount++;
|
|
527
|
+
crossNum++;
|
|
528
|
+
}
|
|
529
|
+
continue;
|
|
530
|
+
}
|
|
531
|
+
// 斜率存在的情况,计算斜率
|
|
532
|
+
var k=(end.y-start.y)/(end.x-start.x);
|
|
533
|
+
// 交点的x坐标
|
|
534
|
+
var x0 = (y-start.y)/k+start.x;
|
|
535
|
+
// 因为射线向右水平,此处说明不相交
|
|
536
|
+
if(x>x0) continue;
|
|
537
|
+
|
|
538
|
+
if((end.x>start.x&&x0>=start.x && x0<=end.x)){
|
|
539
|
+
crossNum++;
|
|
540
|
+
if(k>=0) leftCount++;
|
|
541
|
+
else rightCount++;
|
|
542
|
+
}
|
|
543
|
+
if((end.x<start.x&&x0>=end.x && x0<=start.x)) {
|
|
544
|
+
crossNum++;
|
|
545
|
+
if(k>=0) rightCount++;
|
|
546
|
+
else leftCount++;
|
|
547
|
+
}
|
|
548
|
+
}
|
|
549
|
+
|
|
550
|
+
return noneZeroMode===1?leftCount-rightCount!==0:crossNum%2===1;
|
|
551
|
+
}*/
|
|
552
|
+
|
|
553
|
+
/**
|
|
554
|
+
* 检查边界,子对象是否超出父容器边界
|
|
555
|
+
* 当对象偏移offset后是否出界
|
|
556
|
+
* 返回(left:0,right:0,top:0,bottom:0)
|
|
557
|
+
* 如果right>0表示右边出界right偏移量,left<0则表示左边出界left偏移量
|
|
558
|
+
* 如果bottom>0表示下边出界bottom偏移量,top<0则表示上边出界ltop偏移量
|
|
559
|
+
*
|
|
560
|
+
* @method checkOutSide
|
|
561
|
+
* @static
|
|
562
|
+
* @param {bound} parentBounds 父对象的边界
|
|
563
|
+
* @param {bound} targetBounds 对象的边界
|
|
564
|
+
* @param {number} offset 判断是否越界可容偏差
|
|
565
|
+
* @return {bound} 越界标识
|
|
566
|
+
*/
|
|
567
|
+
static checkOutSide(parentBounds, targetBounds, offset) {
|
|
568
|
+
let result = {left:0,right:0,top:0,bottom:0};
|
|
569
|
+
if(offset.x < 0 ) {
|
|
570
|
+
result.left = targetBounds.left + offset.x - parentBounds.left;
|
|
571
|
+
}
|
|
572
|
+
else if(offset.x > 0 ) {
|
|
573
|
+
result.right = targetBounds.right + offset.x - parentBounds.right;
|
|
574
|
+
}
|
|
575
|
+
|
|
576
|
+
if(offset.y < 0 ) {
|
|
577
|
+
result.top = targetBounds.top + offset.y - parentBounds.top;
|
|
578
|
+
}
|
|
579
|
+
else if(offset.y > 0) {
|
|
580
|
+
result.bottom = targetBounds.bottom + offset.y - parentBounds.bottom;
|
|
581
|
+
}
|
|
582
|
+
return result;
|
|
583
|
+
}
|
|
584
|
+
|
|
585
|
+
/**
|
|
586
|
+
* 把一个或多个点绕某个点旋转一定角度
|
|
587
|
+
* 先把坐标原点移到旋转中心点,计算后移回
|
|
588
|
+
* @method rotatePoints
|
|
589
|
+
* @static
|
|
590
|
+
* @param {Array/object} p 一个或多个点
|
|
591
|
+
* @param {*} rp 旋转中心点
|
|
592
|
+
* @param {*} r 旋转角度
|
|
593
|
+
*/
|
|
594
|
+
static rotatePoints(p, rp, r) {
|
|
595
|
+
if(!r || !p) return p;
|
|
596
|
+
let cos = Math.cos(r);
|
|
597
|
+
let sin = Math.sin(r);
|
|
598
|
+
if(Array.isArray(p)) {
|
|
599
|
+
for(let i=0;i<p.length;i++) {
|
|
600
|
+
if(!p[i]) continue;
|
|
601
|
+
let x1 = p[i].x - rp.x;
|
|
602
|
+
let y1 = p[i].y - rp.y;
|
|
603
|
+
p[i].x = x1 * cos - y1 * sin + rp.x;
|
|
604
|
+
p[i].y = x1 * sin + y1 * cos + rp.y;
|
|
605
|
+
}
|
|
606
|
+
}
|
|
607
|
+
else {
|
|
608
|
+
let x1 = p.x - rp.x;
|
|
609
|
+
let y1 = p.y - rp.y;
|
|
610
|
+
p.x = x1 * cos - y1 * sin + rp.x;
|
|
611
|
+
p.y = x1 * sin + y1 * cos + rp.y;
|
|
612
|
+
}
|
|
613
|
+
return p;
|
|
614
|
+
}
|
|
615
|
+
|
|
616
|
+
/**
|
|
617
|
+
* 去除字符串开始字符
|
|
618
|
+
*
|
|
619
|
+
* @method trimStart
|
|
620
|
+
* @static
|
|
621
|
+
* @param {string} source 需要处理的字符串
|
|
622
|
+
* @param {char} [c] 要去除字符串的前置字符
|
|
623
|
+
* @return {string} 去除前置字符后的字符串
|
|
624
|
+
*/
|
|
625
|
+
static trimStart(source, c) {
|
|
626
|
+
c = c || ' ';
|
|
627
|
+
if(source && source.length > 0) {
|
|
628
|
+
let sc = source[0];
|
|
629
|
+
if(sc === c || c.indexOf(sc) >= 0) {
|
|
630
|
+
source = source.substring(1);
|
|
631
|
+
return this.trimStart(source,c);
|
|
632
|
+
}
|
|
633
|
+
}
|
|
634
|
+
return source;
|
|
635
|
+
}
|
|
636
|
+
|
|
637
|
+
/**
|
|
638
|
+
* 去除字符串结束的字符c
|
|
639
|
+
*
|
|
640
|
+
* @method trimEnd
|
|
641
|
+
* @static
|
|
642
|
+
* @param {string} source 需要处理的字符串
|
|
643
|
+
* @param {char} [c] 要去除字符串的后置字符
|
|
644
|
+
* @return {string} 去除后置字符后的字符串
|
|
645
|
+
*/
|
|
646
|
+
static trimEnd(source, c) {
|
|
647
|
+
c = c || ' ';
|
|
648
|
+
if(source && source.length > 0) {
|
|
649
|
+
let sc = source[source.length - 1];
|
|
650
|
+
if(sc === c || c.indexOf(sc) >= 0) {
|
|
651
|
+
source = source.substring(0,source.length - 1);
|
|
652
|
+
return this.trimStart(source,c);
|
|
653
|
+
}
|
|
654
|
+
}
|
|
655
|
+
return source;
|
|
656
|
+
}
|
|
657
|
+
|
|
658
|
+
/**
|
|
659
|
+
* 去除字符串开始与结束的字符
|
|
660
|
+
*
|
|
661
|
+
* @method trim
|
|
662
|
+
* @static
|
|
663
|
+
* @param {string} source 需要处理的字符串
|
|
664
|
+
* @param {char} [c] 要去除字符串的字符
|
|
665
|
+
* @return {string} 去除字符后的字符串
|
|
666
|
+
*/
|
|
667
|
+
static trim(source,c) {
|
|
668
|
+
return this.trimEnd(this.trimStart(source,c),c);
|
|
669
|
+
}
|
|
670
|
+
|
|
671
|
+
/**
|
|
672
|
+
* 检查是否为百分比参数
|
|
673
|
+
*
|
|
674
|
+
* @method checkPercent
|
|
675
|
+
* @static
|
|
676
|
+
* @param {string} 字符串参数
|
|
677
|
+
* @return {boolean} true=当前字符串为百分比参数,false=不是
|
|
678
|
+
*/
|
|
679
|
+
static checkPercent(per) {
|
|
680
|
+
if(typeof per === 'string') {
|
|
681
|
+
per = this.trim(per);
|
|
682
|
+
if(per[per.length - 1] == '%') {
|
|
683
|
+
return per;
|
|
684
|
+
}
|
|
685
|
+
}
|
|
686
|
+
}
|
|
687
|
+
|
|
688
|
+
/**
|
|
689
|
+
* 转换百分数为数值类型
|
|
690
|
+
*
|
|
691
|
+
* @method percentToNumber
|
|
692
|
+
* @static
|
|
693
|
+
* @param {string} per 把百分比转为数值的参数
|
|
694
|
+
* @return {number} 百分比对应的数值
|
|
695
|
+
*/
|
|
696
|
+
static percentToNumber(per) {
|
|
697
|
+
if(typeof per === 'string') {
|
|
698
|
+
let tmp = this.checkPercent(per);
|
|
699
|
+
if(tmp) {
|
|
700
|
+
per = this.trim(tmp,'% ');
|
|
701
|
+
per = per / 100;
|
|
702
|
+
}
|
|
703
|
+
}
|
|
704
|
+
return per;
|
|
705
|
+
}
|
|
706
|
+
|
|
707
|
+
/**
|
|
708
|
+
* 转换16进制为数值
|
|
709
|
+
*
|
|
710
|
+
* @method hexToNumber
|
|
711
|
+
* @static
|
|
712
|
+
* @param {string} h 16进制颜色表达
|
|
713
|
+
* @return {number} 10进制表达
|
|
714
|
+
*/
|
|
715
|
+
static hexToNumber(h) {
|
|
716
|
+
if(typeof h !== 'string') return h;
|
|
717
|
+
|
|
718
|
+
h = h.toLowerCase();
|
|
719
|
+
let hex = '0123456789abcdef';
|
|
720
|
+
let v = 0;
|
|
721
|
+
let l = h.length;
|
|
722
|
+
for(let i=0;i<l;i++) {
|
|
723
|
+
let iv = hex.indexOf(h[i]);
|
|
724
|
+
if(iv == 0) continue;
|
|
725
|
+
|
|
726
|
+
for(let j=1;j<l - i;j++) {
|
|
727
|
+
iv *= 16;
|
|
728
|
+
}
|
|
729
|
+
v += iv;
|
|
730
|
+
}
|
|
731
|
+
return v;
|
|
732
|
+
}
|
|
733
|
+
|
|
734
|
+
/**
|
|
735
|
+
* 转换数值为16进制字符串表达
|
|
736
|
+
*
|
|
737
|
+
* @method hex
|
|
738
|
+
* @static
|
|
739
|
+
* @param {number} v 数值
|
|
740
|
+
* @return {string} 16进制表达
|
|
741
|
+
*/
|
|
742
|
+
static numberToHex(v) {
|
|
743
|
+
let hex = '0123456789abcdef';
|
|
744
|
+
|
|
745
|
+
let h = '';
|
|
746
|
+
while(v > 0) {
|
|
747
|
+
let t = v % 16;
|
|
748
|
+
h = hex[t] + h;
|
|
749
|
+
v = Math.floor(v / 16);
|
|
750
|
+
}
|
|
751
|
+
return h;
|
|
752
|
+
}
|
|
753
|
+
|
|
754
|
+
/**
|
|
755
|
+
* 16进制颜色转为r g b a 对象 {r, g , b, a}
|
|
756
|
+
* @param {string}} hex 16进度的颜色
|
|
757
|
+
*/
|
|
758
|
+
static hexToRGBA(hex) {
|
|
759
|
+
if(typeof hex === 'string') hex = this.trim(hex);
|
|
760
|
+
else return hex;
|
|
761
|
+
|
|
762
|
+
// 如果缓存存在,则直接返回
|
|
763
|
+
this.__hexToRGBA_Cache = this.__hexToRGBA_Cache || {};
|
|
764
|
+
if(this.__hexToRGBA_Cache[hex]) return this.__hexToRGBA_Cache[hex];
|
|
765
|
+
|
|
766
|
+
let res = hex;
|
|
767
|
+
|
|
768
|
+
// 系统颜色
|
|
769
|
+
if(colorKeywords[res]) res = colorKeywords[res];
|
|
770
|
+
|
|
771
|
+
//当为7位时,表示需要转为带透明度的rgba
|
|
772
|
+
if(res[0] == '#') {
|
|
773
|
+
const color = {
|
|
774
|
+
a: 1
|
|
775
|
+
};
|
|
776
|
+
if(res.length >= 8) {
|
|
777
|
+
color.a = res.substr(1,2);
|
|
778
|
+
color.g = res.substr(5,2);
|
|
779
|
+
color.b = res.substr(7,2);
|
|
780
|
+
color.r = res.substr(3,2);
|
|
781
|
+
//透明度
|
|
782
|
+
color.a = Number((this.hexToNumber(color.a) / 255).toFixed(4));
|
|
783
|
+
|
|
784
|
+
color.r = this.hexToNumber(color.r||0);
|
|
785
|
+
color.g = this.hexToNumber(color.g||0);
|
|
786
|
+
color.b = this.hexToNumber(color.b||0);
|
|
787
|
+
res = color;
|
|
788
|
+
}
|
|
789
|
+
// #cccccc || #ccc
|
|
790
|
+
else if(res.length === 7 || res.length === 4) {
|
|
791
|
+
// #ccc这种情况,把每个位复制一份
|
|
792
|
+
if(res.length === 4) {
|
|
793
|
+
color.g = res.substr(2, 1);
|
|
794
|
+
color.g = color.g + color.g;
|
|
795
|
+
color.b = res.substr(3, 1);
|
|
796
|
+
color.b = color.b + color.b;
|
|
797
|
+
color.r = res.substr(1, 1);
|
|
798
|
+
color.r = color.r + color.r;
|
|
799
|
+
}
|
|
800
|
+
else {
|
|
801
|
+
color.g = res.substr(3, 2);//除#号外的第二位
|
|
802
|
+
color.b = res.substr(5, 2);
|
|
803
|
+
color.r = res.substr(1, 2);
|
|
804
|
+
}
|
|
805
|
+
|
|
806
|
+
color.r = this.hexToNumber(color.r||0);
|
|
807
|
+
color.g = this.hexToNumber(color.g||0);
|
|
808
|
+
color.b = this.hexToNumber(color.b||0);
|
|
809
|
+
|
|
810
|
+
res = color;
|
|
811
|
+
}
|
|
812
|
+
//如果是5位的话,# 则第2位表示A,后面依次是r,g,b
|
|
813
|
+
else if(res.length === 5) {
|
|
814
|
+
color.a = res.substr(1,1);
|
|
815
|
+
color.g = res.substr(3,1);//除#号外的第二位
|
|
816
|
+
color.b = res.substr(4,1);
|
|
817
|
+
color.r = res.substr(2,1);
|
|
818
|
+
|
|
819
|
+
color.r = this.hexToNumber(color.r||0);
|
|
820
|
+
color.g = this.hexToNumber(color.g||0);
|
|
821
|
+
color.b = this.hexToNumber(color.b||0);
|
|
822
|
+
//透明度
|
|
823
|
+
color.a = Number((this.hexToNumber(color.a) / 255).toFixed(4));
|
|
824
|
+
res = color;
|
|
825
|
+
}
|
|
826
|
+
}
|
|
827
|
+
if(typeof res === 'string') {
|
|
828
|
+
const m = res.match(/rgb(a)?\s*\(\s*([\d\.]+)\s*,\s*([\d\.]+)\s*,\s*([\d\.]+)\s*(,\s*[\d\.]+)?\s*\)/i);
|
|
829
|
+
if(m && m.length === 6) {
|
|
830
|
+
const color = {
|
|
831
|
+
r: Number(m[2]),
|
|
832
|
+
g: Number(m[3]),
|
|
833
|
+
b: Number(m[4]),
|
|
834
|
+
a: Number(this.trimStart(m[5]||'1', ','))
|
|
835
|
+
};
|
|
836
|
+
res = color;
|
|
837
|
+
}
|
|
838
|
+
}
|
|
839
|
+
return this.__hexToRGBA_Cache[hex] = res;
|
|
840
|
+
}
|
|
841
|
+
|
|
842
|
+
/**
|
|
843
|
+
* 把255的rgb值转为0-1的值
|
|
844
|
+
* @param {rgba} color 颜色
|
|
845
|
+
*/
|
|
846
|
+
static rgbToDecimal(color) {
|
|
847
|
+
color = this.clone(color);
|
|
848
|
+
color.r = this.byteToDecimal(color.r);
|
|
849
|
+
color.g = this.byteToDecimal(color.g);
|
|
850
|
+
color.b = this.byteToDecimal(color.b);
|
|
851
|
+
return color;
|
|
852
|
+
}
|
|
853
|
+
|
|
854
|
+
//255值转为0-1的小数
|
|
855
|
+
static byteToDecimal(b) {
|
|
856
|
+
return b / 255;
|
|
857
|
+
}
|
|
858
|
+
|
|
859
|
+
/**
|
|
860
|
+
* 转换颜色格式,如果输入r,g,b则转为hex格式,如果为hex则转为r,g,b格式
|
|
861
|
+
*
|
|
862
|
+
* @method toColor
|
|
863
|
+
* @static
|
|
864
|
+
* @param {string} hex 16进制颜色表达
|
|
865
|
+
* @return {string} 颜色字符串
|
|
866
|
+
*/
|
|
867
|
+
static toColor(r, g, b, a) {
|
|
868
|
+
if(typeof r === 'string' && r) {
|
|
869
|
+
r = this.trim(r);
|
|
870
|
+
// 正常的颜色表达,不需要转换
|
|
871
|
+
if(r[0] === '#' && (r.length === 4 || r.length === 7)) return r;
|
|
872
|
+
|
|
873
|
+
const color = this.hexToRGBA(r);
|
|
874
|
+
if(typeof color === 'string') return color;
|
|
875
|
+
|
|
876
|
+
r = typeof color.r !== 'undefined'? color.r: r;
|
|
877
|
+
g = typeof color.g !== 'undefined'? color.g: g;
|
|
878
|
+
b = typeof color.b !== 'undefined'? color.b: b;
|
|
879
|
+
a = typeof color.a !== 'undefined'? color.a: a;
|
|
880
|
+
}
|
|
881
|
+
if(r && typeof r === 'object') {
|
|
882
|
+
g = r.g;
|
|
883
|
+
b = r.b;
|
|
884
|
+
a = r.a || 1;
|
|
885
|
+
r = r.r;
|
|
886
|
+
}
|
|
887
|
+
if(typeof r != 'undefined' && typeof g != 'undefined' && typeof b != 'undefined') {
|
|
888
|
+
if(typeof a != 'undefined') {
|
|
889
|
+
return 'rgba(' + r + ',' + g + ',' + b + ',' + a + ')';
|
|
890
|
+
}
|
|
891
|
+
else {
|
|
892
|
+
return 'rgb(' + r + ',' + g + ',' + b + ')';
|
|
893
|
+
}
|
|
894
|
+
}
|
|
895
|
+
return r;
|
|
896
|
+
}
|
|
897
|
+
// window.requestAnimationFrame() 告诉浏览器——你希望执行一个动画,并且要求浏览器在下次重绘之前调用指定的回调函数更新动画。该方法需要传入一个回调函数作为参数,该回调函数会在浏览器下一次重绘之前执行
|
|
898
|
+
static requestAnimationFrame(callback, win) {
|
|
899
|
+
let fun = win && win.requestAnimationFrame? win.requestAnimationFrame: (typeof window !== 'undefined' && window.requestAnimationFrame? window.requestAnimationFrame: setTimeout);
|
|
900
|
+
return fun(callback, 20);
|
|
901
|
+
}
|
|
902
|
+
static cancelAnimationFrame(handler, win) {
|
|
903
|
+
let fun = win && win.cancelAnimationFrame? win.cancelAnimationFrame: (typeof window !== 'undefined' && window.cancelAnimationFrame? window.cancelAnimationFrame: clearTimeout);
|
|
904
|
+
return fun(handler);
|
|
905
|
+
}
|
|
906
|
+
}
|
|
920
907
|
export { jmUtils };
|