jmgraph 3.2.27 → 3.2.28
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/jmgraph.core.min.js +1 -1
- package/dist/jmgraph.core.min.js.map +1 -1
- package/dist/jmgraph.js +2661 -415
- package/dist/jmgraph.min.js +1 -1
- package/package.json +1 -1
- package/src/core/jmControl.js +827 -127
- package/src/core/jmEvents.js +154 -0
- package/src/core/jmFilter.js +38 -1
- package/src/core/jmGradient.js +47 -2
- package/src/core/jmGraph.js +51 -7
- package/src/core/jmLayer.js +34 -2
- package/src/core/jmList.js +167 -0
- package/src/core/jmObject.js +128 -8
- package/src/core/jmPath.js +43 -5
- package/src/core/jmProperty.js +181 -2
- package/src/core/jmShadow.js +36 -7
- package/src/core/jmUtils.js +149 -12
- package/src/lib/webgl/base.js +211 -83
- package/src/lib/webgl/core/buffer.js +43 -12
- package/src/lib/webgl/core/mapSize.js +16 -7
- package/src/lib/webgl/core/mapType.js +41 -22
- package/src/lib/webgl/core/program.js +94 -54
- package/src/lib/webgl/core/shader.js +20 -8
- package/src/lib/webgl/core/texture.js +55 -32
- package/src/lib/webgl/gradient.js +49 -17
- package/src/lib/webgl/index.js +173 -24
- package/src/lib/webgl/path.js +61 -12
- package/src/shapes/jmArc.js +48 -2
- package/src/shapes/jmArrow.js +35 -2
- package/src/shapes/jmArrowLine.js +33 -2
- package/src/shapes/jmBezier.js +50 -4
- package/src/shapes/jmCircle.js +35 -2
- package/src/shapes/jmEllipse.js +29 -3
- package/src/shapes/jmHArc.js +39 -2
- package/src/shapes/jmImage.js +49 -3
- package/src/shapes/jmLabel.js +41 -2
- package/src/shapes/jmLine.js +42 -2
- package/src/shapes/jmPolygon.js +42 -3
- package/src/shapes/jmPrismatic.js +34 -2
- package/src/shapes/jmRect.js +45 -3
- package/src/shapes/jmResize.js +42 -4
- package/src/shapes/jmStar.js +38 -4
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"jmgraph.core.min.js","sources":["../src/core/jmList.js","../src/core/jmUtils.js","../src/core/jmObject.js","../src/core/jmProperty.js","../src/core/jmShadow.js","../src/core/jmGradient.js","../src/core/jmFilter.js","../src/core/jmEvents.js","../src/lib/earcut.js","../src/lib/webgl/gradient.js","../src/lib/webgl/core/shader.js","../src/lib/webgl/core/mapSize.js","../src/lib/webgl/core/mapType.js","../src/lib/webgl/core/program.js","../src/lib/webgl/core/buffer.js","../src/lib/webgl/core/texture.js","../src/lib/webgl/base.js","../src/lib/webgl/path.js","../src/core/jmControl.js","../src/core/jmPath.js","../src/core/jmGraph.js"],"sourcesContent":["export default class jmList extends Array {\n constructor(...arg) {\n const ps = [];\n if(arg && arg.length && Array.isArray(arg[0])) {\n for(let i=0; i< arg[0].length; i++) ps.push(arg[0][i]);\n super(...ps);\n }\n else {\n super();\n }\n this.option = {};\n this.type = 'jmList';\n }\n\n add(obj) {\n if(obj && Array.isArray(obj)) {\n for(let i=0; i < obj.length; i++) {\n if(!this.includes(obj[i])) this.push(obj[i]);\n }\n return obj;\n }\n if(typeof obj == 'object' && this.includes(obj)) return obj;\n this.push(obj);\n return obj;\n }\n\n remove(obj) {\n for(let i = this.length -1; i>=0; i--) {\n if(this[i] == obj) {\n this.removeAt(i);\n }\n }\n }\n\n removeAt(index) {\n if(this.length > index) {\n const obj = this[index];\n this.splice(index,1);\n if(this.option.removeHandler) this.option.removeHandler.call(this, obj, index);\n }\n }\n\n contain(obj) {\n return this.includes(obj);\n }\n\n get(index) {\n if(typeof index == 'function') {\n return this.find(index);\n }\n else {\n return this[index];\n }\n }\n\n each(cb, inverse) {\n if(cb && typeof cb == 'function') {\n if(inverse) {\n for(let i = this.length - 1;i>=0; i--) {\n const r = cb.call(this, i, this[i]);\n if(r === false) break;\n }\n }\n else {\n const len = this.length;\n for(let i = 0; i < len;i++) {\n const r = cb.call(this, i, this[i]);\n if(r === false) break;\n }\n }\n }\n }\n\n count(handler) {\n if(handler && typeof handler == 'function') {\n let count = 0;\n const len = this.length;\n for(let i = 0; i<len;i++) {\n if(handler(this[i])) {\n count++;\n }\n }\n return count;\n }\n return this.length;\n }\n\n clear() {\n this.splice(0, this.length);\n }\n}\n\nexport { jmList };","\nimport { jmList } from './jmList.js';\n\nconst colorKeywords = {\n aliceblue: \"#f0f8ff\",\n antiquewhite: \"#faebd7\",\n aqua: \"#00ffff\",\n aquamarine: \"#7fffd4\",\n azure: \"#f0ffff\",\n beige: \"#f5f5dc\",\n bisque: \"#ffe4c4\",\n black: \"#000000\",\n blanchedalmond: \"#ffebcd\",\n blue: \"#0000ff\",\n blueviolet: \"#8a2be2\",\n brown: \"#a52a2a\",\n burlywood: \"#deb887\",\n cadetblue: \"#5f9ea0\",\n chartreuse: \"#7fff00\",\n chocolate: \"#d2691e\",\n coral: \"#ff7f50\",\n cornflowerblue: \"#6495ed\",\n cornsilk: \"#fff8dc\",\n crimson: \"#dc143c\",\n cyan: \"#00ffff\",\n darkblue: \"#00008b\",\n darkcyan: \"#008b8b\",\n darkgoldenrod: \"#b8860b\",\n darkgray: \"#a9a9a9\",\n darkgreen: \"#006400\",\n darkkhaki: \"#bdb76b\",\n darkmagenta: \"#8b008b\",\n darkolivegreen: \"#556b2f\",\n darkorange: \"#ff8c00\",\n darkorchid: \"#9932cc\",\n darkred: \"#8b0000\",\n darksalmon: \"#e9967a\",\n darkseagreen: \"#8fbc8f\",\n darkslateblue: \"#483d8b\",\n darkslategray: \"#2f4f4f\",\n darkslategrey: \"#2f4f4f\",\n darkturquoise: \"#00ced1\",\n darkviolet: \"#9400d3\",\n deeppink: \"#ff1493\",\n deepskyblue: \"#00bfff\",\n dimgray: \"#696969\",\n dimgrey: \"#696969\",\n dodgerblue: \"#1e90ff\",\n firebrick: \"#b22222\",\n floralwhite: \"#fffaf0\",\n forestgreen: \"#228b22\",\n fuchsia: \"#ff00ff\",\n gainsboro: \"#dcdcdc\",\n ghostwhite: \"#f8f8ff\",\n gold: \"#ffd700\",\n goldenrod: \"#daa520\",\n gray: \"#808080\",\n green: \"#008000\",\n greenyellow: \"#adff2f\",\n grey: \"#808080\",\n honeydew: \"#f0fff0\",\n hotpink: \"#ff69b4\",\n indianred: \"#cd5c5c\",\n indigo: \"#4b0082\",\n ivory: \"#fffff0\",\n khaki: \"#f0e68c\",\n lavender: \"#e6e6fa\",\n lavenderblush: \"#fff0f5\",\n lawngreen: \"#7cfc00\",\n lemonchiffon: \"#fffacd\",\n lightblue: \"#add8e6\",\n lightcoral: \"#f08080\",\n lightcyan: \"#e0ffff\",\n lightgoldenrodyellow: \"#fafad2\",\n lightgrey: \"#d3d3d3\",\n lightgreen: \"#90ee90\",\n lightpink: \"#ffb6c1\",\n lightsalmon: \"#ffa07a\",\n lightseagreen: \"#20b2aa\",\n lightskyblue: \"#87cefa\",\n lightslategray: \"#778899\",\n lightslategrey: \"#778899\",\n lightsteelblue: \"#b0c4de\",\n lightyellow: \"#ffffe0\",\n lime: \"#00ff00\",\n limegreen: \"#32cd32\",\n linen: \"#faf0e6\",\n magenta: \"#ff00ff\",\n maroon: \"#800000\",\n mediumaquamarine: \"#66cdaa\",\n mediumblue: \"#0000cd\",\n mediumorchid: \"#ba55d3\",\n mediumpurple: \"#9370d8\",\n mediumseagreen: \"#3cb371\",\n mediumslateblue: \"#7b68ee\",\n mediumspringgreen: \"#00fa9a\",\n mediumturquoise: \"#48d1cc\",\n mediumvioletred: \"#c71585\",\n midnightblue: \"#191970\",\n mintcream: \"#f5fffa\",\n mistyrose: \"#ffe4e1\",\n moccasin: \"#ffe4b5\",\n navajowhite: \"#ffdead\",\n navy: \"#000080\",\n oldlace: \"#fdf5e6\",\n olive: \"#808000\",\n olivedrab: \"#6b8e23\",\n orange: \"#ffa500\",\n orangered: \"#ff4500\",\n orchid: \"#da70d6\",\n palegoldenrod: \"#eee8aa\",\n palegreen: \"#98fb98\",\n paleturquoise: \"#afeeee\",\n palevioletred: \"#d87093\",\n papayawhip: \"#ffefd5\",\n peachpuff: \"#ffdab9\",\n peru: \"#cd853f\",\n pink: \"#ffc0cb\",\n plum: \"#dda0dd\",\n powderblue: \"#b0e0e6\",\n purple: \"#800080\",\n red: \"#ff0000\",\n rebeccapurple: \"#663399\",\n rosybrown: \"#bc8f8f\",\n royalblue: \"#4169e1\",\n saddlebrown: \"#8b4513\",\n salmon: \"#fa8072\",\n sandybrown: \"#f4a460\",\n seagreen: \"#2e8b57\",\n seashell: \"#fff5ee\",\n sienna: \"#a0522d\",\n silver: \"#c0c0c0\",\n skyblue: \"#87ceeb\",\n slateblue: \"#6a5acd\",\n slategray: \"#708090\",\n slategrey: \"#708090\",\n snow: \"#fffafa\",\n springgreen: \"#00ff7f\",\n steelblue: \"#4682b4\",\n tan: \"#d2b48c\",\n teal: \"#008080\",\n thistle: \"#d8bfd8\",\n tomato: \"#ff6347\",\n turquoise: \"#40e0d0\",\n violet: \"#ee82ee\",\n wheat: \"#f5deb3\",\n white: \"#ffffff\",\n whitesmoke: \"#f5f5f5\",\n yellow: \"#ffff00\",\n yellowgreen: \"#9acd32\",\n transparent: \"rgba(0,0,0,0)\",\n // grey 别名(已有 darkslategrey/lightslategrey/slategrey/dimgrey)\n // 以下为 CSS 系统颜色\n activeborder: \"#bfcaca\",\n activecaption: \"#000080\",\n appworkspace: \"#ababab\",\n background: \"#636363\",\n buttonface: \"#c0c0c0\",\n buttonhighlight: \"#dedede\",\n buttonshadow: \"#808080\",\n buttontext: \"#000000\",\n captiontext: \"#000000\",\n graytext: \"#808080\",\n highlight: \"#b3d4fc\",\n highlighttext: \"#000000\",\n inactiveborder: \"#d4d0c8\",\n inactivecaption: \"#bfbbb0\",\n inactivecaptiontext: \"#545454\",\n infobackground: \"#fbfcc5\",\n infotext: \"#000000\",\n menu: \"#c0c0c0\",\n menutext: \"#000000\",\n scrollbar: \"#c0c0c0\",\n threeddarkshadow: \"#696969\",\n threedface: \"#c0c0c0\",\n threedhighlight: \"#dfdfdf\",\n threedlightshadow: \"#dcdcdc\",\n threedshadow: \"#808080\",\n window: \"#ffffff\",\n windowframe: \"#646464\",\n windowtext: \"#000000\"\n };\n\n/**\n * 画图基础对象\n * 当前库的工具类\n * \n * @class jmUtils\n * @static\n */\nexport default class jmUtils {\n /**\n * 复制一个对象\n * \n * @method clone\n * @static\n * @param {object} source 被复制的对象\n * @param {object} target 可选,如果指定就表示复制给这个对象,如果为boolean它就是deep参数\n * @param {boolean} deep 是否深度复制,如果为true,数组内的每个对象都会被复制\n * @param {function} copyHandler 复制对象回调,如果返回undefined,就走后面的逻辑,否则到这里中止\n * @return {object} 参数source的拷贝对象\n */\n static clone(source, target, deep = false, copyHandler = null, deepIndex = 0, cloned = null) {\n // 如果有指定回调,则用回调处理,否则走后面的复制逻辑\n if(typeof copyHandler === 'function') {\n const obj = copyHandler(source, deep, deepIndex);\n if(obj) return obj;\n }\n\n // 首次调用时初始化克隆映射表(用于处理循环引用)\n if(!cloned) cloned = new WeakMap();\n\n if(typeof target === 'boolean') {\n deep = target;\n target = undefined;\n }\n\n // 非对象直接返回\n if(!source || typeof source !== 'object') {\n return typeof target !== 'undefined' ? target : source;\n }\n\n // 如果source已经被克隆过,直接返回之前的克隆对象,打破循环引用\n if(cloned.has(source)) return cloned.get(source);\n\n // 数组处理\n if(Array.isArray(source)) {\n //如果为当前泛型,则直接new\n if(this.isType(source, jmList)) {\n return new jmList(source);\n }\n if(deep) {\n let dest = [];\n cloned.set(source, dest);\n for(let i = 0; i < source.length; i++) {\n dest.push(this.clone(source[i], undefined, deep, copyHandler, deepIndex + 1, cloned));\n }\n return dest;\n }\n return source.slice(0);\n }\n\n // 不复制页面元素和class对象(如jmControl实例等复杂对象保持引用)\n if(source.tagName || source.getContext || source.emit) {\n return source;\n }\n\n // 普通对象处理\n target = target || {};\n cloned.set(source, target);\n\n // 保持原型链一致\n if(source.__proto__) target.__proto__ = source.__proto__;\n \n // 遍历自身可枚举属性(字符串键 + Symbol键),避免触发原型链上宿主对象的getter\n const keys = Object.keys(source).concat(Object.getOwnPropertySymbols(source));\n for(const k of keys) {\n if(k === 'constructor') continue;\n const v = source[k];\n // 不复制页面元素和class对象\n if(v && (v.tagName || v.getContext || v.emit)) {\n target[k] = v;\n continue;\n }\n\n // 如果不是对象和空,则采用target的属性\n if(typeof target[k] === 'object' || typeof target[k] === 'undefined') { \n target[k] = this.clone(v, target[k], deep, copyHandler, deepIndex + 1, cloned);\n }\n }\n return target;\n }\n\n /**\n * 绑定事件到html对象\n * \n * @method bindEvent\n * @static\n * @param {element} html元素对象\n * @param {string} name 事件名称\n * @param {function} fun 事件委托\n * @returns {name, fun, target} 返回当前绑定\n */\n static bindEvent(target, name, fun, opt) {\n if(name && name.indexOf && name.indexOf(' ') != -1) {\n let ns = name.split(' ');\n for(let i=0;i<ns.length;i++) {\n this.bindEvent(target, ns[i], fun, opt);\n }\n }\n if(target.attachEvent) {\n target.attachEvent(\"on\"+name, fun, opt);\n } \n else if(target.addEventListener) {\n target.addEventListener(name, fun, opt);\n }\n return {\n name,\n target,\n fun\n };\n }\n\n /**\n * 从对象中移除事件到\n * \n * @method removeEvent\n * @static\n * @param {element} html元素对象\n * @param {string} name 事件名称\n * @param {function} fun 事件委托\n */\n static removeEvent(target, name, fun) {\n if(target.removeEventListener) {\n return target.removeEventListener(name, fun, false);\n } \n else if(target.detachEvent) {\n target.detachEvent('on' + name, fun);\n return true;\n }\n else {\n target['on' + name] = null;\n }\n }\n\n /**\n * 获取元素的绝对定位\n *\n * @method getElementPosition\n * @static\n * @param {element} el 目标元素对象\n * @return {position} 位置对象(top,left)\n */\n static getElementPosition(el) { \n let pos = {\"top\": 0, \"left\": 0};\n if(!el) return pos;\n\n if (el.offsetParent) {\n while (el.offsetParent) {\n pos.top += el.offsetTop;\n pos.left += el.offsetLeft;\n el = el.offsetParent;\n }\n }\n else if(el.x) {\n pos.left += el.x;\n }\n else if(el.x){\n pos.top += el.y;\n } \n return pos;\n }\n /**\n * 获取元素事件触发的位置\n *\n * @method getEventPosition\n * @static\n * @param {eventArg} evt 当前触发事件的参数\n * @param {point} [scale] 当前画布的缩放比例\n * @return {point} 事件触发的位置 \n */\n static getEventPosition (evt, scale) {\n evt = evt || event;\n const isWXMiniApp = evt.isWXMiniApp;\n let isTouch = false;\n let touches = evt.changedTouches || evt.targetTouches || evt.touches;\n let target = evt.target || evt.srcElement;\n if(touches && touches.length) {\n evt = touches[0];//兼容touch事件 \n if(!evt.target) evt.target = target;\n isTouch = true;\n }\n let px = evt.pageX || evt.x;\n if(typeof px == 'undefined') px = evt.clientX + (document.documentElement.scrollLeft || document.body.scrollLeft); \n let py = evt.pageY || evt.y;\n if(typeof py == 'undefined') py = evt.clientY + (document.documentElement.scrollTop || document.body.scrollTop);\n\n let ox = evt.offsetX;\n let oy = evt.offsetY;\n if(typeof ox === 'undefined' && typeof oy === 'undefined') {\n // 小程序下取x,y就是它的相对坐标\n if(isWXMiniApp) {\n ox = evt.x;\n oy = evt.y;\n }\n else {\n let p = this.getElementPosition(target);\n ox= px - p.left;\n oy = py - p.top;\n }\n }\n if(scale) {\n if(scale.x) ox = ox / scale.x;\n if(scale.y) oy = oy / scale.y;\n }\n\n return {\n pageX: px,\n pageY: py,\n clientX: evt.clientX,\n clientY: evt.clientY,\n //相对于容器偏移量\n offsetX: ox,\n offsetY: oy,\n layerX: evt.layerX,\n layerY: evt.layerY,\n screenX: evt.screenX,\n screenY: evt.screenY,\n x: ox,\n y: oy,\n isTouch: isTouch,\n touches,\n isWXMiniApp\n };\n }\n\n /**\n * 检 查对象是否为指定的类型,不包括继承\n * \n * @method isType\n * @static\n * @param {object} target 需要判断类型的对象\n * @param {class} type 对象类型\n * @return {boolean} 返回对象是否为指定类型 \n */\n static isType(target, type) {\n if(!target || typeof target !== 'object') return false;\n if(target.constructor === type) return true;\n /*if(target.__baseType) { \n return jmUtils.isType(target.__baseType.prototype,type);\n }*/\n\n //return target instanceof type;\n return false;\n }\n /**\n * 判断点是否在多边形内\n * 如果一个点在多边形内部,任意角度做射线肯定会与多边形要么有一个交点,要么有与多边形边界线重叠。\n * 如果一个点在多边形外部,任意角度做射线要么与多边形有一个交点,要么有两个交点,要么没有交点,要么有与多边形边界线重叠。\n * 利用上面的结论,我们只要判断这个点与多边形的交点个数,就可以判断出点与多边形的位置关系了。\n * \n * @method pointInPolygon\n * @static\n * @param {point} pt 坐标对象\n * @param {array} polygon 多边型角坐标对象数组\n * @param {number} offset 判断可偏移值\n * @return {integer} 0= 不在图形内和线上,1=在边上,2=在图形内部\n */\n static pointInPolygon(pt, polygon, offset) {\n offset = offset || 1;\n offset = offset / 2;\n const n = polygon.length;\n \n if(!polygon || n == 0) return 0;\n \n if(n == 1) {\n return Math.abs(polygon[0].x - pt.x) <= offset && Math.abs(polygon[0].y - pt.y) <= offset ? 1 : 0;\n }\n \n if(n == 2) {\n return this.pointOnLine(pt, polygon[0], polygon[1], offset);\n }\n\n for (let i = 0; i < n; i++) {\n if (Math.abs(polygon[i].x - pt.x) <= offset && \n Math.abs(polygon[i].y - pt.y) <= offset) {\n return 1;\n }\n }\n\n return this.rayCasting(pt, polygon, offset);\n }\n\n static pointOnLine(pt, p1, p2, offset) {\n const minX = Math.min(p1.x, p2.x);\n const maxX = Math.max(p1.x, p2.x);\n const minY = Math.min(p1.y, p2.y);\n const maxY = Math.max(p1.y, p2.y);\n\n if (minX - pt.x > offset || pt.x - maxX > offset) {\n return 0;\n }\n if (minY - pt.y > offset || pt.y - maxY > offset) {\n return 0;\n }\n\n if (p1.x == p2.x) {\n return Math.abs(p1.x - pt.x) <= offset && \n (pt.y - p1.y) * (pt.y - p2.y) <= 0 ? 1 : 0;\n }\n\n if (p1.y == p2.y) {\n return Math.abs(p1.y - pt.y) <= offset && \n (pt.x - p1.x) * (pt.x - p2.x) <= 0 ? 1 : 0;\n }\n\n if (Math.abs(p1.x - pt.x) < offset && Math.abs(p1.y - pt.y) < offset) {\n return 1;\n }\n if (Math.abs(p2.x - pt.x) < offset && Math.abs(p2.y - pt.y) < offset) {\n return 1;\n }\n\n if (pt.y != p1.y && pt.y != p2.y) {\n const f = (p2.x - p1.x) / (p2.y - p1.y) * (pt.y - p1.y);\n const ff = (pt.y - p1.y) / Math.sqrt(f * f + (pt.y - p1.y) * (pt.y - p1.y));\n const l = ff * (pt.x - p1.x - f);\n \n return Math.abs(l) <= offset ? 1 : 0;\n }\n return 0;\n }\n\n static rayCasting(pt, polygon, offset) {\n const n = polygon.length;\n let inside = false;\n const testY = pt.y;\n const testX = pt.x;\n\n for (let i = 0, j = n - 1; i < n; j = i++) {\n const yi = polygon[i].y;\n const yj = polygon[j].y;\n const xi = polygon[i].x;\n const xj = polygon[j].x;\n\n const intersect = ((yi > testY) !== (yj > testY)) &&\n (testX < (xj - xi) * (testY - yi) / (yj - yi) + xi);\n\n if (intersect) {\n inside = !inside;\n }\n }\n\n return inside ? 2 : 0;\n }\n\n /**\n * @method judge 判断点是否在多边形中\n * @param {point} dot {{x,y}} 需要判断的点\n * @param {array} coordinates {{x,y}} 多边形点坐标的数组,为保证图形能够闭合,起点和终点必须相等。\n * 比如三角形需要四个点表示,第一个点和最后一个点必须相同。 \n * @param {number} 是否为实心 1= 是\n * @returns {boolean} 结果 true=在形状内\n */\n /*static judge(dot,coordinates,noneZeroMode) {\n // 默认启动none zero mode\n noneZeroMode=noneZeroMode||1;\n var x = dot.x,y=dot.y;\n var crossNum = 0;\n // 点在线段的左侧数目\n var leftCount = 0;\n // 点在线段的右侧数目\n var rightCount = 0;\n for(var i=0;i<coordinates.length-1;i++){\n var start = coordinates[i];\n var end = coordinates[i+1];\n \n // 起点、终点斜率不存在的情况\n if(start.x===end.x) {\n // 因为射线向右水平,此处说明不相交\n if(x>start.x) continue;\n \n // 从左侧贯穿\n if((end.y>start.y&&y>=start.y && y<=end.y)){\n leftCount++;\n crossNum++;\n }\n // 从右侧贯穿\n if((end.y<start.y&&y>=end.y && y<=start.y)) {\n rightCount++;\n crossNum++;\n }\n continue;\n }\n // 斜率存在的情况,计算斜率\n var k=(end.y-start.y)/(end.x-start.x);\n // 交点的x坐标\n var x0 = (y-start.y)/k+start.x;\n // 因为射线向右水平,此处说明不相交\n if(x>x0) continue;\n \n if((end.x>start.x&&x0>=start.x && x0<=end.x)){\n crossNum++;\n if(k>=0) leftCount++;\n else rightCount++;\n }\n if((end.x<start.x&&x0>=end.x && x0<=start.x)) {\n crossNum++;\n if(k>=0) rightCount++;\n else leftCount++;\n }\n }\n \n return noneZeroMode===1?leftCount-rightCount!==0:crossNum%2===1;\n }*/\n\n /**\n * 检查边界,子对象是否超出父容器边界\n * 当对象偏移offset后是否出界\n * 返回(left:0,right:0,top:0,bottom:0)\n * 如果right>0表示右边出界right偏移量,left<0则表示左边出界left偏移量\n * 如果bottom>0表示下边出界bottom偏移量,top<0则表示上边出界ltop偏移量\n *\n * @method checkOutSide\n * @static\n * @param {bound} parentBounds 父对象的边界\n * @param {bound} targetBounds 对象的边界\n * @param {number} offset 判断是否越界可容偏差\n * @return {bound} 越界标识\n */\n static checkOutSide(parentBounds, targetBounds, offset) {\n let result = {left:0,right:0,top:0,bottom:0};\n if(offset.x < 0 ) {\n result.left = targetBounds.left + offset.x - parentBounds.left;\n }\n else if(offset.x > 0 ) {\n result.right = targetBounds.right + offset.x - parentBounds.right;\n }\n\n if(offset.y < 0 ) {\n result.top = targetBounds.top + offset.y - parentBounds.top;\n }\n else if(offset.y > 0) {\n result.bottom = targetBounds.bottom + offset.y - parentBounds.bottom;\n }\n return result;\n }\n\n /**\n * 把一个或多个点绕某个点旋转一定角度\n * 先把坐标原点移到旋转中心点,计算后移回\n * @method rotatePoints\n * @static\n * @param {Array/object} p 一个或多个点\n * @param {*} rp 旋转中心点\n * @param {*} r 旋转角度\n */\n static rotatePoints(p, rp, r) {\n if(!r || !p) return p;\n let cos = Math.cos(r);\n let sin = Math.sin(r);\n if(Array.isArray(p)) {\n for(let i=0;i<p.length;i++) {\n if(!p[i]) continue;\n let x1 = p[i].x - rp.x;\n let y1 = p[i].y - rp.y;\n p[i].x = x1 * cos - y1 * sin + rp.x;\n p[i].y = x1 * sin + y1 * cos + rp.y;\n }\n }\n else {\n let x1 = p.x - rp.x;\n let y1 = p.y - rp.y;\n p.x = x1 * cos - y1 * sin + rp.x;\n p.y = x1 * sin + y1 * cos + rp.y;\n }\n return p;\n }\n\n /**\n * 去除字符串开始字符\n * \n * @method trimStart\n * @static\n * @param {string} source 需要处理的字符串\n * @param {char} [c] 要去除字符串的前置字符\n * @return {string} 去除前置字符后的字符串\n */\n static trimStart(source, c) {\n c = c || ' ';\n if(source && source.length > 0) {\n let sc = source[0];\n if(sc === c || c.indexOf(sc) >= 0) {\n source = source.substring(1);\n return this.trimStart(source,c);\n } \n }\n return source;\n }\n\n /**\n * 去除字符串结束的字符c\n *\n * @method trimEnd\n * @static\n * @param {string} source 需要处理的字符串\n * @param {char} [c] 要去除字符串的后置字符\n * @return {string} 去除后置字符后的字符串\n */\n static trimEnd(source, c) {\n c = c || ' ';\n if(source && source.length > 0) {\n let sc = source[source.length - 1];\n if(sc === c || c.indexOf(sc) >= 0) {\n source = source.substring(0,source.length - 1);\n return this.trimStart(source,c);\n } \n }\n return source;\n }\n\n /**\n * 去除字符串开始与结束的字符\n *\n * @method trim\n * @static\n * @param {string} source 需要处理的字符串\n * @param {char} [c] 要去除字符串的字符\n * @return {string} 去除字符后的字符串\n */\n static trim(source,c) {\n return this.trimEnd(this.trimStart(source,c),c);\n }\n\n /**\n * 检查是否为百分比参数\n *\n * @method checkPercent\n * @static\n * @param {string} 字符串参数\n * @return {boolean} true=当前字符串为百分比参数,false=不是\n */\n static checkPercent(per) {\n if(typeof per === 'string') {\n per = this.trim(per);\n if(per[per.length - 1] == '%') {\n return per;\n }\n }\n }\n\n /**\n * 转换百分数为数值类型\n *\n * @method percentToNumber\n * @static\n * @param {string} per 把百分比转为数值的参数\n * @return {number} 百分比对应的数值\n */\n static percentToNumber(per) {\n if(typeof per === 'string') {\n let tmp = this.checkPercent(per);\n if(tmp) {\n per = this.trim(tmp,'% ');\n per = per / 100;\n }\n }\n return per;\n }\n\n /**\n * 转换16进制为数值\n *\n * @method hexToNumber\n * @static\n * @param {string} h 16进制颜色表达\n * @return {number} 10进制表达\n */\n static hexToNumber(h) {\n if(typeof h !== 'string') return h;\n\n h = h.toLowerCase();\n let hex = '0123456789abcdef';\n let v = 0;\n let l = h.length;\n for(let i=0;i<l;i++) {\n let iv = hex.indexOf(h[i]);\n if(iv == 0) continue;\n \n for(let j=1;j<l - i;j++) {\n iv *= 16;\n }\n v += iv;\n }\n return v;\n }\n\n /**\n * 转换数值为16进制字符串表达\n *\n * @method hex\n * @static\n * @param {number} v 数值\n * @return {string} 16进制表达\n */\n static numberToHex(v) {\n let hex = '0123456789abcdef';\n \n let h = '';\n while(v > 0) {\n let t = v % 16;\n h = hex[t] + h;\n v = Math.floor(v / 16);\n }\n return h;\n }\n\n /**\n * 16进制颜色转为r g b a 对象 {r, g , b, a}\n * @param {string}} hex 16进度的颜色\n */\n static hexToRGBA(hex) {\n if(typeof hex === 'string') hex = this.trim(hex); \n else return hex;\n\n // 如果缓存存在,则直接返回\n this.__hexToRGBA_Cache = this.__hexToRGBA_Cache || {};\n if(this.__hexToRGBA_Cache[hex]) return this.__hexToRGBA_Cache[hex];\n\n let res = hex;\n\n // 系统颜色\n if(colorKeywords[res]) res = colorKeywords[res];\n\n //当为7位时,表示需要转为带透明度的rgba\n if(res[0] == '#') {\n const color = {\n a: 1\n };\n if(res.length >= 8) {\n color.a = res.substr(1,2);\n color.g = res.substr(5,2);\n color.b = res.substr(7,2);\n color.r = res.substr(3,2);\n //透明度\n color.a = Number((this.hexToNumber(color.a) / 255).toFixed(4));\n\n color.r = this.hexToNumber(color.r||0);\n color.g = this.hexToNumber(color.g||0);\n color.b = this.hexToNumber(color.b||0);\n res = color; \n }\n // #cccccc || #ccc\n else if(res.length === 7 || res.length === 4) {\n // #ccc这种情况,把每个位复制一份\n if(res.length === 4) {\n color.g = res.substr(2, 1);\n color.g = color.g + color.g;\n color.b = res.substr(3, 1);\n color.b = color.b + color.b;\n color.r = res.substr(1, 1);\n color.r = color.r + color.r;\n }\n else {\n color.g = res.substr(3, 2);//除#号外的第二位\n color.b = res.substr(5, 2);\n color.r = res.substr(1, 2);\n }\n\n color.r = this.hexToNumber(color.r||0);\n color.g = this.hexToNumber(color.g||0);\n color.b = this.hexToNumber(color.b||0);\n \n res = color; \n }\n //如果是5位的话,# 则第2位表示A,后面依次是r,g,b\n else if(res.length === 5) {\n color.a = res.substr(1,1);\n color.g = res.substr(3,1);//除#号外的第二位\n color.b = res.substr(4,1);\n color.r = res.substr(2,1);\n\n color.r = this.hexToNumber(color.r||0);\n color.g = this.hexToNumber(color.g||0);\n color.b = this.hexToNumber(color.b||0);\n //透明度\n color.a = Number((this.hexToNumber(color.a) / 255).toFixed(4));\n res = color; \n }\n } \n if(typeof res === 'string') {\n const m = res.match(/rgb(a)?\\s*\\(\\s*([\\d\\.]+)\\s*,\\s*([\\d\\.]+)\\s*,\\s*([\\d\\.]+)\\s*(,\\s*[\\d\\.]+)?\\s*\\)/i); \n if(m && m.length === 6) {\n const color = {\n r: Number(m[2]),\n g: Number(m[3]),\n b: Number(m[4]),\n a: Number(this.trimStart(m[5]||'1', ','))\n };\n res = color;\n }\n }\n return this.__hexToRGBA_Cache[hex] = res; \n }\n\n /**\n * 把255的rgb值转为0-1的值\n * @param {rgba} color 颜色\n */\n static rgbToDecimal(color) {\n color = this.clone(color);\n color.r = this.byteToDecimal(color.r);\n color.g = this.byteToDecimal(color.g);\n color.b = this.byteToDecimal(color.b);\n return color;\n }\n\n //255值转为0-1的小数\n static byteToDecimal(b) {\n return b / 255;\n }\n\n /**\n * 转换颜色格式,如果输入r,g,b则转为hex格式,如果为hex则转为r,g,b格式\n *\n * @method toColor\n * @static\n * @param {string} hex 16进制颜色表达\n * @return {string} 颜色字符串\n */\n static toColor(r, g, b, a) { \n if(typeof r === 'string' && r) {\n r = this.trim(r); \n // 正常的颜色表达,不需要转换\n if(r[0] === '#' && (r.length === 4 || r.length === 7)) return r;\n\n const color = this.hexToRGBA(r);\n if(typeof color === 'string') return color;\n \n r = typeof color.r !== 'undefined'? color.r: r;\n g = typeof color.g !== 'undefined'? color.g: g;\n b = typeof color.b !== 'undefined'? color.b: b;\n a = typeof color.a !== 'undefined'? color.a: a;\n }\n if(r && typeof r === 'object') {\n g = r.g;\n b = r.b;\n a = r.a || 1;\n r = r.r;\n }\n if(typeof r != 'undefined' && typeof g != 'undefined' && typeof b != 'undefined') {\n if(typeof a != 'undefined') { \n return 'rgba(' + r + ',' + g + ',' + b + ',' + a + ')';\n }\n else {\n return 'rgb(' + r + ',' + g + ',' + b + ')';\n }\n }\n return r;\n }\n // window.requestAnimationFrame() 告诉浏览器——你希望执行一个动画,并且要求浏览器在下次重绘之前调用指定的回调函数更新动画。该方法需要传入一个回调函数作为参数,该回调函数会在浏览器下一次重绘之前执行\n static requestAnimationFrame(callback, win) {\n let fun = win && win.requestAnimationFrame? win.requestAnimationFrame: (typeof window !== 'undefined' && window.requestAnimationFrame? window.requestAnimationFrame: setTimeout); \n\t\treturn fun(callback, 20);\n }\n static cancelAnimationFrame(handler, win) {\n let fun = win && win.cancelAnimationFrame? win.cancelAnimationFrame: (typeof window !== 'undefined' && window.cancelAnimationFrame? window.cancelAnimationFrame: clearTimeout); \n\t\treturn fun(handler);\n }\t\n}\nexport { jmUtils };\nexport { colorKeywords };","\nimport {jmList} from \"./jmList.js\";\n\nlet control_id_counter = 0;\n\nexport default class jmObject {\n\tconstructor(g) {\n\t\tif(g && g.type == 'jmGraph') {\n\t\t\tthis.graph = g;\n\t\t}\n\t\tthis.id = ++control_id_counter;\n\t}\n\t\n\t/**\n\t * 检 查对象是否为指定类型\n\t * \n\t * @method is\n\t * @param {class} type 判断的类型\n\t * @for jmObject\n\t * @return {boolean} true=表示当前对象为指定的类型type,false=表示不是\n\t */\n\tis(type) {\n\t\tif(typeof type == 'string') {\n\t\t\treturn this.type == type;\n\t\t}\n\t\treturn this instanceof type;\n\t}\n\n\tanimate(...args) {\n\t\tif(this.is('jmGraph')) {\n\t\t\tif(args.length > 1) {\n\t\t\t\tif(!this.animateHandles) this.animateHandles = new jmList();\n\t\t\t\t\n\t\t\t\tconst params = [];\n\t\t\t\tif(args.length > 2) {\n\t\t\t\t\tfor(let i=2;i<args.length;i++) {\n\t\t\t\t\t\tparams.push(args[i]);\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\tthis.animateHandles.add({\n\t\t\t\t\tmillisec: args[1] || 20, \n\t\t\t\t\thandle: args[0], \n\t\t\t\t\tparams: params\n\t\t\t\t});\n\t\t\t}\n\t\t\tif(this.animateHandles) {\n\t\t\t\tif(this.animateHandles.count() > 0) {\n\t\t\t\t\tconst self = this;\n\t\t\t\t\tthis.dispatcher = setTimeout(function(_this) {\n\t\t\t\t\t\t_this = _this || self;\n\t\t\t\t\t\tconst overduehandles = [];\n\t\t\t\t\t\tconst curTimes = Date.now();\n\t\t\t\t\t\t_this.animateHandles.each(function(i,ani) {\n\t\t\t\t\t\t\ttry {\n\t\t\t\t\t\t\t\tif(ani && ani.handle && (!ani.times || curTimes - ani.times >= ani.millisec)) {\n\t\t\t\t\t\t\t\t\tconst r = ani.handle.apply(_this, ani.params);\n\t\t\t\t\t\t\t\t\tif(r === false) {\n\t\t\t\t\t\t\t\t\t\toverduehandles.push(ani);\n\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t\tani.times = curTimes;\n\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\tcatch(e) {\n\t\t\t\t\t\t\t\tif(ani) overduehandles.push(ani);\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t});\n\t\t\t\t\t\tfor(const i in overduehandles) {\n\t\t\t\t\t\t\t_this.animateHandles.remove(overduehandles[i]);\n\t\t\t\t\t\t}\n\t\t\t\t\t\t_this.animate();\n\t\t\t\t\t},10,this);\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t\telse {\n\t\t\tconst graph = this.graph;\n\t\t\tif(graph) {\n\t\t\t\tgraph.animate(...args);\n\t\t\t}\n\t\t}\n\t}\n}\n\nexport { jmObject };","\nimport {jmUtils} from \"./jmUtils.js\";\nimport { jmObject } from \"./jmObject.js\";\n\nconst PROPERTY_KEY = Symbol(\"properties\");\n\nexport default class jmProperty extends jmObject {\n\tconstructor(params) {\n\t\tsuper();\n\t\tthis[PROPERTY_KEY] = {};\n\t\tif(params && params.mode) this.mode = params.mode;\n\t}\n\n\tproperty(...pars) {\n\t\tif(pars) {\n\t\t\tconst pros = this[PROPERTY_KEY];\n\t\t\tconst name = pars[0];\n\t\t\tif(pars.length > 1) {\n\t\t\t\tconst value = pars[1];\n\t\t\t\tconst args = {oldValue: pros[name], newValue: value};\n\t\t\t\tpros[name] = pars[1];\n\t\t\t\tif(this.emit) this.emit('propertyChange', name, args);\n\t\t\t\treturn pars[1];\n\t\t\t}\n\t\t\telse if(name) {\n\t\t\t\treturn pros[name];\n\t\t\t}\n\t\t}\n\t}\n\n\tget needUpdate() {\n\t\treturn this.property('needUpdate');\n\t}\n\tset needUpdate(v) {\n\t\tthis.property('needUpdate', v);\n\t\tif(v && !this.is('jmGraph') && this.graph) {\n\t\t\tthis.graph.needUpdate = true;\n\t\t}\n\t}\n\n\tget graph() {\n\t\tlet g = this.property('graph');\n\t\tg = g || (this.property('graph', this.findParent('jmGraph')));\n\t\treturn g;\n\t}\n\tset graph(v) {\n\t\treturn this.property('graph', v);\n\t}\n\n\tget mode() {\n\t\tlet m = this.property('mode');\n\t\tif(m) return m;\n\t\telse if(this.is('jmGraph')) return this.property('mode');\n\t\treturn this.graph.mode;\n\t}\n\tset mode(v) {\n\t\treturn this.property('mode', v);\n\t}\n\n\trequestAnimationFrame(handler) {\n\t\treturn jmUtils.requestAnimationFrame(handler, this.graph? this.graph.canvas: null);\n\t}\n\n\tcancelAnimationFrame(handler) {\n\t\treturn jmUtils.cancelAnimationFrame(handler, this.graph? this.graph.canvas: null);\n\t}\n}\n\nexport { jmProperty };\n\n\n","import {jmUtils} from \"./jmUtils.js\";\n\n/**\n * 画图阴影对象表示法\n *\n * @class jmShadow\n * @param {number} x 横坐标偏移量\n * @param {number} y 纵坐标编移量\n * @param {number} blur 模糊值\n * @param {string} color 阴影的颜色\n */\n\nexport default class jmShadow {\n\tconstructor(x, y, blur, color) {\n\t\tif(typeof x == 'string' && !y && !blur && !color) {\n\t\t\tthis.fromString(x);\n\t\t}\n\t\telse {\n\t\t\tthis.x = x;\n\t\t\tthis.y = y;\n\t\t\tthis.blur = blur;\n\t\t\tthis.color = color;\n\t\t}\n\t}\n\t/**\n\t * 根据字符串格式转为阴影\n\t * @method fromString\n\t * @param {string} s 阴影字符串 x,y,blur,color\n\t */\n\tfromString(s) {\n\t\tif(!s) return;\n\t\tlet ms = s.match(/\\s*([^,]+)\\s*,\\s*([^,]+)\\s*(,[^,]+)?\\s*(,[\\s\\S]+)?\\s*/i);\n\t\tif(ms) {\n\t\t\tthis.x = ms[1]||0;\n\t\t\tthis.y = ms[2]||0;\n\t\t\tif(ms[3]) {\n\t\t\t\tms[3] = jmUtils.trim(ms[3],', ');\n\t\t\t\t//如果第三位是颜色格式,则表示为颜色\n\t\t\t\tif(ms[3].indexOf('#')===0 || /^rgb/i.test(ms[3])) {\n\t\t\t\t\tthis.color = ms[3];\n\t\t\t\t}\n\t\t\t\telse {\n\t\t\t\t\tthis.blur = jmUtils.trim(ms[3],', ');\n\t\t\t\t}\n\t\t\t}\n\t\t\tif(ms[4]) {\n\t\t\t\tthis.color = jmUtils.trim(ms[4],', ');\n\t\t\t}\n\t\t}\n\t\treturn this;\n\t}\n\n\t/**\n\t * 转为字符串格式 x,y,blur,color\n\t * @method toString\n\t * @returns {string} 阴影字符串\n\t */\n\ttoString() {\n\t\tlet s = this.x + ',' + this.y;\n\t\tif(this.blur) s += ',' + this.blur;\n\t\tif(this.color) s += ',' + this.color;\n\t\treturn s;\n\t}\n}\n\nexport { jmShadow };","import {jmUtils, colorKeywords} from \"./jmUtils.js\";\nimport {jmList} from \"./jmList.js\";\n\n/**\n * 渐变类\n *\n * @class jmGradient\n * @param {object} op 渐变参数,type:[linear= 线性渐变,radial=放射性渐变] \n */\nexport default class jmGradient {\n\tconstructor(opt) {\n\t\tthis.stops = new jmList();\n\n\t\tif(opt && typeof opt == 'object') {\n\t\t\tfor(let k in opt) {\n\t\t\t\tif(k === 'stops') continue;\n\t\t\t\tthis[k] = opt[k];\n\t\t\t}\n\t\t\tif(opt.stops && Array.isArray(opt.stops)) {\n\t\t\t\tthis.stops.push(...opt.stops);\n\t\t\t}\n\t\t}\n\t\t//解析字符串格式\n\t\t//linear-gradient(direction, color-stop1, color-stop2, ...);\n\t\t//radial-gradient(center, shape size, start-color, ..., last-color);\n\t\telse if(typeof opt == 'string') {\n\t\t\tthis.fromString(opt);\n\t\t}\n\t}\n\t/**\n\t * 添加渐变色\n\t * \n\t * @method addStop\n\t * @for jmGradient\n\t * @param {number} offset 放射渐变颜色偏移,可为百分比参数。\n\t * @param {string} color 当前偏移颜色值\n\t */\n\taddStop(offset, color) {\n\t\tthis.stops.add({\n\t\t\toffset: Number(offset),\n\t\t\tcolor: color\n\t\t});\n\t}\n\n\t/**\n\t * 生成为canvas的渐变对象\n\t *\n\t * @method toGradient\n\t * @for jmGradient\n\t * @param {jmControl} control 当前渐变对应的控件\n\t * @return {gradient} canvas渐变对象\n\t */\n\ttoGradient(control) {\n\t\tlet gradient;\n\t\tlet context = control.context || control;\n\t\tlet bounds = control.absoluteBounds?control.absoluteBounds:control.getAbsoluteBounds();\n\t\tlet x1 = this.x1||0;\n\t\tlet y1 = this.y1||0;\n\t\tlet x2 = this.x2;\n\t\tlet y2 = this.y2;\n\n\t\tlet location = control.getLocation();\n\n\t\tlet d = 0;\n\t\tif(location.radius) {\n\t\t\td = location.radius * 2;\t\t\t\t\n\t\t}\n\t\tif(!d) {\n\t\t\td = Math.min(location.width || 0, location.height || 0);\t\t\t\t\n\t\t}\n\t\tif(d <= 0) {\n\t\t\td = Math.max(bounds.width || 0, bounds.height || 0, 100);\n\t\t}\n\n\t\tconst width = bounds.width || d;\n\t\tconst height = bounds.height || d;\n\n\t\tif(jmUtils.checkPercent(x1)) {\n\t\t\tx1 = jmUtils.percentToNumber(x1) * width;\n\t\t}\n\t\telse if(typeof x1 === 'number' && x1 >= 0 && x1 <= 1) {\n\t\t\tx1 = x1 * width;\n\t\t}\n\t\telse if(typeof x1 === 'string') {\n\t\t\tconst num = parseFloat(x1);\n\t\t\tif(!isNaN(num)) x1 = num;\n\t\t}\n\t\tif(jmUtils.checkPercent(x2)) {\n\t\t\tx2 = jmUtils.percentToNumber(x2) * width;\n\t\t}\n\t\telse if(typeof x2 === 'number' && x2 >= 0 && x2 <= 1) {\n\t\t\tx2 = x2 * width;\n\t\t}\n\t\telse if(typeof x2 === 'string') {\n\t\t\tconst num = parseFloat(x2);\n\t\t\tif(!isNaN(num)) x2 = num;\n\t\t}\n\t\tif(jmUtils.checkPercent(y1)) {\n\t\t\ty1 = jmUtils.percentToNumber(y1) * height;\n\t\t}\n\t\telse if(typeof y1 === 'number' && y1 >= 0 && y1 <= 1) {\n\t\t\ty1 = y1 * height;\n\t\t}\n\t\telse if(typeof y1 === 'string') {\n\t\t\tconst num = parseFloat(y1);\n\t\t\tif(!isNaN(num)) y1 = num;\n\t\t}\n\t\tif(jmUtils.checkPercent(y2)) {\n\t\t\ty2 = jmUtils.percentToNumber(y2) * height;\n\t\t}\n\t\telse if(typeof y2 === 'number' && y2 >= 0 && y2 <= 1) {\n\t\t\ty2 = y2 * height;\n\t\t}\n\t\telse if(typeof y2 === 'string') {\n\t\t\tconst num = parseFloat(y2);\n\t\t\tif(!isNaN(num)) y2 = num;\n\t\t}\n\n\t\tx1 = Number(x1) || 0;\n\t\ty1 = Number(y1) || 0;\n\t\tx2 = Number(x2) || 0;\n\t\ty2 = Number(y2) || 0;\n\n\t\tlet sx1 = x1 + (bounds.left || 0);\n\t\tlet sy1 = y1 + (bounds.top || 0);\n\t\tlet sx2 = x2 + (bounds.left || 0);\n\t\tlet sy2 = y2 + (bounds.top || 0);\n\t\tif(this.type === 'linear') {\n\t\t\tif(control.mode === 'webgl' && control.webglControl) {\n\t\t\t\t// WebGL 着色器中 v_text_coord 是绝对坐标,需要传递绝对坐标\n\t\t\t\tgradient = control.webglControl.createLinearGradient(sx1, sy1, sx2, sy2, bounds);\n\t\t\t\tgradient.key = this.toString();\n\t\t\t}\t\n\t\t\telse {\t\t\n\t\t\t\tcontext.createLinearGradient && (gradient = context.createLinearGradient(sx1, sy1, sx2, sy2));\n\t\t\t}\n\t\t}\n\t\telse if(this.type === 'radial') {\n\t\t\tlet r1 = this.r1||0;\n\t\t\tlet r2 = this.r2;\n\t\t\t\n\t\t\tif(d <= 0) {\n\t\t\t\td = Math.max(bounds.width || 0, bounds.height || 0, 1);\n\t\t\t}\n\t\t\t\n\t\t\tif(jmUtils.checkPercent(r1)) {\n\t\t\t\tr1 = jmUtils.percentToNumber(r1);\t\t\t\n\t\t\t\tr1 = d * r1;\n\t\t\t}\n\t\t\telse if(typeof r1 === 'number' && r1 >= 0 && r1 <= 1) {\n\t\t\t\tr1 = r1 * d;\n\t\t\t}\n\t\t\telse if(typeof r1 === 'string') {\n\t\t\t\tr1 = parseFloat(r1) || 0;\n\t\t\t}\n\t\t\t\n\t\t\tif(jmUtils.checkPercent(r2)) {\n\t\t\t\tr2 = jmUtils.percentToNumber(r2);\n\t\t\t\tr2 = d * r2;\n\t\t\t}\n\t\t\telse if(typeof r2 === 'number' && r2 >= 0 && r2 <= 1) {\n\t\t\t\tr2 = r2 * d;\n\t\t\t}\n\t\t\telse if(typeof r2 === 'string') {\n\t\t\t\tr2 = parseFloat(r2);\n\t\t\t}\n\t\t\t\n\t\t\tif(r2 === undefined || r2 === null || isNaN(Number(r2)) || Number(r2) <= 0) {\n\t\t\t\tr2 = d / 2;\n\t\t\t}\n\t\t\t\n\t\t\tr1 = Number(r1) || 0;\n\t\t\tr2 = Number(r2) || d / 2;\n\t\t\t\n\t\t\tif(control.mode === 'webgl' && control.webglControl) {\n\t\t\t\tgradient = control.webglControl.createRadialGradient(sx1, sy1, r1, sx2, sy2, r2, bounds);\n\t\t\t\tgradient.key = this.toString();\n\t\t\t}\t\n\t\t\telse if(context.createRadialGradient) {\n\t\t\t\tgradient = context.createRadialGradient(sx1, sy1, r1, sx2, sy2, r2);\t\n\t\t\t}\n\t\t\telse if(context.createCircularGradient) { \n\t\t\t\tgradient = context.createCircularGradient(sx1, sy1, r2);\n\t\t\t}\n\t\t}\n\t\t\n\t\t//颜色渐变\n\t\tif(gradient) {\n\t\t\tthis.stops.each(function(i,s) {\t\n\t\t\t\tlet c = jmUtils.toColor(s.color);\n\t\t\t\t//s.offset 0.0 ~ 1.0\n\t\t\t\tgradient && gradient.addColorStop(s.offset, c);\t\t\n\t\t\t});\n\t\t}\n\t\telse {\n\t\t\tconst s = this.stops.get(0);\n\t\t\treturn (s && s.color) || '#000';\n\t\t}\n\t\t\n\t\treturn gradient;\n\t}\n\n\t/**\n\t * 解析渐变字符串\n\t * 支持的格式:\n\t * - linear-gradient(180deg, #8b5cf6 0%, #6366f1 50%, #4f46e5 100%)\n\t * - linear-gradient(to top, red, blue)\n\t * - linear-gradient(to right bottom, red, blue)\n\t * - linear-gradient(45deg, red, blue)\n\t * - linear-gradient(0.5turn, red, blue)\n\t * - radial-gradient(circle, red, blue)\n\t * - radial-gradient(ellipse at top, red, blue)\n\t *\n\t * @method fromString\n\t * @for jmGradient\n\t * @param {string} s 渐变字符串\n\t */\n\tfromString(s) {\n\t\tif(!s) {\n\t\t\tconsole.warn('jmGradient: 渐变字符串为空');\n\t\t\treturn;\n\t\t}\n\t\t// 使用 [\\s\\S] 匹配任意字符(包括换行符),支持多行渐变字符串\n\t\tconst gradientMatch = s.match(/(linear|radial)-gradient\\s*\\(\\s*([\\s\\S]+)\\)/i);\n\t\tif(!gradientMatch || gradientMatch.length < 3) {\n\t\t\tconsole.warn('jmGradient: 无效的渐变字符串格式: \"' + s + '\"');\n\t\t\treturn;\n\t\t}\n\n\t\tconst type = gradientMatch[1].toLowerCase();\n\t\tif(type !== 'linear' && type !== 'radial') {\n\t\t\tconsole.warn('jmGradient: 不支持的渐变类型 \"' + type + '\",仅支持 linear 和 radial');\n\t\t\treturn;\n\t\t}\n\n\t\tthis.type = type;\n\t\tconst content = jmUtils.trim(gradientMatch[2]);\n\n\t\tconst splitIndex = this._findSplitIndex(content);\n\t\tif(splitIndex < 0) {\n\t\t\tconsole.warn('jmGradient: 无法解析渐变内容: \"' + content + '\"');\n\t\t\treturn;\n\t\t}\n\n\t\tconst params = content.substring(0, splitIndex).trim();\n\t\tconst colorPart = content.substring(splitIndex + 1).trim();\n\n\t\tif(!colorPart) {\n\t\t\tconsole.warn('jmGradient: 未找到颜色停止点');\n\t\t\treturn;\n\t\t}\n\n\t\tif(this.type === 'linear') {\n\t\t\tthis._parseLinearParams(params);\n\t\t}\n\t\telse {\n\t\t\tthis._parseRadialParams(params);\n\t\t}\n\n\t\tconst colorCount = this._parseColorStops(colorPart);\n\t\tif(colorCount === 0) {\n\t\t\tconsole.warn('jmGradient: 未找到有效的颜色停止点: \"' + colorPart + '\"');\n\t\t}\n\t\telse if(colorCount < 2) {\n\t\t\tconsole.warn('jmGradient: 颜色停止点至少需要2个,当前只有 ' + colorCount + ' 个');\n\t\t}\n\t}\n\n\t/**\n\t * 找到参数和颜色的分割位置(第一个不在括号内的逗号)\n\t * @param {string} content 内容字符串\n\t * @returns {number} 分割位置索引\n\t */\n\t_findSplitIndex(content) {\n\t\tlet depth = 0;\n\n\t\tfor(let i = 0; i < content.length; i++) {\n\t\t\tconst char = content[i];\n\t\t\tif(char === '(') {\n\t\t\t\tdepth++;\n\t\t\t}\n\t\t\telse if(char === ')') {\n\t\t\t\tdepth--;\n\t\t\t}\n\t\t\telse if(char === ',' && depth === 0) {\n\t\t\t\treturn i;\n\t\t\t}\n\t\t}\n\n\t\treturn -1;\n\t}\n\n\t/**\n\t * 验证渐变配置是否有效\n\t * @returns {boolean} 是否有效\n\t */\n\tisValid() {\n\t\tif(!this.type) return false;\n\t\tif(this.type === 'linear') {\n\t\t\treturn typeof this.x1 !== 'undefined' ||\n\t\t\t\t typeof this.x2 !== 'undefined' ||\n\t\t\t\t typeof this._angle !== 'undefined';\n\t\t}\n\t\tif(this.type === 'radial') {\n\t\t\treturn this.stops && this.stops.length >= 2;\n\t\t}\n\t\treturn false;\n\t}\n\n\t/**\n\t * 解析线性渐变参数\n\t * @param {string} params 参数字符串\n\t */\n\t_parseLinearParams(params) {\n\t\tconst trimmed = jmUtils.trim(params);\n\n\t\tif(trimmed.startsWith('to ')) {\n\t\t\tconst direction = trimmed.substring(3).toLowerCase().trim();\n\t\t\tconst dir = this._directionToAngle(direction);\n\t\t\tthis._angle = dir.angle;\n\t\t\tthis.x1 = dir.x1;\n\t\t\tthis.y1 = dir.y1;\n\t\t\tthis.x2 = dir.x2;\n\t\t\tthis.y2 = dir.y2;\n\t\t}\n\t\telse if(this._hasAngleUnit(trimmed)) {\n\t\t\tconst angle = this._parseAngle(trimmed);\n\t\t\tthis._angle = angle;\n\t\t\tconst coords = this._angleToCoords(angle);\n\t\t\tthis.x1 = coords.x1;\n\t\t\tthis.y1 = coords.y1;\n\t\t\tthis.x2 = coords.x2;\n\t\t\tthis.y2 = coords.y2;\n\t\t}\n\t\telse if(trimmed.startsWith('at ')) {\n\t\t\tconst radialMatch = trimmed.match(/at\\s+(.+)/i);\n\t\t\tif(radialMatch) {\n\t\t\t\tthis._parseRadialParams(trimmed);\n\t\t\t}\n\t\t}\n\t\telse {\n\t\t\tconst parts = trimmed.split(/\\s+/);\n\t\t\tif(parts.length >= 4) {\n\t\t\t\tthis.x1 = parts[0];\n\t\t\t\tthis.y1 = parts[1];\n\t\t\t\tthis.x2 = parts[2];\n\t\t\t\tthis.y2 = parts[3];\n\t\t\t}\n\t\t\telse if(parts.length === 2) {\n\t\t\t\tthis.x1 = 0;\n\t\t\t\tthis.y1 = 0;\n\t\t\t\tthis.x2 = parts[0];\n\t\t\t\tthis.y2 = parts[1];\n\t\t\t}\n\t\t}\n\t}\n\n\t/**\n\t * 解析径向渐变参数\n\t * @param {string} params 参数字符串\n\t */\n\t_parseRadialParams(params) {\n\t\tconst trimmed = jmUtils.trim(params);\n\n\t\tthis.shape = 'ellipse';\n\t\tthis.position = { x: '50%', y: '50%' };\n\n\t\tconst atMatch = trimmed.match(/^(.+?)\\s+at\\s+(.+)$/i);\n\t\tif(atMatch) {\n\t\t\tconst shapePart = jmUtils.trim(atMatch[1]);\n\t\t\tconst posPart = jmUtils.trim(atMatch[2]);\n\t\t\tthis._parseRadialShape(shapePart);\n\t\t\tthis._parseRadialPosition(posPart);\n\t\t}\n\t\telse if(trimmed.startsWith('circle') || trimmed.startsWith('ellipse')) {\n\t\t\tthis._parseRadialShape(trimmed);\n\t\t\tthis.x1 = '50%';\n\t\t\tthis.y1 = '50%';\n\t\t\tthis.x2 = '50%';\n\t\t\tthis.y2 = '50%';\n\t\t}\n\t\telse {\n\t\t\tconst parts = trimmed.split(/\\s+/);\n\t\t\tif(parts.length >= 3) {\n\t\t\t\tthis.x1 = parts[0];\n\t\t\t\tthis.y1 = parts[1];\n\t\t\t\tthis.r1 = parts[2];\n\t\t\t}\n\t\t\tif(parts.length >= 6) {\n\t\t\t\tthis.x2 = parts[3];\n\t\t\t\tthis.y2 = parts[4];\n\t\t\t\tthis.r2 = parts[5];\n\t\t\t}\n\t\t}\n\n\t\tif(this.x1 === undefined && this.y1 === undefined) {\n\t\t\tthis.x1 = '50%';\n\t\t\tthis.y1 = '50%';\n\t\t}\n\t\tif(this.x2 === undefined && this.y2 === undefined) {\n\t\t\tthis.x2 = '50%';\n\t\t\tthis.y2 = '50%';\n\t\t}\n\t\tif(this.r2 === undefined) {\n\t\t\tthis.r2 = '50%';\n\t\t}\n\t}\n\n\t/**\n\t * 解析径向渐变形状\n\t * @param {string} shapePart 形状描述\n\t */\n\t_parseRadialShape(shapePart) {\n\t\tif(shapePart.startsWith('circle')) {\n\t\t\tthis.shape = 'circle';\n\t\t\tconst sizeMatch = shapePart.match(/circle\\s*\\(\\s*([^)]+)\\s*\\)/i);\n\t\t\tif(sizeMatch) {\n\t\t\t\tthis.r2 = jmUtils.trim(sizeMatch[1]);\n\t\t\t}\n\t\t}\n\t\telse if(shapePart.startsWith('ellipse')) {\n\t\t\tthis.shape = 'ellipse';\n\t\t\tconst sizeMatch = shapePart.match(/ellipse\\s*\\(\\s*([^)]+)\\s*\\)/i);\n\t\t\tif(sizeMatch) {\n\t\t\t\tconst sizes = jmUtils.trim(sizeMatch[1]).split(/\\s+/);\n\t\t\t\tif(sizes.length >= 2) {\n\t\t\t\t\tthis.rx = sizes[0];\n\t\t\t\t\tthis.ry = sizes[1];\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n\n\t/**\n\t * 解析径向渐变位置\n\t * @param {string} posPart 位置描述\n\t */\n\t_parseRadialPosition(posPart) {\n\t\tconst parts = posPart.split(/\\s+/);\n\t\tif(parts.length >= 2) {\n\t\t\tthis.x1 = parts[0];\n\t\t\tthis.y1 = parts[1];\n\t\t\tthis.x2 = parts[0];\n\t\t\tthis.y2 = parts[1];\n\t\t}\n\t}\n\n\t/**\n\t * 解析颜色停止点\n\t * @param {string} colorPart 颜色部分字符串\n\t * @returns {number} 成功解析的颜色数量\n\t */\n\t_parseColorStops(colorPart) {\n\t\tif(!colorPart) {\n\t\t\treturn 0;\n\t\t}\n\n\t\tconst stops = this._splitColorStops(colorPart);\n\t\tlet lastOffset = -1;\n\t\tlet colorCount = 0;\n\n\t\tfor(let i = 0; i < stops.length; i++) {\n\t\t\tconst stop = jmUtils.trim(stops[i]);\n\t\t\tif(!stop) continue;\n\n\t\t\tconst parsed = this._parseSingleColorStop(stop);\n\t\t\tif(!parsed) {\n\t\t\t\tcontinue;\n\t\t\t}\n\n\t\t\tlet { color, offset } = parsed;\n\n\t\t\tif(color === 'transparent') {\n\t\t\t\tcolor = 'rgba(0,0,0,0)';\n\t\t\t}\n\n\t\t\tif(!this._isValidColor(color)) {\n\t\t\t\tconsole.warn('jmGradient: 无效的颜色格式 \"' + color + '\"');\n\t\t\t\tcontinue;\n\t\t\t}\n\n\t\t\tconst normalizedOffset = this._normalizeOffset(offset);\n\t\t\tlet finalOffset = normalizedOffset;\n\n\t\t\tif(finalOffset === null) {\n\t\t\t\tif(i === 0) {\n\t\t\t\t\tfinalOffset = 0;\n\t\t\t\t}\n\t\t\t\telse if(i === stops.length - 1) {\n\t\t\t\t\tfinalOffset = 1;\n\t\t\t\t}\n\t\t\t\telse {\n\t\t\t\t\tconst nextOffset = this._findNextOffset(stops, i);\n\t\t\t\t\tif(nextOffset !== null) {\n\t\t\t\t\t\tfinalOffset = (lastOffset + nextOffset) / 2;\n\t\t\t\t\t}\n\t\t\t\t\telse {\n\t\t\t\t\t\tfinalOffset = Math.min(1, lastOffset + (1 - lastOffset) / (stops.length - i));\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tif(finalOffset !== null) {\n\t\t\t\tif(finalOffset < 0 || finalOffset > 1) {\n\t\t\t\t\tconsole.warn('jmGradient: 颜色偏移量 ' + finalOffset + ' 超出有效范围 [0, 1],将调整为有效范围');\n\t\t\t\t\tfinalOffset = Math.max(0, Math.min(1, finalOffset));\n\t\t\t\t}\n\t\t\t\tlastOffset = finalOffset;\n\t\t\t\tthis.addStop(finalOffset, color);\n\t\t\t\tcolorCount++;\n\t\t\t}\n\t\t}\n\n\t\treturn colorCount;\n\t}\n\n\t/**\n\t * 分割颜色停止点字符串\n\t * @param {string} colorPart 颜色部分字符串\n\t * @returns {string[]} 颜色停止点数组\n\t */\n\t_splitColorStops(colorPart) {\n\t\tconst stops = [];\n\t\tlet depth = 0;\n\t\tlet current = '';\n\n\t\tfor(let i = 0; i < colorPart.length; i++) {\n\t\t\tconst char = colorPart[i];\n\t\t\tif(char === '(') {\n\t\t\t\tdepth++;\n\t\t\t\tcurrent += char;\n\t\t\t}\n\t\t\telse if(char === ')') {\n\t\t\t\tdepth--;\n\t\t\t\tcurrent += char;\n\t\t\t}\n\t\t\telse if(char === ',' && depth === 0) {\n\t\t\t\tstops.push(current.trim());\n\t\t\t\tcurrent = '';\n\t\t\t}\n\t\t\telse {\n\t\t\t\tcurrent += char;\n\t\t\t}\n\t\t}\n\n\t\tif(current.trim()) {\n\t\t\tstops.push(current.trim());\n\t\t}\n\n\t\treturn stops;\n\t}\n\n\t/**\n\t * 解析单个颜色停止点\n\t * @param {string} stop 单个颜色停止点字符串\n\t * @returns {object|null} {color, offset} 或 null\n\t */\n\t_parseSingleColorStop(stop) {\n\t\tconst hexMatch = stop.match(/^(#[a-fA-F0-9]{3,8})\\s*(\\d+(?:\\.\\d+)?%?)?$/i);\n\t\tif(hexMatch) {\n\t\t\treturn { color: hexMatch[1], offset: hexMatch[2] || null };\n\t\t}\n\n\t\tconst rgbaMatch = stop.match(/^(rgba?\\s*\\([^)]+\\))\\s*(\\d+(?:\\.\\d+)?%?)?$/i);\n\t\tif(rgbaMatch) {\n\t\t\treturn { color: rgbaMatch[1], offset: rgbaMatch[2] || null };\n\t\t}\n\n\t\tconst hslaMatch = stop.match(/^(hsla?\\s*\\([^)]+\\))\\s*(\\d+(?:\\.\\d+)?%?)?$/i);\n\t\tif(hslaMatch) {\n\t\t\treturn { color: hslaMatch[1], offset: hslaMatch[2] || null };\n\t\t}\n\n\t\tconst namedMatch = stop.match(/^([a-zA-Z]+)\\s*(\\d+(?:\\.\\d+)?%?)?$/i);\n\t\tif(namedMatch && this._isValidColor(namedMatch[1])) {\n\t\t\treturn { color: namedMatch[1], offset: namedMatch[2] || null };\n\t\t}\n\n\t\treturn null;\n\t}\n\n\t/**\n\t * 查找下一个有偏移量的颜色停止点\n\t * @param {string[]} stops 颜色停止点数组\n\t * @param {number} currentIndex 当前索引\n\t * @returns {number|null} 下一个偏移量或null\n\t */\n\t_findNextOffset(stops, currentIndex) {\n\t\tfor(let i = currentIndex + 1; i < stops.length; i++) {\n\t\t\tconst parsed = this._parseSingleColorStop(jmUtils.trim(stops[i]));\n\t\t\tif(parsed && parsed.offset) {\n\t\t\t\treturn this._normalizeOffset(parsed.offset);\n\t\t\t}\n\t\t}\n\t\treturn null;\n\t}\n\n\t/**\n\t * 验证颜色格式是否有效\n\t * @param {string} color 颜色字符串\n\t * @returns {boolean} 是否有效\n\t */\n\t_isValidColor(color) {\n\t\tif(!color) return false;\n\n\t\tconst hexPattern = /^#([a-fA-F0-9]{3,8})$/;\n\t\tif(hexPattern.test(color)) return true;\n\n\t\t// 支持 rgba(r,g,b,a) 和 rgba(r, g, b, a) 等各种空格格式\n\t\tconst rgbPattern = /^rgba?\\s*\\(\\s*\\d{1,3}\\s*,\\s*\\d{1,3}\\s*,\\s*\\d{1,3}\\s*(,\\s*[\\d.]+\\s*)?\\)$/i;\n\t\tif(rgbPattern.test(color)) return true;\n\n\t\tconst hslPattern = /^hsla?\\s*\\(\\s*\\d{1,3}\\s*,\\s*\\d{1,3}%?\\s*,\\s*\\d{1,3}%?\\s*(,\\s*[\\d.]+\\s*)?\\)$/i;\n\t\tif(hslPattern.test(color)) return true;\n\n\t\t// 使用 jmUtils 中的完整 CSS 颜色关键字表\n\t\tif(colorKeywords && colorKeywords[color.toLowerCase()]) return true;\n\n\t\t// 宽松处理:符合 CSS 关键字命名规则的字符串也视为有效颜色\n\t\t// (纯字母,可能在运行时被浏览器或其他环境解析)\n\t\tif(/^[a-zA-Z]+$/.test(color)) return true;\n\n\t\treturn false;\n\t}\n\n\t/**\n\t * 标准化偏移值\n\t * @param {string} offset 偏移字符串\n\t * @returns {number|null} 0-1之间的数值或null\n\t */\n\t_normalizeOffset(offset) {\n\t\tif(!offset) return null;\n\t\toffset = jmUtils.trim(offset);\n\t\tif(offset.endsWith('%')) {\n\t\t\treturn parseFloat(offset) / 100;\n\t\t}\n\t\tconst num = parseFloat(offset);\n\t\tif(isNaN(num)) return null;\n\t\tif(num > 1) {\n\t\t\treturn num / 100;\n\t\t}\n\t\treturn num;\n\t}\n\n\t/**\n\t * 检查字符串是否包含角度单位\n\t * @param {string} str 待检查字符串\n\t * @returns {boolean}\n\t */\n\t_hasAngleUnit(str) {\n\t\treturn /^-?\\d+(\\.\\d+)?\\s*(deg|rad|grad|turn)$/i.test(str);\n\t}\n\n\t/**\n\t * 解析角度值\n\t * @param {string} angleStr 角度字符串\n\t * @returns {number} 弧度值\n\t */\n\t_parseAngle(angleStr) {\n\t\tangleStr = jmUtils.trim(angleStr);\n\t\tconst match = angleStr.match(/^(-?\\d+(\\.\\d+)?)\\s*(deg|rad|grad|turn)?$/i);\n\t\tif(!match) return 0;\n\n\t\tlet value = parseFloat(match[1]);\n\t\tconst unit = (match[3] || 'deg').toLowerCase();\n\n\t\tswitch(unit) {\n\t\t\tcase 'deg':\n\t\t\t\treturn value * Math.PI / 180;\n\t\t\tcase 'rad':\n\t\t\t\treturn value;\n\t\t\tcase 'grad':\n\t\t\t\treturn value * Math.PI / 200;\n\t\t\tcase 'turn':\n\t\t\t\treturn value * 2 * Math.PI;\n\t\t\tdefault:\n\t\t\t\treturn value * Math.PI / 180;\n\t\t}\n\t}\n\n\t/**\n\t * 将角度转换为起点和终点坐标\n\t * @param {number} angle 弧度值\n\t * @returns {object} 坐标对象\n\t */\n\t_angleToCoords(angle) {\n\t\tconst x = Math.cos(angle);\n\t\tconst y = -Math.sin(angle);\n\n\t\treturn {\n\t\t\tx1: Math.round((0.5 - x * 0.5) * 1000) / 1000,\n\t\t\ty1: Math.round((0.5 + y * 0.5) * 1000) / 1000,\n\t\t\tx2: Math.round((0.5 + x * 0.5) * 1000) / 1000,\n\t\t\ty2: Math.round((0.5 - y * 0.5) * 1000) / 1000\n\t\t};\n\t}\n\n\t/**\n\t * 将方向关键词转换为角度和坐标\n\t * @param {string} direction 方向描述\n\t * @returns {object} 包含angle和坐标的对象\n\t */\n\t_directionToAngle(direction) {\n\t\tconst directions = {\n\t\t\t'to top': { angle: 0, x1: '50%', y1: '100%', x2: '50%', y2: '0%' },\n\t\t\t'to bottom': { angle: Math.PI, x1: '50%', y1: '0%', x2: '50%', y2: '100%' },\n\t\t\t'to left': { angle: -Math.PI / 2, x1: '100%', y1: '50%', x2: '0%', y2: '50%' },\n\t\t\t'to right': { angle: Math.PI / 2, x1: '0%', y1: '50%', x2: '100%', y2: '50%' },\n\t\t\t'to top left': { angle: -Math.PI * 3 / 4, x1: '100%', y1: '100%', x2: '0%', y2: '0%' },\n\t\t\t'to top right': { angle: -Math.PI / 4, x1: '0%', y1: '100%', x2: '100%', y2: '0%' },\n\t\t\t'to bottom left': { angle: Math.PI * 3 / 4, x1: '100%', y1: '0%', x2: '0%', y2: '100%' },\n\t\t\t'to bottom right': { angle: Math.PI / 4, x1: '0%', y1: '0%', x2: '100%', y2: '100%' },\n\t\t\t'top': { angle: 0, x1: '50%', y1: '100%', x2: '50%', y2: '0%' },\n\t\t\t'bottom': { angle: Math.PI, x1: '50%', y1: '0%', x2: '50%', y2: '100%' },\n\t\t\t'left': { angle: -Math.PI / 2, x1: '100%', y1: '50%', x2: '0%', y2: '50%' },\n\t\t\t'right': { angle: Math.PI / 2, x1: '0%', y1: '50%', x2: '100%', y2: '50%' }\n\t\t};\n\n\t\tconst dir = directions[direction];\n\t\tif(dir) {\n\t\t\treturn dir;\n\t\t}\n\n\t\tconst keywordMatch = direction.match(/to\\s+(top|bottom|left|right)/i);\n\t\tif(keywordMatch) {\n\t\t\tconst mainDir = keywordMatch[1].toLowerCase();\n\t\t\tconst secDir = direction.replace(keywordMatch[0], '').trim();\n\t\t\tif(secDir) {\n\t\t\t\tconst combined = `to ${mainDir} ${secDir}`;\n\t\t\t\tif(directions[combined]) {\n\t\t\t\t\treturn directions[combined];\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\treturn { angle: 0, x1: '50%', y1: '100%', x2: '50%', y2: '0%' };\n\t}\n\n\t/**\n\t * 转换为渐变的字符串表达\n\t *\n\t * @method toString\n\t * @for jmGradient\n\t * @return {string} linear-gradient(x1 y1 x2 y2, color1 step, color2 step, ...);\t//radial-gradient(x1 y1 r1 x2 y2 r2, color1 step,color2 step, ...);\n\t */\n\ttoString() {\n\t\tlet str = this.type + '-gradient(';\n\t\tif(this.type == 'linear') {\n\t\t\tstr += this.x1 + ' ' + this.y1 + ' ' + this.x2 + ' ' + this.y2;\n\t\t}\n\t\telse {\n\t\t\tstr += this.x1 + ' ' + this.y1 + ' ' + this.r1 + ' ' + this.x2 + ' ' + this.y2 + ' ' + this.r2;\n\t\t}\n\t\t//颜色渐变\n\t\tthis.stops.each(function(i,s) {\t\n\t\t\tstr += ',' + s.color + ' ' + s.offset;\n\t\t});\n\t\treturn str + ')';\n\t}\n}\n\nexport { jmGradient };\n\n\n\n","import {jmUtils} from \"./jmUtils.js\";\n\n/**\n * CSS滤镜效果类\n * 支持的滤镜: blur, grayscale, sepia, brightness, contrast, saturate, hue-rotate, invert, opacity\n *\n * @class jmFilter\n * @param {string|object} opt 滤镜参数\n * 字符串格式: \"blur(2px) grayscale(50%) brightness(1.2)\"\n * 对象格式: { blur: 2, grayscale: 0.5, brightness: 1.2 }\n */\nexport default class jmFilter {\n\tconstructor(opt) {\n\t\tthis.filters = [];\n\n\t\tif(typeof opt === 'string') {\n\t\t\tthis.fromString(opt);\n\t\t}\n\t\telse if(opt && typeof opt === 'object') {\n\t\t\tfor(let k in opt) {\n\t\t\t\tif(k === 'constructor' || k === 'filters') continue;\n\t\t\t\tthis.addFilter(k, opt[k]);\n\t\t\t}\n\t\t}\n\t}\n\n\t/**\n\t * 添加单个滤镜\n\t * @param {string} name 滤镜名称 (blur, grayscale, sepia, brightness, contrast, saturate, hue-rotate, invert, opacity)\n\t * @param {number|string} value 滤镜值\n\t */\n\taddFilter(name, value) {\n\t\tname = name.toLowerCase().trim();\n\t\tif(typeof value === 'string') {\n\t\t\tvalue = parseFloat(value);\n\t\t}\n\t\tif(isNaN(value)) return;\n\n\t\t// 规范化滤镜名称\n\t\tconst normalized = {\n\t\t\t'blur': 'blur',\n\t\t\t'grayscale': 'grayscale',\n\t\t\t'greyscale': 'grayscale',\n\t\t\t'sepia': 'sepia',\n\t\t\t'brightness': 'brightness',\n\t\t\t'contrast': 'contrast',\n\t\t\t'saturate': 'saturate',\n\t\t\t'hue-rotate': 'hueRotate',\n\t\t\t'hueRotate': 'hueRotate',\n\t\t\t'invert': 'invert',\n\t\t\t'opacity': 'opacity'\n\t\t}[name];\n\n\t\tif(!normalized) return;\n\n\t\t// 检查是否已有同名滤镜,有则更新\n\t\tconst existing = this.filters.find(f => f.name === normalized);\n\t\tif(existing) {\n\t\t\texisting.value = value;\n\t\t}\n\t\telse {\n\t\t\tthis.filters.push({ name: normalized, value: value });\n\t\t}\n\t}\n\n\t/**\n\t * 从字符串格式解析滤镜\n\t * 格式: \"blur(2px) grayscale(50%) brightness(1.2)\"\n\t * @param {string} s 滤镜字符串\n\t */\n\tfromString(s) {\n\t\tif(!s || typeof s !== 'string') return;\n\t\t// 匹配 filterName(value) 模式\n\t\tconst regex = /([a-zA-Z-]+)\\s*\\(\\s*([^)]+)\\s*\\)/g;\n\t\tlet match;\n\t\twhile((match = regex.exec(s)) !== null) {\n\t\t\tconst name = match[1];\n\t\t\tconst valueStr = match[2].replace(/[a-z%]+$/i, '').trim();\n\t\t\tconst value = parseFloat(valueStr);\n\t\t\tif(!isNaN(value)) {\n\t\t\t\tthis.addFilter(name, value);\n\t\t\t}\n\t\t}\n\t}\n\n\t/**\n\t * 转换为CSS filter字符串格式\n\t * @returns {string}\n\t */\n\ttoString() {\n\t\treturn this.filters.map(f => {\n\t\t\tswitch(f.name) {\n\t\t\t\tcase 'blur':\n\t\t\t\t\treturn `blur(${f.value}px)`;\n\t\t\t\tcase 'hueRotate':\n\t\t\t\t\treturn `hue-rotate(${f.value}deg)`;\n\t\t\t\tdefault:\n\t\t\t\t\treturn `${f.name}(${f.value})`;\n\t\t\t}\n\t\t}).join(' ');\n\t}\n\n\t/**\n\t * 转换为Canvas context.filter可用的字符串\n\t * @returns {string}\n\t */\n\ttoCanvasFilter() {\n\t\tif(this.filters.length === 0) return 'none';\n\t\treturn this.toString();\n\t}\n\n\t/**\n\t * 检查是否有指定名称的滤镜\n\t * @param {string} name 滤镜名称\n\t * @returns {boolean}\n\t */\n\thas(name) {\n\t\treturn this.filters.some(f => f.name === name);\n\t}\n\n\t/**\n\t * 获取指定滤镜的值\n\t * @param {string} name 滤镜名称\n\t * @returns {number|undefined}\n\t */\n\tget(name) {\n\t\tconst f = this.filters.find(f => f.name === name);\n\t\treturn f ? f.value : undefined;\n\t}\n\n\t/**\n\t * 移除指定滤镜\n\t * @param {string} name 滤镜名称\n\t */\n\tremove(name) {\n\t\tconst index = this.filters.findIndex(f => f.name === name);\n\t\tif(index > -1) {\n\t\t\tthis.filters.splice(index, 1);\n\t\t}\n\t}\n\n\t/**\n\t * 清空所有滤镜\n\t */\n\tclear() {\n\t\tthis.filters = [];\n\t}\n}\n\nexport { jmFilter };\n","import {jmUtils} from \"./jmUtils.js\";\n\nexport default class jmEvents {\n\n\tconstructor(container, target) {\n\t\tthis.container = container;\n\t\tthis.target = target || container;\n\t\tthis.mouseHandler = new jmMouseEvent(this, container, target);\n\t\tthis.keyHandler = new jmKeyEvent(this, container, target);\n\t}\n\n\ttouchStart(evt) {\n\t\tevt = evt || window.event;\n\t\tevt.eventName = 'touchstart';\n\t\tthis.container.raiseEvent('touchstart',evt);\n\t\tconst t = evt.target || evt.srcElement;\n\t\tif(t == this.target) {\n\t\t\treturn false;\n\t\t}\n\t};\n\n\ttouchMove(evt) {\n\t\tevt = evt || window.event;\n\t\tevt.eventName = 'touchmove';\n\t\tthis.container.raiseEvent('touchmove',evt);\n\t\tconst t = evt.target || evt.srcElement;\n\t\tif(t == this.target) {\n\t\t\treturn false;\n\t\t}\n\t};\n\n\ttouchEnd(evt) {\n\t\tevt = evt || window.event;\n\t\tevt.eventName = 'touchend';\n\t\t\n\t\tthis.container.raiseEvent('touchend',evt);\n\t\tconst t = evt.target || evt.srcElement;\n\t\tif(t == this.target) {\n\t\t\treturn false;\n\t\t}\n\t};\n\n\ttouchCancel(evt) {\n\t\tevt = evt || window.event;\n\t\tevt.eventName = 'touchcancel';\n\t\t\n\t\tthis.container.raiseEvent('touchcancel',evt);\n\t\tconst t = evt.target || evt.srcElement;\n\t\tif(t == this.target) {\n\t\t\treturn false;\n\t\t}\n\t};\n\n\ttap(evt) {\n\t\tevt = evt || window.event;\n\t\tevt.eventName = 'tap';\n\t\t\n\t\tthis.container.raiseEvent('tap',evt);\n\t\tconst t = evt.target || evt.srcElement;\n\t\tif(t == this.target) {\n\t\t\treturn false;\n\t\t}\n\t};\n\n\tdestroy() {\n\t\tthis.mouseHandler.destroy();\n\t\tthis.keyHandler.destroy();\n\t}\n}\n\nclass jmMouseEvent {\n\tconstructor(instance, container, target) {\n\t\tthis.instance = instance;\n\t\tthis.container = container;\n\t\tthis.target = target || container;\n\n\t\tthis.eventEvents = {};\n\n\t\tthis.init(instance, container, target);\n\t}\n\t\n\tinit(instance, container, target) {\n\t\tconst canvas = this.target;\n\t\tconst doc = typeof document != 'undefined'? document: null;\n\n\t\tthis.eventEvents['mousedown'] = jmUtils.bindEvent(this.target,'mousedown',function(evt) {\n\t\t\tevt = evt || window.event;\n\t\t\tevt.eventName = 'mousedown';\n\t\t\tcontainer.raiseEvent('mousedown',evt);\n\t\t});\n\t\t\n\t\tthis.eventEvents['mousemove'] = jmUtils.bindEvent(this.target,'mousemove',function(evt) {\n\t\t\tevt = evt || window.event;\n\t\t\tevt.eventName = 'mousemove';\n\t\t\tconst target = evt.target || evt.srcElement;\n\t\t\tif(target == canvas) {\n\t\t\t\tcontainer.raiseEvent('mousemove',evt);\n\t\t\t\tif(evt.preventDefault) evt.preventDefault();\n\t\t\t\treturn false;\n\t\t\t}\n\t\t});\n\t\t\n\t\tthis.eventEvents['mouseover'] = jmUtils.bindEvent(this.target,'mouseover',function(evt) {\n\t\t\tevt = evt || window.event;\n\t\t\tevt.eventName = 'mouseover';\n\t\t\tcontainer.raiseEvent('mouseover',evt);\n\t\t});\n\t\tthis.eventEvents['mouseleave'] = jmUtils.bindEvent(this.target,'mouseleave',function(evt) {\n\t\t\tevt = evt || window.event;\n\t\t\tevt.eventName = 'mouseleave';\n\t\t\tcontainer.raiseEvent('mouseleave',evt);\n\t\t});\n\t\tthis.eventEvents['mouseout'] = jmUtils.bindEvent(this.target,'mouseout',function(evt) {\n\t\t\tevt = evt || window.event;\n\t\t\tevt.eventName = 'mouseout';\n\t\t\tcontainer.raiseEvent('mouseout',evt);\n\t\t});\n\t\tdoc && (this.eventEvents['mouseup'] = jmUtils.bindEvent(doc,'mouseup',function(evt) {\n\t\t\tevt = evt || window.event;\n\t\t\tevt.eventName = 'mouseup';\n\t\t\tconst r = container.raiseEvent('mouseup',evt);\n\t\t\tif(r === false) {\n\t\t\t\tif(evt.preventDefault) evt.preventDefault();\n\t\t\t\treturn false;\n\t\t\t}\n\t\t}));\n\t\t\n\t\tthis.eventEvents['dblclick'] = jmUtils.bindEvent(this.target,'dblclick',function(evt) {\n\t\t\tevt = evt || window.event;\n\t\t\tevt.eventName = 'dblclick';\n\t\t\tcontainer.raiseEvent('dblclick',evt);\n\t\t});\n\t\tthis.eventEvents['click'] = jmUtils.bindEvent(this.target,'click',function(evt) {\n\t\t\tevt = evt || window.event;\n\t\t\tevt.eventName = 'click';\n\t\t\tcontainer.raiseEvent('click',evt);\n\t\t});\n\n\t\tdoc && (this.eventEvents['resize'] = jmUtils.bindEvent(doc,'resize',function(evt) {\n\t\t\tevt = evt || window.event;\n\t\t\tevt.eventName = 'resize';\n\t\t\treturn container.raiseEvent('resize',evt);\n\t\t}));\n\n\t\tthis.eventEvents['touchstart'] = jmUtils.bindEvent(this.target,'touchstart', function(evt) {\n\t\t\tevt.eventName = 'touchstart';\n\t\t\treturn instance.touchStart(evt);\n\t\t},{ passive: false });\n\n\t\tthis.eventEvents['touchmove'] = jmUtils.bindEvent(this.target,'touchmove', function(evt) {\n\t\t\tevt.eventName = 'touchmove';\n\t\t\treturn instance.touchMove(evt);\n\t\t},{ passive: false });\n\n\t\tdoc && (this.eventEvents['touchend'] = jmUtils.bindEvent(doc,'touchend', function(evt) {\n\t\t\tevt.eventName = 'touchend';\n\t\t\treturn instance.touchEnd(evt);\n\t\t},{ passive: false }));\n\n\t\tdoc && (this.eventEvents['touchcancel'] = jmUtils.bindEvent(doc,'touchcancel', function(evt) {\n\t\t\tevt.eventName = 'touchcancel';\n\t\t\treturn instance.touchCancel(evt);\n\t\t},{ passive: false }));\n\t}\n\n\tdestroy() {\n\t\tfor(const name in this.eventEvents) {\n\t\t\tconst event = this.eventEvents[name];\n\t\t\tif(!event || !event.fun) continue;\n\t\t\tjmUtils.removeEvent(event.target, name, event.fun);\n\t\t}\n\t}\n}\n\nclass jmKeyEvent {\n\tconstructor(instance, container,target) {\n\t\tthis.instance = instance;\n\t\tthis.container = container;\n\t\tthis.target = target || container;\n\n\t\tthis.eventEvents = {};\n\n\t\tthis.init(container, target);\n\t}\n\n\tinit(container, target) {\n\t\tconst doc = typeof document != 'undefined'? document: null;\n\n\t\tconst checkKeyEvent = (evt) => {\n\t\t\tconst target = evt.srcElement || evt.target;\n\t\t\tif(target && (target.tagName == 'INPUT' \n\t\t\t\t|| target.tagName == 'TEXTAREA'\n\t\t\t\t|| target.tagName == 'ANCHOR' \n\t\t\t\t|| target.tagName == 'FORM' \n\t\t\t\t|| target.tagName == 'FILE'\n\t\t\t\t|| target.tagName == 'IMG'\n\t\t\t\t|| target.tagName == 'HIDDEN'\n\t\t\t\t|| target.tagName == 'RADIO'\n\t\t\t\t|| target.tagName == 'TEXT'\t)) {\n\t\t\t\treturn false;\n\t\t\t}\n\t\t\treturn true;\n\t\t}\n\n\t\tdoc && (this.eventEvents['keypress'] = jmUtils.bindEvent(doc,'keypress',function(evt) {\n\t\t\tevt = evt || window.event;\n\t\t\tif(!checkKeyEvent(evt)) return;\n\t\t\tconst r = container.raiseEvent('keypress',evt);\n\t\t\tif(r === false && evt.preventDefault) \n\t\t\t\tevt.preventDefault();\n\t\t\treturn r;\n\t\t}));\n\t\tdoc && (this.eventEvents['keydown'] = jmUtils.bindEvent(doc,'keydown',function(evt) {\n\t\t\tevt = evt || window.event;\n\t\t\tif(!checkKeyEvent(evt)) return;\n\t\t\tconst r = container.raiseEvent('keydown',evt);\n\t\t\tif(r === false && evt.preventDefault) \n\t\t\t\tevt.preventDefault();\n\t\t\treturn r;\n\t\t}));\n\t\tdoc && (this.eventEvents['keyup'] = jmUtils.bindEvent(doc,'keyup',function(evt) {\n\t\t\tevt = evt || window.event;\n\t\t\tif(!checkKeyEvent(evt)) return;\n\t\t\tconst r = container.raiseEvent('keyup',evt);\n\t\t\tif(r === false && evt.preventDefault) \n\t\t\t\tevt.preventDefault();\n\t\t\treturn r;\n\t\t}));\n\t}\n\n\tdestroy() {\n\t\tfor(const name in this.eventEvents) {\n\t\t\tconst event = this.eventEvents[name];\n\t\t\tif(!event || !event.fun) continue;\n\t\t\tjmUtils.removeEvent(event.target, name, event.fun);\n\t\t}\n\t}\n}\n\nexport { jmEvents };\n","'use strict';\n\nexport default earcut;\n\nfunction earcut(data, holeIndices, dim) {\n\n dim = dim || 2;\n\n var hasHoles = holeIndices && holeIndices.length,\n outerLen = hasHoles ? holeIndices[0] * dim : data.length,\n outerNode = linkedList(data, 0, outerLen, dim, true),\n triangles = [];\n\n if (!outerNode || outerNode.next === outerNode.prev) return triangles;\n\n var minX, minY, maxX, maxY, x, y, invSize;\n\n if (hasHoles) outerNode = eliminateHoles(data, holeIndices, outerNode, dim);\n\n // if the shape is not too simple, we'll use z-order curve hash later; calculate polygon bbox\n if (data.length > 80 * dim) {\n minX = maxX = data[0];\n minY = maxY = data[1];\n\n for (var i = dim; i < outerLen; i += dim) {\n x = data[i];\n y = data[i + 1];\n if (x < minX) minX = x;\n if (y < minY) minY = y;\n if (x > maxX) maxX = x;\n if (y > maxY) maxY = y;\n }\n\n // minX, minY and invSize are later used to transform coords into integers for z-order calculation\n invSize = Math.max(maxX - minX, maxY - minY);\n invSize = invSize !== 0 ? 32767 / invSize : 0;\n }\n\n earcutLinked(outerNode, triangles, dim, minX, minY, invSize, 0);\n\n return triangles;\n}\n\n// create a circular doubly linked list from polygon points in the specified winding order\nfunction linkedList(data, start, end, dim, clockwise) {\n var i, last;\n\n if (clockwise === (signedArea(data, start, end, dim) > 0)) {\n for (i = start; i < end; i += dim) last = insertNode(i, data[i], data[i + 1], last);\n } else {\n for (i = end - dim; i >= start; i -= dim) last = insertNode(i, data[i], data[i + 1], last);\n }\n\n if (last && equals(last, last.next)) {\n removeNode(last);\n last = last.next;\n }\n\n return last;\n}\n\n// eliminate colinear or duplicate points\nfunction filterPoints(start, end) {\n if (!start) return start;\n if (!end) end = start;\n\n var p = start,\n again;\n do {\n again = false;\n\n if (!p.steiner && (equals(p, p.next) || area(p.prev, p, p.next) === 0)) {\n removeNode(p);\n p = end = p.prev;\n if (p === p.next) break;\n again = true;\n\n } else {\n p = p.next;\n }\n } while (again || p !== end);\n\n return end;\n}\n\n// main ear slicing loop which triangulates a polygon (given as a linked list)\nfunction earcutLinked(ear, triangles, dim, minX, minY, invSize, pass) {\n if (!ear) return;\n\n // interlink polygon nodes in z-order\n if (!pass && invSize) indexCurve(ear, minX, minY, invSize);\n\n var stop = ear,\n prev, next;\n\n // iterate through ears, slicing them one by one\n while (ear.prev !== ear.next) {\n prev = ear.prev;\n next = ear.next;\n\n if (invSize ? isEarHashed(ear, minX, minY, invSize) : isEar(ear)) {\n // cut off the triangle\n triangles.push(prev.i / dim | 0);\n triangles.push(ear.i / dim | 0);\n triangles.push(next.i / dim | 0);\n\n removeNode(ear);\n\n // skipping the next vertex leads to less sliver triangles\n ear = next.next;\n stop = next.next;\n\n continue;\n }\n\n ear = next;\n\n // if we looped through the whole remaining polygon and can't find any more ears\n if (ear === stop) {\n // try filtering points and slicing again\n if (!pass) {\n earcutLinked(filterPoints(ear), triangles, dim, minX, minY, invSize, 1);\n\n // if this didn't work, try curing all small self-intersections locally\n } else if (pass === 1) {\n ear = cureLocalIntersections(filterPoints(ear), triangles, dim);\n earcutLinked(ear, triangles, dim, minX, minY, invSize, 2);\n\n // as a last resort, try splitting the remaining polygon into two\n } else if (pass === 2) {\n splitEarcut(ear, triangles, dim, minX, minY, invSize);\n }\n\n break;\n }\n }\n}\n\n// check whether a polygon node forms a valid ear with adjacent nodes\nfunction isEar(ear) {\n var a = ear.prev,\n b = ear,\n c = ear.next;\n\n if (area(a, b, c) >= 0) return false; // reflex, can't be an ear\n\n // now make sure we don't have other points inside the potential ear\n var ax = a.x, bx = b.x, cx = c.x, ay = a.y, by = b.y, cy = c.y;\n\n // triangle bbox; min & max are calculated like this for speed\n var x0 = ax < bx ? (ax < cx ? ax : cx) : (bx < cx ? bx : cx),\n y0 = ay < by ? (ay < cy ? ay : cy) : (by < cy ? by : cy),\n x1 = ax > bx ? (ax > cx ? ax : cx) : (bx > cx ? bx : cx),\n y1 = ay > by ? (ay > cy ? ay : cy) : (by > cy ? by : cy);\n\n var p = c.next;\n while (p !== a) {\n if (p.x >= x0 && p.x <= x1 && p.y >= y0 && p.y <= y1 &&\n pointInTriangle(ax, ay, bx, by, cx, cy, p.x, p.y) &&\n area(p.prev, p, p.next) >= 0) return false;\n p = p.next;\n }\n\n return true;\n}\n\nfunction isEarHashed(ear, minX, minY, invSize) {\n var a = ear.prev,\n b = ear,\n c = ear.next;\n\n if (area(a, b, c) >= 0) return false; // reflex, can't be an ear\n\n var ax = a.x, bx = b.x, cx = c.x, ay = a.y, by = b.y, cy = c.y;\n\n // triangle bbox; min & max are calculated like this for speed\n var x0 = ax < bx ? (ax < cx ? ax : cx) : (bx < cx ? bx : cx),\n y0 = ay < by ? (ay < cy ? ay : cy) : (by < cy ? by : cy),\n x1 = ax > bx ? (ax > cx ? ax : cx) : (bx > cx ? bx : cx),\n y1 = ay > by ? (ay > cy ? ay : cy) : (by > cy ? by : cy);\n\n // z-order range for the current triangle bbox;\n var minZ = zOrder(x0, y0, minX, minY, invSize),\n maxZ = zOrder(x1, y1, minX, minY, invSize);\n\n var p = ear.prevZ,\n n = ear.nextZ;\n\n // look for points inside the triangle in both directions\n while (p && p.z >= minZ && n && n.z <= maxZ) {\n if (p.x >= x0 && p.x <= x1 && p.y >= y0 && p.y <= y1 && p !== a && p !== c &&\n pointInTriangle(ax, ay, bx, by, cx, cy, p.x, p.y) && area(p.prev, p, p.next) >= 0) return false;\n p = p.prevZ;\n\n if (n.x >= x0 && n.x <= x1 && n.y >= y0 && n.y <= y1 && n !== a && n !== c &&\n pointInTriangle(ax, ay, bx, by, cx, cy, n.x, n.y) && area(n.prev, n, n.next) >= 0) return false;\n n = n.nextZ;\n }\n\n // look for remaining points in decreasing z-order\n while (p && p.z >= minZ) {\n if (p.x >= x0 && p.x <= x1 && p.y >= y0 && p.y <= y1 && p !== a && p !== c &&\n pointInTriangle(ax, ay, bx, by, cx, cy, p.x, p.y) && area(p.prev, p, p.next) >= 0) return false;\n p = p.prevZ;\n }\n\n // look for remaining points in increasing z-order\n while (n && n.z <= maxZ) {\n if (n.x >= x0 && n.x <= x1 && n.y >= y0 && n.y <= y1 && n !== a && n !== c &&\n pointInTriangle(ax, ay, bx, by, cx, cy, n.x, n.y) && area(n.prev, n, n.next) >= 0) return false;\n n = n.nextZ;\n }\n\n return true;\n}\n\n// go through all polygon nodes and cure small local self-intersections\nfunction cureLocalIntersections(start, triangles, dim) {\n var p = start;\n do {\n var a = p.prev,\n b = p.next.next;\n\n if (!equals(a, b) && intersects(a, p, p.next, b) && locallyInside(a, b) && locallyInside(b, a)) {\n\n triangles.push(a.i / dim | 0);\n triangles.push(p.i / dim | 0);\n triangles.push(b.i / dim | 0);\n\n // remove two nodes involved\n removeNode(p);\n removeNode(p.next);\n\n p = start = b;\n }\n p = p.next;\n } while (p !== start);\n\n return filterPoints(p);\n}\n\n// try splitting polygon into two and triangulate them independently\nfunction splitEarcut(start, triangles, dim, minX, minY, invSize) {\n // look for a valid diagonal that divides the polygon into two\n var a = start;\n do {\n var b = a.next.next;\n while (b !== a.prev) {\n if (a.i !== b.i && isValidDiagonal(a, b)) {\n // split the polygon in two by the diagonal\n var c = splitPolygon(a, b);\n\n // filter colinear points around the cuts\n a = filterPoints(a, a.next);\n c = filterPoints(c, c.next);\n\n // run earcut on each half\n earcutLinked(a, triangles, dim, minX, minY, invSize, 0);\n earcutLinked(c, triangles, dim, minX, minY, invSize, 0);\n return;\n }\n b = b.next;\n }\n a = a.next;\n } while (a !== start);\n}\n\n// link every hole into the outer loop, producing a single-ring polygon without holes\nfunction eliminateHoles(data, holeIndices, outerNode, dim) {\n var queue = [],\n i, len, start, end, list;\n\n for (i = 0, len = holeIndices.length; i < len; i++) {\n start = holeIndices[i] * dim;\n end = i < len - 1 ? holeIndices[i + 1] * dim : data.length;\n list = linkedList(data, start, end, dim, false);\n if (list === list.next) list.steiner = true;\n queue.push(getLeftmost(list));\n }\n\n queue.sort(compareX);\n\n // process holes from left to right\n for (i = 0; i < queue.length; i++) {\n outerNode = eliminateHole(queue[i], outerNode);\n }\n\n return outerNode;\n}\n\nfunction compareX(a, b) {\n return a.x - b.x;\n}\n\n// find a bridge between vertices that connects hole with an outer ring and and link it\nfunction eliminateHole(hole, outerNode) {\n var bridge = findHoleBridge(hole, outerNode);\n if (!bridge) {\n return outerNode;\n }\n\n var bridgeReverse = splitPolygon(bridge, hole);\n\n // filter collinear points around the cuts\n filterPoints(bridgeReverse, bridgeReverse.next);\n return filterPoints(bridge, bridge.next);\n}\n\n// David Eberly's algorithm for finding a bridge between hole and outer polygon\nfunction findHoleBridge(hole, outerNode) {\n var p = outerNode,\n hx = hole.x,\n hy = hole.y,\n qx = -Infinity,\n m;\n\n // find a segment intersected by a ray from the hole's leftmost point to the left;\n // segment's endpoint with lesser x will be potential connection point\n do {\n if (hy <= p.y && hy >= p.next.y && p.next.y !== p.y) {\n var x = p.x + (hy - p.y) * (p.next.x - p.x) / (p.next.y - p.y);\n if (x <= hx && x > qx) {\n qx = x;\n m = p.x < p.next.x ? p : p.next;\n if (x === hx) return m; // hole touches outer segment; pick leftmost endpoint\n }\n }\n p = p.next;\n } while (p !== outerNode);\n\n if (!m) return null;\n\n // look for points inside the triangle of hole point, segment intersection and endpoint;\n // if there are no points found, we have a valid connection;\n // otherwise choose the point of the minimum angle with the ray as connection point\n\n var stop = m,\n mx = m.x,\n my = m.y,\n tanMin = Infinity,\n tan;\n\n p = m;\n\n do {\n if (hx >= p.x && p.x >= mx && hx !== p.x &&\n pointInTriangle(hy < my ? hx : qx, hy, mx, my, hy < my ? qx : hx, hy, p.x, p.y)) {\n\n tan = Math.abs(hy - p.y) / (hx - p.x); // tangential\n\n if (locallyInside(p, hole) &&\n (tan < tanMin || (tan === tanMin && (p.x > m.x || (p.x === m.x && sectorContainsSector(m, p)))))) {\n m = p;\n tanMin = tan;\n }\n }\n\n p = p.next;\n } while (p !== stop);\n\n return m;\n}\n\n// whether sector in vertex m contains sector in vertex p in the same coordinates\nfunction sectorContainsSector(m, p) {\n return area(m.prev, m, p.prev) < 0 && area(p.next, m, m.next) < 0;\n}\n\n// interlink polygon nodes in z-order\nfunction indexCurve(start, minX, minY, invSize) {\n var p = start;\n do {\n if (p.z === 0) p.z = zOrder(p.x, p.y, minX, minY, invSize);\n p.prevZ = p.prev;\n p.nextZ = p.next;\n p = p.next;\n } while (p !== start);\n\n p.prevZ.nextZ = null;\n p.prevZ = null;\n\n sortLinked(p);\n}\n\n// Simon Tatham's linked list merge sort algorithm\n// http://www.chiark.greenend.org.uk/~sgtatham/algorithms/listsort.html\nfunction sortLinked(list) {\n var i, p, q, e, tail, numMerges, pSize, qSize,\n inSize = 1;\n\n do {\n p = list;\n list = null;\n tail = null;\n numMerges = 0;\n\n while (p) {\n numMerges++;\n q = p;\n pSize = 0;\n for (i = 0; i < inSize; i++) {\n pSize++;\n q = q.nextZ;\n if (!q) break;\n }\n qSize = inSize;\n\n while (pSize > 0 || (qSize > 0 && q)) {\n\n if (pSize !== 0 && (qSize === 0 || !q || p.z <= q.z)) {\n e = p;\n p = p.nextZ;\n pSize--;\n } else {\n e = q;\n q = q.nextZ;\n qSize--;\n }\n\n if (tail) tail.nextZ = e;\n else list = e;\n\n e.prevZ = tail;\n tail = e;\n }\n\n p = q;\n }\n\n tail.nextZ = null;\n inSize *= 2;\n\n } while (numMerges > 1);\n\n return list;\n}\n\n// z-order of a point given coords and inverse of the longer side of data bbox\nfunction zOrder(x, y, minX, minY, invSize) {\n // coords are transformed into non-negative 15-bit integer range\n x = (x - minX) * invSize | 0;\n y = (y - minY) * invSize | 0;\n\n x = (x | (x << 8)) & 0x00FF00FF;\n x = (x | (x << 4)) & 0x0F0F0F0F;\n x = (x | (x << 2)) & 0x33333333;\n x = (x | (x << 1)) & 0x55555555;\n\n y = (y | (y << 8)) & 0x00FF00FF;\n y = (y | (y << 4)) & 0x0F0F0F0F;\n y = (y | (y << 2)) & 0x33333333;\n y = (y | (y << 1)) & 0x55555555;\n\n return x | (y << 1);\n}\n\n// find the leftmost node of a polygon ring\nfunction getLeftmost(start) {\n var p = start,\n leftmost = start;\n do {\n if (p.x < leftmost.x || (p.x === leftmost.x && p.y < leftmost.y)) leftmost = p;\n p = p.next;\n } while (p !== start);\n\n return leftmost;\n}\n\n// check if a point lies within a convex triangle\nfunction pointInTriangle(ax, ay, bx, by, cx, cy, px, py) {\n return (cx - px) * (ay - py) >= (ax - px) * (cy - py) &&\n (ax - px) * (by - py) >= (bx - px) * (ay - py) &&\n (bx - px) * (cy - py) >= (cx - px) * (by - py);\n}\n\n// check if a diagonal between two polygon nodes is valid (lies in polygon interior)\nfunction isValidDiagonal(a, b) {\n return a.next.i !== b.i && a.prev.i !== b.i && !intersectsPolygon(a, b) && // dones't intersect other edges\n (locallyInside(a, b) && locallyInside(b, a) && middleInside(a, b) && // locally visible\n (area(a.prev, a, b.prev) || area(a, b.prev, b)) || // does not create opposite-facing sectors\n equals(a, b) && area(a.prev, a, a.next) > 0 && area(b.prev, b, b.next) > 0); // special zero-length case\n}\n\n// signed area of a triangle\nfunction area(p, q, r) {\n return (q.y - p.y) * (r.x - q.x) - (q.x - p.x) * (r.y - q.y);\n}\n\n// check if two points are equal\nfunction equals(p1, p2) {\n return p1.x === p2.x && p1.y === p2.y;\n}\n\n// check if two segments intersect\nfunction intersects(p1, q1, p2, q2) {\n var o1 = sign(area(p1, q1, p2));\n var o2 = sign(area(p1, q1, q2));\n var o3 = sign(area(p2, q2, p1));\n var o4 = sign(area(p2, q2, q1));\n\n if (o1 !== o2 && o3 !== o4) return true; // general case\n\n if (o1 === 0 && onSegment(p1, p2, q1)) return true; // p1, q1 and p2 are collinear and p2 lies on p1q1\n if (o2 === 0 && onSegment(p1, q2, q1)) return true; // p1, q1 and q2 are collinear and q2 lies on p1q1\n if (o3 === 0 && onSegment(p2, p1, q2)) return true; // p2, q2 and p1 are collinear and p1 lies on p2q2\n if (o4 === 0 && onSegment(p2, q1, q2)) return true; // p2, q2 and q1 are collinear and q1 lies on p2q2\n\n return false;\n}\n\n// for collinear points p, q, r, check if point q lies on segment pr\nfunction onSegment(p, q, r) {\n return q.x <= Math.max(p.x, r.x) && q.x >= Math.min(p.x, r.x) && q.y <= Math.max(p.y, r.y) && q.y >= Math.min(p.y, r.y);\n}\n\nfunction sign(num) {\n return num > 0 ? 1 : num < 0 ? -1 : 0;\n}\n\n// check if a polygon diagonal intersects any polygon segments\nfunction intersectsPolygon(a, b) {\n var p = a;\n do {\n if (p.i !== a.i && p.next.i !== a.i && p.i !== b.i && p.next.i !== b.i &&\n intersects(p, p.next, a, b)) return true;\n p = p.next;\n } while (p !== a);\n\n return false;\n}\n\n// check if a polygon diagonal is locally inside the polygon\nfunction locallyInside(a, b) {\n return area(a.prev, a, a.next) < 0 ?\n area(a, b, a.next) >= 0 && area(a, a.prev, b) >= 0 :\n area(a, b, a.prev) < 0 || area(a, a.next, b) < 0;\n}\n\n// check if the middle point of a polygon diagonal is inside the polygon\nfunction middleInside(a, b) {\n var p = a,\n inside = false,\n px = (a.x + b.x) / 2,\n py = (a.y + b.y) / 2;\n do {\n if (((p.y > py) !== (p.next.y > py)) && p.next.y !== p.y &&\n (px < (p.next.x - p.x) * (py - p.y) / (p.next.y - p.y) + p.x))\n inside = !inside;\n p = p.next;\n } while (p !== a);\n\n return inside;\n}\n\n// link two polygon vertices with a bridge; if the vertices belong to the same ring, it splits polygon into two;\n// if one belongs to the outer ring and another to a hole, it merges it into a single ring\nfunction splitPolygon(a, b) {\n var a2 = new Node(a.i, a.x, a.y),\n b2 = new Node(b.i, b.x, b.y),\n an = a.next,\n bp = b.prev;\n\n a.next = b;\n b.prev = a;\n\n a2.next = an;\n an.prev = a2;\n\n b2.next = a2;\n a2.prev = b2;\n\n bp.next = b2;\n b2.prev = bp;\n\n return b2;\n}\n\n// create a node and optionally link it with previous one (in a circular doubly linked list)\nfunction insertNode(i, x, y, last) {\n var p = new Node(i, x, y);\n\n if (!last) {\n p.prev = p;\n p.next = p;\n\n } else {\n p.next = last.next;\n p.prev = last;\n last.next.prev = p;\n last.next = p;\n }\n return p;\n}\n\nfunction removeNode(p) {\n p.next.prev = p.prev;\n p.prev.next = p.next;\n\n if (p.prevZ) p.prevZ.nextZ = p.nextZ;\n if (p.nextZ) p.nextZ.prevZ = p.prevZ;\n}\n\nfunction Node(i, x, y) {\n // vertex index in coordinates array\n this.i = i;\n\n // vertex coordinates\n this.x = x;\n this.y = y;\n\n // previous and next vertex nodes in a polygon ring\n this.prev = null;\n this.next = null;\n\n // z-order curve value\n this.z = 0;\n\n // previous and next nodes in z-order\n this.prevZ = null;\n this.nextZ = null;\n\n // indicates whether this is a steiner point\n this.steiner = false;\n}\n\n// return a percentage difference between the polygon area and its triangulation area;\n// used to verify correctness of triangulation\nearcut.deviation = function (data, holeIndices, dim, triangles) {\n var hasHoles = holeIndices && holeIndices.length;\n var outerLen = hasHoles ? holeIndices[0] * dim : data.length;\n\n var polygonArea = Math.abs(signedArea(data, 0, outerLen, dim));\n if (hasHoles) {\n for (var i = 0, len = holeIndices.length; i < len; i++) {\n var start = holeIndices[i] * dim;\n var end = i < len - 1 ? holeIndices[i + 1] * dim : data.length;\n polygonArea -= Math.abs(signedArea(data, start, end, dim));\n }\n }\n\n var trianglesArea = 0;\n for (i = 0; i < triangles.length; i += 3) {\n var a = triangles[i] * dim;\n var b = triangles[i + 1] * dim;\n var c = triangles[i + 2] * dim;\n trianglesArea += Math.abs(\n (data[a] - data[c]) * (data[b + 1] - data[a + 1]) -\n (data[a] - data[b]) * (data[c + 1] - data[a + 1]));\n }\n\n return polygonArea === 0 && trianglesArea === 0 ? 0 :\n Math.abs((trianglesArea - polygonArea) / polygonArea);\n};\n\nfunction signedArea(data, start, end, dim) {\n var sum = 0;\n for (var i = start, j = end - dim; i < end; i += dim) {\n sum += (data[j] - data[i]) * (data[i + 1] + data[j + 1]);\n j = i;\n }\n return sum;\n}\n\n// turn a polygon in a multi-dimensional array form (e.g. as in GeoJSON) into a form Earcut accepts\nearcut.flatten = function (data) {\n var dim = data[0][0].length,\n result = {vertices: [], holes: [], dimensions: dim},\n holeIndex = 0;\n\n for (var i = 0; i < data.length; i++) {\n for (var j = 0; j < data[i].length; j++) {\n for (var d = 0; d < dim; d++) result.vertices.push(data[i][j][d]);\n }\n if (i > 0) {\n holeIndex += data[i - 1].length;\n result.holes.push(holeIndex);\n }\n }\n return result;\n};\n","const MAX_STOPS = 16;\n\n/**\n * WebGL 渐变对象\n * 支持 GLSL 着色器直接计算渐变色,无需 textureCanvas\n */\nclass WebglGradient {\n constructor(type = 'linear', params = {}) {\n this.type = type || 'linear';\n\n this.x1 = params.x1 || 0;\n this.y1 = params.y1 || 0;\n this.r1 = params.r1 || 0;\n this.x2 = params.x2 || 0;\n this.y2 = params.y2 || 0;\n this.r2 = params.r2 || 0;\n\n this.bounds = params.bounds || {\n left: 0,\n top: 0,\n width: 0,\n height: 0\n };\n\n this.control = params.control;\n\n this.stops = [];\n this._sortedStops = null;\n this._paramsHash = null;\n }\n\n /**\n * 添加颜色断点\n */\n addColorStop(offset, color) {\n this.stops.push({\n offset: Math.max(0, Math.min(1, offset)),\n color\n });\n this._sortedStops = null;\n this._paramsHash = null;\n }\n\n /**\n * 获取排序后的 stops(带解析后的颜色)\n */\n _getSortedStops() {\n if (this._sortedStops) return this._sortedStops;\n\n const utils = this.control && this.control.graph && this.control.graph.utils;\n this._sortedStops = this.stops\n .map(s => {\n let c = s.color;\n if (utils && typeof c === 'string') {\n c = utils.hexToRGBA(c);\n }\n if (typeof c === 'object' && c !== null) {\n // hexToRGBA 返回 r/g/b 为 0~255,a 为 0~1\n // 但如果已经是 0~1 范围(由 rgbToDecimal 处理过),需要检测\n const needNormalize = (c.r > 1 || c.g > 1 || c.b > 1) ? 255 : 1;\n return {\n offset: s.offset,\n r: (c.r !== undefined ? c.r : 0) / needNormalize,\n g: (c.g !== undefined ? c.g : 0) / needNormalize,\n b: (c.b !== undefined ? c.b : 0) / needNormalize,\n a: c.a !== undefined ? c.a : 1\n };\n }\n return { offset: s.offset, r: 0, g: 0, b: 0, a: 1 };\n })\n .sort((a, b) => a.offset - b.offset);\n\n return this._sortedStops;\n }\n\n /**\n * 将渐变参数以 uniform 形式传递给着色器\n * 返回 { type, start, end, stopCount, stops } 供着色器使用\n */\n toUniformParams() {\n const stops = this._getSortedStops();\n const count = Math.min(stops.length, MAX_STOPS);\n\n // 展平为 Float32Array: [offset, r, g, b, a, ...]\n const flatStops = new Float32Array(count * 5);\n for (let i = 0; i < count; i++) {\n const s = stops[i];\n flatStops[i * 5 + 0] = s.offset;\n flatStops[i * 5 + 1] = s.r;\n flatStops[i * 5 + 2] = s.g;\n flatStops[i * 5 + 3] = s.b;\n flatStops[i * 5 + 4] = s.a;\n }\n\n return {\n gradientType: this.type === 'radial' ? 2 : 1,\n gradientStart: new Float32Array([\n this.x1, this.y1,\n this.type === 'radial' ? Math.max(0, this.r1) : 0,\n 0\n ]),\n gradientEnd: new Float32Array([\n this.x2, this.y2,\n this.type === 'radial' ? Math.max(0, this.r2) : 0,\n 0\n ]),\n stopCount: count,\n stops: flatStops\n };\n }\n\n /**\n * 使缓存失效\n */\n invalidateCache() {\n this._sortedStops = null;\n this._paramsHash = null;\n }\n\n /**\n * 转换为渐变的字符串表达\n */\n toString() {\n let str = this.type + '-gradient(';\n if (this.type == 'linear') {\n str += this.x1 + ' ' + this.y1 + ' ' + this.x2 + ' ' + this.y2;\n }\n else {\n str += this.x1 + ' ' + this.y1 + ' ' + this.r1 + ' ' + this.x2 + ' ' + this.y2 + ' ' + this.r2;\n }\n this.stops.forEach(function(s) {\n str += ',' + s.color + ' ' + s.offset;\n });\n return str + ')';\n }\n}\n\nexport default WebglGradient;\nexport { MAX_STOPS };\n","// 生成着色器\n// type: gl.VERTEX_SHADER 顶点着色器 , gl.FRAGMENT_SHADER 片段着色器\n// src: 着色器代码\nfunction createShader(gl, type, src) {\n const shader = gl.createShader(type) // 创建一个顶点着色器\n gl.shaderSource(shader, src); // 编写顶点着色器代码\n gl.compileShader(shader); // 编译着色器\n\n return shader;\n}\n\nexport {\n createShader\n}","\nconst GLSL_TO_SIZE = {\n 'float': 1,\n 'vec2': 2,\n 'vec3': 3,\n 'vec4': 4,\n\n 'int': 1,\n 'ivec2': 2,\n 'ivec3': 3,\n 'ivec4': 4,\n\n 'bool': 1,\n 'bvec2': 2,\n 'bvec3': 3,\n 'bvec4': 4,\n\n 'mat2': 4,\n 'mat3': 9,\n 'mat4': 16,\n\n 'sampler2D': 1\n};\n\n/**\n * @class\n * @memberof PIXI.glCore.shader\n * @param type {String}\n * @return {Number}\n */\nconst mapSize = function(type) { \n return GLSL_TO_SIZE[type];\n};\n\n\n\n\nexport {\n mapSize\n}\n","\nvar GL_TABLE = null;\n\nconst GL_TO_GLSL_TYPES = {\n 'FLOAT': 'float',\n 'FLOAT_VEC2': 'vec2',\n 'FLOAT_VEC3': 'vec3',\n 'FLOAT_VEC4': 'vec4',\n\n 'INT': 'int',\n 'INT_VEC2': 'ivec2',\n 'INT_VEC3': 'ivec3',\n 'INT_VEC4': 'ivec4',\n \n 'BOOL': 'bool',\n 'BOOL_VEC2': 'bvec2',\n 'BOOL_VEC3': 'bvec3',\n 'BOOL_VEC4': 'bvec4',\n \n 'FLOAT_MAT2': 'mat2',\n 'FLOAT_MAT3': 'mat3',\n 'FLOAT_MAT4': 'mat4',\n \n 'SAMPLER_2D': 'sampler2D' \n};\n\nconst mapType = function(gl, type) {\n if(!GL_TABLE) {\n const typeNames = Object.keys(GL_TO_GLSL_TYPES);\n GL_TABLE = {};\n for(let i = 0; i < typeNames.length; ++i) {\n const tn = typeNames[i];\n GL_TABLE[ gl[tn] ] = GL_TO_GLSL_TYPES[tn];\n }\n }\n\n return GL_TABLE[type];\n};\n\n\nexport {\n mapType\n}\n","import {\n createShader\n} from './shader.js';\nimport {\n mapSize\n} from './mapSize.js';\nimport {\n mapType\n} from './mapType.js';\n\n// 创建程序\nfunction createProgram(gl, vertexSrc, fragmentSrc) {\n // 创建顶点着色器\n const vertexShader = createShader(gl, gl.VERTEX_SHADER, vertexSrc);\n // 创建片段着色器\n const fragmentShader = createShader(gl, gl.FRAGMENT_SHADER, fragmentSrc);\n\n const program = gl.createProgram() // 创建一个程序\n gl.attachShader(program, vertexShader) // 添加顶点着色器\n gl.attachShader(program, fragmentShader) // 添加片元着色器\n gl.linkProgram(program) // 连接 program 中的着色器\n\n // 检查程序链接状态\n if (!gl.getProgramParameter(program, gl.LINK_STATUS)) {\n console.error('PError: Could not initialize shader.');\n console.error('gl.VALIDATE_STATUS', gl.getProgramParameter(program, gl.VALIDATE_STATUS));\n console.error('gl.getError()', gl.getError());\n\n // if there is a program info log, log it\n if (gl.getProgramInfoLog(program) !== '') {\n console.warn('Warning: gl.getProgramInfoLog()', gl.getProgramInfoLog(program));\n }\n\n gl.deleteProgram(program);\n }\n\n useProgram(gl, program);\n\n // clean up some shaders\n gl.deleteShader(vertexShader);\n gl.deleteShader(fragmentShader);\n\n const attrs = extractAttributes(gl, program);\n const uniforms = extractUniforms(gl, program);\n \n return {\n program,\n attrs,\n uniforms\n };\n}\n\n// 采用program\nfunction useProgram(gl, program) {\n return gl.useProgram(program); // 告诉 webgl 用这个 program 进行渲染\n}\n\nfunction extractAttributes(gl, program) {\n const attributes = {};\n\n const count = gl.getProgramParameter(program, gl.ACTIVE_ATTRIBUTES);\n\n for (let i = 0; i < count; i++){\n const attribData = gl.getActiveAttrib(program, i);\n const type = mapType(gl, attribData.type);\n attributes[attribData.name] = {\n attribData,\n size: mapSize(type),\n type,\n location: gl.getAttribLocation(program, attribData.name), \n };\n }\n\n return attributes;\n}\n\nfunction extractUniforms(gl, program) {\n\tconst uniforms = {};\n\n const count = gl.getProgramParameter(program, gl.ACTIVE_UNIFORMS);\n\n for (let i = 0; i < count; i++) {\n \tconst uniformData = gl.getActiveUniform(program, i);\n \tconst name = uniformData.name.replace(/\\[.*?\\]/, \"\");\n const type = mapType(gl, uniformData.type );\n\n \tuniforms[name] = {\n uniformData,\n \t\ttype: type,\n \t\tsize: uniformData.size,\n \t\tlocation: gl.getUniformLocation(program, name),\n \t};\n }\n\n\treturn uniforms;\n};\n\n\n// 把缓冲区的值写入变量\n// size: 组成数量,必须是1,2,3或4. 每个单元由多少个数组成\n// strip: 步长 数组中一行长度,0 表示数据是紧密的没有空隙,让OpenGL决定具体步长\n// offset: 字节偏移量,必须是类型的字节长度的倍数。\n// dataType: 每个元素的数据类型\nfunction writeVertexAttrib(gl, buffer, attr, size=2, strip=0, offset=0, dataType=gl.FLOAT) {\n gl.bindBuffer(buffer.type, buffer.buffer);\n gl.vertexAttribPointer( // 告诉 OpenGL 如何从 Buffer 中获取数据\n attr.location, // 顶点属性的索引\n size, // 组成数量,必须是1,2,3或4。我们只提供了 x 和 y\n dataType,\n false, // 是否归一化到特定的范围,对 FLOAT 类型数据设置无效\n strip * buffer.unitSize,\n offset\n );\n gl.enableVertexAttribArray(attr.location);\n return buffer;\n}\n\nfunction disableVertexAttribArray(gl, attr) {\n return gl.disableVertexAttribArray(attr.location);\n}\n\nfunction getAttribLocation(gl, program, name) {\n return gl.getAttribLocation(program, name);\n}\n\nfunction getUniformLocation(gl, program, name) {\n return gl.getUniformLocation(program, name);\n}\n\nexport {\n createProgram,\n useProgram,\n getAttribLocation,\n getUniformLocation,\n extractAttributes,\n extractUniforms,\n writeVertexAttrib,\n disableVertexAttribArray\n}","\n// 创建缓冲区\nfunction createBuffer(gl, data, type=gl.ARRAY_BUFFER, drawType=gl.STATIC_DRAW) {\n //先创建一个缓存对象\n const buffer = gl.createBuffer();\n if(!buffer) {\n throw Error('创建缓冲区对象失败');\n }\n //说明缓存对象保存的类型\n gl.bindBuffer(type, buffer);\n //写入坐标数据\n // 因为会将数据发送到 GPU,为了省去数据解析,这里使用 Float32Array 直接传送数据\n // data.buffer这里要使用data.buffer,否则在edge下可能导至数据发生较大的改变\n gl.bufferData(type, data.buffer || data, drawType); // 表示缓冲区的内容不会经常更改\n return {\n type,\n drawType,\n buffer,\n // 获取到数组中单个元素的字节数\n unitSize: data.BYTES_PER_ELEMENT\n };\n}\n\n// 创建float32的buffer\nfunction createFloat32Buffer(gl, data, type=gl.ARRAY_BUFFER, drawType=gl.STATIC_DRAW) {\n const vertices = new Float32Array(data);\n const buffer = createBuffer(gl, vertices, type, drawType);\n return buffer;\n}\n\n// 创建uint16的bugger\nfunction createUint16Buffer(gl, data, type=gl.ARRAY_BUFFER, drawType=gl.STATIC_DRAW) {\n const vertices = new Uint16Array(data);\n const buffer = createBuffer(gl, vertices, type, drawType);\n return buffer;\n}\n\n// 释放\nfunction deleteBuffer(gl, buffer) {\n gl.deleteBuffer(buffer.buffer || buffer);\n}\n\n\nexport {\n createBuffer,\n createUint16Buffer,\n createFloat32Buffer,\n deleteBuffer,\n}","\n// 生成纹理\nfunction create2DTexture(gl) {\n const texture = gl.createTexture();\n gl.pixelStorei(gl.UNPACK_FLIP_Y_WEBGL, 1); // 图像反转Y轴\n gl.activeTexture(gl.TEXTURE0); // 激活纹理单元\n gl.bindTexture(gl.TEXTURE_2D, texture); // 绑定纹理对象\n \n //gl.generateMipmap(gl.TEXTURE_2D);\n gl.texParameterf(gl.TEXTURE_2D, gl.TEXTURE_MAG_FILTER, gl.NEAREST); // 放大处理方式 // LINEAR / NEAREST\n gl.texParameterf(gl.TEXTURE_2D, gl.TEXTURE_MIN_FILTER, gl.NEAREST); // 缩小处理方式\n gl.texParameterf(gl.TEXTURE_2D, gl.TEXTURE_WRAP_S, gl.CLAMP_TO_EDGE); // 水平平铺方式\n gl.texParameterf(gl.TEXTURE_2D, gl.TEXTURE_WRAP_T, gl.CLAMP_TO_EDGE); // 竖直平铺方式\n\n \n return texture;\n}\n\n// 创建图片纹理\nfunction createImgTexture(gl, img) {\n const texture = create2DTexture(gl);\n\n gl.texImage2D(gl.TEXTURE_2D, 0, gl.RGBA, gl.RGBA, gl.UNSIGNED_BYTE, img) // 配置纹理图像\n return {\n texture\n };\n}\n\n// 用像素值来绘制纹理\nfunction createDataTexture(gl, pixels) {\n const data = new Uint8Array(pixels.data || pixels);\n\n const texture = create2DTexture(gl);\n\n gl.texImage2D(\n gl.TEXTURE_2D, // 纹理目标\n 0, // 细节级别,指定详细级别。0 级是基本图像等级,n 级是第 n 个金字塔简化级。\n gl.RGBA, // 纹理内部格式\n pixels.width || 1, // 指定纹理的宽度\n pixels.height || 1, // 指定纹理的高度\n 0, // 指定纹理的边框宽度。必须为 0。\n gl.RGBA, // 源图像数据格式\n gl.UNSIGNED_BYTE, // 纹理数据类型\n data // 数据\n );\n return {\n texture\n };\n}\n\n// 删除纹理\nfunction deleteTexture(gl, texture) {\n return gl.deleteTexture(texture);\n}\n\nexport {\n create2DTexture,\n createImgTexture,\n createDataTexture,\n deleteTexture\n}","\nimport earcut from '../earcut.js';\nimport webglGradient, { MAX_STOPS } from './gradient.js';\nimport {\n createProgram,\n useProgram,\n writeVertexAttrib,\n disableVertexAttribArray\n} from './core/program.js';\n\nimport {\n createFloat32Buffer,\n createUint16Buffer,\n deleteBuffer,\n} from './core/buffer.js';\n\nimport {\n create2DTexture,\n createImgTexture,\n createDataTexture,\n deleteTexture\n} from './core/texture.js';\n\n// 把canvas坐标转为webgl坐标系\nconst convertPointSource = `\n vec4 translatePosition(vec4 point, float x, float y) {\n point.x = (point.x-x)/x;\n point.y = (y-point.y)/y;\n return point;\n }`;\n// 把纹理的canvas坐标转为纹理的坐标系\nconst convertTexturePosition = `\n vec2 translateTexturePosition(in vec2 point, vec4 bounds) {\n point.x = (point.x-bounds.x)/bounds.z; // 离左上角位置的X长比上纹理宽 0-1\n point.y = 1.0-(point.y-bounds.y)/bounds.w; // 离左上角位置的Y长比上高,因为纹理坐标是左下角起,所以要用1-\n return point;\n }`;\n\n// path顶点着色器源码\nconst pathVertexSource = `\n attribute vec4 a_position;\n attribute vec4 a_color;\n attribute vec2 a_text_coord;\n uniform vec2 a_center_point; // 当前canvas的中心位置\n uniform float a_point_size; // 点的大小\n uniform int a_type;\n varying vec4 v_color;\n varying vec2 v_text_coord;\n varying float v_type;\n\n ${convertPointSource}\n\n void main() {\n gl_PointSize = a_point_size == 0.0? 1.0 : a_point_size;\n v_type = float(a_type);\n vec4 pos = translatePosition(a_position, a_center_point.x, a_center_point.y);\n gl_Position = pos;\n v_color = a_color;\n if(a_type == 2 || a_type == 5) {\n v_text_coord = a_position.xy;\n }\n }\n`;\n// path 片段着色器源码\nconst pathFragmentSource = `\n precision mediump float;\n uniform sampler2D u_sample;\n uniform vec4 v_texture_bounds; // 纹理的左上坐标和大小 x,y,z,w\n uniform vec4 v_single_color;\n // GLSL 渐变 uniforms\n uniform int u_gradient_type; // 0=无 1=线性 2=径向\n uniform vec4 u_gradient_start; // 线性:{x1,y1,0,0} 径向:{cx,cy,r1,0}\n uniform vec4 u_gradient_end; // 线性:{x2,y2,0,0} 径向:{cx,cy,r2,0}\n uniform int u_gradient_stop_count;\n uniform float u_gradient_offsets[${MAX_STOPS}];\n uniform vec4 u_gradient_colors[${MAX_STOPS}]; // {r, g, b, a} 0~1 范围\n varying float v_type;\n varying vec4 v_color;\n varying vec2 v_text_coord;\n\n ${convertTexturePosition}\n\n // 在 sorted stops 中按 t 值采样颜色\n // 兼容 GLSL ES 1.0:循环仅与常量比较,无 break/continue\n vec4 sampleGradient(float t) {\n t = clamp(t, 0.0, 1.0);\n // 正向扫描:始终遍历 MAX_STOPS-1 次,找到 t 所在段并覆盖结果\n float localT = 0.0;\n vec4 c0 = u_gradient_colors[0];\n vec4 c1 = u_gradient_colors[0];\n for(int i = 0; i < ${MAX_STOPS - 1}; i++) {\n float s0 = u_gradient_offsets[i];\n float s1 = u_gradient_offsets[i + 1];\n if(t >= s0) {\n float range = s1 - s0;\n localT = range > 0.0001 ? clamp((t - s0) / range, 0.0, 1.0) : 0.0;\n c0 = u_gradient_colors[i];\n c1 = u_gradient_colors[i + 1];\n }\n }\n return mix(c0, c1, localT);\n }\n\n void main() {\n // 如果是fill,则直接填充颜色\n if(v_type == 1.0) {\n gl_FragColor = v_single_color;\n }\n // 渐变色 (旧方式,顶点颜色插值)\n else if(v_type == 3.0) {\n gl_FragColor = v_color;\n }\n // GLSL 渐变填充 (type=5)\n else if(v_type == 5.0) {\n float t;\n if(u_gradient_type == 2) {\n // 径向渐变\n vec2 d = v_text_coord - u_gradient_start.xy;\n float dist = length(d);\n float r1 = u_gradient_start.z;\n float r2 = u_gradient_end.z;\n float range = r2 - r1;\n t = range > 0.001 ? (dist - r1) / range : 0.0;\n } else {\n // 线性渐变\n vec2 dir = u_gradient_end.xy - u_gradient_start.xy;\n float lenSq = dot(dir, dir);\n if(lenSq > 0.001) {\n vec2 pos = v_text_coord - u_gradient_start.xy;\n t = dot(pos, dir) / lenSq;\n } else {\n t = 0.0;\n }\n }\n gl_FragColor = sampleGradient(t) * v_single_color.a;\n }\n else if(v_type == 2.0) {\n vec2 pos = translateTexturePosition(v_text_coord, v_texture_bounds);\n gl_FragColor = texture2D(u_sample, pos);\n }\n else {\n float r = distance(gl_PointCoord, vec2(0.5, 0.5));\n //根据距离设置片元\n if(r <= 0.5){\n // 方形区域片元距离几何中心半径小于0.5,像素颜色设置红色\n gl_FragColor = v_single_color;\n }else {\n // 方形区域距离几何中心半径不小于0.5的片元剪裁舍弃掉:\n discard;\n }\n }\n }\n`;\n\nclass WeblBase {\n constructor(graph, option) {\n this.graph = graph;\n this.option = option || {};\n this.style = {\n globalAlpha: 1\n };\n this.stateStack = [];\n this.transformMatrix = [1, 0, 0, 1, 0, 0]; // 2D 变换矩阵\n }\n\n get context() {\n if(this.graph) return this.graph.context;\n }\n\n // 保存当前状态\n save() {\n this.stateStack.push({\n transformMatrix: [...this.transformMatrix],\n style: { ...this.style }\n });\n }\n\n // 恢复上一个状态\n restore() {\n if (this.stateStack.length > 0) {\n const state = this.stateStack.pop();\n this.transformMatrix = state.transformMatrix;\n this.style = state.style;\n }\n }\n\n // 平移变换\n translate(x, y) {\n // 更新变换矩阵\n this.transformMatrix[4] += x * this.transformMatrix[0] + y * this.transformMatrix[2];\n this.transformMatrix[5] += x * this.transformMatrix[1] + y * this.transformMatrix[3];\n }\n\n // 缩放变换\n scale(sx, sy) {\n // 更新变换矩阵\n this.transformMatrix[0] *= sx;\n this.transformMatrix[1] *= sx;\n this.transformMatrix[2] *= sy;\n this.transformMatrix[3] *= sy;\n }\n\n // 旋转变换\n rotate(angle) {\n const cos = Math.cos(angle);\n const sin = Math.sin(angle);\n const [a, b, c, d] = this.transformMatrix;\n \n // 更新变换矩阵\n this.transformMatrix[0] = a * cos - b * sin;\n this.transformMatrix[1] = a * sin + b * cos;\n this.transformMatrix[2] = c * cos - d * sin;\n this.transformMatrix[3] = c * sin + d * cos;\n }\n\n // 矩阵变换\n transform(a, b, c, d, e, f) {\n const [currentA, currentB, currentC, currentD, currentE, currentF] = this.transformMatrix;\n \n // 矩阵乘法\n this.transformMatrix[0] = a * currentA + b * currentC;\n this.transformMatrix[1] = a * currentB + b * currentD;\n this.transformMatrix[2] = c * currentA + d * currentC;\n this.transformMatrix[3] = c * currentB + d * currentD;\n this.transformMatrix[4] = e * currentA + f * currentC + currentE;\n this.transformMatrix[5] = e * currentB + f * currentD + currentF;\n }\n\n // 应用变换到点\n applyTransform(point) {\n const [a, b, c, d, tx, ty] = this.transformMatrix;\n return {\n x: a * point.x + c * point.y + tx,\n y: b * point.x + d * point.y + ty\n };\n }\n\n // 文本测量用的离屏 canvas context(1x1 单例缓存,不依赖 textureCanvas)\n get _measureCtx() {\n if(!this.__measureCtx) {\n try {\n if(typeof document !== 'undefined') {\n const c = document.createElement('canvas');\n c.width = c.height = 1;\n this.__measureCtx = c.getContext('2d');\n }\n } catch(e) {\n this.__measureCtx = null;\n }\n }\n return this.__measureCtx;\n }\n\n // i当前程序\n get program() {\n // 默认所有path用同一个编译好的program\n return this.graph.context.pathProgram || (this.graph.context.pathProgram=this.createProgram(pathVertexSource, pathFragmentSource));\n }\n\n // 设置样式\n setStyle(style = this.style, value = '') {\n\n if(typeof style === 'string') {\n const obj = {};\n obj[style] = value;\n style = obj;\n }\n /*\n // 设置线条颜色或填充色\n if(style.strokeStyle) {\n let color = style.strokeStyle;\n if(typeof color === 'string') color = this.graph.utils.hexToRGBA(color);\n this.style.strokeStyle = this.graph.utils.rgbToDecimal(color);\n delete style.strokeStyle;\n }\n else if(style.fillStyle) {\n let color = style.fillStyle;\n if(this.isGradient(color)) {\n this.style.fillStyle = color;\n }\n else {\n if(typeof color === 'string') color = this.graph.utils.hexToRGBA(color);\n this.style.fillStyle = this.graph.utils.rgbToDecimal(color);\n }\n delete style.fillStyle;\n } */ \n\n this.style = {\n ...this.style,\n ...style\n }\n }\n\n // 把传统颜色转为webgl识别的\n convertColor(color) {\n if(this.isGradient(color)) return color;\n if(typeof color === 'string') {\n // 先尝试 hexToRGBA 解析\n color = this.graph.utils.hexToRGBA(color);\n // hexToRGBA 对无法识别的格式(如 hsl)会原样返回字符串\n // 利用离屏 canvas 将任意 CSS 颜色转为 rgba\n if(typeof color === 'string') {\n color = this.__parseCSSColor(color);\n }\n }\n if(typeof color === 'object' && color.r !== undefined) {\n return this.graph.utils.rgbToDecimal(color);\n }\n return color;\n }\n\n // 利用离屏 canvas 解析任意 CSS 颜色(hsl/hsla/命名颜色等)\n __parseCSSColor(colorStr) {\n const ctx = this._measureCtx;\n if(!ctx) return { r: 0, g: 0, b: 0, a: 0 };\n try {\n ctx.clearRect(0, 0, 1, 1);\n ctx.fillStyle = '#000000';\n ctx.fillStyle = colorStr;\n ctx.fillRect(0, 0, 1, 1);\n const [r, g, b, a] = ctx.getImageData(0, 0, 1, 1).data;\n if(ctx.fillStyle === '#000000' && colorStr !== '#000000' && colorStr !== 'black') {\n return { r: 0, g: 0, b: 0, a: 0 };\n }\n return { r, g, b, a: a / 255 };\n } catch(e) {\n return { r: 0, g: 0, b: 0, a: 0 };\n }\n }\n\n // 创建程序\n createProgram(vertexSrc, fragmentSrc) { \n return createProgram(this.context, vertexSrc, fragmentSrc);\n }\n\n // 指定使用某个程序\n useProgram(program=this.program) {\n program = program.program || program;\n if(this.context.__curent_program === program) return program;\n useProgram(this.context, program.program || program);\n this.context.__curent_program = program;\n return program;\n }\n\n getAttribLocation(name) {\n return this.context.getAttribLocation(this.program.program, name);\n }\n \n getUniformLocation(name) {\n return this.context.getUniformLocation(this.program.program, name);\n }\n\n // 把缓冲区的值写入变量\n // buffer: 缓冲区\n // size: 组成数量,必须是1,2,3或4. 每个单元由多少个数组成\n // strip: 步长 数组中一行长度,0 表示数据是紧密的没有空隙,让OpenGL决定具体步长\n // offset: 字节偏移量,必须是类型的字节长度的倍数。\n // dataType: 每个元素的数据类型\n writeVertexAttrib(buffer, attr, size=2, strip=0, offset=0, dataType=this.context.FLOAT) {\n buffer.attr = attr;\n return writeVertexAttrib(this.context, buffer, attr, size, strip, offset, dataType);\n }\n\n // 禁用attri\n disableVertexAttribArray(attr) {\n try{\n if(!attr) return attr;\n return disableVertexAttribArray(this.context, attr);\n }\n catch(e) {\n console.error(e);\n }\n return attr;\n }\n\n // 创建float32的buffer\n createFloat32Buffer(data, type=this.context.ARRAY_BUFFER, drawType=this.context.STATIC_DRAW) {\n const buffer = createFloat32Buffer(this.context, data, type, drawType);\n return {\n data,\n ...buffer\n };\n }\n\n createUint16Buffer(data, type=this.context.ARRAY_BUFFER, drawType=this.context.STATIC_DRAW) {\n const buffer = createUint16Buffer(this.context, data, type, drawType);\n return {\n data,\n ...buffer\n };\n }\n\n // 释放\n deleteBuffer(buffer) {\n try {\n if(!buffer) return;\n const bufferHandler = buffer.buffer || buffer;\n if(bufferHandler) return deleteBuffer(this.context, bufferHandler);\n }\n catch(e) {\n console.log(buffer);\n console.error(e);\n }\n return buffer;\n }\n\n // 生成纹理\n create2DTexture() { \n return create2DTexture(this.context);\n }\n\n // 创建图片纹理\n createImgTexture(img) {\n return createImgTexture(this.context, img);\n }\n\n // 根根像素值生成纹理\n createDataTexture(data) {\n return createDataTexture(this.context, data);\n }\n\n // 删除纹理\n deleteTexture(texture) {\n try {\n return deleteTexture(this.context, texture.texture || texture);\n }\n catch(e) {\n console.error(e);\n }\n return texture;\n }\n\n // 多边切割, 得到三角形顶点索引数组\n // polygonIndices 顶点索引,\n earCutPoints(points) {\n const arr = this.pointsToArray(points);\n const ps = earcut(arr);// 切割得到3角色顶点索引,\n return ps;\n }\n\n // 多边切割, 得到三角形顶点\n // polygonIndices 顶点索引,\n earCutPointsToTriangles(points) {\n this.earCutCache = this.earCutCache || (this.earCutCache = {});\n // 快速缓存 key:用长度和首尾点坐标\n const len = points.length;\n const key = len + '_' + points[0].x + '_' + points[0].y + '_' + points[len-1].x + '_' + points[len-1].y;\n if (this.earCutCache[key]) return this.earCutCache[key];\n\n const ps = this.earCutPoints(points);// 切割得到3角色顶点索引,\n const triangles = [];\n // 用顶点索引再组合成坐标数组\n for(let i=0;i<ps.length; i+=3) {\n const p1 = points[ps[i]];\n const p2 = points[ps[i+1]];\n const p3 = points[ps[i+2]];\n\n triangles.push([p1, p2, p3]);// 每三个顶点构成一个三角\n }\n \n this.earCutCache[key] = triangles;\n return triangles;\n }\n\n // 点坐标数组转为一维数组\n pointsToArray(points) {\n return [].concat(...points.map(p=>[p.x,p.y]));// 把x,y转为数组元素\n }\n // 每2位表示坐标x,y转为坐标点对象\n arrayToPoints(arr) {\n const points = [];\n for(let i=0;i<arr.length; i+=2) {\n points.push({\n x: arr[i],\n y: arr[i+1]\n });\n }\n return points;\n }\n\n // 创建线性渐变\n createLinearGradient(x1, y1, x2, y2, bounds) {\n return new webglGradient('linear', {\n x1, y1, x2, y2, bounds,\n control: this\n });\n }\n // 创建放射性渐变\n createRadialGradient(x1, y1, r1, x2, y2, r2, bounds) {\n return new webglGradient('radial', {\n x1, y1, r1,\n x2, y2, r2,\n bounds,\n control: this\n });\n }\n // 判断是否是一个渐变对象\n isGradient(obj) {\n return obj && obj instanceof webglGradient;\n }\n\n\t/**\n\t * 测试获取文本所占大小\n\t *\n\t * @method testSize\n\t * @return {object} 含文本大小的对象\n\t */\n\ttestSize(text, style=this.style) {\n\t\tconst ctx = this._measureCtx;\n\t\tif(!ctx) return { width: 15, height: style.fontSize || 15 };\n\n\t\tctx.save && ctx.save();\n\t\tif(style.font || style.fontSize) ctx.font = style.font || (style.fontSize + 'px ' + style.fontFamily);\n\t\tconst size = ctx.measureText ? ctx.measureText(text) : { width: 15 };\n ctx.restore && ctx.restore();\n\t\tsize.height = style.fontSize ? parseInt(style.fontSize) : 15;\n\t\treturn size;\n\t}\n}\n\nexport default WeblBase;\nexport { pathVertexSource, pathFragmentSource, MAX_STOPS };\n","import WebglBase, { MAX_STOPS } from './base.js';\nimport earcut from '../earcut.js';\n\n// path 绘制类\nclass WebglPath extends WebglBase {\n constructor(graph, option) {\n super(graph, option);\n // 是否是规则的,不规则的处理方式更为复杂和耗性能\n this.isRegular = option.isRegular || false;\n this.needCut = option.needCut || false;\n this.control = option.control;\n this.points = [];\n // 缓存 buffer 和纹理,避免每帧创建/销毁\n this.__cachedBuffers = [];\n this.__cachedTexture = null;\n this.__cachedTextureKey = null;\n }\n\n // 释放缓存的 WebGL 资源\n dispose() {\n for(const buf of this.__cachedBuffers) {\n this.deleteBuffer(buf);\n }\n this.__cachedBuffers = [];\n if(this.__cachedTexture) {\n this.deleteTexture(this.__cachedTexture);\n this.__cachedTexture = null;\n this.__cachedTextureKey = null;\n }\n }\n\n // 获取或创建 buffer,优先复用缓存\n getOrCreateBuffer(data, attr) {\n let buffer = this.__cachedBuffers.find(b => b.attr === attr);\n if(buffer) {\n const gl = this.context;\n const float32 = new Float32Array(data);\n gl.bindBuffer(gl.ARRAY_BUFFER, buffer.buffer);\n gl.bufferData(gl.ARRAY_BUFFER, float32, gl.DYNAMIC_DRAW);\n buffer.data = data;\n return buffer;\n }\n buffer = this.createFloat32Buffer(data);\n buffer.attr = attr;\n this.__cachedBuffers.push(buffer);\n return buffer;\n }\n\n // 应用变换到点\n applyTransform(point) {\n return super.applyTransform(point);\n }\n\n setParentBounds(parentBounds = this.parentAbsoluteBounds) {\n\n //this.useProgram();\n\n if(parentBounds) this.parentAbsoluteBounds = parentBounds;\n // 缓存中心点值,只在变化时才更新 uniform\n const cx = this.graph.width / 2;\n const cy = this.graph.height / 2;\n if(this.__lastCenterX !== cx || this.__lastCenterY !== cy) {\n this.context.uniform2f(this.program.uniforms.a_center_point.location, cx, cy);\n this.__lastCenterX = cx;\n this.__lastCenterY = cy;\n }\n }\n\n setFragColor(color) {\n \n if(!Array.isArray(color)) {\n color = this.convertColor(color);\n if(typeof color.a === 'undefined') color.a = 1;\n this.context.uniform4f(this.program.uniforms.v_single_color.location, color.r, color.g, color.b, color.a * this.style.globalAlpha);\n return null;\n }\n\n const colorData = [];\n for(let c of color) {\n c = this.convertColor(c);\n if(typeof c.a === 'undefined') c.a = 1;\n colorData.push(c.r, c.g, c.b, c.a * this.style.globalAlpha);\n }\n \n const colorBuffer = this.createFloat32Buffer(colorData); \n this.writeVertexAttrib(colorBuffer, this.program.attrs.a_color, 4, 0, 0);\n colorBuffer.attr = this.program.attrs.a_color;\n return colorBuffer;\n }\n\n beginDraw() {\n this.useProgram();\n }\n\n // 开始绘制\n draw(points, parentBounds = this.parentAbsoluteBounds) {\n //this.useProgram();\n\n this.setParentBounds(parentBounds);\n \n this.points = points;\n }\n\n endDraw() {\n if(this.points) delete this.points;\n if(this.pathPoints) delete this.pathPoints;\n // 缓存的纹理保留到下次绘制(渐变可能不变)\n }\n\n // 图形封闭\n closePath() {\n if(this.points && this.points.length > 2 && this.points[0] !== this.points[this.points.length-1]) {\n const start = this.points[0];\n const end = this.points[this.points.length-1];\n if(start != end && !(start.x === end.x && start.y === end.y)) this.points.push(start);\n }\n }\n\n // 绘制点数组(使用 DYNAMIC_DRAW 复用 buffer,避免每帧 create/delete)\n writePoints(points, attr = this.program.attrs.a_position) {\n const fixedPoints = [];\n const [a, b, c, d, tx, ty] = this.transformMatrix;\n const isIdentity = (a === 1 && b === 0 && c === 0 && d === 1 && tx === 0 && ty === 0);\n const offsetLeft = this.parentAbsoluteBounds.left;\n const offsetTop = this.parentAbsoluteBounds.top;\n\n if(isIdentity) {\n // 单位矩阵时直接加偏移,避免逐点调用 applyTransform\n for(let i = 0; i < points.length; i++) {\n fixedPoints.push(points[i].x + offsetLeft, points[i].y + offsetTop);\n }\n } else {\n for(const p of points) {\n const transformedPoint = this.applyTransform(p);\n fixedPoints.push(\n transformedPoint.x + offsetLeft,\n transformedPoint.y + offsetTop\n );\n }\n }\n const float32 = new Float32Array(fixedPoints);\n const gl = this.context;\n\n // 复用已有 buffer 或创建新的\n if(this.__cachedBuffers.length > 0) {\n // 找一个同 attr 的 buffer 复用\n let buffer = this.__cachedBuffers.find(b => b.attr === attr);\n if(buffer) {\n gl.bindBuffer(gl.ARRAY_BUFFER, buffer.buffer);\n gl.bufferData(gl.ARRAY_BUFFER, float32, gl.DYNAMIC_DRAW);\n buffer.data = fixedPoints;\n this.writeVertexAttrib(buffer, attr, 2, 0, 0);\n return buffer;\n }\n }\n const vertexBuffer = this.createFloat32Buffer(float32, gl.ARRAY_BUFFER, gl.DYNAMIC_DRAW); \n this.writeVertexAttrib(vertexBuffer, attr, 2, 0, 0);\n vertexBuffer.attr = attr;\n this.__cachedBuffers.push(vertexBuffer);\n return vertexBuffer;\n }\n\n // 连接二个点\n genLinePoints(start, end) {\n const points = [start];\n const dx = end.x - start.x;\n const dy = end.y - start.y;\n if(dx !== 0 || dy !== 0) {\n const len = Math.sqrt(Math.pow(dx, 2) + Math.pow(dy, 2));\n const cos = dx / len;\n const sin = dy / len;\n const step = 0.5;\n for(let l=step; l<len; l+=step) {\n const x = start.x + cos * l;\n const y = start.y + sin * l;\n points.push({\n x, \n y\n });\n }\n }\n points.push(end);\n return points;\n }\n\n // 把path坐标集合分解成一个个点,并且处理moveTo线段能力\n pathToPoints(points=this.points) {\n let start = null;\n const res = [];\n for(let i=0; i<points.length; i++) {\n const p = points[i];\n if(start && !p.m) {\n const linePoints = this.genLinePoints(start, p);\n res.push(...linePoints);\n }\n else if(start && !res.includes(start)) {\n res.push(start);\n }\n start = p;\n }\n if(!res.includes(start)) res.push(start);\n return res;\n }\n // 二点是否重合\n equalPoint(p1, p2) {\n return p1.x === p2.x && p1.y === p2.y;\n }\n\n // 将带 moveTo 标记的点集拆分为外轮廓和多个洞\n splitSubPaths(points) {\n const subPaths = [];\n let current = [];\n for(let i = 0; i < points.length; i++) {\n const p = points[i];\n if(p.m && current.length > 0) {\n subPaths.push(current);\n current = [];\n }\n current.push(p);\n }\n if(current.length > 0) subPaths.push(current);\n\n // 面积最大的作为外轮廓,其余作为洞\n let maxArea = -1;\n let outerIdx = 0;\n for(let i = 0; i < subPaths.length; i++) {\n const area = Math.abs(this.polygonArea(subPaths[i]));\n if(area > maxArea) {\n maxArea = area;\n outerIdx = i;\n }\n }\n\n const outerPoints = subPaths[outerIdx];\n const holes = [];\n for(let i = 0; i < subPaths.length; i++) {\n if(i !== outerIdx) holes.push(subPaths[i]);\n }\n return { outerPoints, holes };\n }\n\n // 计算多边形面积(Shoelace 公式)\n polygonArea(points) {\n let area = 0;\n const n = points.length;\n for(let i = 0; i < n; i++) {\n const j = (i + 1) % n;\n area += points[i].x * points[j].y;\n area -= points[j].x * points[i].y;\n }\n return area / 2;\n }\n\n // 使用 earcut 带 holes 填充多边形\n fillWithHoles(outerPoints, holes, isTexture = false) {\n // 将所有点合并:外轮廓 + 各个洞,并记录洞的起始索引\n const allPoints = [...outerPoints];\n const holeIndices = [];\n for(const hole of holes) {\n holeIndices.push(allPoints.length);\n allPoints.push(...hole);\n }\n\n const dim = 2;\n const vertexData = [];\n for(const p of allPoints) {\n vertexData.push(p.x, p.y);\n }\n\n // 用 earcut 进行带洞三角化\n const indices = earcut(vertexData, holeIndices, dim);\n\n if(!indices || indices.length < 3) return;\n\n // 构建 GPU 顶点数据\n const allVertices = [];\n const allTexCoords = [];\n for(let i = 0; i < indices.length; i++) {\n const p = allPoints[indices[i]];\n allVertices.push(p.x, p.y);\n if(isTexture) allTexCoords.push(p.x, p.y);\n }\n\n const gl = this.context;\n const vertexArr = new Float32Array(allVertices);\n\n let posBuffer = this.__cachedBuffers.find(b => b.attr === this.program.attrs.a_position);\n if(!posBuffer) {\n posBuffer = this.createFloat32Buffer(vertexArr, gl.ARRAY_BUFFER, gl.DYNAMIC_DRAW);\n posBuffer.attr = this.program.attrs.a_position;\n this.__cachedBuffers.push(posBuffer);\n } else {\n gl.bindBuffer(gl.ARRAY_BUFFER, posBuffer.buffer);\n gl.bufferData(gl.ARRAY_BUFFER, vertexArr, gl.DYNAMIC_DRAW);\n }\n this.writeVertexAttrib(posBuffer, this.program.attrs.a_position, 2, 0, 0);\n\n if(isTexture && allTexCoords.length) {\n const texData = new Float32Array(allTexCoords);\n let texBuffer = this.__cachedBuffers.find(b => b.attr === this.program.attrs.a_text_coord);\n if(!texBuffer) {\n texBuffer = this.createFloat32Buffer(texData, gl.ARRAY_BUFFER, gl.DYNAMIC_DRAW);\n texBuffer.attr = this.program.attrs.a_text_coord;\n this.__cachedBuffers.push(texBuffer);\n } else {\n gl.bindBuffer(gl.ARRAY_BUFFER, texBuffer.buffer);\n gl.bufferData(gl.ARRAY_BUFFER, texData, gl.DYNAMIC_DRAW);\n }\n this.writeVertexAttrib(texBuffer, this.program.attrs.a_text_coord, 2, 0, 0);\n }\n\n gl.drawArrays(gl.TRIANGLES, 0, allVertices.length / 2);\n }\n // 把path坐标集合转为线段集\n pathToLines(points) {\n let start = null;\n const res = [];\n for(let i=0; i<points.length; i++) {\n const p = points[i];\n // 不重合的二个点,组成线段\n if(start && !p.m && !(start.x == p.x && start.y == p.y)) {\n const line = {\n start,\n end: p,\n };\n res.push(line);\n }\n start = p;\n }\n return res;\n }\n\n // 裁剪线段,如果二段线段有交点,则分割成四段, 端头相交的线段不用分割\n cutLines(lines, index1=0, index2=0) {\n if(lines && lines.length < 3) return lines;\n \n index2 = Math.max(index1 + 1, index2); //如果指定了比下一个更大的索引,则用更大的,说明前面的已经处理过了,不需要重复\n\n // 找出线段相交的点,并切割线段\n while(index1 < lines.length) {\n const line1 = lines[index1];\n\n while(index2 < lines.length) {\n const line2 = lines[index2];\n // 如果二条线顶点有重合,则不用处理\n if(this.equalPoint(line1.start, line2.start) || this.equalPoint(line1.end, line2.end) || \n this.equalPoint(line1.start, line2.end) || this.equalPoint(line1.end, line2.start)) {\n index2++;\n continue;\n }\n let cuted = false;\n const intersection = this.getIntersection(line1, line2);// 计算交点\n if(intersection) {\n // 如果交点不是线段的端点,则分割成二条线段\n if(!this.equalPoint(line1.start, intersection) && !this.equalPoint(line1.end, intersection)) {\n const sub1 = {\n start: line1.start,\n end: intersection\n };\n const sub2 = {\n start: intersection,\n end: line1.end\n };\n // 从原数组中删除当前线段,替换成新的线段\n lines.splice(index1, 1, sub1, sub2);\n // 当前线段被重新替换,需要重新从它开始处理\n cuted = true;\n index2 ++;// 因为多加入了一个线段,则对比线索引需要加1\n }\n // 如果交点不是线段的端点,则分割成二条线段\n if(!this.equalPoint(line2.start, intersection) && !this.equalPoint(line2.end, intersection)) {\n const sub1 = {\n start: line2.start,\n end: intersection\n };\n const sub2 = {\n start: intersection,\n end: line2.end\n };\n // 从原数组中删除当前线段,替换成新的线段\n lines.splice(index2, 1, sub1, sub2);\n index2 ++; // 线段2也切成了二段,对比索引要继续加1\n }\n }\n index2++;\n // 如果已经分割了起始线段,则第一个子线段开始,重新对比后面还未对比完的。直接所有对比完成返回\n if(cuted) return this.cutLines(lines, index1, index2);\n }\n index1++;\n index2 = index1 + 1;\n }\n return lines;\n }\n\n // 计算二个线段的交点\n getIntersection(line1, line2) {\n // 如果首尾相接,也认为是有交点\n if(this.equalPoint(line1.start, line2.start) || this.equalPoint(line1.start, line2.end)) return line1.start;\n if(this.equalPoint(line1.end, line2.start) || this.equalPoint(line1.end, line2.end)) return line1.end;\n\n // 三角形abc 面积的2倍\n const area_abc = (line1.start.x - line2.start.x) * (line1.end.y - line2.start.y) - (line1.start.y - line2.start.y) * (line1.end.x - line2.start.x);\n \n // 三角形abd 面积的2倍\n const area_abd = (line1.start.x - line2.end.x) * (line1.end.y - line2.end.y) - (line1.start.y - line2.end.y) * (line1.end.x - line2.end.x);\n \n // 面积符号相同则两点在线段同侧,不相交 (=0表示在线段顶点上);\n if (area_abc * area_abd > 0) {\n return null;\n }\n \n // 三角形cda 面积的2倍\n const area_cda = (line2.start.x - line1.start.x) * (line2.end.y - line1.start.y) - (line2.start.y - line1.start.y) * (line2.end.x - line1.start.x);\n // 三角形cdb 面积的2倍\n // 注意: 这里有一个小优化.不需要再用公式计算面积,而是通过已知的三个面积加减得出.\n const area_cdb = area_cda + area_abc - area_abd ;\n if(area_cda * area_cdb > 0) {\n return null ;\n }\n if(area_abd === area_abc) return null;\n\n //计算交点坐标\n const t = area_cda / (area_abd - area_abc);\n const dx= t * (line1.end.x - line1.start.x);\n const dy= t * (line1.end.y - line1.start.y);\n\n return { \n x: line1.start.x + dx, \n y: line1.start.y + dy\n };\n }\n\n // 找出跟当前线段尾部相交的所有线段\n getIntersectionLines(line, lines, index, point=line.end, points=[], root=null) {\n const res = {\n line,\n polygons: []\n };\n \n points.push(point);\n \n if(root && this.equalPoint(root.line.start, point)) {\n points.unshift(root.line.start); // 把起始地址加入进去\n root.polygons.push(points);\n return res;\n }\n\n for(;index<lines.length; index++) {\n const l = lines[index];\n if(this.equalPoint(point, l.start)) { \n if(points.includes(l.end)) continue; \n this.getIntersectionLines(l, lines, index+1, l.end, [...points], root||res);\n }\n else if(this.equalPoint(point, l.end)) {\n if(points.includes(l.start)) continue; \n this.getIntersectionLines(l, lines, index+1, l.start, [...points], root||res);\n }\n }\n return res;\n }\n\n // 根据路径点坐标,切割出封闭的多边形\n getPolygon(points) {\n let polygons = [];\n let lines = this.pathToLines(points); // 分解得到线段\n if(lines && lines.length > 2) {\n lines = this.cutLines(lines); // 把所有相交点切割线段找出来\n for(let i=0; i<lines.length-1; i++) {\n const line1 = lines[i];\n let polygon = [];// 当前图形\n\n const treeLine = this.getIntersectionLines(line1, lines, i+1);\n \n if(treeLine.polygons.length) polygons.push(...treeLine.polygons);\n continue;\n let lastLine = line1; // 下一个还在连接状态的线\n for(let j=i+1; j<lines.length; j++) {\n const line2 = lines[j];\n // 如果跟下一条线相接,则表示还在形成图形中\n if(this.equalPoint(lastLine.end, line2.start)) {\n polygon.push(lastLine.end);\n lastLine = line2;\n if(i === j+1) continue; //下一条相连 则不需要处理相交情况\n }\n else {\n polygon = [];\n } \n // 因为前面进行了分割线段,则里只有处理端点相连的情况\n const intersection = this.equalPoint(line1.start, line2.end)? line1.start: null;//this.getIntersection(line1, line2);// 计算交点\n if(intersection) {\n polygon.push(intersection);// 交叉点为图形顶点\n // 如果上一个连接线不是当前交叉线,则表示重新开始闭合\n // 如果上一个连接线是当前交叉线,形成了封闭的图形\n if(lastLine === line2 && polygon.length > 1) {\n polygons.push(polygon);\n \n // 封闭后,下一个起始线条就是从交点开始计算起\n /*lastLine = {\n start: intersection,\n end: line2.end\n };*/\n polygon = [];// 重新开始新一轮找图形\n\n /*\n // 如果交点是上一条线的终点,则新图形为空\n if(this.equalPoint(line2.end, intersection)) {\n polygon = [];// 重新开始新一轮找图形\n }\n else {\n // 同时交点也要加到上一个图形中第一个点,形成封闭\n polygon.unshift(intersection);\n\n polygon = [ intersection ];// 重新开始新一轮找图形\n }*/\n }\n else {\n lastLine = line2;\n }\n }\n }\n }\n }\n \n // 当有多个封闭图形时,再弟归一下,里面是不是有封闭图形内还有子封闭图形\n /*if(polygons.length > 1) {\n const newPolygons = [];\n for(const polygon of polygons) {\n // 只有大于4才有可能有子封闭图形\n if(polygon.length > 4) {\n const childPolygons = this.getPolygon(polygon);\n // 当有多个子图形时,表示它不是最终封闭图形,跳过,\n // 因为它的子图形之前有加入的,不需要重复加入\n if(childPolygons.length > 1) {\n //newPolygons.push(...childPolygons);\n continue;\n }\n }\n newPolygons.push(polygon);\n }\n polygons = newPolygons;\n }*/\n return polygons;\n }\n\n // 分割成一个个规则的三角形,不规则的多边形不全割的话纹理就会没法正确覆盖\n getTriangles(points) {\n this.trianglesCache = this.trianglesCache||(this.trianglesCache={});\n // 快速缓存 key:用长度和首尾点坐标(比 JSON.stringify 快几个数量级)\n const len = points.length;\n const key = len + '_' + points[0].x + '_' + points[0].y + '_' + points[len-1].x + '_' + points[len-1].y;\n if(this.trianglesCache[key]) return this.trianglesCache[key];\n\n const res = [];\n const polygons = this.getPolygon(points); \n if(polygons.length) { \n for(const polygon of polygons) {\n // 需要分割三角形,不然填充会有问题\n const triangles = this.earCutPointsToTriangles(polygon);\n res.push(...triangles);\n } \n }\n this.trianglesCache[key] = res;\n return res;\n }\n\n // 画线条\n stroke(points = this.points, color = this.style.strokeStyle, lineWidth = this.style.lineWidth) {\n if(!points || !points.length) return;\n // this.useProgram();\n\n let colorBuffer = null;\n if(color) {\n colorBuffer = this.setFragColor(color);\n }\n // 线宽\n if(lineWidth) {\n this.context.uniform1f(this.program.uniforms.a_point_size.location, lineWidth);// * this.graph.devicePixelRatio\n }\n // 标注为stroke\n if(this.program.uniforms.a_type) {\n // 4表示单画一个圆点,1表示方块形成的线条\n this.context.uniform1i(this.program.uniforms.a_type.location, points.length === 1? 4 :1);\n }\n if(points && points.length) {\n const regular = lineWidth <= 1.2;\n const hasMoveTo = points.some && points.some(p => p.m);\n const isRing = !hasMoveTo && this.needCut; // 空心形状(jmHArc close=true 时无 m 标记)\n if(regular && (hasMoveTo || isRing)) {\n // 有 moveTo 标记或空心形状时,分段绘制每个子路径的 LINE_LOOP\n // 避免 LINE_LOOP 把不同子路径的点连起来产生拉扯线\n if(hasMoveTo) {\n let subPath = [];\n for(let i = 0; i < points.length; i++) {\n if(points[i].m && subPath.length > 0) {\n const buffer = this.writePoints(subPath);\n this.context.drawArrays(this.context.LINE_LOOP, 0, subPath.length);\n subPath = [];\n }\n subPath.push(points[i]);\n }\n if(subPath.length > 1) {\n const buffer = this.writePoints(subPath);\n this.context.drawArrays(this.context.LINE_LOOP, 0, subPath.length);\n }\n }\n else if(isRing) {\n // 空心形状:前半段为内弧,后半段为外弧(反向),各自 LINE_LOOP\n const mid = Math.floor(points.length / 2);\n const inner = points.slice(0, mid);\n const outer = points.slice(mid);\n if(inner.length > 1) {\n this.writePoints(inner);\n this.context.drawArrays(this.context.LINE_LOOP, 0, inner.length);\n }\n if(outer.length > 1) {\n this.writePoints(outer);\n this.context.drawArrays(this.context.LINE_LOOP, 0, outer.length);\n }\n }\n }\n else {\n points = regular? points : this.pathToPoints(points);\n const buffer = this.writePoints(points);\n this.context.drawArrays(regular? this.context.LINE_LOOP: this.context.POINTS, 0, points.length);\n }\n // buffer 由 endDraw 统一清理\n }\n colorBuffer && this.disableVertexAttribArray(colorBuffer && colorBuffer.attr);\n }\n\n // 填充图形\n fill(bounds = {left: 0, top: 0, width: 0, height: 0}, type = 1) {\n \n if(this.points && this.points.length) { \n // 如果是颜色rgba\n if(this.style.fillStyle) { \n this.fillColor(this.style.fillStyle, this.points, bounds, type);\n }\n if(this.style.fillImage) { \n this.fillImage(this.style.fillImage, this.points, bounds, type); \n }\n }\n }\n\n fillColor(color, points, bounds, type=1) {\n \n // 如果是渐变色,使用 GLSL 着色器直接计算\n if(this.isGradient(color)) {\n return this.fillGradient(color, points, bounds);\n }\n \n // 标注为fill\n this.context.uniform1i(this.program.uniforms.a_type.location, type);\n const colorBuffer = this.setFragColor(color);\n\n this.fillPolygons(points); \n\n colorBuffer && this.disableVertexAttribArray(colorBuffer && colorBuffer.attr);\n\n }\n\n /**\n * 使用 GLSL 着色器渲染渐变填充\n * 无需 textureCanvas,直接通过 uniform 传递渐变参数给 GPU\n */\n fillGradient(gradient, points, bounds) {\n const params = gradient.toUniformParams();\n if(!params) return;\n\n // 标注为 GLSL 渐变 (type=5)\n this.context.uniform1i(this.program.uniforms.a_type.location, 5);\n\n // 设置 globalAlpha(通过 v_single_color.a 传递给着色器)\n this.context.uniform4f(this.program.uniforms.v_single_color.location, 1.0, 1.0, 1.0, this.style.globalAlpha);\n\n // 设置渐变类型\n if(this.program.uniforms.u_gradient_type) {\n this.context.uniform1i(this.program.uniforms.u_gradient_type.location, params.gradientType);\n }\n\n // 设置渐变起点/终点\n if(this.program.uniforms.u_gradient_start) {\n this.context.uniform4fv(this.program.uniforms.u_gradient_start.location, params.gradientStart);\n }\n if(this.program.uniforms.u_gradient_end) {\n this.context.uniform4fv(this.program.uniforms.u_gradient_end.location, params.gradientEnd);\n }\n\n // 设置颜色断点数量\n if(this.program.uniforms.u_gradient_stop_count) {\n this.context.uniform1i(this.program.uniforms.u_gradient_stop_count.location, params.stopCount);\n }\n\n // 设置每个 stop 的 offset\n // 关键:必须填充完整的 MAX_STOPS 长度数组,否则未初始化元素默认为 0\n // 会导致着色器循环中 t >= 0 始终为 true,返回黑色\n if(this.program.uniforms.u_gradient_offsets) {\n const offsets = new Float32Array(MAX_STOPS);\n for(let i = 0; i < params.stopCount; i++) {\n offsets[i] = params.stops[i * 5];\n }\n // 用 2.0 填充剩余项,使 t(0~1) >= 2.0 为 false,不会被匹配\n for(let i = params.stopCount; i < MAX_STOPS; i++) {\n offsets[i] = 2.0;\n }\n this.context.uniform1fv(this.program.uniforms.u_gradient_offsets.location, offsets);\n }\n\n // 设置每个 stop 的颜色 (rgba)\n if(this.program.uniforms.u_gradient_colors) {\n const colors = new Float32Array(MAX_STOPS * 4);\n for(let i = 0; i < params.stopCount; i++) {\n colors[i * 4 + 0] = params.stops[i * 5 + 1]; // r\n colors[i * 4 + 1] = params.stops[i * 5 + 2]; // g\n colors[i * 4 + 2] = params.stops[i * 5 + 3]; // b\n colors[i * 4 + 3] = params.stops[i * 5 + 4]; // a\n }\n // 用最后一个 stop 的颜色填充剩余项,确保不会返回黑色\n if(params.stopCount > 0) {\n const lastR = params.stops[(params.stopCount - 1) * 5 + 1];\n const lastG = params.stops[(params.stopCount - 1) * 5 + 2];\n const lastB = params.stops[(params.stopCount - 1) * 5 + 3];\n const lastA = params.stops[(params.stopCount - 1) * 5 + 4];\n for(let i = params.stopCount; i < MAX_STOPS; i++) {\n colors[i * 4 + 0] = lastR;\n colors[i * 4 + 1] = lastG;\n colors[i * 4 + 2] = lastB;\n colors[i * 4 + 3] = lastA;\n }\n }\n this.context.uniform4fv(this.program.uniforms.u_gradient_colors.location, colors);\n }\n\n // 填充多边形(需要纹理坐标来计算渐变位置)\n this.fillPolygons(points, true);\n this.disableVertexAttribArray(this.program.attrs.a_text_coord);\n }\n\n // 区域填充图片\n // points绘制的图形顶点\n // 图片整体绘制区域\n fillImage(img, points, bounds) {\n if(!img) return;\n\n // 对于 ImageData,生成缓存 key(基于渐变参数或 bounds),复用纹理\n let texture = null;\n if(img instanceof ImageData) {\n const key = `${img.width}_${img.height}_${bounds.width}_${bounds.height}_${bounds.left}_${bounds.top}`;\n if(this.__cachedTexture && this.__cachedTextureKey === key) {\n texture = this.__cachedTexture;\n } else {\n texture = this.createDataTexture(img);\n // 释放旧纹理\n if(this.__cachedTexture) {\n this.deleteTexture(this.__cachedTexture);\n }\n this.__cachedTexture = texture;\n this.__cachedTextureKey = key;\n }\n } else {\n texture = this.createImgTexture(img);\n }\n this.context.uniform1i(this.program.uniforms.u_sample.location, 0); // 纹理单元传递给着色器\n\n // 指定纹理区域尺寸\n this.context.uniform4f(this.program.uniforms.v_texture_bounds.location, \n bounds.left + this.parentAbsoluteBounds.left,\n bounds.top + this.parentAbsoluteBounds.top,\n bounds.width,\n bounds.height,\n ); // 纹理单元传递给着色器\n\n this.fillTexture(points);\n \n // 仅对非缓存纹理(非 ImageData)立即删除\n if(!(img instanceof ImageData)) {\n this.deleteTexture(texture);\n }\n }\n\n fillTexture(points) { \n if(points && points.length) { // 标注为纹理对象\n this.context.uniform1i(this.program.uniforms.a_type.location, 2); \n // 纹理坐标\n //const coordBuffer = this.writePoints(points, this.program.attrs.a_text_coord);\n this.fillPolygons(points, true);\n //this.deleteBuffer(coordBuffer); \n this.disableVertexAttribArray(this.program.attrs.a_text_coord); \n } \n }\n\n // 进行多边形填充\n fillPolygons(points, isTexture = false) { \n if(points.length <= 3) {\n // 3个点以下的三角形直接画\n const buffer = this.writePoints(points);\n const coordBuffer = isTexture? this.writePoints(points, this.program.attrs.a_text_coord): null;\n this.context.drawArrays(this.context.TRIANGLE_FAN, 0, points.length);\n return;\n }\n\n // 规则图形(凸多边形,如圆):直接用 TRIANGLE_FAN 一次性绘制,无需 earcut\n if(this.isRegular) {\n // 检查是否有 moveTo 标记,如果有说明路径包含多个子路径(如空心圆弧 jmHArc)\n const hasMoveTo = points.some && points.some(p => p.m);\n if(hasMoveTo) {\n // 有 m 标记:按 m 标记拆分子路径\n const { outerPoints, holes } = this.splitSubPaths(points);\n this.fillWithHoles(outerPoints, holes, isTexture);\n return;\n }\n // 无 m 标记但 needCut=true 表示空心形状(如 jmHArc close=true)\n // 前半段为内弧,后半段为外弧(反向),按中点拆分\n if(this.needCut && points.length >= 6) {\n const mid = Math.floor(points.length / 2);\n const inner = points.slice(0, mid);\n const outer = points.slice(mid);\n const innerArea = Math.abs(this.polygonArea(inner));\n const outerArea = Math.abs(this.polygonArea(outer));\n if(outerArea >= innerArea) {\n this.fillWithHoles(outer, [inner], isTexture);\n } else {\n this.fillWithHoles(inner, [outer], isTexture);\n }\n return;\n }\n const buffer = this.writePoints(points);\n const coordBuffer = isTexture? this.writePoints(points, this.program.attrs.a_text_coord): null;\n this.context.drawArrays(this.context.TRIANGLE_FAN, 0, points.length);\n return;\n }\n\n // 不规则图形:需要 earcut 三角化后,合并为一个大的顶点缓冲区,单次 drawArrays\n const triangles = this.needCut? this.earCutPointsToTriangles(points): this.getTriangles(points);\n if(!triangles.length) return;\n\n // 合并所有三角形的顶点到一个数组\n const allVertices = [];\n const allTexCoords = [];\n for(const triangle of triangles) {\n for(const p of triangle) {\n allVertices.push(p.x, p.y);\n if(isTexture) allTexCoords.push(p.x, p.y);\n }\n }\n\n // 一次性上传所有数据并绘制\n const vertexData = new Float32Array(allVertices);\n const gl = this.context;\n\n // 复用或创建 position buffer\n let posBuffer = this.__cachedBuffers.find(b => b.attr === this.program.attrs.a_position);\n if(!posBuffer) {\n posBuffer = this.createFloat32Buffer(vertexData, gl.ARRAY_BUFFER, gl.DYNAMIC_DRAW);\n posBuffer.attr = this.program.attrs.a_position;\n this.__cachedBuffers.push(posBuffer);\n } else {\n gl.bindBuffer(gl.ARRAY_BUFFER, posBuffer.buffer);\n gl.bufferData(gl.ARRAY_BUFFER, vertexData, gl.DYNAMIC_DRAW);\n }\n this.writeVertexAttrib(posBuffer, this.program.attrs.a_position, 2, 0, 0);\n\n if(isTexture && allTexCoords.length) {\n const texData = new Float32Array(allTexCoords);\n let texBuffer = this.__cachedBuffers.find(b => b.attr === this.program.attrs.a_text_coord);\n if(!texBuffer) {\n texBuffer = this.createFloat32Buffer(texData, gl.ARRAY_BUFFER, gl.DYNAMIC_DRAW);\n texBuffer.attr = this.program.attrs.a_text_coord;\n this.__cachedBuffers.push(texBuffer);\n } else {\n gl.bindBuffer(gl.ARRAY_BUFFER, texBuffer.buffer);\n gl.bufferData(gl.ARRAY_BUFFER, texData, gl.DYNAMIC_DRAW);\n }\n this.writeVertexAttrib(texBuffer, this.program.attrs.a_text_coord, 2, 0, 0);\n }\n\n gl.drawArrays(gl.TRIANGLES, 0, allVertices.length / 2);\n }\n\n // 填充图形\n drawImage(img, left=0, top=0, width=img.width, height=img.height) {\n width = width || img.width;\n height = height || img.height;\n\n this.fillImage(img, this.points, {\n left,\n top,\n width, \n height\n });\n }\n\n drawText(text, x, y, bounds) {\n // 文本渲染仍需要 2D canvas 绘制字形,然后作为纹理上传\n // 使用临时 canvas,不依赖共享的 textureCanvas\n if(!bounds.width || !bounds.height) return null;\n if(typeof document === 'undefined') return null;\n\n let canvas = this.__textCanvas;\n if(!canvas) {\n canvas = document.createElement('canvas');\n this.__textCanvas = canvas;\n }\n canvas.width = bounds.width;\n canvas.height = bounds.height;\n\n const ctx = canvas.getContext('2d', { willReadFrequently: true });\n ctx.clearRect(0, 0, canvas.width, canvas.height);\n\n // 修改字体\n ctx.font = this.style.font || (this.style.fontSize + 'px ' + this.style.fontFamily);\n\n x -= bounds.left;\n y -= bounds.top;\n\n // 设置文本样式\n if(this.style.fillStyle) {\n ctx.fillStyle = this.graph.utils.toColor(this.style.fillStyle);\n }\n if(this.style.strokeStyle) {\n ctx.strokeStyle = this.graph.utils.toColor(this.style.strokeStyle);\n }\n if(this.style.shadowColor) {\n ctx.shadowColor = this.graph.utils.toColor(this.style.shadowColor);\n }\n if(this.style.shadowBlur) {\n ctx.shadowBlur = this.style.shadowBlur;\n }\n if(this.style.shadowOffsetX !== undefined) {\n ctx.shadowOffsetX = this.style.shadowOffsetX;\n }\n if(this.style.shadowOffsetY !== undefined) {\n ctx.shadowOffsetY = this.style.shadowOffsetY;\n }\n if(this.style.textAlign) {\n ctx.textAlign = this.style.textAlign;\n }\n if(this.style.textBaseline) {\n ctx.textBaseline = this.style.textBaseline;\n }\n\n if(this.style.fillStyle && ctx.fillText) {\n if(this.style.maxWidth) {\n ctx.fillText(text, x, y, this.style.maxWidth);\n }\n else {\n ctx.fillText(text, x, y);\n }\n }\n if(this.style.strokeStyle && ctx.strokeText) {\n if(this.style.maxWidth) {\n ctx.strokeText(text, x, y, this.style.maxWidth);\n }\n else {\n ctx.strokeText(text, x, y);\n }\n }\n\n // 用纹理图片代替文字\n const data = ctx.getImageData(0, 0, canvas.width, canvas.height);\n this.fillImage(data, this.points, bounds);\n }\n}\n\nexport default WebglPath;","\nimport {jmUtils} from \"./jmUtils.js\";\nimport {jmList} from \"./jmList.js\";\nimport {jmGradient} from \"./jmGradient.js\";\nimport {jmShadow} from \"./jmShadow.js\";\nimport {jmFilter} from \"./jmFilter.js\";\nimport {jmProperty} from \"./jmProperty.js\";\nimport WebglPath from \"../lib/webgl/path.js\";\n\nconst jmStyleMap = {\n\t'fill':'fillStyle',\n\t'fillImage':'fillImage',\n\t'stroke':'strokeStyle',\n\t'shadow.blur':'shadowBlur',\n\t'shadow.x':'shadowOffsetX',\n\t'shadow.y':'shadowOffsetY',\n\t'shadow.color':'shadowColor',\n\t'lineWidth' : 'lineWidth',\n\t'miterLimit': 'miterLimit',\n\t'fillStyle' : 'fillStyle',\n\t'strokeStyle' : 'strokeStyle',\n\t'font' : 'font',\n\t'opacity' : 'globalAlpha',\n\t'textAlign' : 'textAlign',\n\t'textBaseline' : 'textBaseline',\n\t'shadowBlur' : 'shadowBlur',\n\t'shadowOffsetX' : 'shadowOffsetX',\n\t'shadowOffsetY' : 'shadowOffsetY',\n\t'shadowColor' : 'shadowColor',\n\t'lineJoin': 'lineJoin',\n\t'lineCap':'lineCap',\n\t'lineDashOffset': 'lineDashOffset',\n\t'globalCompositeOperation': 'globalCompositeOperation'\n};\n\nexport default class jmControl extends jmProperty {\n\n\tconstructor(params, t) {\n\t\tparams = params||{};\n\t\tsuper(params);\n\t\tthis.property('type', t || new.target.name);\n\t\tthis.style = params && params.style ? params.style : {};\n\t\tthis.width = params.width || 0;\n\t\tthis.height = params.height || 0;\n\t\tthis.hitArea = params.hitArea || null;\n\n\t\tif(params.position) {\n\t\t\tthis.position = params.position;\n\t\t}\n\n\t\tthis.graph = params.graph || null;\n\t\tthis.zIndex = params.zIndex || 0;\n\t\tthis.interactive = typeof params.interactive == 'undefined'? false : params.interactive;\n\n\t\tif(this.mode === 'webgl') {\n\t\t\tthis.webglControl = new WebglPath(this.graph, {\n\t\t\t\tstyle: this.style,\n\t\t\t\tcontrol: this,\n\t\t\t\tisRegular: params.isRegular,\n\t\t\t\tneedCut: params.needCut\n\t\t\t});\n\t\t}\n\n\t\tthis.initializing();\n\t\t\n\t\tthis.on = this.bind;\n\t\t\n\t\tthis.option = params;\n\t}\n\n\tget type() {\n\t\treturn this.property('type');\n\t}\n\n\tget context() {\n\t\tlet s = this.property('context');\n\t\tif(s) return s;\n\t\telse if(this.is('jmGraph') && this.canvas && this.canvas.getContext) {\n\t\t\treturn this.context = this.canvas.getContext(this.mode || '2d');\n\t\t}\n\t\tconst g = this.graph;\n\t\tif(g) return g.context;\n\t\treturn g.canvas.getContext(this.mode || '2d');\n\t}\n\tset context(v) {\n\t\treturn this.property('context', v);\n\t}\n\n\tget style() {\n\t\tlet s = this.property('style');\n\t\tif(!s) s = this.property('style', {});\n\t\treturn s;\n\t}\n\tset style(v) {\n\t\tthis.needUpdate = true;\n\t\treturn this.property('style', v);\n\t}\n\n\tget visible() {\n\t\tlet s = this.property('visible');\n\t\tif(typeof s == 'undefined') s = this.property('visible', true);\n\t\treturn s;\n\t}\n\tset visible(v) {\n\t\tthis.needUpdate = true;\n\t\treturn this.property('visible', v);\n\t}\n\n\tget interactive() {\n\t\tconst s = this.property('interactive');\n\t\treturn s;\n\t}\n\tset interactive(v) {\n\t\treturn this.property('interactive', v);\n\t}\n\n\tget hitArea() {\n\t\tconst s = this.property('hitArea');\n\t\treturn s;\n\t}\n\tset hitArea(v) {\n\t\treturn this.property('hitArea', v);\n\t}\n\t\t\n\tget children() {\n\t\tlet s = this.property('children');\n\t\tif(!s) s = this.property('children', new jmList());\n\t\treturn s;\n\t}\n\tset children(v) {\n\t\tthis.needUpdate = true;\n\t\treturn this.property('children', v);\n\t}\n\n\tget width() {\n\t\tlet s = this.property('width');\n\t\tif(typeof s == 'undefined') s = this.property('width', 0);\n\t\treturn s;\n\t}\n\tset width(v) {\n\t\tthis.needUpdate = true;\n\t\treturn this.property('width', v);\n\t}\n\n\tget height() {\n\t\tlet s = this.property('height');\n\t\tif(typeof s == 'undefined') s = this.property('height', 0);\n\t\treturn s;\n\t}\n\tset height(v) {\n\t\tthis.needUpdate = true;\n\t\treturn this.property('height', v);\n\t}\n\n\tget zIndex() {\n\t\tlet s = this.property('zIndex');\n\t\tif(!s) s = this.property('zIndex', 0);\n\t\treturn s;\n\t}\n\tset zIndex(v) {\n\t\tthis.property('zIndex', v);\n\t\tthis.children.sort();\n\t\tthis.needUpdate = true;\n\t\treturn v;\n\t}\n\n\tset cursor(cur) {\n\t\tconst graph = this.graph;\n\t\tif(graph) {\n\t\t\tgraph.css('cursor',cur);\n\t\t}\n\t}\n\tget cursor() {\n\t\tconst graph = this.graph;\n\t\tif(graph) {\n\t\t\treturn graph.css('cursor');\n\t\t}\n\t}\n\n\tinitializing() {\n\n\t\tconst self = this;\n\t\tthis.children = this.children || new jmList();\n\t\tconst oadd = this.children.add;\n\t\t\n\t\tthis.children.add = function(obj) {\n\t\t\tif(typeof obj === 'object') {\n\t\t\t\tif(obj.parent && obj.parent != self && obj.parent.children) {\n\t\t\t\t\tobj.parent.children.remove(obj);\n\t\t\t\t}\n\t\t\t\tobj.parent = self;\n\t\t\t\tif(this.contain(obj)) {\n\t\t\t\t\tthis.oremove(obj);\n\t\t\t\t}\n\t\t\t\toadd.call(this, obj);\n\t\t\t\tobj.emit('add', obj);\n\n\t\t\t\tself.needUpdate = true;\n\t\t\t\tif(self.graph) obj.graph = self.graph;\n\t\t\t\tthis.sort();\n\t\t\t\treturn obj;\n\t\t\t}\n\t\t};\n\t\tthis.children.oremove= this.children.remove;\n\t\t\n\t\tthis.children.remove = function(obj) {\n\t\t\tif(typeof obj === 'object') {\n\t\t\t\tobj.parent = null;\n\t\t\t\tobj.graph = null;\n\t\t\t\tobj.remove(true);\n\t\t\t\tthis.oremove(obj);\n\t\t\t\tself.needUpdate = true;\n\t\t\t}\n\t\t};\n\t\t\n\t\tthis.children.sort = function() {\n\t\t\tconst levelItems = {};\n\t\t\tthis.each(function(i, obj) {\n\t\t\t\tif(!obj) return;\n\t\t\t\tlet zindex = obj.zIndex;\n\t\t\t\tif(!zindex && obj.style && obj.style.zIndex) {\n\t\t\t\t\tzindex = Number(obj.style.zIndex);\n\t\t\t\t\tif(isNaN(zindex)) zindex=obj.style.zIndex||0;\n\t\t\t\t}\n\t\t\t\tlet items = levelItems[zindex] || (levelItems[zindex] = []);\n\t\t\t\titems.push(obj);\n\t\t\t});\n\n\t\t\tthis.splice(0, this.length);\n\t\t\t\n\t\t\tfor(let index in levelItems) {\n\t\t\t\toadd.call(this, levelItems[index]);\n\t\t\t}\n\t\t}\n\t\tthis.children.clear = function() {\n\t\t\tthis.each(function(i,obj) {\n\t\t\t\tthis.remove(obj);\n\t\t\t},true);\n\t\t}\n\t\tthis.needUpdate = true;\n\t} \n\n\tsetStyle(style) {\n\t\tif(!style) {\n\t\t\tstyle = this.style;\n\t\t}\n\t\tif(!style) return;\n\n\t\tconst __setStyle = (style, name, mpkey) => {\n\t\t\tif(style) {\n\t\t\t\tlet styleValue = style;\n\t\t\t\tif(typeof styleValue === 'function') {\n\t\t\t\t\ttry {\n\t\t\t\t\t\tstyleValue = styleValue.call(this);\n\t\t\t\t\t}\n\t\t\t\t\tcatch(e) {\n\t\t\t\t\t\tconsole.warn(e);\n\t\t\t\t\t\treturn;\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\tlet t = typeof styleValue;\n\t\t\t\tlet mpname = jmStyleMap[mpkey || name];\n\n\t\t\t\tif((styleValue instanceof jmGradient) || (t == 'string' && styleValue.indexOf('-gradient') > -1)) {\n\t\t\t\t\tif(t == 'string' && styleValue.indexOf('-gradient') > -1) {\n\t\t\t\t\t\tstyleValue = new jmGradient(styleValue);\n\t\t\t\t\t}\n\t\t\t\t\t__setStyle(styleValue.toGradient(this), mpname||name);\n\t\t\t\t}\n\t\t\t\telse if(mpname) {\n\t\t\t\t\tif(this.webglControl) {\n\t\t\t\t\t\tthis.webglControl.setStyle(mpname, styleValue);\n\t\t\t\t\t}\n\t\t\t\t\telse {\n\t\t\t\t\t\tif(t == 'string' && ['fillStyle', 'strokeStyle', 'shadowColor'].indexOf(mpname) > -1) {\n\t\t\t\t\t\t\tstyleValue = jmUtils.toColor(styleValue);\n\t\t\t\t\t\t}\n\t\t\t\t\t\tthis.context[mpname] = styleValue;\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\telse {\n\t\t\t\t\tswitch(name) {\n\t\t\t\t\t\tcase 'shadow' : {\n\t\t\t\t\t\t\tif(t == 'string') {\n\t\t\t\t\t\t\t\t__setStyle(new jmShadow(styleValue), name);\n\t\t\t\t\t\t\t\tbreak;\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\tfor(let k in styleValue) {\n\t\t\t\t\t\t\t\t__setStyle(styleValue[k], k, name + '.' + k);\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\tbreak;\n\t\t\t\t\t\t}\n\t\t\t\t\t\tcase 'translate' : {\n\t\t\t\t\t\t\tbreak;\n\t\t\t\t\t\t}\n\t\t\t\t\t\tcase 'rotation' : {\n\t\t\t\t\t\t\tif(typeof styleValue.angle === 'undefined' || isNaN(styleValue.angle)) break;\n\t\t\t\t\t\t\tstyleValue = this.getRotation(styleValue);\n\t\t\t\t\t\t\t\n\t\t\t\t\t\t\tthis.__translateAbsolutePosition = this.toAbsolutePoint({\n\t\t\t\t\t\t\t\tx: styleValue.x,\n\t\t\t\t\t\t\t\ty: styleValue.y\n\t\t\t\t\t\t\t});\n\t\t\t\t\t\t\tthis.context.translate && this.context.translate(this.__translateAbsolutePosition.x, this.__translateAbsolutePosition.y);\n\t\t\t\t\t\t\tthis.context.rotate && this.context.rotate(styleValue.angle);\n\t\t\t\t\t\t\tthis.context.translate && this.context.translate(-this.__translateAbsolutePosition.x, -this.__translateAbsolutePosition.y);\n\t\t\t\t\t\t\tbreak;\n\t\t\t\t\t\t}\n\t\t\t\t\t\tcase 'transform' : {\n\t\t\t\t\t\t\tif(!this.context.transform) break;\n\t\t\t\t\t\t\tif(Array.isArray(styleValue)) {\n\t\t\t\t\t\t\t\tthis.context.transform.apply(this.context, styleValue);\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\telse if(typeof styleValue == 'object') {\n\t\t\t\t\t\t\t\tthis.context.transform(\n\t\t\t\t\t\t\t\t\tstyleValue.scaleX || 1,\n\t\t\t\t\t\t\t\t\tstyleValue.skewX || 0,\n\t\t\t\t\t\t\t\t\tstyleValue.skewY || 0,\n\t\t\t\t\t\t\t\t\tstyleValue.scaleY || 1,\n\t\t\t\t\t\t\t\t\tstyleValue.offsetX || 0,\n\t\t\t\t\t\t\t\t\tstyleValue.offsetY || 0\n\t\t\t\t\t\t\t\t);\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\tbreak;\n\t\t\t\t\t\t}\n\t\t\t\t\t\tcase 'cursor' : {\n\t\t\t\t\t\t\tthis.cursor = styleValue;\n\t\t\t\t\t\t\tbreak;\n\t\t\t\t\t\t}\n\t\t\t\t\t\t// ===== 新增样式特性 =====\n\n\t\t\t\t\t\t// 虚线样式:支持自定义lineDash模式 (如 [5, 3, 2] 或 \"5,3,2\")\n\t\t\t\t\t\tcase 'lineDash' : {\n\t\t\t\t\t\t\tif(!this.context.setLineDash) break;\n\t\t\t\t\t\t\tlet dash;\n\t\t\t\t\t\t\tif(typeof styleValue === 'string') {\n\t\t\t\t\t\t\t\tdash = styleValue.split(',').map(v => parseFloat(v.trim())).filter(v => !isNaN(v));\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\telse if(Array.isArray(styleValue)) {\n\t\t\t\t\t\t\t\tdash = styleValue.map(v => parseFloat(v)).filter(v => !isNaN(v));\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\tif(dash && dash.length) {\n\t\t\t\t\t\t\t\tthis.context.setLineDash(dash);\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\telse {\n\t\t\t\t\t\t\t\tthis.context.setLineDash([]);\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\tbreak;\n\t\t\t\t\t\t}\n\t\t\t\t\t\t// 虚线偏移量\n\t\t\t\t\t\tcase 'lineDashOffset' : {\n\t\t\t\t\t\t\tif(!this.context.setLineDash) break;\n\t\t\t\t\t\t\tthis.context.lineDashOffset = Number(styleValue) || 0;\n\t\t\t\t\t\t\tbreak;\n\t\t\t\t\t\t}\n\t\t\t\t\t\t// CSS滤镜效果 (blur, grayscale, sepia, brightness, contrast, saturate, hue-rotate, invert, opacity)\n\t\t\t\t\t\tcase 'filter' : {\n\t\t\t\t\t\t\tif(this.context.filter === undefined) break;\n\t\t\t\t\t\t\tif(styleValue instanceof jmFilter) {\n\t\t\t\t\t\t\t\tthis.context.filter = styleValue.toCanvasFilter();\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\telse if(typeof styleValue === 'string') {\n\t\t\t\t\t\t\t\tthis.context.filter = styleValue || 'none';\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\telse if(typeof styleValue === 'object') {\n\t\t\t\t\t\t\t\tthis.context.filter = (new jmFilter(styleValue)).toCanvasFilter();\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\tbreak;\n\t\t\t\t\t\t}\n\t\t\t\t\t\t// 混合模式 (source-over, multiply, screen, overlay, darken, lighten, etc.)\n\t\t\t\t\t\tcase 'globalCompositeOperation' : {\n\t\t\t\t\t\t\tif(!this.context.globalCompositeOperation) break;\n\t\t\t\t\t\t\tthis.context.globalCompositeOperation = styleValue;\n\t\t\t\t\t\t\tbreak;\n\t\t\t\t\t\t}\n\t\t\t\t\t\t// 裁剪路径:通过canvas clip实现\n\t\t\t\t\t\tcase 'clipPath' : {\n\t\t\t\t\t\t\tif(!this.context.clip) break;\n\t\t\t\t\t\t\t// clipPath可以是一个图形控件实例\n\t\t\t\t\t\t\tif(styleValue && styleValue.points && styleValue.points.length > 0) {\n\t\t\t\t\t\t\t\tconst bounds = this.parent && this.parent.absoluteBounds ? this.parent.absoluteBounds : this.absoluteBounds;\n\t\t\t\t\t\t\t\tthis.context.beginPath();\n\t\t\t\t\t\t\t\tthis.context.moveTo(styleValue.points[0].x + (bounds ? bounds.left : 0), styleValue.points[0].y + (bounds ? bounds.top : 0));\n\t\t\t\t\t\t\t\tfor(let i = 1; i < styleValue.points.length; i++) {\n\t\t\t\t\t\t\t\t\tif(styleValue.points[i].m) {\n\t\t\t\t\t\t\t\t\t\tthis.context.moveTo(styleValue.points[i].x + (bounds ? bounds.left : 0), styleValue.points[i].y + (bounds ? bounds.top : 0));\n\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t\telse {\n\t\t\t\t\t\t\t\t\t\tthis.context.lineTo(styleValue.points[i].x + (bounds ? bounds.left : 0), styleValue.points[i].y + (bounds ? bounds.top : 0));\n\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\tif(styleValue.style && styleValue.style.close) {\n\t\t\t\t\t\t\t\t\tthis.context.closePath();\n\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\tthis.context.clip();\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\tbreak;\n\t\t\t\t\t\t}\n\t\t\t\t\t\t// 遮罩效果:通过globalCompositeOperation + destination-in实现\n\t\t\t\t\t\tcase 'mask' : {\n\t\t\t\t\t\t\tif(!this.context.globalCompositeOperation) break;\n\t\t\t\t\t\t\t// mask是一个图形控件实例,在绘制前需要先应用mask\n\t\t\t\t\t\t\t// 这里只是标记,实际绘制在paint流程中处理\n\t\t\t\t\t\t\tthis.__mask = styleValue;\n\t\t\t\t\t\t\tbreak;\n\t\t\t\t\t\t}\n\t\t\t\t\t\t// 图片阴影描边阴影(WebGL纹理canvas用)\n\t\t\t\t\t\tcase 'shadowColor' : {\n\t\t\t\t\t\t\tif(this.webglControl) {\n\t\t\t\t\t\t\t\tthis.webglControl.setStyle('shadowColor', styleValue);\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\telse {\n\t\t\t\t\t\t\t\tthis.context.shadowColor = jmUtils.toColor(styleValue);\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\tbreak;\n\t\t\t\t\t\t}\n\t\t\t\t\t\tcase 'shadowBlur' : {\n\t\t\t\t\t\t\tif(this.webglControl) {\n\t\t\t\t\t\t\t\tthis.webglControl.setStyle('shadowBlur', styleValue);\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\telse {\n\t\t\t\t\t\t\t\tthis.context.shadowBlur = Number(styleValue) || 0;\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\tbreak;\n\t\t\t\t\t\t}\n\t\t\t\t\t\tcase 'shadowOffsetX' : {\n\t\t\t\t\t\t\tif(this.webglControl) {\n\t\t\t\t\t\t\t\tthis.webglControl.setStyle('shadowOffsetX', styleValue);\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\telse {\n\t\t\t\t\t\t\t\tthis.context.shadowOffsetX = Number(styleValue) || 0;\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\tbreak;\n\t\t\t\t\t\t}\n\t\t\t\t\t\tcase 'shadowOffsetY' : {\n\t\t\t\t\t\t\tif(this.webglControl) {\n\t\t\t\t\t\t\t\tthis.webglControl.setStyle('shadowOffsetY', styleValue);\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\telse {\n\t\t\t\t\t\t\t\tthis.context.shadowOffsetY = Number(styleValue) || 0;\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\tbreak;\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\tif(this.translate) {\n\t\t\t__setStyle(this.translate, 'translate');\n\t\t}\n\t\tif(this.transform) {\n\t\t\t__setStyle(this.transform, 'transform');\n\t\t}\n\t\tfor(let k in style) {\n\t\t\tif(k === 'constructor') continue;\n\t\t\tlet t = typeof style[k];\n\t\t\tif(t == 'string' && style[k].indexOf('-gradient') > -1) {\n\t\t\t\tstyle[k] = new jmGradient(style[k]);\n\t\t\t}\n\t\t\telse if(t == 'string' && k == 'shadow') {\n\t\t\t\tstyle[k] = new jmShadow(style[k]);\n\t\t\t}\n\t\t\telse if(t == 'string' && k == 'filter') {\n\t\t\t\tstyle[k] = new jmFilter(style[k]);\n\t\t\t}\n\t\t\t__setStyle(style[k], k);\n\t\t}\n\t}\n\n\t/**\n\t * 获取当前控件的边界\n\t * 通过分析控件的描点或位置加宽高得到为方形的边界\n\t *\n\t * @method getBounds\n\t * @for jmControl\n\t * @param {boolean} [isReset=false] 是否强制重新计算\n\t * @return {object} 控件的边界描述对象(left,top,right,bottom,width,height)\n\t */\n\tgetBounds(isReset) {\n\t\t//如果当次计算过,则不重复计算\n\t\tif(this.bounds && !isReset) return this.bounds;\n\n\t\tconst rect = {}; // left top\n\t\t//jmGraph,特殊处理\n\t\tif(this.type == 'jmGraph' && this.canvas) {\n\t\t\tif(typeof this.canvas.width === 'function') {\n\t\t\t\trect.right = this.canvas.width(); \n\t\t\t}\n\t\t\telse if(this.width) {\n\t\t\t\trect.right = this.width;\n\t\t\t}\n\t\t\t\n\t\t\tif(typeof this.canvas.height === 'function') {\n\t\t\t\trect.bottom = this.canvas.height(); \n\t\t\t}\n\t\t\telse if(this.height) {\n\t\t\t\trect.bottom = this.height;\n\t\t\t}\n\t\t}\n\t\telse if(this.points && this.points.length > 0) {\t\t\n\t\t\tfor(const p of this.points) {\n\t\t\t\tif(typeof rect.left === 'undefined' || rect.left > p.x) {\n\t\t\t\t\trect.left = p.x;\n\t\t\t\t}\n\t\t\t\tif(typeof rect.top === 'undefined' || rect.top > p.y) {\n\t\t\t\t\trect.top = p.y;\n\t\t\t\t}\n\n\t\t\t\tif(typeof rect.right === 'undefined' || rect.right < p.x) {\n\t\t\t\t\trect.right = p.x;\n\t\t\t\t}\n\t\t\t\tif(typeof rect.bottom === 'undefined' || rect.bottom < p.y) {\n\t\t\t\t\trect.bottom = p.y;\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t\telse if(this.getLocation) {\n\t\t\tlet p = this.getLocation();\n\t\t\tif(p) {\n\t\t\t\trect.left = p.left;\n\t\t\t\trect.top = p.top;\n\t\t\t\trect.right = p.left + p.width;\n\t\t\t\trect.bottom = p.top + p.height;\n\t\t\t}\t\t\n\t\t}\n\t\tif(!rect.left) rect.left = 0; \n\t\tif(!rect.top) rect.top = 0; \n\t\tif(!rect.right) rect.right = 0; \n\t\tif(!rect.bottom) rect.bottom = 0; \n\t\trect.width = rect.right - rect.left;\n\t\trect.height = rect.bottom - rect.top;\n\t\t\n\t\treturn this.bounds=rect;\n\t}\n\n\t/**\n\t * 获取被旋转后的边界\n\t */\n\tgetRotationBounds(rotation=null) {\n\t\trotation = rotation || this.getRotation();\n\t\tconst bounds = this.getBounds();\n\t\tif(!rotation || !rotation.angle) return bounds;\n\n\t\tconst rect = {\n\t\t\twidth: 0,\n\t\t\theight: 0,\n\t\t\toldBounds: bounds\n\t\t}; // left top\n\t\tlet points = [];\n\t\tif(this.points && this.points.length > 0) {\t\n\t\t\tpoints = jmUtils.clone(this.points, true); // 深度拷贝\t\t\t\n\t\t}\n\t\telse if(this.getLocation) {\n\t\t\tconst local = this.getLocation();\n\t\t\tif(local) {\n\t\t\t\tpoints.push({\n\t\t\t\t\tx: local.left,\n\t\t\t\t\ty: local.top\n\t\t\t\t},{\n\t\t\t\t\tx: local.left + local.width,\n\t\t\t\t\ty: local.top\n\t\t\t\t},{\n\t\t\t\t\tx: local.left + local.width,\n\t\t\t\t\ty: local.top + local.height\n\t\t\t\t},{\n\t\t\t\t\tx: local.left,\n\t\t\t\t\ty: local.top + local.height\n\t\t\t\t});\n\t\t\t}\t\t\n\t\t}\n\t\tpoints = jmUtils.rotatePoints(points, {\n\t\t\tx: rotation.x + bounds.left,\n\t\t\ty: rotation.y + bounds.top\n\t\t}, rotation.angle);// 对现在点进行旋转\n\n\t\tfor(const p of points) {\n\t\t\tif(typeof rect.left === 'undefined' || rect.left > p.x) {\n\t\t\t\trect.left = p.x;\n\t\t\t}\n\t\t\tif(typeof rect.top === 'undefined' || rect.top > p.y) {\n\t\t\t\trect.top = p.y;\n\t\t\t}\n\n\t\t\tif(typeof rect.right === 'undefined' || rect.right < p.x) {\n\t\t\t\trect.right = p.x;\n\t\t\t}\n\t\t\tif(typeof rect.bottom === 'undefined' || rect.bottom < p.y) {\n\t\t\t\trect.bottom = p.y;\n\t\t\t}\n\t\t}\n\n\t\tif(!rect.left) rect.left = 0; \n\t\tif(!rect.top) rect.top = 0; \n\t\tif(!rect.right) rect.right = 0; \n\t\tif(!rect.bottom) rect.bottom = 0; \n\n\t\trect.width = rect.right - rect.left;\n\t\trect.height = rect.bottom - rect.top;\n\n\t\treturn rect;\n\t}\n\n\t/**\n\t * 获取当前控件的位置相关参数\n\t * 解析百分比和margin参数\n\t *\n\t * @method getLocation\n\t * @return {object} 当前控件位置参数,包括中心点坐标,右上角坐标,宽高\n\t */\n\tgetLocation() {\n\t\t//如果已经计算过则直接返回\n\t\t//在开画之前会清空此对象\n\t\t//if(reset !== true && this.location) return this.location;\n\n\t\tlet local = this.location = {left: 0,top: 0,width: 0,height: 0};\n\n\t\t// 检查是否有百分比参数需要解析,没有则直接引用避免克隆开销\n\t\tconst needResolve = this.parent && (jmUtils.checkPercent(this.width) || jmUtils.checkPercent(this.height) ||\n\t\t\t(this.position && jmUtils.checkPercent(this.position.x)) || (this.position && jmUtils.checkPercent(this.position.y)));\n\t\tlocal.position = typeof this.position == 'function'? this.position(): (needResolve? jmUtils.clone(this.position) : this.position);\t\n\t\tlocal.center = this.center && typeof this.center === 'function'?this.center(): (needResolve? jmUtils.clone(this.center) : this.center);//中心\n\t\tlocal.start = this.start && typeof this.start === 'function'?this.start(): (needResolve? jmUtils.clone(this.start) : this.start);//起点\n\t\tlocal.end = this.end && typeof this.end === 'function'?this.end(): (needResolve? jmUtils.clone(this.end) : this.end);//起点\n\t\tlocal.radius = this.radius;//半径\n\t\tlocal.width = this.width;\n\t\tlocal.height = this.height;\n\n\t\tconst margin = this.style.margin;\n\t\tconst marginObj = needResolve && margin ? jmUtils.clone(margin, {}) : (margin || {});\n\t\tmarginObj.left = (marginObj.left || 0);\n\t\tmarginObj.top = (marginObj.top || 0);\n\t\tmarginObj.right = (marginObj.right || 0);\n\t\tmarginObj.bottom = (marginObj.bottom || 0);\n\t\t\n\t\t//如果没有指定位置,但指定了margin。则位置取margin偏移量\n\t\tif(local.position) {\n\t\t\tlocal.left = local.position.x;\n\t\t\tlocal.top = local.position.y;\n\t\t}\n\t\telse {\n\t\t\tlocal.left = marginObj.left;\n\t\t\tlocal.top = marginObj.top;\n\t\t}\n\n\t\tif(this.parent) {\n\t\t\tconst parentBounds = this.parent.getBounds();\t\n\n\t\t\t//处理百分比参数\n\t\t\tif(jmUtils.checkPercent(local.left)) {\n\t\t\t\tlocal.left = jmUtils.percentToNumber(local.left) * parentBounds.width;\n\t\t\t}\n\t\t\tif(jmUtils.checkPercent(local.top)) {\n\t\t\t\tlocal.top = jmUtils.percentToNumber(local.top) * parentBounds.height;\n\t\t\t}\n\t\t\t\n\t\t\t//如果没有指定宽度或高度,则按百分之百计算其父宽度或高度\n\t\t\tif(jmUtils.checkPercent(local.width)) {\n\t\t\t\tlocal.width = jmUtils.percentToNumber(local.width) * parentBounds.width;\n\t\t\t}\n\t\t\tif(jmUtils.checkPercent(local.height)) {\n\t\t\t\tlocal.height = jmUtils.percentToNumber(local.height) * parentBounds.height;\n\t\t\t}\n\t\t\t//处理中心点\n\t\t\tif(local.center) {\n\t\t\t\t//处理百分比参数\n\t\t\t\tif(jmUtils.checkPercent(local.center.x)) {\n\t\t\t\t\tlocal.center.x = jmUtils.percentToNumber(local.center.x) * parentBounds.width;\n\t\t\t\t}\n\t\t\t\tif(jmUtils.checkPercent(local.center.y)) {\n\t\t\t\t\tlocal.center.y = jmUtils.percentToNumber(local.center.y) * parentBounds.height;\n\t\t\t\t}\n\t\t\t}\n\t\t\tif(local.radius) {\n\t\t\t\t//处理百分比参数\n\t\t\t\tif(jmUtils.checkPercent(local.radius)) {\n\t\t\t\t\tlocal.radius = jmUtils.percentToNumber(local.radius) * Math.min(parentBounds.width, parentBounds.height);\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t\treturn local;\n\t}\n\n\t/**\n\t * 获取当前控制的旋转信息\n\t * @returns {object} 旋转中心和角度\n\t */\n\tgetRotation(rotation, bounds = null) {\n\t\trotation = rotation || jmUtils.clone(this.style.rotation);\n\n\t\tif(!rotation) {\n\t\t\t//如果本身没有,则可以继承父级的\n\t\t\trotation = this.parent && this.parent.getRotation?this.parent.getRotation():null;\n\t\t\t//如果父级有旋转,则把坐标转换为当前控件区域\n\t\t\tif(rotation) {\n\t\t\t\tbounds = bounds || this.getBounds();\n\t\t\t\trotation.x -= bounds.left;\n\t\t\t\trotation.y -= bounds.top;\n\t\t\t}\n\t\t}\n\t\telse {\n\t\t\tbounds = bounds || this.getBounds();\n\t\t\tif(typeof rotation.x === 'undefined') rotation.x = '50%';\n\t\t\tif(typeof rotation.y === 'undefined') rotation.y = '50%';\n\t\t\tif(jmUtils.checkPercent(rotation.x)) {\n\t\t\t\trotation.x = jmUtils.percentToNumber(rotation.x) * bounds.width;\n\t\t\t}\n\t\t\tif(jmUtils.checkPercent(rotation.y)) {\n\t\t\t\trotation.y = jmUtils.percentToNumber(rotation.y) * bounds.height;\n\t\t\t}\n\t\t}\n\t\treturn {\n\t\t\t...rotation,\n\t\t\tbounds\n\t\t};\n\n\t}\n\n\t// 计算位移偏移量\n\tgetTranslate(translate, bounds = null) {\n\t\ttranslate = translate || this.style.translate;\n\t\tif(!translate) return {x: 0, y: 0};\n\t\tconst result = {\n\t\t\tx: translate.x || 0,\n\t\t\ty: translate.y || 0\n\t\t}\n\t\t\n\t\tif(jmUtils.checkPercent(result.x)) {\n\t\t\tif(!bounds && this.parent) bounds = this.parent.getBounds();\n\t\t\tresult.x = jmUtils.percentToNumber(result.x) * bounds.width;\n\t\t}\n\t\tif(jmUtils.checkPercent(result.y)) {\n\t\t\tif(!bounds && this.parent) bounds = this.parent.getBounds();\n\t\t\tresult.y = jmUtils.percentToNumber(result.y) * bounds.height;\n\t\t}\n\t\treturn result;\n\t}\n\n\t/**\n\t * 移除当前控件\n\t * 如果是VML元素,则调用其删除元素\n\t *\n\t * @method remove \n\t */\n\tremove() {\t\n\t\tif(this.parent) {\n\t\t\tthis.parent.children.remove(this);\n\t\t}\n\t}\n\n\t/**\n\t * 对控件进行平移\n\t * 遍历控件所有描点或位置,设置其偏移量。\n\t *\n\t * @method offset\n\t * @param {number} x x轴偏移量\n\t * @param {number} y y轴偏移量\n\t * @param {boolean} [trans] 是否传递,监听者可以通过此属性是否决定是否响应移动事件,默认=true\n\t * @param {object} [evt] 如果是事件触发,则传递move事件参数\n\t */\n\toffset(x, y, trans, evt) {\n\t\ttrans = trans === false?false:true;\t\n\t\tlet local = this.getLocation(true);\t\t\n\t\tlet offseted = false;\n\t\t\n\t\tif(local.position) {\n\t\t\tlocal.left += x;\n\t\t\tlocal.top += y;\n\t\t\t// 由于local是clone出来的对象,为了保留位移,则要修改原属性\n\t\t\tthis.position.x = local.left;\n\t\t\tthis.position.y = local.top;\n\t\t\toffseted = true;\n\t\t}\n\n\t\tif(local.center) {\t\t\n\t\t\tthis.center.x = local.center.x + x;\n\t\t\tthis.center.y = local.center.y + y;\n\t\t\toffseted = true;\n\t\t}\n\n\t\tif(local.start && typeof local.start == 'object') {\t\n\t\t\tthis.start.x = local.start.x + x;\n\t\t\tthis.start.y = local.start.y + y;\n\t\t\toffseted = true;\n\t\t}\n\n\t\tif(local.end && typeof local.end == 'object') {\t\t\n\t\t\tthis.end.x = local.end.x + x;\n\t\t\tthis.end.y = local.end.y + y;\n\t\t\toffseted = true;\n\t\t}\n\n\n\t\tif(offseted == false && this.cpoints) {\n\t\t\tlet p = typeof this.cpoints == 'function'?this.cpoints:this.cpoints;\n\t\t\tif(p) {\t\t\t\n\t\t\t\tlet len = p.length;\n\t\t\t\tfor(let i=0; i < len;i++) {\n\t\t\t\t\tp[i].x += x;\n\t\t\t\t\tp[i].y += y;\n\t\t\t\t}\t\t\n\t\t\t\toffseted = true;\n\t\t\t}\t\t\t\n\t\t}\n\t\t\n\t\tif(offseted == false && this.points) {\n\t\t\tlet len = this.points.length;\n\t\t\tfor(let i=0; i < len;i++) {\n\t\t\t\tthis.points[i].x += x;\n\t\t\t\tthis.points[i].y += y;\n\t\t\t}\n\t\t\toffseted = true;\n\t\t}\n\t\t\n\t\t//触发控件移动事件\t\n\t\tthis.emit('move',{\n\t\t\toffsetX: x,\n\t\t\toffsetY: y,\n\t\t\ttrans: trans,\n\t\t\tevt: evt\n\t\t});\n\n\t\tthis.needUpdate = true;\n\t}\n\n\t/**\n\t * 获取控件相对于画布的绝对边界,\n\t * 与getBounds不同的是:getBounds获取的是相对于父容器的边界.\n\t *\n\t * @method getAbsoluteBounds\n\t * @return {object} 边界对象(left,top,right,bottom,width,height)\n\t */\n\tgetAbsoluteBounds() {\n\t\t//当前控件的边界,\n\t\tlet rec = this.getBounds();\n\t\tif(this.parent && this.parent.absoluteBounds) {\n\t\t\t//父容器的绝对边界\n\t\t\tlet prec = this.parent.absoluteBounds || this.parent.getAbsoluteBounds();\n\t\t\t\n\t\t\treturn {\n\t\t\t\tleft : prec.left + rec.left,\n\t\t\t\ttop : prec.top + rec.top,\n\t\t\t\tright : prec.left + rec.right,\n\t\t\t\tbottom : prec.top + rec.bottom,\n\t\t\t\twidth : rec.width,\n\t\t\t\theight : rec.height\n\t\t\t};\n\t\t}\n\t\treturn rec;\n\t}\n\n\t/**\n\t * 把当前控制内部坐标转为canvas绝对定位坐标\n\t * \n\t * @method toAbsolutePoint\n\t * @param {x: number, y: number} 内部坐标\n\t */\n\ttoAbsolutePoint(point) {\n\t\tif(point.x || point.y) {\n\t\t\tconst bounds = this.absoluteBounds?this.absoluteBounds:this.getAbsoluteBounds();\n\t\t\t\n\t\t\tpoint.x = (point.x||0) + bounds.left;\n\t\t\tpoint.y = (point.y||0) + bounds.top;\t\n\t\t}\n\t\treturn point;\n\t}\n\n\t/**\n\t * 把绝对定位坐标转为当前控件坐标系内\n\t * @param {*} point \n\t */\n\ttoLocalPosition(point) {\n\t\t\n\t\tconst bounds = this.absoluteBounds?this.absoluteBounds:this.getAbsoluteBounds();\n\t\tif(!bounds) return false;\t\n\t\treturn { \n\t\t\tx: point.x - bounds.left,\n\t\t\ty: point.y - bounds.top\n\t\t};\n\t}\n\n\t/**\n\t * 画控件前初始化\n\t * 执行beginPath开始控件的绘制\n\t * \n\t * @method beginDraw\n\t */\n\tbeginDraw() {\t\n\t\tthis.getLocation(true);//重置位置信息\n\t\tthis.context.beginPath && this.context.beginPath();\t\t\n\t\tif(this.webglControl && this.webglControl.beginDraw) this.webglControl.beginDraw();\n\t}\n\n\t/**\n\t * 结束控件绘制\n\t *\n\t * @method endDraw\n\t */\n\tendDraw() {\n\t\t//如果当前为封闭路径\n\t\tif(this.style.close) {\n\t\t\tif(this.webglControl) this.webglControl.closePath();\n\t\t\tthis.context.closePath && this.context.closePath();\n\t\t}\n\n\t\t// 根据渲染模式选择不同的绘制路径\n\t\tif(this.webglControl) {\n\t\t\t// WebGL 模式:使用 WebGL 绘制\n\t\t\tconst fill = this.style['fill'] || this.style['fillStyle'];\n\t\t\tif(fill) {\n\t\t\t\tconst bounds = this.getBounds();\n\t\t\t\tthis.webglControl.fill(bounds);\n\t\t\t}\n\t\t\tif(this.style['stroke'] || (!fill && !this.is('jmGraph'))) {\n\t\t\t\tthis.webglControl.stroke();\n\t\t\t}\n\t\t\tif(this.webglControl.endDraw) this.webglControl.endDraw();\n\t\t}\n\t\telse {\n\t\t\t// 2D 模式:使用 Canvas 2D API 绘制\n\t\t\tconst fill = this.style['fill'] || this.style['fillStyle'];\n\t\t\tif(fill) {\n\t\t\t\tthis.context.fill && this.context.fill();\n\t\t\t}\n\t\t\tif(this.style['stroke'] || (!fill && !this.is('jmGraph'))) {\n\t\t\t\tthis.context.stroke && this.context.stroke();\n\t\t\t}\n\t\t}\n\n\t\tthis.needUpdate = false;\n\t}\n\n\t/**\n\t * 绘制控件\n\t * 在画布上描点\n\t * \n\t * @method draw\n\t */\n\tdraw() {\t\n\t\tif(this.points && this.points.length > 0) {\n\t\t\t//获取当前控件的绝对位置\n\t\t\tconst bounds = this.parent && this.parent.absoluteBounds?this.parent.absoluteBounds:this.absoluteBounds;\n\t\t\tif(this.webglControl) {\n\t\t\t\tthis.webglControl.setParentBounds(bounds);\n\t\t\t\tthis.webglControl.draw(this.points);\n\t\t\t}\n\t\t\telse if(this.context && this.context.moveTo) {\n\t\t\t\tthis.context.moveTo(this.points[0].x + bounds.left,this.points[0].y + bounds.top);\n\t\t\t\tlet len = this.points.length;\t\t\t\n\t\t\t\tfor(let i=1; i < len;i++) {\n\t\t\t\t\tlet p = this.points[i];\n\t\t\t\t\t//移至当前坐标\n\t\t\t\t\tif(p.m) {\n\t\t\t\t\t\tthis.context.moveTo(p.x + bounds.left,p.y + bounds.top);\n\t\t\t\t\t}\n\t\t\t\t\telse {\n\t\t\t\t\t\tthis.context.lineTo(p.x+ bounds.left,p.y + bounds.top);\n\t\t\t\t\t}\t\t\t\n\t\t\t\t}\t\n\t\t\t}\t\n\t\t}\t\n\t}\n\n\t/**\n\t * 绘制当前控件\n\t * 协调控件的绘制,先从其子控件开始绘制,再往上冒。\n\t *\n\t * @method paint\n\t */\n\tpaint(v) {\n\t\tif(v !== false && this.visible !== false) {\t\t\n\t\t\tif(this.initPoints) this.initPoints();\n\t\t\t//计算当前边界\n\t\t\tthis.bounds = null;\n\t\t\tthis.absoluteBounds = this.getAbsoluteBounds();\n\t\t\tlet needDraw = true;//是否需要绘制\n\t\t\tif(!this.is('jmGraph') && this.graph) {\n\t\t\t\tif(this.absoluteBounds.left >= this.graph.width) needDraw = false;\n\t\t\t\telse if(this.absoluteBounds.top >= this.graph.height) needDraw = false;\n\t\t\t\telse if(this.absoluteBounds.right <= 0) needDraw = false;\n\t\t\t\telse if(this.absoluteBounds.bottom <= 0) needDraw = false;\n\t\t\t}\n\t\t\t\n\t\t\tthis.context.save && this.context.save();\n\n\t\t\tthis.emit('beginDraw', this);\n\t\t\t\n\t\t\tthis.setStyle();//设定样式\n\n\t\t\t// 应用mask遮罩效果:在mask区域内绘制当前控件\n\t\t\t// 使用 destination-in 合成模式,只保留mask区域内的内容\n\t\t\tconst maskStyle = this.style.mask || this.__mask;\n\t\t\tif(maskStyle && maskStyle.points && this.context.globalCompositeOperation) {\n\t\t\t\t// 先绘制当前控件\n\t\t\t\tif(needDraw && this.beginDraw) this.beginDraw();\n\t\t\t\tif(needDraw && this.draw) this.draw();\t\n\t\t\t\tif(needDraw && this.endDraw) this.endDraw();\n\n\t\t\t\t// 再应用mask裁剪\n\t\t\t\tthis.context.globalCompositeOperation = 'destination-in';\n\t\t\t\tif(maskStyle.initPoints) maskStyle.initPoints();\n\t\t\t\tconst mBounds = maskStyle.parent && maskStyle.parent.absoluteBounds ? maskStyle.parent.absoluteBounds : this.absoluteBounds;\n\t\t\t\tthis.context.beginPath();\n\t\t\t\tif(maskStyle.points && maskStyle.points.length > 0) {\n\t\t\t\t\tthis.context.moveTo(maskStyle.points[0].x + (mBounds ? mBounds.left : 0), maskStyle.points[0].y + (mBounds ? mBounds.top : 0));\n\t\t\t\t\tfor(let i = 1; i < maskStyle.points.length; i++) {\n\t\t\t\t\t\tif(maskStyle.points[i].m) {\n\t\t\t\t\t\t\tthis.context.moveTo(maskStyle.points[i].x + (mBounds ? mBounds.left : 0), maskStyle.points[i].y + (mBounds ? mBounds.top : 0));\n\t\t\t\t\t\t}\n\t\t\t\t\t\telse {\n\t\t\t\t\t\t\tthis.context.lineTo(maskStyle.points[i].x + (mBounds ? mBounds.left : 0), maskStyle.points[i].y + (mBounds ? mBounds.top : 0));\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t\tif(maskStyle.style && maskStyle.style.close) {\n\t\t\t\t\t\tthis.context.closePath();\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\tthis.context.fillStyle = '#ffffff';\n\t\t\t\tthis.context.fill();\n\t\t\t\t// 恢复合成模式\n\t\t\t\tthis.context.globalCompositeOperation = 'source-over';\n\t\t\t}\n\t\t\telse {\n\t\t\t\tif(needDraw && this.beginDraw) this.beginDraw();\n\t\t\t\tif(needDraw && this.draw) this.draw();\t\n\t\t\t\tif(needDraw && this.endDraw) this.endDraw();\n\t\t\t}\n\n\t\t\tif(this.children) {\n\t\t\t\tthis.children.each(function(i,item) {\n\t\t\t\t\tif(item && item.paint) item.paint();\n\t\t\t\t});\n\t\t\t}\n\n\t\t\tthis.emit('endDraw',this);\t\n\t\t\tthis.context.restore && this.context.restore();\n\t\t\t\n\t\t\tthis.needUpdate = false;\n\t\t}\n\t}\n\n\t/**\n\t * 获取指定事件的集合\n\t * 比如mousedown,mouseup等\n\t *\n\t * @method getEvent\n\t * @param {string} name 事件名称\n\t * @return {list} 事件委托的集合\n\t */\n\tgetEvent(name) {\t\t\n\t\treturn this.__events?this.__events[name]:null;\n\t}\n\n\t/**\n\t * 绑定控件的事件\n\t *\n\t * @method bind\n\t * @param {string} name 事件名称\n\t * @param {function} handle 事件委托\n\t */\n\tbind(name, handle) {\t\n\t\tif(name && name.indexOf(' ') > -1) {\n\t\t\tname = name.split(' ');\n\t\t\tfor(let n of name) {\n\t\t\t\tn && this.bind(n, handle);\n\t\t\t}\n\t\t\treturn;\n\t\t}\t\n\t\t/**\n\t\t * 添加事件的集合\n\t\t *\n\t\t * @method _setEvent\n\t\t * @private\n\t\t */\n\t\tfunction _setEvent(name, events) {\n\t\t\tif(!this.__events) this.__events = {};\n\t\t\treturn this.__events[name] = events;\n\t\t}\n\t\tlet eventCollection = this.getEvent(name) || _setEvent.call(this, name, new jmList());\n\t\tif(!eventCollection.contain(handle)) {\n\t\t\teventCollection.add(handle);\n\t\t}\n\t}\n\n\t/**\n\t * 移除控件的事件\n\t *\n\t * @method unbind \n\t * @param {string} name 事件名称\n\t * @param {function} handle 从控件中移除事件的委托\n\t */\n\tunbind(name, handle) {\t\n\t\tif(name && name.indexOf(' ') > -1) {\n\t\t\tname = name.split(' ');\n\t\t\tfor(let n of name) {\n\t\t\t\tn && this.unbind(n, handle);\n\t\t\t}\n\t\t\treturn;\n\t\t}\t\n\t\tlet eventCollection = this.getEvent(name) ;\t\t\n\t\tif(eventCollection) {\n\t\t\tif(handle) eventCollection.remove(handle);\n\t\t\telse eventCollection.clear();\n\t\t}\n\t}\n\n\n\t/**\n\t * 执行监听回调\n\t * \n\t * @method emit\n\t * @for jmControl\n\t * @param {string} name 触发事件的名称\n\t * @param {array} args 事件参数数组\n\t */\n\temit(...args) {\t\t\t\n\t\t// 避免每帧 args.slice(1) 分配临时数组\n\t\t// runEventHandle 内部会把非数组参数包装成数组\n\t\tif(args.length > 2) {\n\t\t\tthis.runEventHandle(args[0], args.slice(1));\n\t\t} else if(args.length === 2) {\n\t\t\tthis.runEventHandle(args[0], [args[1]]);\n\t\t} else {\n\t\t\tthis.runEventHandle(args[0], []);\n\t\t}\n\t\treturn this;\n\t}\n\n\t/**\n\t * 独立执行事件委托\n\t *\n\t * @method runEventHandle\n\t * @param {string} 将执行的事件名称\n\t * @param {object} 事件执行的参数,包括触发事件的对象和位置\n\t */\n\trunEventHandle(name, args) {\n\t\tlet events = this.getEvent(name);\t\t\n\t\tif(events) {\n\t\t\tvar self = this;\n\t\t\tif(!Array.isArray(args)) args = [args];\t\n\t\t\tevents.each(function(i, handle) {\n\t\t\t\t//只要有一个事件被阻止,则不再处理同级事件,并设置冒泡被阻断\n\t\t\t\tif(false === handle.apply(self, args)) {\n\t\t\t\t\targs.cancel = true;\n\t\t\t\t}\n\t\t\t});\t\t\n\t\t}\t\n\t\treturn args.cancel;\n\t}\n\n\t/**\n\t * 检 查坐标是否落在当前控件区域中..true=在区域内\n\t *\n\t * @method checkPoint\n\t * @param {point} p 位置参数\n\t * @param {number} [pad] 可选参数,表示线条多远内都算在线上\n\t * @return {boolean} 当前位置如果在区域内则为true,否则为false。\n\t */\n\tcheckPoint(p, pad) {\n\t\t//jmGraph 需要判断dom位置\n\t\tif(this.type == 'jmGraph') {\n\t\t\t//获取dom位置\n\t\t\tlet position = this.getPosition();\n\t\t\t// 由于高清屏会有放大坐标,所以这里用pagex就只能用真实的canvas大小\n\t\t\tconst right = position.left + this.width;\n\t\t\tconst bottom = position.top + this.height;\n\t\t\tif(p.x > right || p.x < position.left) {\n\t\t\t\treturn false;\n\t\t\t}\n\t\t\tif(p.y > bottom || p.y < position.top) {\n\t\t\t\treturn false;\n\t\t\t}\t\n\t\t\treturn true;\n\t\t}\n\t\t\n\t\tconst bounds = this.getBounds();\t\n\t\t// 如果指定了合中区域,则以命中区域为准\n\t\tif(this.hitArea) {\n\t\t\tconst hitArea = {\n\t\t\t\tleft: this.hitArea.x + bounds.left,\n\t\t\t\ttop: this.hitArea.y + bounds.top,\n\t\t\t\tright: this.hitArea.width + bounds.left,\n\t\t\t\tbottom: this.hitArea.height + bounds.top,\n\t\t\t};\n\t\t\tif(p.x > hitArea.right || p.x < hitArea.left) {\n\t\t\t\treturn false;\n\t\t\t}\n\t\t\tif(p.y > hitArea.bottom || p.y < hitArea.top) {\n\t\t\t\treturn false;\n\t\t\t}\n\t\t\treturn true;\n\t\t}\n\t\t\n\t\tlet ps = this.points;\n\t\t//如果不是路径组成,则采用边界做为顶点\n\t\tif(!ps || !ps.length) {\n\t\t\tps = [];\n\t\t\tps.push({x: bounds.left, y: bounds.top}); //左上角\n\t\t\tps.push({x: bounds.right, y: bounds.top});//右上角\n\t\t\tps.push({x: bounds.right, y: bounds.bottom});//右下角\n\t\t\tps.push({x: bounds.left, y: bounds.bottom}); //左下\n\t\t\tps.push({x: bounds.left, y: bounds.top}); //左上角 //闭合\n\t\t}\n\t\t//如果有指定padding 表示接受区域加宽,命中更易\n\t\tpad = Number(pad || this.style['touchPadding'] || this.style['lineWidth'] || 1);\n\t\tif(ps && ps.length) {\n\t\t\tconst rotation = this.getRotation(null, bounds);//获取当前旋转参数\n\t\t\t//如果有旋转参数,则需要转换坐标再处理\n\t\t\tif(rotation && rotation.angle) {\n\t\t\t\tps = jmUtils.clone(ps, true);//拷贝一份数据\n\t\t\t\t//rotateX ,rotateY 是相对当前控件的位置\n\t\t\t\tps = jmUtils.rotatePoints(ps, {\n\t\t\t\t\tx: rotation.x + bounds.left,\n\t\t\t\t\ty: rotation.y + bounds.top\n\t\t\t\t}, rotation.angle || 0);\n\t\t\t}\n\t\t\t//如果当前路径不是实心的\n\t\t\t//就只用判断点是否在边上即可\t\n\t\t\tif(ps.length > 2 && (!this.style['fill'] || this.style['stroke'])) {\n\t\t\t\tlet i = 0;\n\t\t\t\tconst count = ps.length;\n\t\t\t\tfor(let j = i+1; j <= count; j = (++i + 1)) {\n\t\t\t\t\t//如果j超出最后一个\n\t\t\t\t\t//则当为封闭图形时跟第一点连线处理.否则直接返回false\n\t\t\t\t\tif(j == count) {\n\t\t\t\t\t\tif(this.style.close) {\n\t\t\t\t\t\t\tconst r = jmUtils.pointInPolygon(p,[ps[i],ps[0]], pad);\n\t\t\t\t\t\t\tif(r) return true;\n\t\t\t\t\t\t}\n\t\t\t\t\t} \n\t\t\t\t\telse {\n\t\t\t\t\t\t//判断是否在点i,j连成的线上\n\t\t\t\t\t\tconst s = jmUtils.pointInPolygon(p,[ps[i],ps[j]], pad);\n\t\t\t\t\t\tif(s) return true;\n\t\t\t\t\t}\t\t\t\n\t\t\t\t}\n\t\t\t\t//不是封闭的图形,则直接返回\n\t\t\t\tif(!this.style['fill']) return false;\n\t\t\t}\n\n\t\t\tconst r = jmUtils.pointInPolygon(p,ps, pad);\t\t\n\t\t\treturn r;\n\t\t}\n\n\t\tif(p.x > bounds.right || p.x < bounds.left) {\n\t\t\treturn false;\n\t\t}\n\t\tif(p.y > bounds.bottom || p.y < bounds.top) {\n\t\t\treturn false;\n\t\t}\n\t\t\n\t\treturn true;\n\t}\n\n\n\t/**\n\t * 触发控件事件,组合参数并按控件层级关系执行事件冒泡。\n\t *\n\t * @method raiseEvent\n\t * @param {string} name 事件名称\n\t * @param {object} args 事件执行参数\n\t * @return {boolean} 如果事件被组止冒泡则返回false,否则返回true\n\t */\n\traiseEvent(name, args) {\n\t\tif(this.visible === false) return ;//如果不显示则不响应事件\t\n\t\tif(!args.position) {\t\t\n\t\t\tconst graph = this.graph;\n\t\t\targs.isWXMiniApp = graph.isWXMiniApp;\n\n\t\t\tconst srcElement = args.srcElement || args.target;\t\t\t\n\t\t\t\n\t\t\tconst position = jmUtils.getEventPosition(args);//初始化事件位置\n\t\t\n\t\t\targs = {\n\t\t\t\tposition: position,\n\t\t\t\tbutton: args.button == 0 || position.isTouch? 1: args.button,\n\t\t\t\tkeyCode: args.keyCode || args.charCode || args.which,\n\t\t\t\tctrlKey: args.ctrlKey,\n\t\t\t\tcancel : false,\n\t\t\t\tevent: args, // 原生事件\n\t\t\t\tsrcElement : srcElement,\n\t\t\t\tisWXMiniApp: graph.isWXMiniApp,\n\t\t\t};\t\t\n\t\t}\n\t\targs.path = args.path||[]; //事件冒泡路径\n\n\t\t//先执行子元素事件,如果事件没有被阻断,则向上冒泡\n\t\tlet stoped = false;\n\t\tif(this.children) {\n\t\t\tthis.children.each(function(j, el) {\n\t\t\t\t//未被阻止才执行\t\t\t\n\t\t\t\tif(args.cancel !== true) {\n\t\t\t\t\t//如果被阻止冒泡,\n\t\t\t\t\tstoped = el.raiseEvent(name, args) === false? true: stoped;\n\t\t\t\t\t// 不再响应其它元素\n\t\t\t\t\tif(stoped) return false;\n\t\t\t\t}\n\t\t\t}, true);//按逆序处理\n\t\t}\n\t\t// 如果已被阻止,不再响应上级事件\n\t\tif(stoped) return false;\n\t\t\n\t\t//获取当前对象的父元素绝对位置\n\t\t//生成当前坐标对应的父级元素的相对位置\n\t\tlet abounds = this.parent && this.parent.absoluteBounds?this.parent.absoluteBounds : this.absoluteBounds;\n\t\tif(!abounds) return false;\t\n\t\t//args = jmUtils.clone(args);//参数副本\n\t\targs.position.x = args.position.offsetX - abounds.left;\n\t\targs.position.y = args.position.offsetY - abounds.top;\n\n\t\t// 是否在当前控件内操作\n\t\tconst inpos = this.interactive !== false && this.checkPoint(args.position);\n\t\t\n\t\t//事件发生在边界内或健盘事件发生在画布中才触发\n\t\tif(inpos) {\n\t\t\t//如果没有指定触发对象,则认为当前为第一触发对象\n\t\t\tif(!args.target) {\n\t\t\t\targs.target = this;\n\t\t\t}\n\t\t\t\n\t\t\tthis.runEventAndPopEvent(name, args);\n\n\t\t\tif(!this.focused && (name === 'mousemove' || name === 'touchmove')) {\n\t\t\t\tthis.focused = true;//表明当前焦点在此控件中\n\t\t\t\tthis.raiseEvent(name === 'mousemove'? 'mouseover': 'touchover', args);\n\t\t\t}\t\n\t\t}\n\t\telse {\n\t\t\t//如果焦点不在,且原焦点在,则触发mouseleave事件\n\t\t\tif(this.interactive !== false && !inpos &&\n\t\t\t\tthis.focused && \n\t\t\t\t(name === 'mousemove' || name === 'touchmove')) {\n\n\t\t\t\tthis.focused = false;//表明当前焦点离开\n\t\t\t\tthis.runEventHandle(name === 'mousemove'? 'mouseleave' : 'touchleave', args);//执行事件\t\n\t\t\t}\t\n\t\t}\n\t\t\t\n\t\treturn args.cancel === false;//如果被阻止则返回false,否则返回true\n\t}\n\n\t/**\n\t * 执行事件,并进行冒泡\n\t * @param {string} name 事件名称 \n\t * @param {object} args 事件参数\n\t */\n\trunEventAndPopEvent(name, args) {\t\n\n\t\tif(args.cancel !== true) {\n\t\t\t// 添加到触发路径\n\t\t\targs.path.push(this);\n\n\t\t\t//如果返回true则阻断冒泡\n\t\t\tthis.runEventHandle(name, args);//执行事件\n\n\t\t\t// // 向父节点冒泡事件\t\t\n\t\t\t// if(args.cancel !== true && this.parent && this.parent.runEventAndPopEvent) {\n\t\t\t// \t// 相对位置需要改为父节点的\n\t\t\t// \tif(args.position) {\n\t\t\t// \t\tlet bounds = this.parent.getBounds();\n\t\t\t// \t\targs.position.x += bounds.left;\n\t\t\t// \t\targs.position.y += bounds.top;\n\t\t\t// \t}\n\t\t\t// \tthis.parent.runEventAndPopEvent(name, args);\n\t\t\t// }\t\t\n\t\t}\n\t}\n\n\t/**\n\t * 清空控件指定事件\n\t *\n\t * @method clearEvents\n\t * @param {string} name 需要清除的事件名称\n\t */\n\tclearEvents(name) {\n\t\tvar eventCollection = this.getEvent(name) ;\t\t\n\t\tif(eventCollection) {\n\t\t\teventCollection.clear;\n\t\t}\n\t}\n\n\t/**\n\t * 查找其父级类型为type的元素,直到找到指定的对象或到最顶级控件后返回空。\n\t *\n\t * @method findParent \n\t * @param {object} 类型名称或类型对象\n\t * @return {object} 指定类型的实例\n\t */\n\tfindParent(type) {\n\t\t//如果为类型名称,则返回名称相同的类型对象\n\t\tif(typeof type === 'string') {\n\t\t\tif(this.type == type)\n\t\t\t\treturn this;\n\t\t}\n\t\telse if(this.is(type)) {\n\t\t\treturn this;\n\t\t}\n\t\tif(this.parent) {\n\t\t\treturn this.parent.findParent(type);\n\t\t}\n\t\treturn null;\n\t}\n\n\t/**\n\t * 设定是否可以移动\n\t * 此方法需指定jmgraph或在控件添加到jmgraph后再调用才能生效。\n\t *\n\t * @method canMove\n\t * @param {boolean} m true=可以移动,false=不可移动或清除移动。\n\t * @param {jmGraph} [graph] 当前画布,如果为空的话必需是已加入画布的控件,否则得指定画布。\n\t */\n\tcanMove(m, graph) {\n\t\tif(!this.__mvMonitor) {\n\t\t\t/**\n\t\t\t * 控制控件移动对象\n\t\t\t * \n\t\t\t * @property __mvMonitor\n\t\t\t * @private\n\t\t\t */\n\t\t\tthis.__mvMonitor = {};\n\t\t\tthis.__mvMonitor.mouseDown = false;\n\t\t\tthis.__mvMonitor.curposition={x:0,y:0};\n\t\t\tvar self = this;\n\t\t\t/**\n\t\t\t * 控件移动鼠标事件\n\t\t\t *\n\t\t\t * @method mv\n\t\t\t * @private\n\t\t\t */\n\t\t\tthis.__mvMonitor.mv = function(evt) {\n\t\t\t\tlet _this = self;\n\t\t\t\t//如果鼠标经过当前可移动控件,则显示可移动指针\n\t\t\t\t//if(evt.path && evt.path.indexOf(_this)>-1) {\n\t\t\t\t//\t_this.cursor('move');\t\n\t\t\t\t//}\n\n\t\t\t\tif(_this.__mvMonitor.mouseDown) {\n\t\t\t\t\t_this.parent.bounds = null;\n\t\t\t\t\t//let parentbounds = _this.parent.getAbsoluteBounds();\t\t\n\t\t\t\t\tlet offsetx = evt.position.offsetX - _this.__mvMonitor.curposition.x;\n\t\t\t\t\tlet offsety = evt.position.offsetY - _this.__mvMonitor.curposition.y;\t\t\t\t\n\t\t\t\t\t//console.log(offsetx + ',' + offsety);\n\t\t\t\t\t//如果锁定边界\n\t\t\t\t\tif(_this.option.lockSide) {\n\t\t\t\t\t\tlet thisbounds = _this.bounds || _this.getAbsoluteBounds();\t\t\t\t\t\n\t\t\t\t\t\t//检查边界出界\n\t\t\t\t\t\tlet outside = jmUtils.checkOutSide(_this.option.lockSide, thisbounds, { x: offsetx, y: offsety });\n\t\t\t\t\t\tif(outside.left < 0 && offsetx < 0) {\n\t\t\t\t\t\t\t//offsetx -= outside.left;\n\t\t\t\t\t\t\toffsetx = 0;\n\t\t\t\t\t\t}\n\t\t\t\t\t\telse if(outside.right > 0 && offsetx > 0) {\n\t\t\t\t\t\t\t//offsetx -= outside.right;\n\t\t\t\t\t\t\toffsetx = 0;\n\t\t\t\t\t\t}\n\t\t\t\t\t\tif(outside.top < 0 && offsety < 0) {\n\t\t\t\t\t\t\t//offsety -= outside.top;\n\t\t\t\t\t\t\toffsety = 0;\n\t\t\t\t\t\t}\n\t\t\t\t\t\telse if(outside.bottom > 0 && offsety > 0) {\n\t\t\t\t\t\t\t//offsety -= outside.bottom;\n\t\t\t\t\t\t\toffsety = 0;\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t\t\n\t\t\t\t\tif(offsetx || offsety) {\n\t\t\t\t\t\t_this.offset(offsetx, offsety, true, evt);\n\t\t\t\t\t\tif(offsetx) _this.__mvMonitor.curposition.x = evt.position.offsetX;\n\t\t\t\t\t\tif(offsety) _this.__mvMonitor.curposition.y = evt.position.offsetY;\t\n\t\t\t\t\t\t//console.log(offsetx + '.' + offsety);\n\t\t\t\t\t}\n\t\t\t\t\treturn false;\n\t\t\t\t}\n\t\t\t}\n\t\t\t/**\n\t\t\t * 控件移动鼠标松开事件\n\t\t\t *\n\t\t\t * @method mu\n\t\t\t * @private\n\t\t\t */\n\t\t\tthis.__mvMonitor.mu = function(evt) {\n\t\t\t\tlet _this = self;\n\t\t\t\tif(_this.__mvMonitor.mouseDown) {\n\t\t\t\t\t_this.__mvMonitor.mouseDown = false;\n\t\t\t\t\t//_this.cursor('default');\n\t\t\t\t\t_this.emit('moveend',{position:_this.__mvMonitor.curposition});\t\n\t\t\t\t\t//return false;\n\t\t\t\t}\t\t\t\n\t\t\t}\n\t\t\t/**\n\t\t\t * 控件移动鼠标离开事件\n\t\t\t *\n\t\t\t * @method ml\n\t\t\t * @private\n\t\t\t */\n\t\t\tthis.__mvMonitor.ml = function() {\n\t\t\t\tlet _this = self;\n\t\t\t\tif(_this.__mvMonitor.mouseDown) {\n\t\t\t\t\t_this.__mvMonitor.mouseDown = false;\n\t\t\t\t\t//_this.cursor('default');\t\n\t\t\t\t\t_this.emit('moveend',{position:_this.__mvMonitor.curposition});\n\t\t\t\t\treturn false;\n\t\t\t\t}\t\n\t\t\t}\n\t\t\t/**\n\t\t\t * 控件移动鼠标按下事件\n\t\t\t *\n\t\t\t * @method md\n\t\t\t * @private\n\t\t\t */\n\t\t\tthis.__mvMonitor.md = function(evt) {\n\t\t\t\t\n\t\t\t\tif(this.__mvMonitor.mouseDown) return;\n\t\t\t\tif(evt.button == 0 || evt.button == 1) {\n\t\t\t\t\tthis.__mvMonitor.mouseDown = true;\n\t\t\t\t\t//this.cursor('move');\n\t\t\t\t\t//var parentbounds = this.parent.absoluteBounds || this.parent.getAbsoluteBounds();\t\n\t\t\t\t\tthis.__mvMonitor.curposition.x = evt.position.offsetX;//evt.position.x + parentbounds.left;\n\t\t\t\t\tthis.__mvMonitor.curposition.y = evt.position.offsetY;//evt.position.y + parentbounds.top;\n\t\t\t\t\t//触发控件移动事件\n\t\t\t\t\tthis.emit('movestart',{position:this.__mvMonitor.curposition});\n\t\t\t\t\t\n\t\t\t\t\tevt.cancel = true;\n\t\t\t\t\treturn false;\n\t\t\t\t}\t\t\t\n\t\t\t}\n\t\t}\n\t\tgraph = graph || this.graph ;//获取最顶级元素画布\n\t\t\n\t\tif(m !== false) {\t\t\t\n\t\t\tgraph.bind('mousemove',this.__mvMonitor.mv);\n\t\t\tgraph.bind('mouseup',this.__mvMonitor.mu);\n\t\t\tgraph.bind('mouseleave',this.__mvMonitor.ml);\n\t\t\tthis.bind('mousedown',this.__mvMonitor.md);\n\t\t\tgraph.bind('touchmove',this.__mvMonitor.mv);\n\t\t\tgraph.bind('touchend',this.__mvMonitor.mu);\n\t\t\tthis.bind('touchstart',this.__mvMonitor.md);\n\t\t}\n\t\telse {\t\t\t\n\t\t\tgraph.unbind('mousemove',this.__mvMonitor.mv);\n\t\t\tgraph.unbind('mouseup',this.__mvMonitor.mu);\n\t\t\tgraph.unbind('mouseleave',this.__mvMonitor.ml);\n\t\t\tthis.unbind('mousedown',this.__mvMonitor.md);\n\t\t\tgraph.unbind('touchmove',this.__mvMonitor.mv);\n\t\t\tgraph.unbind('touchend',this.__mvMonitor.mu);\n\t\t\tthis.unbind('touchstart',this.__mvMonitor.md);\t\n\t\t}\n\n\t\tthis.interactive = true;// 如果可以移动,则响应事件\n\t\treturn this;\n\t}\n};\n\nexport { jmControl };","import {jmControl} from \"./jmControl.js\";\n/**\n * 基础路径,大部分图型的基类\n * 指定一系列点,画出图形\n *\n * @class jmPath\n * @extends jmControl\n * @param {object} params 路径参数 points=所有描点\n */\n\nexport default class jmPath extends jmControl {\t\n\n\tconstructor(params, t='jmPath') {\n\t\tsuper(params, t);\t\t\n\t\tthis.points = params && params.points ? params.points : [];\t\n\t}\n\t\n\t/**\n\t * 描点集合\n\t * point格式:{x:0,y:0,m:true}\n\t * @property points\n\t * @type {array}\n\t */\n\tget points() {\n\t\tlet s = this.property('points');\n\t\treturn s;\n\t}\n\tset points(v) {\n\t\tthis.needUpdate = true;\n\t\treturn this.property('points', v);\n\t}\n\n\t/**\n\t * 转换为SVG路径\n\t * \n\t * @method toSVG\n\t * @return {string} SVG路径字符串\n\t */\n\ttoSVG() {\n\t\tif(!this.points || this.points.length === 0) return '';\n\t\t\n\t\tlet pathData = '';\n\t\tconst points = this.points;\n\t\t\n\t\t// 移动到起点\n\t\tpathData += `M ${points[0].x} ${points[0].y}`;\n\t\t\n\t\t// 绘制路径\n\t\tfor(let i = 1; i < points.length; i++) {\n\t\t\tconst p = points[i];\n\t\t\tif(p.m) {\n\t\t\t\t// 移动到新位置\n\t\t\t\tpathData += ` M ${p.x} ${p.y}`;\n\t\t\t} else {\n\t\t\t\t// 直线到\n\t\t\t\tpathData += ` L ${p.x} ${p.y}`;\n\t\t\t}\n\t\t}\n\t\t\n\t\t// 如果是封闭路径\n\t\tif(this.style && this.style.close) {\n\t\t\tpathData += ' Z';\n\t\t}\n\t\t\n\t\t// 构建SVG元素\n\t\tlet svg = '<path d=\"' + pathData + '\"';\n\t\t\n\t\t// 添加样式\n\t\tif(this.style) {\n\t\t\tif(this.style.fill) {\n\t\t\t\tsvg += ' fill=\"' + this.style.fill + '\"';\n\t\t\t}\n\t\t\tif(this.style.stroke) {\n\t\t\t\tsvg += ' stroke=\"' + this.style.stroke + '\"';\n\t\t\t}\n\t\t\tif(this.style.lineWidth) {\n\t\t\t\tsvg += ' stroke-width=\"' + this.style.lineWidth + '\"';\n\t\t\t}\n\t\t\tif(this.style.opacity) {\n\t\t\t\tsvg += ' opacity=\"' + this.style.opacity + '\"';\n\t\t\t}\n\t\t}\n\t\t\n\t\tsvg += '/>';\n\t\treturn svg;\n\t}\t\n\t\n}\n\nexport { jmPath };\n","import {jmUtils} from \"./jmUtils.js\";\nimport {jmList} from \"./jmList.js\";\nimport {jmProperty} from './jmProperty.js';\nimport {jmShadow} from \"./jmShadow.js\";\nimport {jmGradient} from \"./jmGradient.js\";\nimport {jmFilter} from \"./jmFilter.js\";\nimport {jmEvents} from \"./jmEvents.js\";\nimport {jmControl} from \"./jmControl.js\";\nimport {jmPath} from \"./jmPath.js\";\n\n/**\n * jmGraph画图类库\n * 对canvas画图api进行二次封装,使其更易调用,省去很多重复的工作。\n *\n * @module jmGraph\n * @class jmGraph\n * @extends jmControl\n * @param {element} canvas 标签canvas\n * @param {object} option 参数:{width:宽,height:高}\n * @param {function} callback 初始化后的回调\n */\nexport default class jmGraph extends jmControl {\n\n\tconstructor(canvas, option, callback) {\n\t\tif(typeof option == 'function') {\n\t\t\tcallback = option;\n\t\t\toption = {};\n\t\t}\n\t\n\t\toption = option || {};\n\t\t//option.mode = '2d'; // webgl | 2d 暂不支持webgl\n\t\toption.interactive = true;\n\t\toption.isRegular = true;// 规则的\n\n\t\tsuper(option, 'jmGraph');\n\n\t\tthis.option = option || {};\n\t\t\n\t\tthis.devicePixelRatio = 1; // 根据屏幕的缩放倍数\n\n\t\t/**\n\t\t * 工具类\n\t\t * @property utils/util\n\t\t * @type {jmUtils}\n\t\t */\n\t\tthis.util = this.utils = jmUtils;\t\n\t\t// 模式 webgl | 2d\n\t\tthis.mode = option.mode || '2d';\n\n\t\t// 缩放和平移相关\n\t\tthis.scaleFactor = 1;\n\t\tthis.translation = {x: 0, y: 0};\n\n\t\t//如果是小程序\n\t\tif(typeof wx != 'undefined' && wx.canIUse && wx.canIUse('canvas')) {\t\t\t\n\t\t\tif(typeof canvas === 'string') canvas = wx.createSelectorQuery().select('#' + canvas);\n\t\t\tthis.isWXMiniApp = true;// 微信小程序平台\n\t\t\tthis.container = canvas;\n\t\t}\n\t\telse {\n\t\t\tif(typeof canvas === 'string' && typeof document != 'undefined') {\n\t\t\t\tcanvas = document.getElementById(canvas);\n\t\t\t}\n\t\t\telse if(canvas.length) {\n\t\t\t\tcanvas = canvas[0];\n\t\t\t}\n\n\t\t\tif(!canvas.getContext && typeof document != 'undefined') {\n\t\t\t\tthis.container = canvas;\n\t\t\t\tlet cn = document.createElement('canvas');\n\t\t\t\tcanvas.appendChild(cn);\n\t\t\t\tcn.width = canvas.offsetWidth||canvas.clientWidth;\n\t\t\t\tcn.height = canvas.offsetHeight||canvas.clientHeight;\n\t\t\t\tcanvas = cn;\n\t\t\t}\t\n\t\t\telse {\n\t\t\t\tthis.container = canvas.parentElement;\n\t\t\t}\n\t\t}\t\n\t\tthis.canvas = canvas;\t\n\t\t// Create context with preserveDrawingBuffer for webgl to prevent flickering\n\t\tif(this.mode === 'webgl') {\n\t\t\tthis.context = canvas.getContext(this.mode, { preserveDrawingBuffer: true });\n\t\t}\n\t\telse {\n\t\t\tthis.context = canvas.getContext(this.mode);\n\t\t}\n\t\t\n\t\t// webgl模式\n\t\tif(this.mode === 'webgl') {\n\n\t\t\tthis.context.enable(this.context.BLEND);// 开启混合功能:(注意,它不可和gl.DEPTH_TEST一起使用)\n\t\t\tthis.context.blendFunc(this.context.SRC_ALPHA, this.context.ONE_MINUS_SRC_ALPHA); // 指定混合函数:\n\t\t\t// webglcontextlost webglcontextrestored\n\t\t\tjmUtils.bindEvent(canvas, 'webglcontextlost', (e)=> {\n\t\t\t\tconsole.log('canvas webglcontextlost', e);\n\t\t\t\tthis.emit('webglcontextlost', e);\n\t\t\t});\n\t\t\tjmUtils.bindEvent(canvas, 'webglcontextrestored', (e)=> {\n\t\t\t\tconsole.log('canvas webglcontextrestored', e);\n\t\t\t\tthis.emit('webglcontextrestored', e);\n\t\t\t});\n\t\t} \n\t\tthis.__init(callback);\n\t}\n\n\t/**\n\t * 初始化画布\n\t * @method init\n\t */\n\t__init(callback) {\n\t\t/**\n\t\t * 当前所有图形类型\n\t\t * @property shapes\n\t\t * @type {object}\n\t\t */\n\t\tthis.shapes = Object.assign({\n\t\t\t\"path\": jmPath,\n\t\t}, this.option.shapes);\n\t\t\n\t\t/**\n\t\t * 画控件前初始化\n\t\t * 为了解决一像素线条问题\n\t\t */\n\t\tthis.on('beginDraw', function() { \n\t\t\tthis.context.translate && this.context.translate(0.5, 0.5);\n\t\t\t// 应用缩放和平移变换\n\t\t\tif(this.context.translate && this.context.scale) {\n\t\t\t\tthis.context.translate(this.translation.x, this.translation.y);\n\t\t\t\tthis.context.scale(this.scaleFactor, this.scaleFactor);\n\t\t\t}\n\t\t});\n\t\t/**\n\t\t * 结束控件绘制 为了解决一像素线条问题\n\t\t */\n\t\tthis.on('endDraw', function() { \n\t\t\tthis.context.translate && this.context.translate(-0.5, -0.5);\n\t\t\t// 恢复缩放和平移变换\n\t\t\tif(this.context.translate && this.context.scale) {\n\t\t\t\tthis.context.scale(1/this.scaleFactor, 1/this.scaleFactor);\n\t\t\t\tthis.context.translate(-this.translation.x, -this.translation.y);\n\t\t\t}\n\t\t});\n\n\t\t// devicePixelRatio初始化\n\t\tlet dpr = typeof window != 'undefined' && window.devicePixelRatio > 1? window.devicePixelRatio : 1;\n\t\tif(this.isWXMiniApp) {\n\t\t\tdpr = wx.getWindowInfo().pixelRatio || 1;\n\t\t}\t\t\n\t\tthis.devicePixelRatio = dpr;\n\t\t// 为了解决锯齿问题,先放大canvas再缩放\n\t\tthis.dprScaleSize = this.devicePixelRatio > 1? this.devicePixelRatio : 2;\n\t\t\n\t\tif(this.option.width > 0) this.width = this.option.width;\n\t\tif(this.option.height > 0) this.height = this.option.height;\t\n\t\tthis.resize();\t\t\n\n\t\t//绑定事件\n\t\tthis.eventHandler = new jmEvents(this, this.canvas.canvas || this.canvas);\t\n\n\t\t//如果指定了自动刷新\n\t\tif(this.option.autoRefresh) {\n\t\t\tthis.autoRefresh();\n\t\t}\n\n\t\tif(callback) callback(this);\t\t\n\t}\n\n\t// 重置canvas大小,并判断高清屏,画图先放大二倍\n\tresize(w, h) {\n\t\tif(!this.canvas) return;\n\n\t\tthis.__normalSize = this.__normalSize || { width: 0, height: 0};\n\t\tw = w || this.__normalSize.width || this.width, h = h || this.__normalSize.height || this.height;\n\n\t\tif(w) this.__normalSize.width = w;\n\t\tif(h) this.__normalSize.height = h;\n\t\n\t\tthis.css('width', w + \"px\");\n\t\tthis.css('height', h + \"px\");\n\t\tif(this.mode === '2d') {\n\t\t\tthis.canvas.height = h * this.dprScaleSize;\n\t\t\tthis.canvas.width = w * this.dprScaleSize;\n\t\t\tif(this.dprScaleSize !== 1) this.context.scale && this.context.scale(this.dprScaleSize, this.dprScaleSize);\t\n\t\t}\n\t\telse {\n\t\t\tthis.canvas.width = w;\n\t\t\tthis.canvas.height = h;\n\t\t}\n\n\t\tthis.context.viewport && this.context.viewport(0, 0, w, h);\n\t\tthis.needUpdate = true;\n\t}\n\n\t/**\n\t * 宽度\n\t * @property width\n\t * @type {number}\n\t */\n\tget width() {\n\t\tif(this.__normalSize && this.__normalSize.width) return this.__normalSize.width;\n\t\tif(this.canvas) return this.canvas.width;\n\t\treturn 0;\n\t}\n\tset width(v) {\n\t\tthis.needUpdate = true;\n\t\tif(this.canvas) {\n\t\t\tthis.resize(v);\n\t\t}\t\n\t\treturn v;\n\t}\n\n\t/**\n\t * 高度\n\t * @property height\n\t * @type {number}\n\t */\n\tget height() {\n\t\tif(this.__normalSize && this.__normalSize.height) return this.__normalSize.height;\n\t\tif(this.canvas) return this.canvas.height;\n\t\treturn 0;\n\t}\n\tset height(v) {\n\t\tthis.needUpdate = true;\n\t\tif(this.canvas) {\n\t\t\tthis.resize(0, v);\n\t\t}\n\t\treturn v;\n\t}\n\n\t/**\n\t * 创建jmGraph的静态对象\n\t *\n\t * @method create\n\t * @return {jmGraph} jmGraph实例对象\n\t */\n\tstatic create(...args) {\n\t\treturn new jmGraph(...args);\n\t}\n\n\t/**\n\t * 获取当前画布在浏览器中的绝对定位\n\t *\n\t * @method getPosition\n\t * @return {postion} 返回定位坐标\n\t */\n\tgetPosition() {\n\t\tconst p = this.isWXMiniApp? {\n\t\t\tleft: 0,\n\t\t\ttop: 0\n\t\t} :jmUtils.getElementPosition(this.canvas.canvas || this.canvas);\n\t\t\n\t\tp.width = this.width;\n\t\tp.height = this.height;\n\t\tp.right = p.left + p.width;\n\t\tp.bottom = p.top + p.height;\n\t\treturn p;\n\t}\n\n\t/**\n\t * 注册图形类型,图形类型必需有统一的构造函数。参数为画布句柄和参数对象。\n\t *\n\t * @method registerShape \n\t * @param {string} name 控件图形名称\n\t * @param {class} shape 图形控件类型\n\t */\n\tregisterShape(name, shape) {\n\t\tthis.shapes[name] = shape;\n\t}\n\n\t/**\n\t * 从已注册的图形类创建图形\n\t * 简单直观创建对象\n\t *\n\t * @method createShape \n\t * @param {string} shape 注册控件的名称 也可以直接是控件类型\n\t * @param {object} args 实例化控件的参数\n\t * @return {object} 已实例化控件的对象\n\t */\n\tcreateShape(shape, args) {\n\t\tif(typeof shape === 'string') {\n\t\t\tshape = this.shapes[shape];\n\t\t}\n\t\tif(shape) {\n\t\t\tif(!args) args = {};\n\t\t\targs.graph = this;\n\t\t\tconst obj = new shape(args);\n\t\t\treturn obj;\n\t\t}\n\t}\n\n\t/**\n\t * 生成阴影对象\n\t *\n\t * @method createShadow\n\t * @param {number} x x偏移量\n\t * @param {number} y y偏移量\n\t * @param {number} blur 模糊值\n\t * @param {string} color 颜色\n\t * @return {jmShadow} 阴影对象\n\t */\n\tcreateShadow(x, y, blur, color) {\n\t\tconst sh = new jmShadow(x, y, blur, color);\n\t\treturn sh;\n\t}\n\n\t/**\n\t * 生成线性渐变对象\n\t *\n\t * @method createLinearGradient\n\t * @param {number} x1 线性渐变起始点X坐标\n\t * @param {number} y1 线性渐变起始点Y坐标\n\t * @param {number} x2 线性渐变结束点X坐标\n\t * @param {number} y2 线性渐变结束点Y坐标\n\t * @return {jmGradient} 线性渐变对象\n\t */\n\tcreateLinearGradient(x1, y1, x2, y2, stops=[]) {\n\t\tconst gradient = new jmGradient({\n\t\t\ttype:'linear',\n\t\t\tx1: x1,\n\t\t\ty1: y1,\n\t\t\tx2: x2,\n\t\t\ty2: y2,\n\t\t\tstops\n\t\t});\n\t\treturn gradient;\n\t}\n\n\t/**\n\t * 生成放射渐变对象\n\t *\n\t * @method createRadialGradient\n\t * @param {number} x1 放射渐变小圆中心X坐标\n\t * @param {number} y1 放射渐变小圆中心Y坐标\n\t * @param {number} r1 放射渐变小圆半径\n\t * @param {number} x2 放射渐变大圆中心X坐标\n\t * @param {number} y2 放射渐变大圆中心Y坐标\n\t * @param {number} r2 放射渐变大圆半径\n\t * @return {jmGradient} 放射渐变对象\n\t */\n\tcreateRadialGradient(x1, y1, r1, x2, y2, r2, stops=[]) {\t\n\t\tconst gradient = new jmGradient({\n\t\t\ttype:'radial',\n\t\t\tx1: x1,\n\t\t\ty1: y1,\n\t\t\tr1: r1,\n\t\t\tx2: x2,\n\t\t\ty2: y2,\n\t\t\tr2: r2,\n\t\t\tstops\n\t\t});\n\t\treturn gradient;\n\t}\n\n\t/**\n\t * 重新刷新整个画板\n\t * 以加入动画事件触发延时10毫秒刷新,保存最尽的调用只刷新一次,加强性能的效果。\n\t *\n\t * @method refresh\n\t */\n\trefresh() {\t\n\t\t//加入动画,触发redraw,会导致多次refresh只redraw一次\n\t\t/*this.animate(function() {\n\t\t\treturn false;\n\t\t},100,'jmgraph_refresh');*/\n\t\tthis.redraw();\n\t}\n\n\t/**\n\t * 重新刷新整个画板\n\t * 此方法直接重画,与refresh效果类似\n\t *\n\t * @method redraw\n\t * @param {number} [w] 清除画布的宽度\n\t * @param {number} [h] 清除画布的高度\n\t */\n\tredraw(w, h) {\t\n\t\tthis.clear(w||this.width, h||this.height);\n\t\tthis.paint();\n\t}\n\n\t/**\n\t * 清除画布\n\t * \n\t * @method clear\n\t * @param {number} [w] 清除画布的宽度\n\t * @param {number} [h] 清除画布的高度\n\t */\n\tclear(w, h) {\n\t\tif(!w || !h) {\n\t\t\tw = this.width;\n\t\t\th = this.height;\n\t\t\t/*if(this.scaleSize) {\n\t\t\t\tw = w / this.scaleSize.x;\n\t\t\t\th = h / this.scaleSize.y;\n\t\t\t}*/\n\t\t}\n\t\t\n\t\tif(this.context.clearRect) {\n\t\t\tif(this.style && this.style.fill) {\n\t\t\t\tthis.points = [\n\t\t\t\t\t{x:0, y:0},\n\t\t\t\t\t{x:w, y:0},\n\t\t\t\t\t{x:w, y:h},\n\t\t\t\t\t{x:0, y:h}\n\t\t\t\t];\n\t\t\t\tthis.style.close = true;// 封闭填充\n\t\t\t}\n\n\t\t\tthis.context.clearRect(0, 0, w, h);\n\t\t}\n\t\telse if(this.mode === 'webgl' && this.context.clear) {\n\t\t\t// 缓存 clearColor 对象,避免每帧创建\n\t\t\tif(this.style && this.style.fill) {\n\t\t\t\tconst color = this.utils.hexToRGBA(this.style.fill);\n\t\t\t\tthis.__lastClearColor = color;\n\t\t\t\tthis.context.clearColor(color.r, color.g, color.b, color.a);\n\t\t\t}\n\t\t\telse if(!this.__lastClearColor) {\n\t\t\t\tthis.__lastClearColor = { r: 0, g: 0, b: 0, a: 0 };\n\t\t\t\tthis.context.clearColor(0, 0, 0, 0);\n\t\t\t}\n\t\t\telse {\n\t\t\t\tthis.context.clearColor(this.__lastClearColor.r, this.__lastClearColor.g, this.__lastClearColor.b, this.__lastClearColor.a);\n\t\t\t}\n \tthis.context.clear(this.context.COLOR_BUFFER_BIT); // 清空颜色缓冲区,也就是清空画布\n\t\t}\n\t}\n\n\t/**\n\t* 设置画布样式,此处只是设置其css样式\n\t*\n\t* @method css\n\t* @param {string} name 样式名\n\t* @param {string} value 样式值\n\t*/\n\tcss(name, value) {\n\t\tif(this.canvas && this.canvas.style) {\n\t\t\tif(typeof value != 'undefined') this.canvas.style[name] = value;\n\t\t\treturn this.canvas.style[name];\n\t\t}\n\t}\n\n\t/**\n\t * 生成路径对象\n\t *\n\t * @method createPath\n\t * @param {array} points 路径中的描点集合\n\t * @param {style} style 当前路径的样式\n\t * @return {jmPath} 路径对象jmPath\n\t */\n\tcreatePath(points, style, option={}) {\n\t\tconst path = this.createShape('path',{\n\t\t\tpoints: points,\n\t\t\tstyle: style,\n\t\t\t...option\n\t\t});\n\t\treturn path;\n\t}\n\n\t/**\n\t * 生成直线\n\t * \n\t * @method createLine\n\t * @param {point} start 直线的起点\n\t * @param {point} end 直线的终点\n\t * @param {style} 直线的样式\n\t * @return {jmLine} 直线对象\n\t */\n\tcreateLine(start, end, style) {\n\t\tconst line = this.createShape('line', {\n\t\t\tstart: start,\n\t\t\tend: end,\n\t\t\tstyle: style\n\t\t});\n\t\treturn line;\n\t}\n\n\t/**\n\t * 缩小整个画布按比例0.9\n\t * \n\t * @method zoomOut\n\t */\n\tzoomOut() {\n\t\tthis.scale(0.9 ,0.9);\n\t}\n\n\t/**\n\t * 放大 每次增大0.1的比例\n\t * \n\t * @method zoomIn\n\t */\n\tzoomIn() {\t\t\n\t\tthis.scale(1.1 ,1.1);\n\t}\n\n\t/**\n\t * 大小复原\n\t * \n\t * @method zoomActual\n\t */\n\tzoomActual() {\n\t\tif(this.scaleSize) {\n\t\t\tthis.scale(1 / this.scaleSize.x ,1 / this.scaleSize.y);\t\n\t\t}\n\t\telse {\n\t\t\tthis.scale(1 ,1);\t\n\t\t}\t\n\t}\n\n\t/**\n\t * 放大缩小画布\n\t * \n\t * @method scale\n\t * @param {number} dx 缩放X轴比例\n\t * @param {number} dy 缩放Y轴比例\n\t */\n\tscale(dx, dy) {\n\t\tif(!this.normalSize) {\n\t\t\tthis.normalSize = {\n\t\t\t\twidth: this.canvas.width,\n\t\t\t\theight: this.canvas.height\n\t\t\t};\n\t\t}\n\t\t\n\t\t//this.context.scale && this.context.scale(dx,dy);\n\t\tif(!this.scaleSize) {\n\t\t\tthis.scaleSize = {x: 1,y: 1};\n\t\t}\n\t\telse {\n\t\t\tthis.scaleSize = {x: dx * this.scaleSize.x, y: dy * this.scaleSize.y};\n\t\t}\n\t\tthis.canvas.style && (this.canvas.style.transform = `scale(${this.scaleSize.x}, ${this.scaleSize.y})`);\n\t}\n\n\t/**\n\t * 设置缩放因子\n\t * 支持以指定点为中心进行缩放,保持该点在屏幕上的位置不变\n\t * \n\t * @method setZoom\n\t * @param {number} zoom 缩放因子(建议范围:0.1 - 10)\n\t * @param {number} [x] 缩放中心X坐标(画布坐标)\n\t * @param {number} [y] 缩放中心Y坐标(画布坐标)\n\t * @return {jmGraph} 返回当前实例,支持链式调用\n\t */\n\tsetZoom(zoom, x, y) {\n\t\t// 参数验证\n\t\tif(typeof zoom !== 'number' || isNaN(zoom)) {\n\t\t\tconsole.warn('jmGraph: setZoom - 无效的缩放因子');\n\t\t\treturn this;\n\t\t}\n\t\t\n\t\t// 限制缩放范围,防止过度缩放导致性能问题或显示异常\n\t\tconst minZoom = 0.1; // 最小缩放到10%\n\t\tconst maxZoom = 10; // 最大放大到10倍\n\t\tzoom = Math.max(minZoom, Math.min(maxZoom, zoom));\n\t\t\n\t\tif (x !== undefined && y !== undefined) {\n\t\t\t// 计算缩放前后的坐标偏移\n\t\t\t// 保持缩放中心点在屏幕上的位置不变\n\t\t\tconst oldZoom = this.scaleFactor;\n\t\t\tconst newZoom = zoom;\n\t\t\t\n\t\t\t// 调整平移量以保持缩放中心位置不变\n\t\t\tthis.translation.x = x - (x - this.translation.x) * (newZoom / oldZoom);\n\t\t\tthis.translation.y = y - (y - this.translation.y) * (newZoom / oldZoom);\n\t\t}\n\t\t\n\t\tthis.scaleFactor = zoom;\n\t\tthis.needUpdate = true;\n\t\tthis.redraw();\n\t\t\n\t\treturn this; // 支持链式调用\n\t}\n\n\t/**\n\t * 平移画布\n\t * 移动画布视图,改变可视区域\n\t * \n\t * @method pan\n\t * @param {number} dx X轴平移量(像素)\n\t * @param {number} dy Y轴平移量(像素)\n\t * @return {jmGraph} 返回当前实例,支持链式调用\n\t */\n\tpan(dx, dy) {\n\t\t// 参数验证\n\t\tif(typeof dx !== 'number' || typeof dy !== 'number' || isNaN(dx) || isNaN(dy)) {\n\t\t\tconsole.warn('jmGraph: pan - 无效的平移参数');\n\t\t\treturn this;\n\t\t}\n\t\t\n\t\tthis.translation.x += dx;\n\t\tthis.translation.y += dy;\n\t\tthis.needUpdate = true;\n\t\tthis.redraw();\n\t\t\n\t\treturn this; // 支持链式调用\n\t}\n\n\t/**\n\t * 重置缩放和平移\n\t * 恢复画布到初始状态(缩放为1,平移为0)\n\t * \n\t * @method resetTransform\n\t * @return {jmGraph} 返回当前实例,支持链式调用\n\t */\n\tresetTransform() {\n\t\tthis.scaleFactor = 1;\n\t\tthis.translation = {x: 0, y: 0};\n\t\tthis.needUpdate = true;\n\t\tthis.redraw();\n\t\t\n\t\treturn this; // 支持链式调用\n\t}\n\n\t/**\n\t * 保存为base64图形数据\n\t * \n\t * @method toDataURL\n\t * @return {string} 当前画布图的base64字符串\n\t */\n\ttoDataURL() {\n\t\tlet data = this.canvas.toDataURL?this.canvas.toDataURL():'';\n\t\treturn data;\n\t}\n\n\t/**\n\t * 导出为PNG图片\n\t * 使用Canvas的toDataURL方法导出当前画布内容\n\t * \n\t * @method exportToPNG\n\t * @param {string} [fileName='jmgraph-export'] 文件名(不含扩展名)\n\t * @param {string} [format='image/png'] 图片格式,支持image/png和image/jpeg\n\t * @param {number} [quality=0.9] 图片质量(0-1之间,仅对JPEG格式有效)\n\t */\n\texportToPNG(fileName = 'jmgraph-export', format = 'image/png', quality = 0.9) {\n\t\ttry {\n\t\t\t// 确保画布已渲染\n\t\t\tthis.redraw();\n\t\t\t\n\t\t\tconst dataURL = this.canvas.toDataURL(format, quality);\n\t\t\tthis.downloadFile(dataURL, fileName, 'png');\n\t\t} catch(error) {\n\t\t\tconsole.error('jmGraph: exportToPNG - 导出失败', error);\n\t\t}\n\t}\n\n\t/**\n\t * 导出为JPEG图片\n\t * \n\t * @method exportToJPEG\n\t * @param {string} [fileName='jmgraph-export'] 文件名(不含扩展名)\n\t * @param {number} [quality=0.9] 图片质量(0-1之间)\n\t */\n\texportToJPEG(fileName = 'jmgraph-export', quality = 0.9) {\n\t\tthis.exportToPNG(fileName, 'image/jpeg', quality);\n\t}\n\n\t/**\n\t * 导出为SVG文件\n\t * 将当前画布内容转换为SVG格式\n\t * 注意:只有实现了toSVG方法的形状才能被导出\n\t * \n\t * @method exportToSVG\n\t * @param {string} [fileName='jmgraph-export'] 文件名(不含扩展名)\n\t */\n\texportToSVG(fileName = 'jmgraph-export') {\n\t\ttry {\n\t\t\tconst svg = this.toSVG();\n\t\t\tconst blob = new Blob([svg], { type: 'image/svg+xml;charset=utf-8' });\n\t\t\tconst url = URL.createObjectURL(blob);\n\t\t\tthis.downloadFile(url, fileName, 'svg');\n\t\t\t\n\t\t\t// 释放URL对象,避免内存泄漏\n\t\t\tsetTimeout(() => URL.revokeObjectURL(url), 100);\n\t\t} catch(error) {\n\t\t\tconsole.error('jmGraph: exportToSVG - 导出失败', error);\n\t\t}\n\t}\n\n\t/**\n\t * 遍历所有形状,生成SVG标记\n\t *\n\t * @method toSVG\n\t * @return {string} SVG字符串\n\t */\n\ttoSVG() {\n\t\t// SVG头部,包含命名空间和画布尺寸\n\t\tlet svg = `<svg width=\"${this.width}\" height=\"${this.height}\" xmlns=\"http://www.w3.org/2000/svg\" viewBox=\"0 0 ${this.width} ${this.height}\">`;\n\n\t\t// 添加背景色(如果有)\n\t\tif(this.style && this.style.fill) {\n\t\t\tsvg += `<rect width=\"100%\" height=\"100%\" fill=\"${this.style.fill}\"/>`;\n\t\t}\n\n\t\t// 遍历所有直接添加的形状\n\t\tthis.children.each((i, shape) => {\n\t\t\tif(shape.toSVG) {\n\t\t\t\tsvg += shape.toSVG();\n\t\t\t}\n\t\t});\n\n\t\tsvg += '</svg>';\n\t\treturn svg;\n\t}\n\n\t/**\n\t * 下载文件\n\t * 创建临时链接元素触发浏览器下载\n\t * \n\t * @method downloadFile\n\t * @private\n\t * @param {string} url 文件URL或Data URL\n\t * @param {string} fileName 文件名(不含扩展名)\n\t * @param {string} extension 文件扩展名\n\t */\n\tdownloadFile(url, fileName, extension) {\n\t\t// 创建临时链接元素\n\t\tconst link = document.createElement('a');\n\t\tlink.href = url;\n\t\tlink.download = `${fileName}.${extension}`;\n\t\t\n\t\t// 添加到DOM并触发点击\n\t\tdocument.body.appendChild(link);\n\t\tlink.click();\n\t\t\n\t\t// 清理DOM\n\t\tdocument.body.removeChild(link);\n\t}\n\n\t/** \n\t * 自动刷新画版\n\t * @param {function} callback 执行回调\n\t */\n\tautoRefresh(callback) {\n\t\tif(this.___isAutoRefreshing) return;\n\t\tconst self = this;\n\t\tthis.___isAutoRefreshing = true;\n\t\t\n\t\tconst refreshStartTime = Date.now();\n\t\tfunction update() {\n\t\t\tif(self.destroyed) {\n\t\t\t\tself.___isAutoRefreshing = false;\n\t\t\t\treturn;// 已销毁\n\t\t\t}\n\t\t\tif(self.needUpdate) self.redraw();\n\n\t\t\tconst time = Date.now() - refreshStartTime;\n\t\t\t// 触发刷新事件\n\t\t\tself.emit('update', time);\n\n\t\t\t// 直接 requestAnimationFrame,无需先 cancel\n\t\t\tself.__requestAnimationFrameFunHandler = self.requestAnimationFrame(update);\n\t\t\tif(callback) callback();\n\t\t}\n\t\tself.__requestAnimationFrameFunHandler && this.cancelAnimationFrame(self.__requestAnimationFrameFunHandler);\n\t\tself.__requestAnimationFrameFunHandler = this.requestAnimationFrame(update);\n\t\treturn this;\n\t}\n\n\t// 销毁当前对象\n\tdestroy() {\n\t\tthis.eventHandler.destroy();\n\t\tthis.destroyed = true;// 标记已销毁\n\t}\n}\n\nexport {\n\tjmGraph,\n\tjmUtils,\n\tjmList,\n\tjmProperty,\n\tjmShadow,\n\tjmGradient,\n\tjmFilter,\n\tjmEvents,\n\tjmControl,\n\tjmPath,\n };\n"],"names":["jmList","Array","ps","arg","length","isArray","i","push","option","type","obj","this","includes","_typeof","removeAt","index","splice","removeHandler","call","find","cb","inverse","len","handler","count","colorKeywords","aliceblue","antiquewhite","aqua","aquamarine","azure","beige","bisque","black","blanchedalmond","blue","blueviolet","brown","burlywood","cadetblue","chartreuse","chocolate","coral","cornflowerblue","cornsilk","crimson","cyan","darkblue","darkcyan","darkgoldenrod","darkgray","darkgreen","darkkhaki","darkmagenta","darkolivegreen","darkorange","darkorchid","darkred","darksalmon","darkseagreen","darkslateblue","darkslategray","darkslategrey","darkturquoise","darkviolet","deeppink","deepskyblue","dimgray","dimgrey","dodgerblue","firebrick","floralwhite","forestgreen","fuchsia","gainsboro","ghostwhite","gold","goldenrod","gray","green","greenyellow","grey","honeydew","hotpink","indianred","indigo","ivory","khaki","lavender","lavenderblush","lawngreen","lemonchiffon","lightblue","lightcoral","lightcyan","lightgoldenrodyellow","lightgrey","lightgreen","lightpink","lightsalmon","lightseagreen","lightskyblue","lightslategray","lightslategrey","lightsteelblue","lightyellow","lime","limegreen","linen","magenta","maroon","mediumaquamarine","mediumblue","mediumorchid","mediumpurple","mediumseagreen","mediumslateblue","mediumspringgreen","mediumturquoise","mediumvioletred","midnightblue","mintcream","mistyrose","moccasin","navajowhite","navy","oldlace","olive","olivedrab","orange","orangered","orchid","palegoldenrod","palegreen","paleturquoise","palevioletred","papayawhip","peachpuff","peru","pink","plum","powderblue","purple","red","rebeccapurple","rosybrown","royalblue","saddlebrown","salmon","sandybrown","seagreen","seashell","sienna","silver","skyblue","slateblue","slategray","slategrey","snow","springgreen","steelblue","tan","teal","thistle","tomato","turquoise","violet","wheat","white","whitesmoke","yellow","yellowgreen","transparent","activeborder","activecaption","appworkspace","background","buttonface","buttonhighlight","buttonshadow","buttontext","captiontext","graytext","highlight","highlighttext","inactiveborder","inactivecaption","inactivecaptiontext","infobackground","infotext","menu","menutext","scrollbar","threeddarkshadow","threedface","threedhighlight","threedlightshadow","threedshadow","window","windowframe","windowtext","jmUtils","source","target","deep","copyHandler","deepIndex","cloned","WeakMap","undefined","has","get","isType","dest","set","clone","slice","tagName","getContext","emit","__proto__","Object","keys","concat","getOwnPropertySymbols","v","k","name","fun","opt","indexOf","ns","split","bindEvent","attachEvent","addEventListener","removeEventListener","detachEvent","el","pos","offsetParent","top","offsetTop","left","offsetLeft","x","y","evt","scale","isWXMiniApp","event","isTouch","touches","changedTouches","targetTouches","srcElement","px","pageX","clientX","document","documentElement","scrollLeft","body","py","pageY","clientY","scrollTop","ox","offsetX","oy","offsetY","p","getElementPosition","layerX","layerY","screenX","screenY","constructor","pt","polygon","offset","n","Math","abs","pointOnLine","rayCasting","p1","p2","minX","min","maxX","max","minY","maxY","f","l","sqrt","inside","testY","testX","j","yi","yj","xi","xj","parentBounds","targetBounds","result","right","bottom","rp","r","cos","sin","x1","y1","c","sc","substring","trimStart","trimEnd","per","trim","tmp","checkPercent","h","toLowerCase","iv","floor","hex","__hexToRGBA_Cache","m","res","color","a","substr","g","b","Number","hexToNumber","toFixed","match","byteToDecimal","hexToRGBA","callback","win","requestAnimationFrame","setTimeout","cancelAnimationFrame","clearTimeout","control_id_counter","jmObject","graph","id","is","arguments","animateHandles","params","add","millisec","handle","self","dispatcher","_this","overduehandles","curTimes","Date","now","each","ani","times","apply","e","remove","animate","PROPERTY_KEY","Symbol","jmProperty","mode","pars","pros","value","args","oldValue","newValue","property","needUpdate","findParent","canvas","jmShadow","blur","fromString","s","ms","test","jmGradient","stops","control","gradient","context","bounds","absoluteBounds","getAbsoluteBounds","x2","y2","location","getLocation","d","radius","width","height","num","percentToNumber","parseFloat","isNaN","sx1","sy1","sx2","sy2","webglControl","createLinearGradient","key","toString","r1","r2","createRadialGradient","createCircularGradient","toColor","addColorStop","content","colorCount","gradientMatch","console","warn","splitIndex","_findSplitIndex","colorPart","_parseLinearParams","_parseRadialParams","_parseColorStops","depth","char","_angle","coords","trimmed","startsWith","direction","dir","_directionToAngle","angle","_hasAngleUnit","_parseAngle","_angleToCoords","parts","shape","position","atMatch","shapePart","posPart","_parseRadialShape","_parseRadialPosition","sizeMatch","sizes","rx","ry","_splitColorStops","lastOffset","finalOffset","stop","parsed","_parseSingleColorStop","_isValidColor","_normalizeOffset","nextOffset","_findNextOffset","addStop","current","hexMatch","rgbaMatch","hslaMatch","namedMatch","currentIndex","endsWith","str","angleStr","PI","round","directions","keywordMatch","mainDir","secDir","replace","combined","jmFilter","filters","addFilter","normalized","existing","regex","exec","valueStr","map","join","some","findIndex","jmEvents","container","mouseHandler","jmMouseEvent","keyHandler","jmKeyEvent","eventName","raiseEvent","destroy","instance","eventEvents","init","doc","preventDefault","touchStart","passive","touchMove","touchEnd","touchCancel","removeEvent","checkKeyEvent","earcut","data","holeIndices","dim","invSize","hasHoles","outerLen","outerNode","linkedList","triangles","next","prev","start","list","queue","end","steiner","leftmost","getLeftmost","sort","compareX","hole","bridge","hx","hy","qx","Infinity","mx","my","tanMin","pointInTriangle","locallyInside","area","sectorContainsSector","findHoleBridge","bridgeReverse","splitPolygon","filterPoints","eliminateHole","eliminateHoles","earcutLinked","clockwise","last","signedArea","insertNode","equals","removeNode","again","ear","pass","z","zOrder","prevZ","nextZ","q","tail","numMerges","pSize","qSize","inSize","sortLinked","indexCurve","ax","bx","cx","ay","by","cy","x0","y0","minZ","maxZ","isEarHashed","isEar","intersects","cureLocalIntersections","intersectsPolygon","middleInside","isValidDiagonal","splitEarcut","q1","q2","o1","sign","o2","o3","o4","onSegment","a2","Node","b2","an","bp","sum","deviation","polygonArea","trianglesArea","flatten","vertices","holes","dimensions","holeIndex","WebglGradient","_sortedStops","_paramsHash","utils","needNormalize","_getSortedStops","flatStops","Float32Array","gradientType","gradientStart","gradientEnd","stopCount","forEach","createShader","gl","src","shader","shaderSource","compileShader","GLSL_TO_SIZE","mapSize","GL_TABLE","GL_TO_GLSL_TYPES","mapType","typeNames","tn","createProgram","vertexSrc","fragmentSrc","vertexShader","VERTEX_SHADER","fragmentShader","FRAGMENT_SHADER","program","attachShader","linkProgram","getProgramParameter","LINK_STATUS","error","VALIDATE_STATUS","getError","getProgramInfoLog","deleteProgram","useProgram","deleteShader","attrs","attributes","ACTIVE_ATTRIBUTES","attribData","getActiveAttrib","size","getAttribLocation","extractAttributes","uniforms","ACTIVE_UNIFORMS","uniformData","getActiveUniform","getUniformLocation","extractUniforms","createBuffer","ARRAY_BUFFER","drawType","STATIC_DRAW","buffer","Error","bindBuffer","bufferData","unitSize","BYTES_PER_ELEMENT","create2DTexture","texture","createTexture","pixelStorei","UNPACK_FLIP_Y_WEBGL","activeTexture","TEXTURE0","bindTexture","TEXTURE_2D","texParameterf","TEXTURE_MAG_FILTER","NEAREST","TEXTURE_MIN_FILTER","TEXTURE_WRAP_S","CLAMP_TO_EDGE","TEXTURE_WRAP_T","pathVertexSource","pathFragmentSource","MAX_STOPS","WeblBase","style","globalAlpha","stateStack","transformMatrix","state","pop","sx","sy","currentA","currentB","currentC","currentD","currentE","currentF","point","tx","ty","__measureCtx","createElement","pathProgram","isGradient","__parseCSSColor","rgbToDecimal","colorStr","ctx","_measureCtx","clearRect","fillStyle","fillRect","getImageData","__curent_program","attr","strip","dataType","FLOAT","vertexAttribPointer","enableVertexAttribArray","writeVertexAttrib","disableVertexAttribArray","createFloat32Buffer","Uint16Array","createUint16Buffer","bufferHandler","deleteBuffer","log","img","texImage2D","RGBA","UNSIGNED_BYTE","pixels","Uint8Array","deleteTexture","points","pointsToArray","earCutCache","earCutPoints","p3","arr","webglGradient","text","fontSize","save","font","fontFamily","measureText","restore","parseInt","WebglPath","WebglBase","isRegular","needCut","__cachedBuffers","__cachedTexture","__cachedTextureKey","buf","float32","DYNAMIC_DRAW","parentAbsoluteBounds","__lastCenterX","__lastCenterY","uniform2f","a_center_point","convertColor","uniform4f","v_single_color","colorData","colorBuffer","a_color","setParentBounds","pathPoints","a_position","fixedPoints","transformedPoint","applyTransform","vertexBuffer","dx","dy","pow","linePoints","genLinePoints","subPaths","maxArea","outerIdx","outerPoints","isTexture","allPoints","vertexData","indices","allVertices","allTexCoords","vertexArr","posBuffer","_this2","texData","texBuffer","a_text_coord","drawArrays","TRIANGLES","lines","index1","index2","line1","line2","equalPoint","sub1","cuted","intersection","getIntersection","sub2","cutLines","area_abc","area_abd","area_cda","t","line","root","polygons","unshift","getIntersectionLines","pathToLines","treeLine","trianglesCache","getPolygon","earCutPointsToTriangles","strokeStyle","lineWidth","setFragColor","uniform1f","a_point_size","a_type","uniform1i","regular","hasMoveTo","isRing","subPath","writePoints","LINE_LOOP","mid","inner","outer","pathToPoints","POINTS","fillColor","fillImage","fillGradient","fillPolygons","toUniformParams","u_gradient_type","u_gradient_start","uniform4fv","u_gradient_end","u_gradient_stop_count","u_gradient_offsets","offsets","uniform1fv","u_gradient_colors","colors","lastR","lastG","lastB","lastA","ImageData","createDataTexture","createImgTexture","u_sample","v_texture_bounds","fillTexture","TRIANGLE_FAN","splitSubPaths","fillWithHoles","getTriangles","_this3","__textCanvas","willReadFrequently","shadowColor","shadowBlur","shadowOffsetX","shadowOffsetY","textAlign","textBaseline","fillText","maxWidth","strokeText","jmStyleMap","jmControl","hitArea","zIndex","interactive","initializing","on","bind","children","css","cur","oadd","parent","contain","oremove","levelItems","zindex","clear","__setStyle","mpkey","styleValue","dash","mpname","toGradient","setStyle","getRotation","__translateAbsolutePosition","toAbsolutePoint","translate","rotate","transform","scaleX","skewX","skewY","scaleY","cursor","setLineDash","filter","lineDashOffset","toCanvasFilter","globalCompositeOperation","clip","beginPath","moveTo","lineTo","close","closePath","__mask","isReset","rect","rotation","getBounds","local","oldBounds","rotatePoints","needResolve","center","margin","marginObj","trans","offseted","cpoints","rec","prec","beginDraw","fill","stroke","endDraw","draw","visible","initPoints","needDraw","maskStyle","mask","mBounds","item","paint","__events","eventCollection","getEvent","events","unbind","runEventHandle","cancel","pad","getPosition","pointInPolygon","getEventPosition","button","keyCode","charCode","which","ctrlKey","path","stoped","abounds","inpos","checkPoint","runEventAndPopEvent","focused","__mvMonitor","mouseDown","curposition","mv","outside","offsetx","offsety","lockSide","thisbounds","checkOutSide","mu","ml","md","jmPath","pathData","svg","opacity","jmGraph","devicePixelRatio","util","scaleFactor","translation","wx","canIUse","createSelectorQuery","select","getElementById","parentElement","cn","appendChild","offsetWidth","clientWidth","offsetHeight","clientHeight","preserveDrawingBuffer","enable","BLEND","blendFunc","SRC_ALPHA","ONE_MINUS_SRC_ALPHA","__init","shapes","assign","dpr","getWindowInfo","pixelRatio","dprScaleSize","resize","eventHandler","autoRefresh","w","__normalSize","viewport","redraw","__lastClearColor","clearColor","COLOR_BUFFER_BIT","createShape","scaleSize","normalSize","zoom","oldZoom","newZoom","toDataURL","fileName","format","quality","dataURL","downloadFile","exportToPNG","toSVG","blob","Blob","url","URL","createObjectURL","revokeObjectURL","extension","link","href","download","click","removeChild","___isAutoRefreshing","refreshStartTime","__requestAnimationFrameFunHandler","update","time","destroyed"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"jmgraph.core.min.js","sources":["../src/core/jmList.js","../src/core/jmUtils.js","../src/core/jmObject.js","../src/core/jmProperty.js","../src/core/jmShadow.js","../src/core/jmGradient.js","../src/core/jmFilter.js","../src/core/jmEvents.js","../src/lib/earcut.js","../src/lib/webgl/gradient.js","../src/lib/webgl/core/shader.js","../src/lib/webgl/core/mapSize.js","../src/lib/webgl/core/mapType.js","../src/lib/webgl/core/program.js","../src/lib/webgl/core/buffer.js","../src/lib/webgl/core/texture.js","../src/lib/webgl/base.js","../src/lib/webgl/path.js","../src/core/jmControl.js","../src/core/jmPath.js","../src/core/jmGraph.js"],"sourcesContent":["/**\n * @fileoverview jmList 列表类\n * \n * jmList 是 jmGraph 库的集合类,继承自原生 Array。\n * 提供了增强的列表操作方法,包括去重添加、条件查找、遍历等。\n * \n * 主要功能:\n * - 去重添加元素(add)\n * - 条件查找(get)\n * - 正向/反向遍历(each)\n * - 元素计数(count)\n * - 移除回调支持\n * \n * @module jmList\n * @author jmGraph Team\n * @license MIT\n */\n\n/**\n * jmList 列表类\n * \n * 继承自 Array 的增强列表类,提供去重、遍历、查找等功能。\n * 主要用于管理图形对象的子元素集合。\n * \n * @class jmList\n * @extends Array\n * \n * @param {...*} arg 初始元素或数组\n * \n * @example\n * // 创建列表\n * const list = new jmList([1, 2, 3]);\n * \n * // 添加元素(自动去重)\n * list.add(4);\n * list.add([5, 6]);\n * \n * // 遍历\n * list.each((index, item) => {\n * console.log(index, item);\n * });\n * \n * // 条件查找\n * const found = list.get(item => item > 3);\n */\nexport default class jmList extends Array {\n /**\n * 构造函数\n * \n * @param {...*} arg 初始元素或数组\n */\n constructor(...arg) {\n const ps = [];\n if(arg && arg.length && Array.isArray(arg[0])) {\n for(let i=0; i< arg[0].length; i++) ps.push(arg[0][i]);\n super(...ps);\n }\n else {\n super();\n }\n /**\n * 配置选项\n * @type {Object}\n * @property {function} removeHandler 元素移除时的回调函数\n */\n this.option = {};\n /**\n * 类型标识\n * @type {string}\n */\n this.type = 'jmList';\n }\n\n /**\n * 添加元素到列表\n * \n * 自动去重,如果元素已存在则不会重复添加。\n * 支持添加单个元素或数组。\n * \n * @method add\n * @param {*} obj 要添加的元素或数组\n * @returns {*} 添加的元素\n * \n * @example\n * list.add(1); // 添加单个元素\n * list.add([2, 3, 4]); // 添加数组\n */\n add(obj) {\n if(obj && Array.isArray(obj)) {\n for(let i=0; i < obj.length; i++) {\n if(!this.includes(obj[i])) this.push(obj[i]);\n }\n return obj;\n }\n if(typeof obj == 'object' && this.includes(obj)) return obj;\n this.push(obj);\n return obj;\n }\n\n /**\n * 从列表中移除元素\n * \n * 移除所有匹配的元素,并触发移除回调。\n * \n * @method remove\n * @param {*} obj 要移除的元素\n * \n * @example\n * list.remove(item);\n */\n remove(obj) {\n for(let i = this.length -1; i>=0; i--) {\n if(this[i] == obj) {\n this.removeAt(i);\n }\n }\n }\n\n /**\n * 移除指定索引位置的元素\n * \n * @method removeAt\n * @param {number} index 要移除的元素索引\n * \n * @example\n * list.removeAt(0); // 移除第一个元素\n */\n removeAt(index) {\n if(this.length > index) {\n const obj = this[index];\n this.splice(index,1);\n if(this.option.removeHandler) this.option.removeHandler.call(this, obj, index);\n }\n }\n\n /**\n * 检查列表是否包含指定元素\n * \n * @method contain\n * @param {*} obj 要检查的元素\n * @returns {boolean} 如果包含返回 true,否则返回 false\n * \n * @example\n * if (list.contain(item)) {\n * console.log('元素存在');\n * }\n */\n contain(obj) {\n return this.includes(obj);\n }\n\n /**\n * 获取元素\n * \n * 如果参数是函数,则返回第一个满足条件的元素;\n * 如果参数是数字,则返回指定索引的元素。\n * \n * @method get\n * @param {number|function} index 索引或条件函数\n * @returns {*} 找到的元素,如果未找到返回 undefined\n * \n * @example\n * // 按索引获取\n * const item = list.get(0);\n * \n * // 按条件查找\n * const found = list.get(item => item.id === 5);\n */\n get(index) {\n if(typeof index == 'function') {\n return this.find(index);\n }\n else {\n return this[index];\n }\n }\n\n /**\n * 遍历列表\n * \n * 支持正向和反向遍历。在回调中返回 false 可以中断遍历。\n * \n * @method each\n * @param {function} cb 回调函数,参数为 (index, item)\n * @param {boolean} [inverse=false] 是否反向遍历\n * \n * @example\n * // 正向遍历\n * list.each((index, item) => {\n * console.log(index, item);\n * if (item.id === 3) return false; // 中断遍历\n * });\n * \n * // 反向遍历\n * list.each((index, item) => {\n * console.log(index, item);\n * }, true);\n */\n each(cb, inverse) {\n if(cb && typeof cb == 'function') {\n if(inverse) {\n for(let i = this.length - 1;i>=0; i--) {\n const r = cb.call(this, i, this[i]);\n if(r === false) break;\n }\n }\n else {\n const len = this.length;\n for(let i = 0; i < len;i++) {\n const r = cb.call(this, i, this[i]);\n if(r === false) break;\n }\n }\n }\n }\n\n /**\n * 统计元素数量\n * \n * 如果提供了条件函数,返回满足条件的元素数量;\n * 否则返回列表总长度。\n * \n * @method count\n * @param {function} [handler] 条件函数\n * @returns {number} 元素数量\n * \n * @example\n * const total = list.count(); // 总数量\n * const matched = list.count(item => item.active); // 满足条件的数量\n */\n count(handler) {\n if(handler && typeof handler == 'function') {\n let count = 0;\n const len = this.length;\n for(let i = 0; i<len;i++) {\n if(handler(this[i])) {\n count++;\n }\n }\n return count;\n }\n return this.length;\n }\n\n /**\n * 清空列表\n * \n * 移除列表中的所有元素。\n * \n * @method clear\n * \n * @example\n * list.clear();\n */\n clear() {\n this.splice(0, this.length);\n }\n}\n\nexport { jmList };","\n/**\n * @fileoverview jmGraph 工具类\n * \n * jmUtils 是 jmGraph 库的核心工具类,提供了一系列静态工具方法:\n * - 对象克隆与深拷贝\n * - 事件绑定与解绑\n * - DOM 元素位置计算\n * - 几何计算(点在多边形内判断、旋转等)\n * - 颜色解析与转换\n * - 字符串处理\n * \n * 所有方法都是静态的,可以直接通过 jmUtils.methodName() 调用。\n * \n * @module jmUtils\n * @author jmGraph Team\n * @license MIT\n */\n\nimport { jmList } from './jmList.js';\n\n/**\n * CSS 颜色关键字映射表\n * \n * 包含所有 CSS 标准颜色名称到十六进制值的映射。\n * 支持 147 种命名颜色 + CSS 系统颜色。\n * \n * @constant {Object.<string, string>}\n * @private\n */\nconst colorKeywords = {\n aliceblue: \"#f0f8ff\",\n antiquewhite: \"#faebd7\",\n aqua: \"#00ffff\",\n aquamarine: \"#7fffd4\",\n azure: \"#f0ffff\",\n beige: \"#f5f5dc\",\n bisque: \"#ffe4c4\",\n black: \"#000000\",\n blanchedalmond: \"#ffebcd\",\n blue: \"#0000ff\",\n blueviolet: \"#8a2be2\",\n brown: \"#a52a2a\",\n burlywood: \"#deb887\",\n cadetblue: \"#5f9ea0\",\n chartreuse: \"#7fff00\",\n chocolate: \"#d2691e\",\n coral: \"#ff7f50\",\n cornflowerblue: \"#6495ed\",\n cornsilk: \"#fff8dc\",\n crimson: \"#dc143c\",\n cyan: \"#00ffff\",\n darkblue: \"#00008b\",\n darkcyan: \"#008b8b\",\n darkgoldenrod: \"#b8860b\",\n darkgray: \"#a9a9a9\",\n darkgreen: \"#006400\",\n darkkhaki: \"#bdb76b\",\n darkmagenta: \"#8b008b\",\n darkolivegreen: \"#556b2f\",\n darkorange: \"#ff8c00\",\n darkorchid: \"#9932cc\",\n darkred: \"#8b0000\",\n darksalmon: \"#e9967a\",\n darkseagreen: \"#8fbc8f\",\n darkslateblue: \"#483d8b\",\n darkslategray: \"#2f4f4f\",\n darkslategrey: \"#2f4f4f\",\n darkturquoise: \"#00ced1\",\n darkviolet: \"#9400d3\",\n deeppink: \"#ff1493\",\n deepskyblue: \"#00bfff\",\n dimgray: \"#696969\",\n dimgrey: \"#696969\",\n dodgerblue: \"#1e90ff\",\n firebrick: \"#b22222\",\n floralwhite: \"#fffaf0\",\n forestgreen: \"#228b22\",\n fuchsia: \"#ff00ff\",\n gainsboro: \"#dcdcdc\",\n ghostwhite: \"#f8f8ff\",\n gold: \"#ffd700\",\n goldenrod: \"#daa520\",\n gray: \"#808080\",\n green: \"#008000\",\n greenyellow: \"#adff2f\",\n grey: \"#808080\",\n honeydew: \"#f0fff0\",\n hotpink: \"#ff69b4\",\n indianred: \"#cd5c5c\",\n indigo: \"#4b0082\",\n ivory: \"#fffff0\",\n khaki: \"#f0e68c\",\n lavender: \"#e6e6fa\",\n lavenderblush: \"#fff0f5\",\n lawngreen: \"#7cfc00\",\n lemonchiffon: \"#fffacd\",\n lightblue: \"#add8e6\",\n lightcoral: \"#f08080\",\n lightcyan: \"#e0ffff\",\n lightgoldenrodyellow: \"#fafad2\",\n lightgrey: \"#d3d3d3\",\n lightgreen: \"#90ee90\",\n lightpink: \"#ffb6c1\",\n lightsalmon: \"#ffa07a\",\n lightseagreen: \"#20b2aa\",\n lightskyblue: \"#87cefa\",\n lightslategray: \"#778899\",\n lightslategrey: \"#778899\",\n lightsteelblue: \"#b0c4de\",\n lightyellow: \"#ffffe0\",\n lime: \"#00ff00\",\n limegreen: \"#32cd32\",\n linen: \"#faf0e6\",\n magenta: \"#ff00ff\",\n maroon: \"#800000\",\n mediumaquamarine: \"#66cdaa\",\n mediumblue: \"#0000cd\",\n mediumorchid: \"#ba55d3\",\n mediumpurple: \"#9370d8\",\n mediumseagreen: \"#3cb371\",\n mediumslateblue: \"#7b68ee\",\n mediumspringgreen: \"#00fa9a\",\n mediumturquoise: \"#48d1cc\",\n mediumvioletred: \"#c71585\",\n midnightblue: \"#191970\",\n mintcream: \"#f5fffa\",\n mistyrose: \"#ffe4e1\",\n moccasin: \"#ffe4b5\",\n navajowhite: \"#ffdead\",\n navy: \"#000080\",\n oldlace: \"#fdf5e6\",\n olive: \"#808000\",\n olivedrab: \"#6b8e23\",\n orange: \"#ffa500\",\n orangered: \"#ff4500\",\n orchid: \"#da70d6\",\n palegoldenrod: \"#eee8aa\",\n palegreen: \"#98fb98\",\n paleturquoise: \"#afeeee\",\n palevioletred: \"#d87093\",\n papayawhip: \"#ffefd5\",\n peachpuff: \"#ffdab9\",\n peru: \"#cd853f\",\n pink: \"#ffc0cb\",\n plum: \"#dda0dd\",\n powderblue: \"#b0e0e6\",\n purple: \"#800080\",\n red: \"#ff0000\",\n rebeccapurple: \"#663399\",\n rosybrown: \"#bc8f8f\",\n royalblue: \"#4169e1\",\n saddlebrown: \"#8b4513\",\n salmon: \"#fa8072\",\n sandybrown: \"#f4a460\",\n seagreen: \"#2e8b57\",\n seashell: \"#fff5ee\",\n sienna: \"#a0522d\",\n silver: \"#c0c0c0\",\n skyblue: \"#87ceeb\",\n slateblue: \"#6a5acd\",\n slategray: \"#708090\",\n slategrey: \"#708090\",\n snow: \"#fffafa\",\n springgreen: \"#00ff7f\",\n steelblue: \"#4682b4\",\n tan: \"#d2b48c\",\n teal: \"#008080\",\n thistle: \"#d8bfd8\",\n tomato: \"#ff6347\",\n turquoise: \"#40e0d0\",\n violet: \"#ee82ee\",\n wheat: \"#f5deb3\",\n white: \"#ffffff\",\n whitesmoke: \"#f5f5f5\",\n yellow: \"#ffff00\",\n yellowgreen: \"#9acd32\",\n transparent: \"rgba(0,0,0,0)\",\n // grey 别名(已有 darkslategrey/lightslategrey/slategrey/dimgrey)\n // 以下为 CSS 系统颜色\n activeborder: \"#bfcaca\",\n activecaption: \"#000080\",\n appworkspace: \"#ababab\",\n background: \"#636363\",\n buttonface: \"#c0c0c0\",\n buttonhighlight: \"#dedede\",\n buttonshadow: \"#808080\",\n buttontext: \"#000000\",\n captiontext: \"#000000\",\n graytext: \"#808080\",\n highlight: \"#b3d4fc\",\n highlighttext: \"#000000\",\n inactiveborder: \"#d4d0c8\",\n inactivecaption: \"#bfbbb0\",\n inactivecaptiontext: \"#545454\",\n infobackground: \"#fbfcc5\",\n infotext: \"#000000\",\n menu: \"#c0c0c0\",\n menutext: \"#000000\",\n scrollbar: \"#c0c0c0\",\n threeddarkshadow: \"#696969\",\n threedface: \"#c0c0c0\",\n threedhighlight: \"#dfdfdf\",\n threedlightshadow: \"#dcdcdc\",\n threedshadow: \"#808080\",\n window: \"#ffffff\",\n windowframe: \"#646464\",\n windowtext: \"#000000\"\n };\n\n/**\n * jmGraph 工具类\n * \n * 提供常用的静态工具方法,包括对象操作、事件处理、几何计算、颜色转换等。\n * \n * @class jmUtils\n * @static\n * \n * @example\n * // 克隆对象\n * const newObj = jmUtils.clone({ a: 1, b: 2 });\n * \n * // 绑定事件\n * jmUtils.bindEvent(element, 'click', handler);\n * \n * // 检查点是否在多边形内\n * const inside = jmUtils.pointInPolygon({x: 10, y: 10}, polygonPoints);\n */\nexport default class jmUtils {\n /**\n * 复制一个对象\n * \n * @method clone\n * @static\n * @param {object} source 被复制的对象\n * @param {object} target 可选,如果指定就表示复制给这个对象,如果为boolean它就是deep参数\n * @param {boolean} deep 是否深度复制,如果为true,数组内的每个对象都会被复制\n * @param {function} copyHandler 复制对象回调,如果返回undefined,就走后面的逻辑,否则到这里中止\n * @return {object} 参数source的拷贝对象\n */\n static clone(source, target, deep = false, copyHandler = null, deepIndex = 0, cloned = null) {\n // 如果有指定回调,则用回调处理,否则走后面的复制逻辑\n if(typeof copyHandler === 'function') {\n const obj = copyHandler(source, deep, deepIndex);\n if(obj) return obj;\n }\n\n // 首次调用时初始化克隆映射表(用于处理循环引用)\n if(!cloned) cloned = new WeakMap();\n\n if(typeof target === 'boolean') {\n deep = target;\n target = undefined;\n }\n\n // 非对象直接返回\n if(!source || typeof source !== 'object') {\n return typeof target !== 'undefined' ? target : source;\n }\n\n // 如果source已经被克隆过,直接返回之前的克隆对象,打破循环引用\n if(cloned.has(source)) return cloned.get(source);\n\n // 数组处理\n if(Array.isArray(source)) {\n //如果为当前泛型,则直接new\n if(this.isType(source, jmList)) {\n return new jmList(source);\n }\n if(deep) {\n let dest = [];\n cloned.set(source, dest);\n for(let i = 0; i < source.length; i++) {\n dest.push(this.clone(source[i], undefined, deep, copyHandler, deepIndex + 1, cloned));\n }\n return dest;\n }\n return source.slice(0);\n }\n\n // 不复制页面元素和class对象(如jmControl实例等复杂对象保持引用)\n if(source.tagName || source.getContext || source.emit) {\n return source;\n }\n\n // 普通对象处理\n target = target || {};\n cloned.set(source, target);\n\n // 保持原型链一致\n if(source.__proto__) target.__proto__ = source.__proto__;\n \n // 遍历自身可枚举属性(字符串键 + Symbol键),避免触发原型链上宿主对象的getter\n const keys = Object.keys(source).concat(Object.getOwnPropertySymbols(source));\n for(const k of keys) {\n if(k === 'constructor') continue;\n const v = source[k];\n // 不复制页面元素和class对象\n if(v && (v.tagName || v.getContext || v.emit)) {\n target[k] = v;\n continue;\n }\n\n // 如果不是对象和空,则采用target的属性\n if(typeof target[k] === 'object' || typeof target[k] === 'undefined') { \n target[k] = this.clone(v, target[k], deep, copyHandler, deepIndex + 1, cloned);\n }\n }\n return target;\n }\n\n /**\n * 绑定事件到html对象\n * \n * @method bindEvent\n * @static\n * @param {element} html元素对象\n * @param {string} name 事件名称\n * @param {function} fun 事件委托\n * @returns {name, fun, target} 返回当前绑定\n */\n static bindEvent(target, name, fun, opt) {\n if(name && name.indexOf && name.indexOf(' ') != -1) {\n let ns = name.split(' ');\n for(let i=0;i<ns.length;i++) {\n this.bindEvent(target, ns[i], fun, opt);\n }\n }\n if(target.attachEvent) {\n target.attachEvent(\"on\"+name, fun, opt);\n } \n else if(target.addEventListener) {\n target.addEventListener(name, fun, opt);\n }\n return {\n name,\n target,\n fun\n };\n }\n\n /**\n * 从对象中移除事件到\n * \n * @method removeEvent\n * @static\n * @param {element} html元素对象\n * @param {string} name 事件名称\n * @param {function} fun 事件委托\n */\n static removeEvent(target, name, fun) {\n if(target.removeEventListener) {\n return target.removeEventListener(name, fun, false);\n } \n else if(target.detachEvent) {\n target.detachEvent('on' + name, fun);\n return true;\n }\n else {\n target['on' + name] = null;\n }\n }\n\n /**\n * 获取元素的绝对定位\n *\n * @method getElementPosition\n * @static\n * @param {element} el 目标元素对象\n * @return {position} 位置对象(top,left)\n */\n static getElementPosition(el) { \n let pos = {\"top\": 0, \"left\": 0};\n if(!el) return pos;\n\n if (el.offsetParent) {\n while (el.offsetParent) {\n pos.top += el.offsetTop;\n pos.left += el.offsetLeft;\n el = el.offsetParent;\n }\n }\n\t\telse if(el.x) {\n\t\t\tpos.left += el.x;\n\t\t}\n\t\telse if(el.y){\n\t\t\tpos.top += el.y;\n\t\t}\n return pos;\n }\n /**\n * 获取元素事件触发的位置\n *\n * @method getEventPosition\n * @static\n * @param {eventArg} evt 当前触发事件的参数\n * @param {point} [scale] 当前画布的缩放比例\n * @return {point} 事件触发的位置 \n */\n static getEventPosition (evt, scale) {\n evt = evt || event;\n const isWXMiniApp = evt.isWXMiniApp;\n let isTouch = false;\n let touches = evt.changedTouches || evt.targetTouches || evt.touches;\n let target = evt.target || evt.srcElement;\n if(touches && touches.length) {\n evt = touches[0];//兼容touch事件 \n if(!evt.target) evt.target = target;\n isTouch = true;\n }\n let px = evt.pageX || evt.x;\n if(typeof px == 'undefined') px = evt.clientX + (document.documentElement.scrollLeft || document.body.scrollLeft); \n let py = evt.pageY || evt.y;\n if(typeof py == 'undefined') py = evt.clientY + (document.documentElement.scrollTop || document.body.scrollTop);\n\n let ox = evt.offsetX;\n let oy = evt.offsetY;\n if(typeof ox === 'undefined' && typeof oy === 'undefined') {\n // 小程序下取x,y就是它的相对坐标\n if(isWXMiniApp) {\n ox = evt.x;\n oy = evt.y;\n }\n else {\n let p = this.getElementPosition(target);\n ox= px - p.left;\n oy = py - p.top;\n }\n }\n if(scale) {\n if(scale.x) ox = ox / scale.x;\n if(scale.y) oy = oy / scale.y;\n }\n\n return {\n pageX: px,\n pageY: py,\n clientX: evt.clientX,\n clientY: evt.clientY,\n //相对于容器偏移量\n offsetX: ox,\n offsetY: oy,\n layerX: evt.layerX,\n layerY: evt.layerY,\n screenX: evt.screenX,\n screenY: evt.screenY,\n x: ox,\n y: oy,\n isTouch: isTouch,\n touches,\n isWXMiniApp\n };\n }\n\n /**\n * 检 查对象是否为指定的类型,不包括继承\n * \n * @method isType\n * @static\n * @param {object} target 需要判断类型的对象\n * @param {class} type 对象类型\n * @return {boolean} 返回对象是否为指定类型 \n */\n static isType(target, type) {\n if(!target || typeof target !== 'object') return false;\n if(target.constructor === type) return true;\n /*if(target.__baseType) { \n return jmUtils.isType(target.__baseType.prototype,type);\n }*/\n\n //return target instanceof type;\n return false;\n }\n /**\n * 判断点是否在多边形内\n * 如果一个点在多边形内部,任意角度做射线肯定会与多边形要么有一个交点,要么有与多边形边界线重叠。\n * 如果一个点在多边形外部,任意角度做射线要么与多边形有一个交点,要么有两个交点,要么没有交点,要么有与多边形边界线重叠。\n * 利用上面的结论,我们只要判断这个点与多边形的交点个数,就可以判断出点与多边形的位置关系了。\n * \n * @method pointInPolygon\n * @static\n * @param {point} pt 坐标对象\n * @param {array} polygon 多边型角坐标对象数组\n * @param {number} offset 判断可偏移值\n * @return {integer} 0= 不在图形内和线上,1=在边上,2=在图形内部\n */\n static pointInPolygon(pt, polygon, offset) {\n offset = offset || 1;\n offset = offset / 2;\n const n = polygon.length;\n \n if(!polygon || n == 0) return 0;\n \n if(n == 1) {\n return Math.abs(polygon[0].x - pt.x) <= offset && Math.abs(polygon[0].y - pt.y) <= offset ? 1 : 0;\n }\n \n if(n == 2) {\n return this.pointOnLine(pt, polygon[0], polygon[1], offset);\n }\n\n for (let i = 0; i < n; i++) {\n if (Math.abs(polygon[i].x - pt.x) <= offset && \n Math.abs(polygon[i].y - pt.y) <= offset) {\n return 1;\n }\n }\n\n return this.rayCasting(pt, polygon, offset);\n }\n\n /**\n * 判断点是否在线段上\n * \n * 通过计算点到线段的垂直距离来判断点是否在线段上。\n * 同时检查点是否在线段的范围内(不仅仅是直线上)。\n * \n * @method pointOnLine\n * @static\n * @private\n * @param {Object} pt 待检测的点 {x, y}\n * @param {Object} p1 线段起点 {x, y}\n * @param {Object} p2 线段终点 {x, y}\n * @param {number} offset 允许的偏差值(像素)\n * @returns {number} 0=不在线段上, 1=在线段上\n * \n * @example\n * const onLine = jmUtils.pointOnLine(\n * {x: 5, y: 5}, // 待检测点\n * {x: 0, y: 0}, // 起点\n * {x: 10, y: 10}, // 终点\n * 2 // 允许偏差\n * );\n * // 返回 1,点在对角线上\n */\n static pointOnLine(pt, p1, p2, offset) {\n const minX = Math.min(p1.x, p2.x);\n const maxX = Math.max(p1.x, p2.x);\n const minY = Math.min(p1.y, p2.y);\n const maxY = Math.max(p1.y, p2.y);\n\n if (minX - pt.x > offset || pt.x - maxX > offset) {\n return 0;\n }\n if (minY - pt.y > offset || pt.y - maxY > offset) {\n return 0;\n }\n\n if (p1.x == p2.x) {\n return Math.abs(p1.x - pt.x) <= offset && \n (pt.y - p1.y) * (pt.y - p2.y) <= 0 ? 1 : 0;\n }\n\n if (p1.y == p2.y) {\n return Math.abs(p1.y - pt.y) <= offset && \n (pt.x - p1.x) * (pt.x - p2.x) <= 0 ? 1 : 0;\n }\n\n if (Math.abs(p1.x - pt.x) < offset && Math.abs(p1.y - pt.y) < offset) {\n return 1;\n }\n if (Math.abs(p2.x - pt.x) < offset && Math.abs(p2.y - pt.y) < offset) {\n return 1;\n }\n\n if (pt.y != p1.y && pt.y != p2.y) {\n const f = (p2.x - p1.x) / (p2.y - p1.y) * (pt.y - p1.y);\n const ff = (pt.y - p1.y) / Math.sqrt(f * f + (pt.y - p1.y) * (pt.y - p1.y));\n const l = ff * (pt.x - p1.x - f);\n \n return Math.abs(l) <= offset ? 1 : 0;\n }\n return 0;\n }\n\n /**\n * 射线法判断点是否在多边形内部\n * \n * 从待测点向右发射一条水平射线,计算与多边形边界的交点数量。\n * - 交点数为奇数:点在多边形内部\n * - 交点数为偶数:点在多边形外部\n * \n * 这是判断点是否在任意多边形内的经典算法,时间复杂度 O(n)。\n * \n * @method rayCasting\n * @static\n * @private\n * @param {Object} pt 待检测的点 {x, y}\n * @param {Array<Object>} polygon 多边形顶点数组 [{x, y}, ...]\n * @param {number} offset 允许的偏差值(未使用)\n * @returns {number} 0=在多边形外部, 2=在多边形内部\n * \n * @see {@link https://en.wikipedia.org/wiki/Point_in_polygon Point in polygon - Wikipedia}\n */\n static rayCasting(pt, polygon, offset) {\n const n = polygon.length;\n let inside = false;\n const testY = pt.y;\n const testX = pt.x;\n\n for (let i = 0, j = n - 1; i < n; j = i++) {\n const yi = polygon[i].y;\n const yj = polygon[j].y;\n const xi = polygon[i].x;\n const xj = polygon[j].x;\n\n const intersect = ((yi > testY) !== (yj > testY)) &&\n (testX < (xj - xi) * (testY - yi) / (yj - yi) + xi);\n\n if (intersect) {\n inside = !inside;\n }\n }\n\n return inside ? 2 : 0;\n }\n\n /**\n * @method judge 判断点是否在多边形中\n * @param {point} dot {{x,y}} 需要判断的点\n * @param {array} coordinates {{x,y}} 多边形点坐标的数组,为保证图形能够闭合,起点和终点必须相等。\n * 比如三角形需要四个点表示,第一个点和最后一个点必须相同。 \n * @param {number} 是否为实心 1= 是\n * @returns {boolean} 结果 true=在形状内\n */\n /*static judge(dot,coordinates,noneZeroMode) {\n // 默认启动none zero mode\n noneZeroMode=noneZeroMode||1;\n var x = dot.x,y=dot.y;\n var crossNum = 0;\n // 点在线段的左侧数目\n var leftCount = 0;\n // 点在线段的右侧数目\n var rightCount = 0;\n for(var i=0;i<coordinates.length-1;i++){\n var start = coordinates[i];\n var end = coordinates[i+1];\n \n // 起点、终点斜率不存在的情况\n if(start.x===end.x) {\n // 因为射线向右水平,此处说明不相交\n if(x>start.x) continue;\n \n // 从左侧贯穿\n if((end.y>start.y&&y>=start.y && y<=end.y)){\n leftCount++;\n crossNum++;\n }\n // 从右侧贯穿\n if((end.y<start.y&&y>=end.y && y<=start.y)) {\n rightCount++;\n crossNum++;\n }\n continue;\n }\n // 斜率存在的情况,计算斜率\n var k=(end.y-start.y)/(end.x-start.x);\n // 交点的x坐标\n var x0 = (y-start.y)/k+start.x;\n // 因为射线向右水平,此处说明不相交\n if(x>x0) continue;\n \n if((end.x>start.x&&x0>=start.x && x0<=end.x)){\n crossNum++;\n if(k>=0) leftCount++;\n else rightCount++;\n }\n if((end.x<start.x&&x0>=end.x && x0<=start.x)) {\n crossNum++;\n if(k>=0) rightCount++;\n else leftCount++;\n }\n }\n \n return noneZeroMode===1?leftCount-rightCount!==0:crossNum%2===1;\n }*/\n\n /**\n * 检查边界,子对象是否超出父容器边界\n * 当对象偏移offset后是否出界\n * 返回(left:0,right:0,top:0,bottom:0)\n * 如果right>0表示右边出界right偏移量,left<0则表示左边出界left偏移量\n * 如果bottom>0表示下边出界bottom偏移量,top<0则表示上边出界ltop偏移量\n *\n * @method checkOutSide\n * @static\n * @param {bound} parentBounds 父对象的边界\n * @param {bound} targetBounds 对象的边界\n * @param {number} offset 判断是否越界可容偏差\n * @return {bound} 越界标识\n */\n static checkOutSide(parentBounds, targetBounds, offset) {\n let result = {left:0,right:0,top:0,bottom:0};\n if(offset.x < 0 ) {\n result.left = targetBounds.left + offset.x - parentBounds.left;\n }\n else if(offset.x > 0 ) {\n result.right = targetBounds.right + offset.x - parentBounds.right;\n }\n\n if(offset.y < 0 ) {\n result.top = targetBounds.top + offset.y - parentBounds.top;\n }\n else if(offset.y > 0) {\n result.bottom = targetBounds.bottom + offset.y - parentBounds.bottom;\n }\n return result;\n }\n\n /**\n * 把一个或多个点绕某个点旋转一定角度\n * 先把坐标原点移到旋转中心点,计算后移回\n * @method rotatePoints\n * @static\n * @param {Array/object} p 一个或多个点\n * @param {*} rp 旋转中心点\n * @param {*} r 旋转角度\n */\n static rotatePoints(p, rp, r) {\n if(!r || !p) return p;\n let cos = Math.cos(r);\n let sin = Math.sin(r);\n if(Array.isArray(p)) {\n for(let i=0;i<p.length;i++) {\n if(!p[i]) continue;\n let x1 = p[i].x - rp.x;\n let y1 = p[i].y - rp.y;\n p[i].x = x1 * cos - y1 * sin + rp.x;\n p[i].y = x1 * sin + y1 * cos + rp.y;\n }\n }\n else {\n let x1 = p.x - rp.x;\n let y1 = p.y - rp.y;\n p.x = x1 * cos - y1 * sin + rp.x;\n p.y = x1 * sin + y1 * cos + rp.y;\n }\n return p;\n }\n\n /**\n * 去除字符串开始字符\n * \n * @method trimStart\n * @static\n * @param {string} source 需要处理的字符串\n * @param {char} [c] 要去除字符串的前置字符\n * @return {string} 去除前置字符后的字符串\n */\n static trimStart(source, c) {\n c = c || ' ';\n if(source && source.length > 0) {\n let sc = source[0];\n if(sc === c || c.indexOf(sc) >= 0) {\n source = source.substring(1);\n return this.trimStart(source,c);\n } \n }\n return source;\n }\n\n /**\n * 去除字符串结束的字符c\n *\n * @method trimEnd\n * @static\n * @param {string} source 需要处理的字符串\n * @param {char} [c] 要去除字符串的后置字符\n * @return {string} 去除后置字符后的字符串\n */\n static trimEnd(source, c) {\n c = c || ' ';\n if(source && source.length > 0) {\n let sc = source[source.length - 1];\n if(sc === c || c.indexOf(sc) >= 0) {\n source = source.substring(0,source.length - 1);\n return this.trimStart(source,c);\n } \n }\n return source;\n }\n\n /**\n * 去除字符串开始与结束的字符\n *\n * @method trim\n * @static\n * @param {string} source 需要处理的字符串\n * @param {char} [c] 要去除字符串的字符\n * @return {string} 去除字符后的字符串\n */\n static trim(source,c) {\n return this.trimEnd(this.trimStart(source,c),c);\n }\n\n /**\n * 检查是否为百分比参数\n *\n * @method checkPercent\n * @static\n * @param {string} 字符串参数\n * @return {boolean} true=当前字符串为百分比参数,false=不是\n */\n static checkPercent(per) {\n if(typeof per === 'string') {\n per = this.trim(per);\n if(per[per.length - 1] == '%') {\n return per;\n }\n }\n }\n\n /**\n * 转换百分数为数值类型\n *\n * @method percentToNumber\n * @static\n * @param {string} per 把百分比转为数值的参数\n * @return {number} 百分比对应的数值\n */\n static percentToNumber(per) {\n if(typeof per === 'string') {\n let tmp = this.checkPercent(per);\n if(tmp) {\n per = this.trim(tmp,'% ');\n per = per / 100;\n }\n }\n return per;\n }\n\n /**\n * 转换16进制为数值\n *\n * @method hexToNumber\n * @static\n * @param {string} h 16进制颜色表达\n * @return {number} 10进制表达\n */\n static hexToNumber(h) {\n if(typeof h !== 'string') return h;\n\n h = h.toLowerCase();\n let hex = '0123456789abcdef';\n let v = 0;\n let l = h.length;\n for(let i=0;i<l;i++) {\n let iv = hex.indexOf(h[i]);\n if(iv == 0) continue;\n \n for(let j=1;j<l - i;j++) {\n iv *= 16;\n }\n v += iv;\n }\n return v;\n }\n\n /**\n * 转换数值为16进制字符串表达\n *\n * @method hex\n * @static\n * @param {number} v 数值\n * @return {string} 16进制表达\n */\n static numberToHex(v) {\n let hex = '0123456789abcdef';\n \n let h = '';\n while(v > 0) {\n let t = v % 16;\n h = hex[t] + h;\n v = Math.floor(v / 16);\n }\n return h;\n }\n\n /**\n * 16进制颜色转为r g b a 对象 {r, g , b, a}\n * @param {string}} hex 16进度的颜色\n */\n static hexToRGBA(hex) {\n if(typeof hex === 'string') hex = this.trim(hex); \n else return hex;\n\n // 如果缓存存在,则直接返回\n this.__hexToRGBA_Cache = this.__hexToRGBA_Cache || {};\n if(this.__hexToRGBA_Cache[hex]) return this.__hexToRGBA_Cache[hex];\n\n let res = hex;\n\n // 系统颜色\n if(colorKeywords[res]) res = colorKeywords[res];\n\n //当为7位时,表示需要转为带透明度的rgba\n if(res[0] == '#') {\n const color = {\n a: 1\n };\n if(res.length >= 8) {\n color.a = res.substr(1,2);\n color.g = res.substr(5,2);\n color.b = res.substr(7,2);\n color.r = res.substr(3,2);\n //透明度\n color.a = Number((this.hexToNumber(color.a) / 255).toFixed(4));\n\n color.r = this.hexToNumber(color.r||0);\n color.g = this.hexToNumber(color.g||0);\n color.b = this.hexToNumber(color.b||0);\n res = color; \n }\n // #cccccc || #ccc\n else if(res.length === 7 || res.length === 4) {\n // #ccc这种情况,把每个位复制一份\n if(res.length === 4) {\n color.g = res.substr(2, 1);\n color.g = color.g + color.g;\n color.b = res.substr(3, 1);\n color.b = color.b + color.b;\n color.r = res.substr(1, 1);\n color.r = color.r + color.r;\n }\n else {\n color.g = res.substr(3, 2);//除#号外的第二位\n color.b = res.substr(5, 2);\n color.r = res.substr(1, 2);\n }\n\n color.r = this.hexToNumber(color.r||0);\n color.g = this.hexToNumber(color.g||0);\n color.b = this.hexToNumber(color.b||0);\n \n res = color; \n }\n //如果是5位的话,# 则第2位表示A,后面依次是r,g,b\n else if(res.length === 5) {\n color.a = res.substr(1,1);\n color.g = res.substr(3,1);//除#号外的第二位\n color.b = res.substr(4,1);\n color.r = res.substr(2,1);\n\n color.r = this.hexToNumber(color.r||0);\n color.g = this.hexToNumber(color.g||0);\n color.b = this.hexToNumber(color.b||0);\n //透明度\n color.a = Number((this.hexToNumber(color.a) / 255).toFixed(4));\n res = color; \n }\n } \n if(typeof res === 'string') {\n const m = res.match(/rgb(a)?\\s*\\(\\s*([\\d\\.]+)\\s*,\\s*([\\d\\.]+)\\s*,\\s*([\\d\\.]+)\\s*(,\\s*[\\d\\.]+)?\\s*\\)/i); \n if(m && m.length === 6) {\n const color = {\n r: Number(m[2]),\n g: Number(m[3]),\n b: Number(m[4]),\n a: Number(this.trimStart(m[5]||'1', ','))\n };\n res = color;\n }\n }\n return this.__hexToRGBA_Cache[hex] = res; \n }\n\n /**\n * 将 RGB 颜色值从 0-255 范围转换为 0-1 范围\n * \n * WebGL 中的颜色值通常使用 0-1 的浮点数表示,\n * 此方法用于将标准 RGB 值转换为 WebGL 兼容格式。\n * \n * @method rgbToDecimal\n * @static\n * @param {Object} color 颜色对象 {r, g, b, a?}\n * @returns {Object} 转换后的颜色对象 {r, g, b, a?},其中 r/g/b 为 0-1 范围\n * \n * @example\n * const color = jmUtils.rgbToDecimal({ r: 255, g: 128, b: 64 });\n * // 返回 { r: 1, g: 0.502, b: 0.251 }\n */\n static rgbToDecimal(color) {\n color = this.clone(color);\n color.r = this.byteToDecimal(color.r);\n color.g = this.byteToDecimal(color.g);\n color.b = this.byteToDecimal(color.b);\n return color;\n }\n\n /**\n * 将字节值(0-255)转换为小数(0-1)\n * \n * @method byteToDecimal\n * @static\n * @private\n * @param {number} b 字节值(0-255)\n * @returns {number} 小数值(0-1)\n */\n static byteToDecimal(b) {\n return b / 255;\n }\n\n /**\n * 转换颜色格式,如果输入r,g,b则转为hex格式,如果为hex则转为r,g,b格式\n *\n * @method toColor\n * @static\n * @param {string} hex 16进制颜色表达\n * @return {string} 颜色字符串\n */\n static toColor(r, g, b, a) { \n if(typeof r === 'string' && r) {\n r = this.trim(r); \n // 正常的颜色表达,不需要转换\n if(r[0] === '#' && (r.length === 4 || r.length === 7)) return r;\n\n const color = this.hexToRGBA(r);\n if(typeof color === 'string') return color;\n \n r = typeof color.r !== 'undefined'? color.r: r;\n g = typeof color.g !== 'undefined'? color.g: g;\n b = typeof color.b !== 'undefined'? color.b: b;\n a = typeof color.a !== 'undefined'? color.a: a;\n }\n if(r && typeof r === 'object') {\n g = r.g;\n b = r.b;\n a = r.a || 1;\n r = r.r;\n }\n if(typeof r != 'undefined' && typeof g != 'undefined' && typeof b != 'undefined') {\n if(typeof a != 'undefined') { \n return 'rgba(' + r + ',' + g + ',' + b + ',' + a + ')';\n }\n else {\n return 'rgb(' + r + ',' + g + ',' + b + ')';\n }\n }\n return r;\n }\n /**\n * 请求动画帧\n * \n * 封装浏览器原生的 requestAnimationFrame 方法,提供跨浏览器兼容性。\n * 在不支持 requestAnimationFrame 的环境中降级为 setTimeout。\n * \n * @method requestAnimationFrame\n * @static\n * @param {Function} callback 动画帧回调函数,接收时间戳参数\n * @param {Window} [win] 可选的窗口对象(用于多窗口环境)\n * @returns {number} 动画帧请求ID,用于取消\n * \n * @example\n * let animationId;\n * function animate(timestamp) {\n * // 更新动画\n * animationId = jmUtils.requestAnimationFrame(animate);\n * }\n * animationId = jmUtils.requestAnimationFrame(animate);\n * \n * // 取消动画\n * jmUtils.cancelAnimationFrame(animationId);\n */\n static requestAnimationFrame(callback, win) {\n let fun = win && win.requestAnimationFrame? win.requestAnimationFrame: (typeof window !== 'undefined' && window.requestAnimationFrame? window.requestAnimationFrame: setTimeout); \n\t\treturn fun(callback, 20);\n }\n /**\n * 取消动画帧请求\n * \n * 取消之前通过 requestAnimationFrame 注册的回调。\n * 在不支持 cancelAnimationFrame 的环境中降级为 clearTimeout。\n * \n * @method cancelAnimationFrame\n * @static\n * @param {number} handler requestAnimationFrame 返回的请求ID\n * @param {Window} [win] 可选的窗口对象(用于多窗口环境)\n * \n * @example\n * const animationId = jmUtils.requestAnimationFrame(animate);\n * jmUtils.cancelAnimationFrame(animationId);\n */\n static cancelAnimationFrame(handler, win) {\n let fun = win && win.cancelAnimationFrame? win.cancelAnimationFrame: (typeof window !== 'undefined' && window.cancelAnimationFrame? window.cancelAnimationFrame: clearTimeout); \n\t\treturn fun(handler);\n }\t\n}\nexport { jmUtils };\nexport { colorKeywords };","\n/**\n * @fileoverview jmGraph 基础对象类\n * \n * jmObject 是 jmGraph 库中所有对象的基类,提供了:\n * - 唯一ID生成机制\n * - 类型检查方法\n * - 动画帧调度系统\n * \n * @module jmObject\n * @author jmGraph Team\n * @license MIT\n */\n\nimport {jmList} from \"./jmList.js\";\n\n/**\n * 控件ID计数器\n * 用于为每个新创建的对象生成唯一标识符\n * @type {number}\n * @private\n */\nlet control_id_counter = 0;\n\n/**\n * jmGraph 基础对象类\n * \n * 所有图形控件、属性对象、工具类的基类。\n * 提供了对象标识、类型检查和动画调度等核心功能。\n * \n * @class jmObject\n * @example\n * // 创建一个基础对象\n * const obj = new jmObject();\n * console.log(obj.id); // 输出唯一ID\n * \n * // 类型检查\n * obj.is('jmObject'); // true\n * obj.is(jmObject); // true\n */\nexport default class jmObject {\n\t/**\n\t * 构造函数\n\t * \n\t * 创建一个新的基础对象实例,自动分配唯一ID。\n\t * 如果传入的是 jmGraph 实例,则建立关联关系。\n\t * \n\t * @constructor\n\t * @param {jmGraph} [g] - 可选的 jmGraph 实例,用于建立对象与画布的关联\n\t * \n\t * @example\n\t * // 创建独立对象\n\t * const obj = new jmObject();\n\t * \n\t * // 创建关联画布的对象\n\t * const graph = new jmGraph(canvas);\n\t * const objWithGraph = new jmObject(graph);\n\t */\n\tconstructor(g) {\n\t\t// 如果传入的是 jmGraph 实例,则建立引用关系\n\t\tif(g && g.type == 'jmGraph') {\n\t\t\tthis.graph = g;\n\t\t}\n\t\t// 生成唯一ID\n\t\tthis.id = ++control_id_counter;\n\t}\n\t\n\t/**\n\t * 检查对象是否为指定类型\n\t * \n\t * 支持两种类型检查方式:\n\t * 1. 字符串方式:检查对象的 type 属性是否匹配\n\t * 2. 类构造函数方式:使用 instanceof 检查原型链\n\t * \n\t * @method is\n\t * @param {string|Function} type - 要检查的类型名称(字符串)或类构造函数\n\t * @returns {boolean} 如果对象是指定类型则返回 true,否则返回 false\n\t * \n\t * @example\n\t * // 使用字符串检查\n\t * control.is('jmRect'); // 检查是否为矩形\n\t * \n\t * // 使用类构造函数检查\n\t * control.is(jmControl); // 检查是否为 jmControl 实例\n\t * control.is(jmPath); // 检查是否继承自 jmPath\n\t */\n\tis(type) {\n\t\t// 字符串类型:检查 type 属性\n\t\tif(typeof type == 'string') {\n\t\t\treturn this.type == type;\n\t\t}\n\t\t// 类构造函数:使用 instanceof 检查原型链\n\t\treturn this instanceof type;\n\t}\n\n\t/**\n\t * 注册并执行动画帧回调\n\t * \n\t * 提供动画帧调度功能,支持:\n\t * - 按指定时间间隔执行回调\n\t * - 多个动画句柄并行执行\n\t * - 自动清理返回 false 的动画\n\t * - 错误自动移除异常动画\n\t * \n\t * 此方法通常由 jmGraph 实例调用,子控件会委托给所属的 graph 处理。\n\t * \n\t * @method animate\n\t * @param {Function} handle - 动画回调函数,返回 false 时自动移除\n\t * @param {number} [millisec=20] - 执行间隔(毫秒),默认 20ms\n\t * @param {...*} [params] - 传递给回调函数的额外参数\n\t * \n\t * @example\n\t * // 创建一个简单的动画\n\t * let x = 0;\n\t * graph.animate(function() {\n\t * x += 1;\n\t * rect.position.x = x;\n\t * graph.redraw();\n\t * \n\t * // 动画结束条件\n\t * if(x > 100) return false;\n\t * }, 16); // 约60fps\n\t * \n\t * // 带参数的动画\n\t * graph.animate(function(speed) {\n\t * x += speed;\n\t * // ...\n\t * }, 16, 5); // speed = 5\n\t */\n\tanimate(...args) {\n\t\t// 只有 jmGraph 实例才真正处理动画调度\n\t\tif(this.is('jmGraph')) {\n\t\t\t// 注册新的动画句柄\n\t\t\tif(args.length > 1) {\n\t\t\t\tif(!this.animateHandles) this.animateHandles = new jmList();\n\t\t\t\t\n\t\t\t\t// 收集额外参数\n\t\t\t\tconst params = [];\n\t\t\t\tif(args.length > 2) {\n\t\t\t\t\tfor(let i=2;i<args.length;i++) {\n\t\t\t\t\t\tparams.push(args[i]);\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\t// 添加动画句柄到列表\n\t\t\t\tthis.animateHandles.add({\n\t\t\t\t\tmillisec: args[1] || 20, // 执行间隔\n\t\t\t\t\thandle: args[0], // 回调函数\n\t\t\t\t\tparams: params // 额外参数\n\t\t\t\t});\n\t\t\t}\n\t\t\t\n\t\t\t// 如果有动画句柄,启动调度循环\n\t\t\tif(this.animateHandles) {\n\t\t\t\tif(this.animateHandles.count() > 0) {\n\t\t\t\t\tconst self = this;\n\t\t\t\t\t// 使用 setTimeout 进行调度(避免 requestAnimationFrame 的固定帧率限制)\n\t\t\t\t\tthis.dispatcher = setTimeout(function(_this) {\n\t\t\t\t\t\t_this = _this || self;\n\t\t\t\t\t\tconst overduehandles = []; // 需要移除的句柄\n\t\t\t\t\t\tconst curTimes = Date.now();\n\t\t\t\t\t\t\n\t\t\t\t\t\t// 遍历执行所有动画句柄\n\t\t\t\t\t\t_this.animateHandles.each(function(i,ani) {\n\t\t\t\t\t\t\ttry {\n\t\t\t\t\t\t\t\t// 检查是否到达执行时间\n\t\t\t\t\t\t\t\tif(ani && ani.handle && (!ani.times || curTimes - ani.times >= ani.millisec)) {\n\t\t\t\t\t\t\t\t\t// 执行回调\n\t\t\t\t\t\t\t\t\tconst r = ani.handle.apply(_this, ani.params);\n\t\t\t\t\t\t\t\t\t// 返回 false 表示动画结束\n\t\t\t\t\t\t\t\t\tif(r === false) {\n\t\t\t\t\t\t\t\t\t\toverduehandles.push(ani);\n\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t\t// 更新最后执行时间\n\t\t\t\t\t\t\t\t\tani.times = curTimes;\n\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\tcatch(e) {\n\t\t\t\t\t\t\t\t// 出错的句柄自动移除\n\t\t\t\t\t\t\t\tif(ani) overduehandles.push(ani);\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t});\n\t\t\t\t\t\t\n\t\t\t\t\t\t// 移除已完成的动画句柄\n\t\t\t\t\t\tfor(const i in overduehandles) {\n\t\t\t\t\t\t\t_this.animateHandles.remove(overduehandles[i]);\n\t\t\t\t\t\t}\n\t\t\t\t\t\t\n\t\t\t\t\t\t// 继续下一轮调度\n\t\t\t\t\t\t_this.animate();\n\t\t\t\t\t},10,this);\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t\telse {\n\t\t\t// 非 jmGraph 对象委托给所属的 graph 处理\n\t\t\tconst graph = this.graph;\n\t\t\tif(graph) {\n\t\t\t\tgraph.animate(...args);\n\t\t\t}\n\t\t}\n\t}\n}\n\nexport { jmObject };","\n/**\n * @fileoverview jmGraph 属性管理基类\n * \n * jmProperty 是 jmGraph 库中属性管理的核心类,继承自 jmObject。\n * 提供了:\n * - 基于 Symbol 的私有属性存储\n * - 属性变更事件通知机制\n * - 渲染模式管理(2D/WebGL)\n * - 动画帧请求封装\n * \n * @module jmProperty\n * @extends jmObject\n * @author jmGraph Team\n * @license MIT\n */\n\nimport {jmUtils} from \"./jmUtils.js\";\nimport { jmObject } from \"./jmObject.js\";\n\n/**\n * 属性存储的 Symbol 键\n * 使用 Symbol 确保属性存储的私有性和唯一性\n * @type {Symbol}\n * @private\n */\nconst PROPERTY_KEY = Symbol(\"properties\");\n\n/**\n * jmGraph 属性管理基类\n * \n * jmProperty 是 jmControl 的父类,为所有图形控件提供属性管理功能。\n * 采用 Symbol + WeakMap 模式实现真正的私有属性存储,避免属性名冲突。\n * \n * 核心特性:\n * 1. **私有属性存储**:使用 Symbol 键确保属性不被外部直接访问\n * 2. **属性变更通知**:设置属性时自动触发 'propertyChange' 事件\n * 3. **渲染模式继承**:子控件自动继承所属 graph 的渲染模式\n * 4. **脏标记传播**:子控件 needUpdate 会自动传播到 graph\n * \n * @class jmProperty\n * @extends jmObject\n * \n * @example\n * // 创建属性对象\n * const prop = new jmProperty({ mode: 'webgl' });\n * \n * // 设置和获取属性\n * prop.property('customValue', 100);\n * console.log(prop.property('customValue')); // 100\n * \n * // 监听属性变更\n * prop.on('propertyChange', (name, args) => {\n * console.log(`${name} changed from ${args.oldValue} to ${args.newValue}`);\n * });\n */\nexport default class jmProperty extends jmObject {\n\t/**\n\t * 构造函数\n\t * \n\t * 初始化属性存储对象,并设置初始渲染模式。\n\t * \n\t * @constructor\n\t * @param {Object} [params] - 初始化参数\n\t * @param {'2d'|'webgl'} [params.mode] - 渲染模式,默认 '2d'\n\t * \n\t * @example\n\t * // 创建使用 WebGL 渲染的属性对象\n\t * const prop = new jmProperty({ mode: 'webgl' });\n\t */\n\tconstructor(params) {\n\t\tsuper();\n\t\t// 初始化私有属性存储对象\n\t\tthis[PROPERTY_KEY] = {};\n\t\t// 设置渲染模式\n\t\tif(params && params.mode) this.mode = params.mode;\n\t}\n\n\t/**\n\t * 获取或设置属性值\n\t * \n\t * 这是属性系统的核心方法,所有属性的存取都通过此方法。\n\t * 设置属性时会自动触发 'propertyChange' 事件,便于实现响应式更新。\n\t * \n\t * @method property\n\t * @param {string} name - 属性名称\n\t * @param {*} [value] - 属性值(设置时提供)\n\t * @returns {*} 获取时返回属性值,设置时返回设置的值\n\t * \n\t * @example\n\t * // 获取属性\n\t * const value = obj.property('myProp');\n\t * \n\t * // 设置属性\n\t * obj.property('myProp', 'newValue');\n\t * \n\t * // 链式调用\n\t * obj.property('a', 1).property('b', 2);\n\t */\n\tproperty(...pars) {\n\t\tif(pars) {\n\t\t\tconst pros = this[PROPERTY_KEY];\n\t\t\tconst name = pars[0];\n\t\t\t\n\t\t\t// 设置属性\n\t\t\tif(pars.length > 1) {\n\t\t\t\tconst value = pars[1];\n\t\t\t\tconst args = {oldValue: pros[name], newValue: value};\n\t\t\t\tpros[name] = pars[1];\n\t\t\t\t// 触发属性变更事件(如果对象支持事件)\n\t\t\t\tif(this.emit) this.emit('propertyChange', name, args);\n\t\t\t\treturn pars[1];\n\t\t\t}\n\t\t\t// 获取属性\n\t\t\telse if(name) {\n\t\t\t\treturn pros[name];\n\t\t\t}\n\t\t}\n\t}\n\n\t/**\n\t * 是否需要重绘标记\n\t * \n\t * 当属性变化导致需要重新渲染时设置此标记。\n\t * 设置为 true 时,会自动将所属 graph 的 needUpdate 设为 true,\n\t * 从而触发画布重绘。\n\t * \n\t * @type {boolean}\n\t * \n\t * @example\n\t * // 标记需要重绘\n\t * control.needUpdate = true;\n\t * \n\t * // 检查是否需要重绘\n\t * if(control.needUpdate) {\n\t * control.redraw();\n\t * }\n\t */\n\tget needUpdate() {\n\t\treturn this.property('needUpdate');\n\t}\n\tset needUpdate(v) {\n\t\tthis.property('needUpdate', v);\n\t\t// 传播脏标记到 graph(避免 jmGraph 自身循环)\n\t\tif(v && !this.is('jmGraph') && this.graph) {\n\t\t\tthis.graph.needUpdate = true;\n\t\t}\n\t}\n\n\t/**\n\t * 所属的画布实例\n\t * \n\t * 获取或设置当前对象所属的 jmGraph 实例。\n\t * 如果未显式设置,会自动向上查找父级链中的 jmGraph。\n\t * \n\t * @type {jmGraph}\n\t * \n\t * @example\n\t * // 获取所属画布\n\t * const graph = control.graph;\n\t * \n\t * // 设置所属画布(通常由框架内部调用)\n\t * control.graph = myGraph;\n\t */\n\tget graph() {\n\t\tlet g = this.property('graph');\n\t\t// 如果未设置,尝试从父级链查找\n\t\tg = g || (this.property('graph', this.findParent('jmGraph')));\n\t\treturn g;\n\t}\n\tset graph(v) {\n\t\treturn this.property('graph', v);\n\t}\n\n\t/**\n\t * 渲染模式\n\t * \n\t * 获取当前渲染模式,支持 '2d' 和 'webgl' 两种模式。\n\t * 渲染模式的查找优先级:\n\t * 1. 当前对象设置的 mode\n\t * 2. 如果是 jmGraph,默认 '2d'\n\t * 3. 从所属 graph 继承 mode\n\t * \n\t * @type {'2d'|'webgl'}\n\t * @readonly\n\t * \n\t * @example\n\t * // 检查渲染模式\n\t * if(control.mode === 'webgl') {\n\t * // 使用 WebGL 特性\n\t * } else {\n\t * // 使用 Canvas 2D API\n\t * }\n\t */\n\tget mode() {\n\t\tlet m = this.property('mode');\n\t\tif(m) return m;\n\t\t// 如果当前对象是jmGraph且没有设置mode,返回默认值\n\t\tif(this.is('jmGraph')) return this.property('mode') || '2d';\n\t\t// 否则从所属的graph获取mode\n\t\treturn this.graph?.mode || '2d';\n\t}\n\tset mode(v) {\n\t\treturn this.property('mode', v);\n\t}\n\n\t/**\n\t * 请求动画帧\n\t * \n\t * 封装 requestAnimationFrame,支持在不同环境下工作。\n\t * 如果当前对象关联了 canvas,会使用 canvas 的 requestAnimationFrame。\n\t * \n\t * @method requestAnimationFrame\n\t * @param {Function} handler - 动画帧回调函数\n\t * @returns {number} 动画帧请求ID,用于取消\n\t * \n\t * @example\n\t * // 请求下一帧动画\n\t * const frameId = control.requestAnimationFrame(() => {\n\t * // 更新动画状态\n\t * control.redraw();\n\t * });\n\t * \n\t * // 取消动画帧\n\t * control.cancelAnimationFrame(frameId);\n\t */\n\trequestAnimationFrame(handler) {\n\t\treturn jmUtils.requestAnimationFrame(handler, this.graph? this.graph.canvas: null);\n\t}\n\n\t/**\n\t * 取消动画帧请求\n\t * \n\t * 取消之前通过 requestAnimationFrame 注册的回调。\n\t * \n\t * @method cancelAnimationFrame\n\t * @param {number} handler - 动画帧请求ID\n\t * \n\t * @example\n\t * // 取消动画帧\n\t * control.cancelAnimationFrame(frameId);\n\t */\n\tcancelAnimationFrame(handler) {\n\t\treturn jmUtils.cancelAnimationFrame(handler, this.graph? this.graph.canvas: null);\n\t}\n}\n\nexport { jmProperty };\n\n\n","/**\n * @fileoverview jmShadow 阴影类\n * \n * jmShadow 提供了图形阴影效果的创建和管理功能。\n * 支持设置阴影的偏移、模糊程度和颜色。\n * \n * 主要功能:\n * - 阴影偏移设置(x, y)\n * - 模糊程度设置(blur)\n * - 阴影颜色设置(color)\n * - 字符串解析和序列化\n * \n * @module jmShadow\n * @author jmGraph Team\n * @license MIT\n */\n\nimport {jmUtils} from \"./jmUtils.js\";\n\n/**\n * 阴影类\n * \n * 用于创建图形的阴影效果。阴影可以应用于任何图形控件。\n * \n * @class jmShadow\n * \n * @param {number|string} x 横坐标偏移量,或阴影字符串格式 'x,y,blur,color'\n * @param {number} [y] 纵坐标偏移量\n * @param {number} [blur] 模糊值\n * @param {string} [color] 阴影颜色\n * \n * @example\n * // 创建阴影\n * const shadow = new jmShadow(5, 5, 10, 'rgba(0,0,0,0.5)');\n * \n * // 从字符串创建\n * const shadow = new jmShadow('5, 5, 10, rgba(0,0,0,0.5)');\n * \n * // 应用到图形\n * rect.style.shadow = shadow;\n */\nexport default class jmShadow {\n\tconstructor(x, y, blur, color) {\n\t\tif(typeof x == 'string' && !y && !blur && !color) {\n\t\t\tthis.fromString(x);\n\t\t}\n\t\telse {\n\t\t\tthis.x = x;\n\t\t\tthis.y = y;\n\t\t\tthis.blur = blur;\n\t\t\tthis.color = color;\n\t\t}\n\t}\n\t/**\n\t * 根据字符串格式转为阴影\n\t * @method fromString\n\t * @param {string} s 阴影字符串 x,y,blur,color\n\t */\n\tfromString(s) {\n\t\tif(!s) return;\n\t\tlet ms = s.match(/\\s*([^,]+)\\s*,\\s*([^,]+)\\s*(,[^,]+)?\\s*(,[\\s\\S]+)?\\s*/i);\n\t\tif(ms) {\n\t\t\tthis.x = ms[1]||0;\n\t\t\tthis.y = ms[2]||0;\n\t\t\tif(ms[3]) {\n\t\t\t\tms[3] = jmUtils.trim(ms[3],', ');\n\t\t\t\t//如果第三位是颜色格式,则表示为颜色\n\t\t\t\tif(ms[3].indexOf('#')===0 || /^rgb/i.test(ms[3])) {\n\t\t\t\t\tthis.color = ms[3];\n\t\t\t\t}\n\t\t\t\telse {\n\t\t\t\t\tthis.blur = jmUtils.trim(ms[3],', ');\n\t\t\t\t}\n\t\t\t}\n\t\t\tif(ms[4]) {\n\t\t\t\tthis.color = jmUtils.trim(ms[4],', ');\n\t\t\t}\n\t\t}\n\t\treturn this;\n\t}\n\n\t/**\n\t * 转为字符串格式 x,y,blur,color\n\t * @method toString\n\t * @returns {string} 阴影字符串\n\t */\n\ttoString() {\n\t\tlet s = this.x + ',' + this.y;\n\t\tif(this.blur) s += ',' + this.blur;\n\t\tif(this.color) s += ',' + this.color;\n\t\treturn s;\n\t}\n}\n\nexport { jmShadow };","/**\n * @fileoverview jmGradient 渐变类\n * \n * jmGradient 提供了线性渐变和径向渐变的创建和管理功能。\n * 支持从 CSS 渐变字符串解析,以及转换为 Canvas 渐变对象。\n * \n * 主要功能:\n * - 线性渐变(linear-gradient)\n * - 径向渐变(radial-gradient)\n * - CSS 渐变字符串解析\n * - Canvas 渐变对象生成\n * - WebGL 渐变支持\n * \n * @module jmGradient\n * @author jmGraph Team\n * @license MIT\n */\n\nimport {jmUtils, colorKeywords} from \"./jmUtils.js\";\nimport {jmList} from \"./jmList.js\";\n\n/**\n * 渐变类\n * \n * 用于创建和管理线性渐变或径向渐变效果。\n * 支持 CSS 渐变字符串格式解析,可以转换为 Canvas 或 WebGL 兼容的渐变对象。\n * \n * @class jmGradient\n * \n * @param {Object|string} opt 渐变参数对象或 CSS 渐变字符串\n * @param {string} [opt.type='linear'] 渐变类型:'linear' 或 'radial'\n * @param {number|string} [opt.x1] 起点X坐标(支持百分比)\n * @param {number|string} [opt.y1] 起点Y坐标(支持百分比)\n * @param {number|string} [opt.x2] 终点X坐标(支持百分比)\n * @param {number|string} [opt.y2] 终点Y坐标(支持百分比)\n * @param {number|string} [opt.r1] 内圆半径(径向渐变)\n * @param {number|string} [opt.r2] 外圆半径(径向渐变)\n * @param {Array} [opt.stops] 颜色停止点数组 [{offset, color}, ...]\n * \n * @example\n * // 创建线性渐变\n * const gradient = new jmGradient({\n * type: 'linear',\n * x1: 0, y1: 0,\n * x2: '100%', y2: '100%',\n * stops: [\n * { offset: 0, color: '#ff0000' },\n * { offset: 1, color: '#0000ff' }\n * ]\n * });\n * \n * // 从 CSS 字符串创建\n * const gradient = new jmGradient('linear-gradient(180deg, #ff0000, #0000ff)');\n */\nexport default class jmGradient {\n\tconstructor(opt) {\n\t\tthis.stops = new jmList();\n\n\t\tif(opt && typeof opt == 'object') {\n\t\t\tfor(let k in opt) {\n\t\t\t\tif(k === 'stops') continue;\n\t\t\t\tthis[k] = opt[k];\n\t\t\t}\n\t\t\tif(opt.stops && Array.isArray(opt.stops)) {\n\t\t\t\tthis.stops.push(...opt.stops);\n\t\t\t}\n\t\t}\n\t\t//解析字符串格式\n\t\t//linear-gradient(direction, color-stop1, color-stop2, ...);\n\t\t//radial-gradient(center, shape size, start-color, ..., last-color);\n\t\telse if(typeof opt == 'string') {\n\t\t\tthis.fromString(opt);\n\t\t}\n\t}\n\t/**\n\t * 添加渐变色\n\t * \n\t * @method addStop\n\t * @for jmGradient\n\t * @param {number} offset 放射渐变颜色偏移,可为百分比参数。\n\t * @param {string} color 当前偏移颜色值\n\t */\n\taddStop(offset, color) {\n\t\tthis.stops.add({\n\t\t\toffset: Number(offset),\n\t\t\tcolor: color\n\t\t});\n\t}\n\n\t/**\n\t * 生成为canvas的渐变对象\n\t *\n\t * @method toGradient\n\t * @for jmGradient\n\t * @param {jmControl} control 当前渐变对应的控件\n\t * @return {gradient} canvas渐变对象\n\t */\n\ttoGradient(control) {\n\t\tlet gradient;\n\t\tlet context = control.context || control;\n\t\tlet bounds = control.absoluteBounds?control.absoluteBounds:control.getAbsoluteBounds();\n\t\tlet x1 = this.x1||0;\n\t\tlet y1 = this.y1||0;\n\t\tlet x2 = this.x2;\n\t\tlet y2 = this.y2;\n\n\t\tlet location = control.getLocation();\n\n\t\tlet d = 0;\n\t\tif(location.radius) {\n\t\t\td = location.radius * 2;\t\t\t\t\n\t\t}\n\t\tif(!d) {\n\t\t\td = Math.min(location.width || 0, location.height || 0);\t\t\t\t\n\t\t}\n\t\tif(d <= 0) {\n\t\t\td = Math.max(bounds.width || 0, bounds.height || 0, 100);\n\t\t}\n\n\t\tconst width = bounds.width || d;\n\t\tconst height = bounds.height || d;\n\n\t\tif(jmUtils.checkPercent(x1)) {\n\t\t\tx1 = jmUtils.percentToNumber(x1) * width;\n\t\t}\n\t\telse if(typeof x1 === 'number' && x1 >= 0 && x1 <= 1) {\n\t\t\tx1 = x1 * width;\n\t\t}\n\t\telse if(typeof x1 === 'string') {\n\t\t\tconst num = parseFloat(x1);\n\t\t\tif(!isNaN(num)) x1 = num;\n\t\t}\n\t\tif(jmUtils.checkPercent(x2)) {\n\t\t\tx2 = jmUtils.percentToNumber(x2) * width;\n\t\t}\n\t\telse if(typeof x2 === 'number' && x2 >= 0 && x2 <= 1) {\n\t\t\tx2 = x2 * width;\n\t\t}\n\t\telse if(typeof x2 === 'string') {\n\t\t\tconst num = parseFloat(x2);\n\t\t\tif(!isNaN(num)) x2 = num;\n\t\t}\n\t\tif(jmUtils.checkPercent(y1)) {\n\t\t\ty1 = jmUtils.percentToNumber(y1) * height;\n\t\t}\n\t\telse if(typeof y1 === 'number' && y1 >= 0 && y1 <= 1) {\n\t\t\ty1 = y1 * height;\n\t\t}\n\t\telse if(typeof y1 === 'string') {\n\t\t\tconst num = parseFloat(y1);\n\t\t\tif(!isNaN(num)) y1 = num;\n\t\t}\n\t\tif(jmUtils.checkPercent(y2)) {\n\t\t\ty2 = jmUtils.percentToNumber(y2) * height;\n\t\t}\n\t\telse if(typeof y2 === 'number' && y2 >= 0 && y2 <= 1) {\n\t\t\ty2 = y2 * height;\n\t\t}\n\t\telse if(typeof y2 === 'string') {\n\t\t\tconst num = parseFloat(y2);\n\t\t\tif(!isNaN(num)) y2 = num;\n\t\t}\n\n\t\tx1 = Number(x1) || 0;\n\t\ty1 = Number(y1) || 0;\n\t\tx2 = Number(x2) || 0;\n\t\ty2 = Number(y2) || 0;\n\n\t\tlet sx1 = x1 + (bounds.left || 0);\n\t\tlet sy1 = y1 + (bounds.top || 0);\n\t\tlet sx2 = x2 + (bounds.left || 0);\n\t\tlet sy2 = y2 + (bounds.top || 0);\n\t\tif(this.type === 'linear') {\n\t\t\tif(control.mode === 'webgl' && control.webglControl) {\n\t\t\t\t// WebGL 着色器中 v_text_coord 是绝对坐标,需要传递绝对坐标\n\t\t\t\tgradient = control.webglControl.createLinearGradient(sx1, sy1, sx2, sy2, bounds);\n\t\t\t\tgradient.key = this.toString();\n\t\t\t}\t\n\t\t\telse {\t\t\n\t\t\t\tcontext.createLinearGradient && (gradient = context.createLinearGradient(sx1, sy1, sx2, sy2));\n\t\t\t}\n\t\t}\n\t\telse if(this.type === 'radial') {\n\t\t\tlet r1 = this.r1||0;\n\t\t\tlet r2 = this.r2;\n\t\t\t\n\t\t\tif(d <= 0) {\n\t\t\t\td = Math.max(bounds.width || 0, bounds.height || 0, 1);\n\t\t\t}\n\t\t\t\n\t\t\tif(jmUtils.checkPercent(r1)) {\n\t\t\t\tr1 = jmUtils.percentToNumber(r1);\t\t\t\n\t\t\t\tr1 = d * r1;\n\t\t\t}\n\t\t\telse if(typeof r1 === 'number' && r1 >= 0 && r1 <= 1) {\n\t\t\t\tr1 = r1 * d;\n\t\t\t}\n\t\t\telse if(typeof r1 === 'string') {\n\t\t\t\tr1 = parseFloat(r1) || 0;\n\t\t\t}\n\t\t\t\n\t\t\tif(jmUtils.checkPercent(r2)) {\n\t\t\t\tr2 = jmUtils.percentToNumber(r2);\n\t\t\t\tr2 = d * r2;\n\t\t\t}\n\t\t\telse if(typeof r2 === 'number' && r2 >= 0 && r2 <= 1) {\n\t\t\t\tr2 = r2 * d;\n\t\t\t}\n\t\t\telse if(typeof r2 === 'string') {\n\t\t\t\tr2 = parseFloat(r2);\n\t\t\t}\n\t\t\t\n\t\t\tif(r2 === undefined || r2 === null || isNaN(Number(r2)) || Number(r2) <= 0) {\n\t\t\t\tr2 = d / 2;\n\t\t\t}\n\t\t\t\n\t\t\tr1 = Number(r1) || 0;\n\t\t\tr2 = Number(r2) || d / 2;\n\t\t\t\n\t\t\tif(control.mode === 'webgl' && control.webglControl) {\n\t\t\t\tgradient = control.webglControl.createRadialGradient(sx1, sy1, r1, sx2, sy2, r2, bounds);\n\t\t\t\tgradient.key = this.toString();\n\t\t\t}\t\n\t\t\telse if(context.createRadialGradient) {\n\t\t\t\tgradient = context.createRadialGradient(sx1, sy1, r1, sx2, sy2, r2);\t\n\t\t\t}\n\t\t\telse if(context.createCircularGradient) { \n\t\t\t\tgradient = context.createCircularGradient(sx1, sy1, r2);\n\t\t\t}\n\t\t}\n\t\t\n\t\t//颜色渐变\n\t\tif(gradient) {\n\t\t\tthis.stops.each(function(i,s) {\t\n\t\t\t\tlet c = jmUtils.toColor(s.color);\n\t\t\t\t//s.offset 0.0 ~ 1.0\n\t\t\t\tgradient && gradient.addColorStop(s.offset, c);\t\t\n\t\t\t});\n\t\t}\n\t\telse {\n\t\t\tconst s = this.stops.get(0);\n\t\t\treturn (s && s.color) || '#000';\n\t\t}\n\t\t\n\t\treturn gradient;\n\t}\n\n\t/**\n\t * 解析渐变字符串\n\t * 支持的格式:\n\t * - linear-gradient(180deg, #8b5cf6 0%, #6366f1 50%, #4f46e5 100%)\n\t * - linear-gradient(to top, red, blue)\n\t * - linear-gradient(to right bottom, red, blue)\n\t * - linear-gradient(45deg, red, blue)\n\t * - linear-gradient(0.5turn, red, blue)\n\t * - radial-gradient(circle, red, blue)\n\t * - radial-gradient(ellipse at top, red, blue)\n\t *\n\t * @method fromString\n\t * @for jmGradient\n\t * @param {string} s 渐变字符串\n\t */\n\tfromString(s) {\n\t\tif(!s) {\n\t\t\tconsole.warn('jmGradient: 渐变字符串为空');\n\t\t\treturn;\n\t\t}\n\t\t// 使用 [\\s\\S] 匹配任意字符(包括换行符),支持多行渐变字符串\n\t\tconst gradientMatch = s.match(/(linear|radial)-gradient\\s*\\(\\s*([\\s\\S]+)\\)/i);\n\t\tif(!gradientMatch || gradientMatch.length < 3) {\n\t\t\tconsole.warn('jmGradient: 无效的渐变字符串格式: \"' + s + '\"');\n\t\t\treturn;\n\t\t}\n\n\t\tconst type = gradientMatch[1].toLowerCase();\n\t\tif(type !== 'linear' && type !== 'radial') {\n\t\t\tconsole.warn('jmGradient: 不支持的渐变类型 \"' + type + '\",仅支持 linear 和 radial');\n\t\t\treturn;\n\t\t}\n\n\t\tthis.type = type;\n\t\tconst content = jmUtils.trim(gradientMatch[2]);\n\n\t\tconst splitIndex = this._findSplitIndex(content);\n\t\tif(splitIndex < 0) {\n\t\t\tconsole.warn('jmGradient: 无法解析渐变内容: \"' + content + '\"');\n\t\t\treturn;\n\t\t}\n\n\t\tconst params = content.substring(0, splitIndex).trim();\n\t\tconst colorPart = content.substring(splitIndex + 1).trim();\n\n\t\tif(!colorPart) {\n\t\t\tconsole.warn('jmGradient: 未找到颜色停止点');\n\t\t\treturn;\n\t\t}\n\n\t\tif(this.type === 'linear') {\n\t\t\tthis._parseLinearParams(params);\n\t\t}\n\t\telse {\n\t\t\tthis._parseRadialParams(params);\n\t\t}\n\n\t\tconst colorCount = this._parseColorStops(colorPart);\n\t\tif(colorCount === 0) {\n\t\t\tconsole.warn('jmGradient: 未找到有效的颜色停止点: \"' + colorPart + '\"');\n\t\t}\n\t\telse if(colorCount < 2) {\n\t\t\tconsole.warn('jmGradient: 颜色停止点至少需要2个,当前只有 ' + colorCount + ' 个');\n\t\t}\n\t}\n\n\t/**\n\t * 找到参数和颜色的分割位置(第一个不在括号内的逗号)\n\t * @param {string} content 内容字符串\n\t * @returns {number} 分割位置索引\n\t */\n\t_findSplitIndex(content) {\n\t\tlet depth = 0;\n\n\t\tfor(let i = 0; i < content.length; i++) {\n\t\t\tconst char = content[i];\n\t\t\tif(char === '(') {\n\t\t\t\tdepth++;\n\t\t\t}\n\t\t\telse if(char === ')') {\n\t\t\t\tdepth--;\n\t\t\t}\n\t\t\telse if(char === ',' && depth === 0) {\n\t\t\t\treturn i;\n\t\t\t}\n\t\t}\n\n\t\treturn -1;\n\t}\n\n\t/**\n\t * 验证渐变配置是否有效\n\t * @returns {boolean} 是否有效\n\t */\n\tisValid() {\n\t\tif(!this.type) return false;\n\t\tif(this.type === 'linear') {\n\t\t\treturn typeof this.x1 !== 'undefined' ||\n\t\t\t\t typeof this.x2 !== 'undefined' ||\n\t\t\t\t typeof this._angle !== 'undefined';\n\t\t}\n\t\tif(this.type === 'radial') {\n\t\t\treturn this.stops && this.stops.length >= 2;\n\t\t}\n\t\treturn false;\n\t}\n\n\t/**\n\t * 解析线性渐变参数\n\t * @param {string} params 参数字符串\n\t */\n\t_parseLinearParams(params) {\n\t\tconst trimmed = jmUtils.trim(params);\n\n\t\tif(trimmed.startsWith('to ')) {\n\t\t\tconst direction = trimmed.substring(3).toLowerCase().trim();\n\t\t\tconst dir = this._directionToAngle(direction);\n\t\t\tthis._angle = dir.angle;\n\t\t\tthis.x1 = dir.x1;\n\t\t\tthis.y1 = dir.y1;\n\t\t\tthis.x2 = dir.x2;\n\t\t\tthis.y2 = dir.y2;\n\t\t}\n\t\telse if(this._hasAngleUnit(trimmed)) {\n\t\t\tconst angle = this._parseAngle(trimmed);\n\t\t\tthis._angle = angle;\n\t\t\tconst coords = this._angleToCoords(angle);\n\t\t\tthis.x1 = coords.x1;\n\t\t\tthis.y1 = coords.y1;\n\t\t\tthis.x2 = coords.x2;\n\t\t\tthis.y2 = coords.y2;\n\t\t}\n\t\telse if(trimmed.startsWith('at ')) {\n\t\t\tconst radialMatch = trimmed.match(/at\\s+(.+)/i);\n\t\t\tif(radialMatch) {\n\t\t\t\tthis._parseRadialParams(trimmed);\n\t\t\t}\n\t\t}\n\t\telse {\n\t\t\tconst parts = trimmed.split(/\\s+/);\n\t\t\tif(parts.length >= 4) {\n\t\t\t\tthis.x1 = parts[0];\n\t\t\t\tthis.y1 = parts[1];\n\t\t\t\tthis.x2 = parts[2];\n\t\t\t\tthis.y2 = parts[3];\n\t\t\t}\n\t\t\telse if(parts.length === 2) {\n\t\t\t\tthis.x1 = 0;\n\t\t\t\tthis.y1 = 0;\n\t\t\t\tthis.x2 = parts[0];\n\t\t\t\tthis.y2 = parts[1];\n\t\t\t}\n\t\t}\n\t}\n\n\t/**\n\t * 解析径向渐变参数\n\t * @param {string} params 参数字符串\n\t */\n\t_parseRadialParams(params) {\n\t\tconst trimmed = jmUtils.trim(params);\n\n\t\tthis.shape = 'ellipse';\n\t\tthis.position = { x: '50%', y: '50%' };\n\n\t\tconst atMatch = trimmed.match(/^(.+?)\\s+at\\s+(.+)$/i);\n\t\tif(atMatch) {\n\t\t\tconst shapePart = jmUtils.trim(atMatch[1]);\n\t\t\tconst posPart = jmUtils.trim(atMatch[2]);\n\t\t\tthis._parseRadialShape(shapePart);\n\t\t\tthis._parseRadialPosition(posPart);\n\t\t}\n\t\telse if(trimmed.startsWith('circle') || trimmed.startsWith('ellipse')) {\n\t\t\tthis._parseRadialShape(trimmed);\n\t\t\tthis.x1 = '50%';\n\t\t\tthis.y1 = '50%';\n\t\t\tthis.x2 = '50%';\n\t\t\tthis.y2 = '50%';\n\t\t}\n\t\telse {\n\t\t\tconst parts = trimmed.split(/\\s+/);\n\t\t\tif(parts.length >= 3) {\n\t\t\t\tthis.x1 = parts[0];\n\t\t\t\tthis.y1 = parts[1];\n\t\t\t\tthis.r1 = parts[2];\n\t\t\t}\n\t\t\tif(parts.length >= 6) {\n\t\t\t\tthis.x2 = parts[3];\n\t\t\t\tthis.y2 = parts[4];\n\t\t\t\tthis.r2 = parts[5];\n\t\t\t}\n\t\t}\n\n\t\tif(this.x1 === undefined && this.y1 === undefined) {\n\t\t\tthis.x1 = '50%';\n\t\t\tthis.y1 = '50%';\n\t\t}\n\t\tif(this.x2 === undefined && this.y2 === undefined) {\n\t\t\tthis.x2 = '50%';\n\t\t\tthis.y2 = '50%';\n\t\t}\n\t\tif(this.r2 === undefined) {\n\t\t\tthis.r2 = '50%';\n\t\t}\n\t}\n\n\t/**\n\t * 解析径向渐变形状\n\t * @param {string} shapePart 形状描述\n\t */\n\t_parseRadialShape(shapePart) {\n\t\tif(shapePart.startsWith('circle')) {\n\t\t\tthis.shape = 'circle';\n\t\t\tconst sizeMatch = shapePart.match(/circle\\s*\\(\\s*([^)]+)\\s*\\)/i);\n\t\t\tif(sizeMatch) {\n\t\t\t\tthis.r2 = jmUtils.trim(sizeMatch[1]);\n\t\t\t}\n\t\t}\n\t\telse if(shapePart.startsWith('ellipse')) {\n\t\t\tthis.shape = 'ellipse';\n\t\t\tconst sizeMatch = shapePart.match(/ellipse\\s*\\(\\s*([^)]+)\\s*\\)/i);\n\t\t\tif(sizeMatch) {\n\t\t\t\tconst sizes = jmUtils.trim(sizeMatch[1]).split(/\\s+/);\n\t\t\t\tif(sizes.length >= 2) {\n\t\t\t\t\tthis.rx = sizes[0];\n\t\t\t\t\tthis.ry = sizes[1];\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n\n\t/**\n\t * 解析径向渐变位置\n\t * @param {string} posPart 位置描述\n\t */\n\t_parseRadialPosition(posPart) {\n\t\tconst parts = posPart.split(/\\s+/);\n\t\tif(parts.length >= 2) {\n\t\t\tthis.x1 = parts[0];\n\t\t\tthis.y1 = parts[1];\n\t\t\tthis.x2 = parts[0];\n\t\t\tthis.y2 = parts[1];\n\t\t}\n\t}\n\n\t/**\n\t * 解析颜色停止点\n\t * @param {string} colorPart 颜色部分字符串\n\t * @returns {number} 成功解析的颜色数量\n\t */\n\t_parseColorStops(colorPart) {\n\t\tif(!colorPart) {\n\t\t\treturn 0;\n\t\t}\n\n\t\tconst stops = this._splitColorStops(colorPart);\n\t\tlet lastOffset = -1;\n\t\tlet colorCount = 0;\n\n\t\tfor(let i = 0; i < stops.length; i++) {\n\t\t\tconst stop = jmUtils.trim(stops[i]);\n\t\t\tif(!stop) continue;\n\n\t\t\tconst parsed = this._parseSingleColorStop(stop);\n\t\t\tif(!parsed) {\n\t\t\t\tcontinue;\n\t\t\t}\n\n\t\t\tlet { color, offset } = parsed;\n\n\t\t\tif(color === 'transparent') {\n\t\t\t\tcolor = 'rgba(0,0,0,0)';\n\t\t\t}\n\n\t\t\tif(!this._isValidColor(color)) {\n\t\t\t\tconsole.warn('jmGradient: 无效的颜色格式 \"' + color + '\"');\n\t\t\t\tcontinue;\n\t\t\t}\n\n\t\t\tconst normalizedOffset = this._normalizeOffset(offset);\n\t\t\tlet finalOffset = normalizedOffset;\n\n\t\t\tif(finalOffset === null) {\n\t\t\t\tif(i === 0) {\n\t\t\t\t\tfinalOffset = 0;\n\t\t\t\t}\n\t\t\t\telse if(i === stops.length - 1) {\n\t\t\t\t\tfinalOffset = 1;\n\t\t\t\t}\n\t\t\t\telse {\n\t\t\t\t\tconst nextOffset = this._findNextOffset(stops, i);\n\t\t\t\t\tif(nextOffset !== null) {\n\t\t\t\t\t\tfinalOffset = (lastOffset + nextOffset) / 2;\n\t\t\t\t\t}\n\t\t\t\t\telse {\n\t\t\t\t\t\tfinalOffset = Math.min(1, lastOffset + (1 - lastOffset) / (stops.length - i));\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tif(finalOffset !== null) {\n\t\t\t\tif(finalOffset < 0 || finalOffset > 1) {\n\t\t\t\t\tconsole.warn('jmGradient: 颜色偏移量 ' + finalOffset + ' 超出有效范围 [0, 1],将调整为有效范围');\n\t\t\t\t\tfinalOffset = Math.max(0, Math.min(1, finalOffset));\n\t\t\t\t}\n\t\t\t\tlastOffset = finalOffset;\n\t\t\t\tthis.addStop(finalOffset, color);\n\t\t\t\tcolorCount++;\n\t\t\t}\n\t\t}\n\n\t\treturn colorCount;\n\t}\n\n\t/**\n\t * 分割颜色停止点字符串\n\t * @param {string} colorPart 颜色部分字符串\n\t * @returns {string[]} 颜色停止点数组\n\t */\n\t_splitColorStops(colorPart) {\n\t\tconst stops = [];\n\t\tlet depth = 0;\n\t\tlet current = '';\n\n\t\tfor(let i = 0; i < colorPart.length; i++) {\n\t\t\tconst char = colorPart[i];\n\t\t\tif(char === '(') {\n\t\t\t\tdepth++;\n\t\t\t\tcurrent += char;\n\t\t\t}\n\t\t\telse if(char === ')') {\n\t\t\t\tdepth--;\n\t\t\t\tcurrent += char;\n\t\t\t}\n\t\t\telse if(char === ',' && depth === 0) {\n\t\t\t\tstops.push(current.trim());\n\t\t\t\tcurrent = '';\n\t\t\t}\n\t\t\telse {\n\t\t\t\tcurrent += char;\n\t\t\t}\n\t\t}\n\n\t\tif(current.trim()) {\n\t\t\tstops.push(current.trim());\n\t\t}\n\n\t\treturn stops;\n\t}\n\n\t/**\n\t * 解析单个颜色停止点\n\t * @param {string} stop 单个颜色停止点字符串\n\t * @returns {object|null} {color, offset} 或 null\n\t */\n\t_parseSingleColorStop(stop) {\n\t\tconst hexMatch = stop.match(/^(#[a-fA-F0-9]{3,8})\\s*(\\d+(?:\\.\\d+)?%?)?$/i);\n\t\tif(hexMatch) {\n\t\t\treturn { color: hexMatch[1], offset: hexMatch[2] || null };\n\t\t}\n\n\t\tconst rgbaMatch = stop.match(/^(rgba?\\s*\\([^)]+\\))\\s*(\\d+(?:\\.\\d+)?%?)?$/i);\n\t\tif(rgbaMatch) {\n\t\t\treturn { color: rgbaMatch[1], offset: rgbaMatch[2] || null };\n\t\t}\n\n\t\tconst hslaMatch = stop.match(/^(hsla?\\s*\\([^)]+\\))\\s*(\\d+(?:\\.\\d+)?%?)?$/i);\n\t\tif(hslaMatch) {\n\t\t\treturn { color: hslaMatch[1], offset: hslaMatch[2] || null };\n\t\t}\n\n\t\tconst namedMatch = stop.match(/^([a-zA-Z]+)\\s*(\\d+(?:\\.\\d+)?%?)?$/i);\n\t\tif(namedMatch && this._isValidColor(namedMatch[1])) {\n\t\t\treturn { color: namedMatch[1], offset: namedMatch[2] || null };\n\t\t}\n\n\t\treturn null;\n\t}\n\n\t/**\n\t * 查找下一个有偏移量的颜色停止点\n\t * @param {string[]} stops 颜色停止点数组\n\t * @param {number} currentIndex 当前索引\n\t * @returns {number|null} 下一个偏移量或null\n\t */\n\t_findNextOffset(stops, currentIndex) {\n\t\tfor(let i = currentIndex + 1; i < stops.length; i++) {\n\t\t\tconst parsed = this._parseSingleColorStop(jmUtils.trim(stops[i]));\n\t\t\tif(parsed && parsed.offset) {\n\t\t\t\treturn this._normalizeOffset(parsed.offset);\n\t\t\t}\n\t\t}\n\t\treturn null;\n\t}\n\n\t/**\n\t * 验证颜色格式是否有效\n\t * @param {string} color 颜色字符串\n\t * @returns {boolean} 是否有效\n\t */\n\t_isValidColor(color) {\n\t\tif(!color) return false;\n\n\t\tconst hexPattern = /^#([a-fA-F0-9]{3,8})$/;\n\t\tif(hexPattern.test(color)) return true;\n\n\t\t// 支持 rgba(r,g,b,a) 和 rgba(r, g, b, a) 等各种空格格式\n\t\tconst rgbPattern = /^rgba?\\s*\\(\\s*\\d{1,3}\\s*,\\s*\\d{1,3}\\s*,\\s*\\d{1,3}\\s*(,\\s*[\\d.]+\\s*)?\\)$/i;\n\t\tif(rgbPattern.test(color)) return true;\n\n\t\tconst hslPattern = /^hsla?\\s*\\(\\s*\\d{1,3}\\s*,\\s*\\d{1,3}%?\\s*,\\s*\\d{1,3}%?\\s*(,\\s*[\\d.]+\\s*)?\\)$/i;\n\t\tif(hslPattern.test(color)) return true;\n\n\t\t// 使用 jmUtils 中的完整 CSS 颜色关键字表\n\t\tif(colorKeywords && colorKeywords[color.toLowerCase()]) return true;\n\n\t\t// 宽松处理:符合 CSS 关键字命名规则的字符串也视为有效颜色\n\t\t// (纯字母,可能在运行时被浏览器或其他环境解析)\n\t\tif(/^[a-zA-Z]+$/.test(color)) return true;\n\n\t\treturn false;\n\t}\n\n\t/**\n\t * 标准化偏移值\n\t * @param {string} offset 偏移字符串\n\t * @returns {number|null} 0-1之间的数值或null\n\t */\n\t_normalizeOffset(offset) {\n\t\tif(!offset) return null;\n\t\toffset = jmUtils.trim(offset);\n\t\tif(offset.endsWith('%')) {\n\t\t\treturn parseFloat(offset) / 100;\n\t\t}\n\t\tconst num = parseFloat(offset);\n\t\tif(isNaN(num)) return null;\n\t\tif(num > 1) {\n\t\t\treturn num / 100;\n\t\t}\n\t\treturn num;\n\t}\n\n\t/**\n\t * 检查字符串是否包含角度单位\n\t * @param {string} str 待检查字符串\n\t * @returns {boolean}\n\t */\n\t_hasAngleUnit(str) {\n\t\treturn /^-?\\d+(\\.\\d+)?\\s*(deg|rad|grad|turn)$/i.test(str);\n\t}\n\n\t/**\n\t * 解析角度值\n\t * @param {string} angleStr 角度字符串\n\t * @returns {number} 弧度值\n\t */\n\t_parseAngle(angleStr) {\n\t\tangleStr = jmUtils.trim(angleStr);\n\t\tconst match = angleStr.match(/^(-?\\d+(\\.\\d+)?)\\s*(deg|rad|grad|turn)?$/i);\n\t\tif(!match) return 0;\n\n\t\tlet value = parseFloat(match[1]);\n\t\tconst unit = (match[3] || 'deg').toLowerCase();\n\n\t\tswitch(unit) {\n\t\t\tcase 'deg':\n\t\t\t\treturn value * Math.PI / 180;\n\t\t\tcase 'rad':\n\t\t\t\treturn value;\n\t\t\tcase 'grad':\n\t\t\t\treturn value * Math.PI / 200;\n\t\t\tcase 'turn':\n\t\t\t\treturn value * 2 * Math.PI;\n\t\t\tdefault:\n\t\t\t\treturn value * Math.PI / 180;\n\t\t}\n\t}\n\n\t/**\n\t * 将角度转换为起点和终点坐标\n\t * @param {number} angle 弧度值\n\t * @returns {object} 坐标对象\n\t */\n\t_angleToCoords(angle) {\n\t\tconst x = Math.cos(angle);\n\t\tconst y = -Math.sin(angle);\n\n\t\treturn {\n\t\t\tx1: Math.round((0.5 - x * 0.5) * 1000) / 1000,\n\t\t\ty1: Math.round((0.5 + y * 0.5) * 1000) / 1000,\n\t\t\tx2: Math.round((0.5 + x * 0.5) * 1000) / 1000,\n\t\t\ty2: Math.round((0.5 - y * 0.5) * 1000) / 1000\n\t\t};\n\t}\n\n\t/**\n\t * 将方向关键词转换为角度和坐标\n\t * @param {string} direction 方向描述\n\t * @returns {object} 包含angle和坐标的对象\n\t */\n\t_directionToAngle(direction) {\n\t\tconst directions = {\n\t\t\t'to top': { angle: 0, x1: '50%', y1: '100%', x2: '50%', y2: '0%' },\n\t\t\t'to bottom': { angle: Math.PI, x1: '50%', y1: '0%', x2: '50%', y2: '100%' },\n\t\t\t'to left': { angle: -Math.PI / 2, x1: '100%', y1: '50%', x2: '0%', y2: '50%' },\n\t\t\t'to right': { angle: Math.PI / 2, x1: '0%', y1: '50%', x2: '100%', y2: '50%' },\n\t\t\t'to top left': { angle: -Math.PI * 3 / 4, x1: '100%', y1: '100%', x2: '0%', y2: '0%' },\n\t\t\t'to top right': { angle: -Math.PI / 4, x1: '0%', y1: '100%', x2: '100%', y2: '0%' },\n\t\t\t'to bottom left': { angle: Math.PI * 3 / 4, x1: '100%', y1: '0%', x2: '0%', y2: '100%' },\n\t\t\t'to bottom right': { angle: Math.PI / 4, x1: '0%', y1: '0%', x2: '100%', y2: '100%' },\n\t\t\t'top': { angle: 0, x1: '50%', y1: '100%', x2: '50%', y2: '0%' },\n\t\t\t'bottom': { angle: Math.PI, x1: '50%', y1: '0%', x2: '50%', y2: '100%' },\n\t\t\t'left': { angle: -Math.PI / 2, x1: '100%', y1: '50%', x2: '0%', y2: '50%' },\n\t\t\t'right': { angle: Math.PI / 2, x1: '0%', y1: '50%', x2: '100%', y2: '50%' }\n\t\t};\n\n\t\tconst dir = directions[direction];\n\t\tif(dir) {\n\t\t\treturn dir;\n\t\t}\n\n\t\tconst keywordMatch = direction.match(/to\\s+(top|bottom|left|right)/i);\n\t\tif(keywordMatch) {\n\t\t\tconst mainDir = keywordMatch[1].toLowerCase();\n\t\t\tconst secDir = direction.replace(keywordMatch[0], '').trim();\n\t\t\tif(secDir) {\n\t\t\t\tconst combined = `to ${mainDir} ${secDir}`;\n\t\t\t\tif(directions[combined]) {\n\t\t\t\t\treturn directions[combined];\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\treturn { angle: 0, x1: '50%', y1: '100%', x2: '50%', y2: '0%' };\n\t}\n\n\t/**\n\t * 转换为渐变的字符串表达\n\t *\n\t * @method toString\n\t * @for jmGradient\n\t * @return {string} linear-gradient(x1 y1 x2 y2, color1 step, color2 step, ...);\t//radial-gradient(x1 y1 r1 x2 y2 r2, color1 step,color2 step, ...);\n\t */\n\ttoString() {\n\t\tlet str = this.type + '-gradient(';\n\t\tif(this.type == 'linear') {\n\t\t\tstr += this.x1 + ' ' + this.y1 + ' ' + this.x2 + ' ' + this.y2;\n\t\t}\n\t\telse {\n\t\t\tstr += this.x1 + ' ' + this.y1 + ' ' + this.r1 + ' ' + this.x2 + ' ' + this.y2 + ' ' + this.r2;\n\t\t}\n\t\t//颜色渐变\n\t\tthis.stops.each(function(i,s) {\t\n\t\t\tstr += ',' + s.color + ' ' + s.offset;\n\t\t});\n\t\treturn str + ')';\n\t}\n}\n\nexport { jmGradient };\n\n\n\n","/**\n * @fileoverview jmFilter 滤镜类\n * \n * jmFilter 提供了 CSS 滤镜效果的管理和应用功能。\n * 支持多种滤镜效果,可以组合使用。\n * \n * 支持的滤镜:\n * - blur: 模糊效果\n * - grayscale: 灰度效果\n * - sepia: 复古效果\n * - brightness: 亮度调节\n * - contrast: 对比度调节\n * - saturate: 饱和度调节\n * - hue-rotate: 色相旋转\n * - invert: 反色效果\n * - opacity: 透明度调节\n * \n * @module jmFilter\n * @author jmGraph Team\n * @license MIT\n */\n\nimport {jmUtils} from \"./jmUtils.js\";\n\n/**\n * CSS 滤镜效果类\n * \n * 支持的滤镜: blur, grayscale, sepia, brightness, contrast, saturate, hue-rotate, invert, opacity\n *\n * @class jmFilter\n * @param {string|object} opt 滤镜参数\n * 字符串格式: \"blur(2px) grayscale(50%) brightness(1.2)\"\n * 对象格式: { blur: 2, grayscale: 0.5, brightness: 1.2 }\n * \n * @example\n * // 从字符串创建\n * const filter = new jmFilter('blur(2px) grayscale(50%)');\n * \n * // 从对象创建\n * const filter = new jmFilter({\n * blur: 2,\n * grayscale: 0.5,\n * brightness: 1.2\n * });\n * \n * // 应用到图形\n * shape.style.filter = filter;\n */\nexport default class jmFilter {\n\tconstructor(opt) {\n\t\tthis.filters = [];\n\n\t\tif(typeof opt === 'string') {\n\t\t\tthis.fromString(opt);\n\t\t}\n\t\telse if(opt && typeof opt === 'object') {\n\t\t\tfor(let k in opt) {\n\t\t\t\tif(k === 'constructor' || k === 'filters') continue;\n\t\t\t\tthis.addFilter(k, opt[k]);\n\t\t\t}\n\t\t}\n\t}\n\n\t/**\n\t * 添加单个滤镜\n\t * @param {string} name 滤镜名称 (blur, grayscale, sepia, brightness, contrast, saturate, hue-rotate, invert, opacity)\n\t * @param {number|string} value 滤镜值\n\t */\n\taddFilter(name, value) {\n\t\tname = name.toLowerCase().trim();\n\t\tif(typeof value === 'string') {\n\t\t\tvalue = parseFloat(value);\n\t\t}\n\t\tif(isNaN(value)) return;\n\n\t\t// 规范化滤镜名称\n\t\tconst normalized = {\n\t\t\t'blur': 'blur',\n\t\t\t'grayscale': 'grayscale',\n\t\t\t'greyscale': 'grayscale',\n\t\t\t'sepia': 'sepia',\n\t\t\t'brightness': 'brightness',\n\t\t\t'contrast': 'contrast',\n\t\t\t'saturate': 'saturate',\n\t\t\t'hue-rotate': 'hueRotate',\n\t\t\t'hueRotate': 'hueRotate',\n\t\t\t'invert': 'invert',\n\t\t\t'opacity': 'opacity'\n\t\t}[name];\n\n\t\tif(!normalized) return;\n\n\t\t// 检查是否已有同名滤镜,有则更新\n\t\tconst existing = this.filters.find(f => f.name === normalized);\n\t\tif(existing) {\n\t\t\texisting.value = value;\n\t\t}\n\t\telse {\n\t\t\tthis.filters.push({ name: normalized, value: value });\n\t\t}\n\t}\n\n\t/**\n\t * 从字符串格式解析滤镜\n\t * 格式: \"blur(2px) grayscale(50%) brightness(1.2)\"\n\t * @param {string} s 滤镜字符串\n\t */\n\tfromString(s) {\n\t\tif(!s || typeof s !== 'string') return;\n\t\t// 匹配 filterName(value) 模式\n\t\tconst regex = /([a-zA-Z-]+)\\s*\\(\\s*([^)]+)\\s*\\)/g;\n\t\tlet match;\n\t\twhile((match = regex.exec(s)) !== null) {\n\t\t\tconst name = match[1];\n\t\t\tconst valueStr = match[2].replace(/[a-z%]+$/i, '').trim();\n\t\t\tconst value = parseFloat(valueStr);\n\t\t\tif(!isNaN(value)) {\n\t\t\t\tthis.addFilter(name, value);\n\t\t\t}\n\t\t}\n\t}\n\n\t/**\n\t * 转换为CSS filter字符串格式\n\t * @returns {string}\n\t */\n\ttoString() {\n\t\treturn this.filters.map(f => {\n\t\t\tswitch(f.name) {\n\t\t\t\tcase 'blur':\n\t\t\t\t\treturn `blur(${f.value}px)`;\n\t\t\t\tcase 'hueRotate':\n\t\t\t\t\treturn `hue-rotate(${f.value}deg)`;\n\t\t\t\tdefault:\n\t\t\t\t\treturn `${f.name}(${f.value})`;\n\t\t\t}\n\t\t}).join(' ');\n\t}\n\n\t/**\n\t * 转换为Canvas context.filter可用的字符串\n\t * @returns {string}\n\t */\n\ttoCanvasFilter() {\n\t\tif(this.filters.length === 0) return 'none';\n\t\treturn this.toString();\n\t}\n\n\t/**\n\t * 检查是否有指定名称的滤镜\n\t * @param {string} name 滤镜名称\n\t * @returns {boolean}\n\t */\n\thas(name) {\n\t\treturn this.filters.some(f => f.name === name);\n\t}\n\n\t/**\n\t * 获取指定滤镜的值\n\t * @param {string} name 滤镜名称\n\t * @returns {number|undefined}\n\t */\n\tget(name) {\n\t\tconst f = this.filters.find(f => f.name === name);\n\t\treturn f ? f.value : undefined;\n\t}\n\n\t/**\n\t * 移除指定滤镜\n\t * @param {string} name 滤镜名称\n\t */\n\tremove(name) {\n\t\tconst index = this.filters.findIndex(f => f.name === name);\n\t\tif(index > -1) {\n\t\t\tthis.filters.splice(index, 1);\n\t\t}\n\t}\n\n\t/**\n\t * 清空所有滤镜\n\t */\n\tclear() {\n\t\tthis.filters = [];\n\t}\n}\n\nexport { jmFilter };\n","/**\n * @fileoverview jmEvents 事件处理系统\n * \n * jmEvents 是 jmGraph 库的事件处理模块,负责管理所有用户交互事件。\n * 包括鼠标事件、触摸事件和键盘事件的绑定、分发和销毁。\n * \n * 主要功能:\n * - 鼠标事件:mousedown, mousemove, mouseup, click, dblclick 等\n * - 触摸事件:touchstart, touchmove, touchend, touchcancel, tap\n * - 键盘事件:keydown, keyup, keypress\n * - 事件冒泡和委托机制\n * \n * @module jmEvents\n * @author jmGraph Team\n * @license MIT\n */\n\nimport {jmUtils} from \"./jmUtils.js\";\n\n/**\n * jmEvents 事件处理类\n * \n * 统一管理画布上的所有交互事件,包括鼠标、触摸和键盘事件。\n * 支持事件冒泡机制,可以将事件传递给子控件处理。\n * \n * @class jmEvents\n * \n * @param {jmGraph} container jmGraph 实例\n * @param {HTMLElement} target 事件目标元素(通常是 canvas 元素)\n * \n * @example\n * // 通常由 jmGraph 内部创建,不需要手动实例化\n * const events = new jmEvents(graph, canvasElement);\n */\nexport default class jmEvents {\n\n\t/**\n\t * 构造函数\n\t * \n\t * @param {jmGraph} container jmGraph 实例\n\t * @param {HTMLElement} target 事件目标元素\n\t */\n\tconstructor(container, target) {\n\t\t/**\n\t\t * jmGraph 实例\n\t\t * @type {jmGraph}\n\t\t */\n\t\tthis.container = container;\n\t\t/**\n\t\t * 事件目标元素\n\t\t * @type {HTMLElement}\n\t\t */\n\t\tthis.target = target || container;\n\t\t/**\n\t\t * 鼠标事件处理器\n\t\t * @type {jmMouseEvent}\n\t\t */\n\t\tthis.mouseHandler = new jmMouseEvent(this, container, target);\n\t\t/**\n\t\t * 键盘事件处理器\n\t\t * @type {jmKeyEvent}\n\t\t */\n\t\tthis.keyHandler = new jmKeyEvent(this, container, target);\n\t}\n\n\t/**\n\t * 触摸开始事件处理\n\t * \n\t * @method touchStart\n\t * @param {TouchEvent} evt 触摸事件对象\n\t * @return {boolean} 如果事件目标为画布本身则返回 false\n\t */\n\ttouchStart(evt) {\n\t\tevt = evt || window.event;\n\t\tevt.eventName = 'touchstart';\n\t\tthis.container.raiseEvent('touchstart',evt);\n\t\tconst t = evt.target || evt.srcElement;\n\t\tif(t == this.target) {\n\t\t\treturn false;\n\t\t}\n\t};\n\n\t/**\n\t * 触摸移动事件处理\n\t * \n\t * @method touchMove\n\t * @param {TouchEvent} evt 触摸事件对象\n\t * @return {boolean} 如果事件目标为画布本身则返回 false\n\t */\n\ttouchMove(evt) {\n\t\tevt = evt || window.event;\n\t\tevt.eventName = 'touchmove';\n\t\tthis.container.raiseEvent('touchmove',evt);\n\t\tconst t = evt.target || evt.srcElement;\n\t\tif(t == this.target) {\n\t\t\treturn false;\n\t\t}\n\t};\n\n\t/**\n\t * 触摸结束事件处理\n\t * \n\t * @method touchEnd\n\t * @param {TouchEvent} evt 触摸事件对象\n\t * @return {boolean} 如果事件目标为画布本身则返回 false\n\t */\n\ttouchEnd(evt) {\n\t\tevt = evt || window.event;\n\t\tevt.eventName = 'touchend';\n\t\t\n\t\tthis.container.raiseEvent('touchend',evt);\n\t\tconst t = evt.target || evt.srcElement;\n\t\tif(t == this.target) {\n\t\t\treturn false;\n\t\t}\n\t};\n\n\t/**\n\t * 触摸取消事件处理\n\t * \n\t * @method touchCancel\n\t * @param {TouchEvent} evt 触摸事件对象\n\t * @return {boolean} 如果事件目标为画布本身则返回 false\n\t */\n\ttouchCancel(evt) {\n\t\tevt = evt || window.event;\n\t\tevt.eventName = 'touchcancel';\n\t\t\n\t\tthis.container.raiseEvent('touchcancel',evt);\n\t\tconst t = evt.target || evt.srcElement;\n\t\tif(t == this.target) {\n\t\t\treturn false;\n\t\t}\n\t};\n\n\t/**\n\t * 轻触事件处理\n\t * \n\t * @method tap\n\t * @param {Event} evt 事件对象\n\t * @return {boolean} 如果事件目标为画布本身则返回 false\n\t */\n\ttap(evt) {\n\t\tevt = evt || window.event;\n\t\tevt.eventName = 'tap';\n\t\t\n\t\tthis.container.raiseEvent('tap',evt);\n\t\tconst t = evt.target || evt.srcElement;\n\t\tif(t == this.target) {\n\t\t\treturn false;\n\t\t}\n\t};\n\n\t/**\n\t * 销毁事件处理器\n\t * \n\t * 移除所有绑定的事件监听器,释放资源。\n\t * \n\t * @method destroy\n\t */\n\tdestroy() {\n\t\tthis.mouseHandler.destroy();\n\t\tthis.keyHandler.destroy();\n\t}\n}\n\n/**\n * 鼠标事件处理器\n * \n * @class jmMouseEvent\n * @private\n */\nclass jmMouseEvent {\n\t/**\n\t * 构造函数\n\t * \n\t * @param {jmEvents} instance jmEvents 实例\n\t * @param {jmGraph} container jmGraph 实例\n\t * @param {HTMLElement} target 事件目标元素\n\t */\n\tconstructor(instance, container, target) {\n\t\tthis.instance = instance;\n\t\tthis.container = container;\n\t\tthis.target = target || container;\n\n\t\t/**\n\t\t * 已绑定的事件映射表\n\t\t * @type {Object}\n\t\t */\n\t\tthis.eventEvents = {};\n\n\t\tthis.init(instance, container, target);\n\t}\n\t\n\t/**\n\t * 初始化鼠标事件绑定\n\t * \n\t * @method init\n\t * @private\n\t * @param {jmEvents} instance jmEvents 实例\n\t * @param {jmGraph} container jmGraph 实例\n\t * @param {HTMLElement} target 事件目标元素\n\t */\n\tinit(instance, container, target) {\n\t\tconst canvas = this.target;\n\t\tconst doc = typeof document != 'undefined'? document: null;\n\n\t\tthis.eventEvents['mousedown'] = jmUtils.bindEvent(this.target,'mousedown',function(evt) {\n\t\t\tevt = evt || window.event;\n\t\t\tevt.eventName = 'mousedown';\n\t\t\tcontainer.raiseEvent('mousedown',evt);\n\t\t});\n\t\t\n\t\tthis.eventEvents['mousemove'] = jmUtils.bindEvent(this.target,'mousemove',function(evt) {\n\t\t\tevt = evt || window.event;\n\t\t\tevt.eventName = 'mousemove';\n\t\t\tconst target = evt.target || evt.srcElement;\n\t\t\tif(target == canvas) {\n\t\t\t\tcontainer.raiseEvent('mousemove',evt);\n\t\t\t\tif(evt.preventDefault) evt.preventDefault();\n\t\t\t\treturn false;\n\t\t\t}\n\t\t});\n\t\t\n\t\tthis.eventEvents['mouseover'] = jmUtils.bindEvent(this.target,'mouseover',function(evt) {\n\t\t\tevt = evt || window.event;\n\t\t\tevt.eventName = 'mouseover';\n\t\t\tcontainer.raiseEvent('mouseover',evt);\n\t\t});\n\t\tthis.eventEvents['mouseleave'] = jmUtils.bindEvent(this.target,'mouseleave',function(evt) {\n\t\t\tevt = evt || window.event;\n\t\t\tevt.eventName = 'mouseleave';\n\t\t\tcontainer.raiseEvent('mouseleave',evt);\n\t\t});\n\t\tthis.eventEvents['mouseout'] = jmUtils.bindEvent(this.target,'mouseout',function(evt) {\n\t\t\tevt = evt || window.event;\n\t\t\tevt.eventName = 'mouseout';\n\t\t\tcontainer.raiseEvent('mouseout',evt);\n\t\t});\n\t\tdoc && (this.eventEvents['mouseup'] = jmUtils.bindEvent(doc,'mouseup',function(evt) {\n\t\t\tevt = evt || window.event;\n\t\t\tevt.eventName = 'mouseup';\n\t\t\tconst r = container.raiseEvent('mouseup',evt);\n\t\t\tif(r === false) {\n\t\t\t\tif(evt.preventDefault) evt.preventDefault();\n\t\t\t\treturn false;\n\t\t\t}\n\t\t}));\n\t\t\n\t\tthis.eventEvents['dblclick'] = jmUtils.bindEvent(this.target,'dblclick',function(evt) {\n\t\t\tevt = evt || window.event;\n\t\t\tevt.eventName = 'dblclick';\n\t\t\tcontainer.raiseEvent('dblclick',evt);\n\t\t});\n\t\tthis.eventEvents['click'] = jmUtils.bindEvent(this.target,'click',function(evt) {\n\t\t\tevt = evt || window.event;\n\t\t\tevt.eventName = 'click';\n\t\t\tcontainer.raiseEvent('click',evt);\n\t\t});\n\n\t\tdoc && (this.eventEvents['resize'] = jmUtils.bindEvent(doc,'resize',function(evt) {\n\t\t\tevt = evt || window.event;\n\t\t\tevt.eventName = 'resize';\n\t\t\treturn container.raiseEvent('resize',evt);\n\t\t}));\n\n\t\tthis.eventEvents['touchstart'] = jmUtils.bindEvent(this.target,'touchstart', function(evt) {\n\t\t\tevt.eventName = 'touchstart';\n\t\t\treturn instance.touchStart(evt);\n\t\t},{ passive: false });\n\n\t\tthis.eventEvents['touchmove'] = jmUtils.bindEvent(this.target,'touchmove', function(evt) {\n\t\t\tevt.eventName = 'touchmove';\n\t\t\treturn instance.touchMove(evt);\n\t\t},{ passive: false });\n\n\t\tdoc && (this.eventEvents['touchend'] = jmUtils.bindEvent(doc,'touchend', function(evt) {\n\t\t\tevt.eventName = 'touchend';\n\t\t\treturn instance.touchEnd(evt);\n\t\t},{ passive: false }));\n\n\t\tdoc && (this.eventEvents['touchcancel'] = jmUtils.bindEvent(doc,'touchcancel', function(evt) {\n\t\t\tevt.eventName = 'touchcancel';\n\t\t\treturn instance.touchCancel(evt);\n\t\t},{ passive: false }));\n\t}\n\n\t/**\n\t * 销毁鼠标事件处理器\n\t * \n\t * 移除所有绑定的鼠标事件监听器。\n\t * \n\t * @method destroy\n\t */\n\tdestroy() {\n\t\tfor(const name in this.eventEvents) {\n\t\t\tconst event = this.eventEvents[name];\n\t\t\tif(!event || !event.fun) continue;\n\t\t\tjmUtils.removeEvent(event.target, name, event.fun);\n\t\t}\n\t}\n}\n\n/**\n * 键盘事件处理器\n * \n * @class jmKeyEvent\n * @private\n */\nclass jmKeyEvent {\n\t/**\n\t * 构造函数\n\t * \n\t * @param {jmEvents} instance jmEvents 实例\n\t * @param {jmGraph} container jmGraph 实例\n\t * @param {HTMLElement} target 事件目标元素\n\t */\n\tconstructor(instance, container,target) {\n\t\tthis.instance = instance;\n\t\tthis.container = container;\n\t\tthis.target = target || container;\n\n\t\t/**\n\t\t * 已绑定的事件映射表\n\t\t * @type {Object}\n\t\t */\n\t\tthis.eventEvents = {};\n\n\t\tthis.init(container, target);\n\t}\n\n\t/**\n\t * 初始化键盘事件绑定\n\t * \n\t * @method init\n\t * @private\n\t * @param {jmGraph} container jmGraph 实例\n\t * @param {HTMLElement} target 事件目标元素\n\t */\n\tinit(container, target) {\n\t\tconst doc = typeof document != 'undefined'? document: null;\n\n\t\tconst checkKeyEvent = (evt) => {\n\t\t\tconst target = evt.srcElement || evt.target;\n\t\t\tif(target && (target.tagName == 'INPUT' \n\t\t\t\t|| target.tagName == 'TEXTAREA'\n\t\t\t\t|| target.tagName == 'ANCHOR' \n\t\t\t\t|| target.tagName == 'FORM' \n\t\t\t\t|| target.tagName == 'FILE'\n\t\t\t\t|| target.tagName == 'IMG'\n\t\t\t\t|| target.tagName == 'HIDDEN'\n\t\t\t\t|| target.tagName == 'RADIO'\n\t\t\t\t|| target.tagName == 'TEXT'\t)) {\n\t\t\t\treturn false;\n\t\t\t}\n\t\t\treturn true;\n\t\t}\n\n\t\tdoc && (this.eventEvents['keypress'] = jmUtils.bindEvent(doc,'keypress',function(evt) {\n\t\t\tevt = evt || window.event;\n\t\t\tif(!checkKeyEvent(evt)) return;\n\t\t\tconst r = container.raiseEvent('keypress',evt);\n\t\t\tif(r === false && evt.preventDefault) \n\t\t\t\tevt.preventDefault();\n\t\t\treturn r;\n\t\t}));\n\t\tdoc && (this.eventEvents['keydown'] = jmUtils.bindEvent(doc,'keydown',function(evt) {\n\t\t\tevt = evt || window.event;\n\t\t\tif(!checkKeyEvent(evt)) return;\n\t\t\tconst r = container.raiseEvent('keydown',evt);\n\t\t\tif(r === false && evt.preventDefault) \n\t\t\t\tevt.preventDefault();\n\t\t\treturn r;\n\t\t}));\n\t\tdoc && (this.eventEvents['keyup'] = jmUtils.bindEvent(doc,'keyup',function(evt) {\n\t\t\tevt = evt || window.event;\n\t\t\tif(!checkKeyEvent(evt)) return;\n\t\t\tconst r = container.raiseEvent('keyup',evt);\n\t\t\tif(r === false && evt.preventDefault) \n\t\t\t\tevt.preventDefault();\n\t\t\treturn r;\n\t\t}));\n\t}\n\n\tdestroy() {\n\t\tfor(const name in this.eventEvents) {\n\t\t\tconst event = this.eventEvents[name];\n\t\t\tif(!event || !event.fun) continue;\n\t\t\tjmUtils.removeEvent(event.target, name, event.fun);\n\t\t}\n\t}\n}\n\nexport { jmEvents };\n","'use strict';\n\nexport default earcut;\n\nfunction earcut(data, holeIndices, dim) {\n\n dim = dim || 2;\n\n var hasHoles = holeIndices && holeIndices.length,\n outerLen = hasHoles ? holeIndices[0] * dim : data.length,\n outerNode = linkedList(data, 0, outerLen, dim, true),\n triangles = [];\n\n if (!outerNode || outerNode.next === outerNode.prev) return triangles;\n\n var minX, minY, maxX, maxY, x, y, invSize;\n\n if (hasHoles) outerNode = eliminateHoles(data, holeIndices, outerNode, dim);\n\n // if the shape is not too simple, we'll use z-order curve hash later; calculate polygon bbox\n if (data.length > 80 * dim) {\n minX = maxX = data[0];\n minY = maxY = data[1];\n\n for (var i = dim; i < outerLen; i += dim) {\n x = data[i];\n y = data[i + 1];\n if (x < minX) minX = x;\n if (y < minY) minY = y;\n if (x > maxX) maxX = x;\n if (y > maxY) maxY = y;\n }\n\n // minX, minY and invSize are later used to transform coords into integers for z-order calculation\n invSize = Math.max(maxX - minX, maxY - minY);\n invSize = invSize !== 0 ? 32767 / invSize : 0;\n }\n\n earcutLinked(outerNode, triangles, dim, minX, minY, invSize, 0);\n\n return triangles;\n}\n\n// create a circular doubly linked list from polygon points in the specified winding order\nfunction linkedList(data, start, end, dim, clockwise) {\n var i, last;\n\n if (clockwise === (signedArea(data, start, end, dim) > 0)) {\n for (i = start; i < end; i += dim) last = insertNode(i, data[i], data[i + 1], last);\n } else {\n for (i = end - dim; i >= start; i -= dim) last = insertNode(i, data[i], data[i + 1], last);\n }\n\n if (last && equals(last, last.next)) {\n removeNode(last);\n last = last.next;\n }\n\n return last;\n}\n\n// eliminate colinear or duplicate points\nfunction filterPoints(start, end) {\n if (!start) return start;\n if (!end) end = start;\n\n var p = start,\n again;\n do {\n again = false;\n\n if (!p.steiner && (equals(p, p.next) || area(p.prev, p, p.next) === 0)) {\n removeNode(p);\n p = end = p.prev;\n if (p === p.next) break;\n again = true;\n\n } else {\n p = p.next;\n }\n } while (again || p !== end);\n\n return end;\n}\n\n// main ear slicing loop which triangulates a polygon (given as a linked list)\nfunction earcutLinked(ear, triangles, dim, minX, minY, invSize, pass) {\n if (!ear) return;\n\n // interlink polygon nodes in z-order\n if (!pass && invSize) indexCurve(ear, minX, minY, invSize);\n\n var stop = ear,\n prev, next;\n\n // iterate through ears, slicing them one by one\n while (ear.prev !== ear.next) {\n prev = ear.prev;\n next = ear.next;\n\n if (invSize ? isEarHashed(ear, minX, minY, invSize) : isEar(ear)) {\n // cut off the triangle\n triangles.push(prev.i / dim | 0);\n triangles.push(ear.i / dim | 0);\n triangles.push(next.i / dim | 0);\n\n removeNode(ear);\n\n // skipping the next vertex leads to less sliver triangles\n ear = next.next;\n stop = next.next;\n\n continue;\n }\n\n ear = next;\n\n // if we looped through the whole remaining polygon and can't find any more ears\n if (ear === stop) {\n // try filtering points and slicing again\n if (!pass) {\n earcutLinked(filterPoints(ear), triangles, dim, minX, minY, invSize, 1);\n\n // if this didn't work, try curing all small self-intersections locally\n } else if (pass === 1) {\n ear = cureLocalIntersections(filterPoints(ear), triangles, dim);\n earcutLinked(ear, triangles, dim, minX, minY, invSize, 2);\n\n // as a last resort, try splitting the remaining polygon into two\n } else if (pass === 2) {\n splitEarcut(ear, triangles, dim, minX, minY, invSize);\n }\n\n break;\n }\n }\n}\n\n// check whether a polygon node forms a valid ear with adjacent nodes\nfunction isEar(ear) {\n var a = ear.prev,\n b = ear,\n c = ear.next;\n\n if (area(a, b, c) >= 0) return false; // reflex, can't be an ear\n\n // now make sure we don't have other points inside the potential ear\n var ax = a.x, bx = b.x, cx = c.x, ay = a.y, by = b.y, cy = c.y;\n\n // triangle bbox; min & max are calculated like this for speed\n var x0 = ax < bx ? (ax < cx ? ax : cx) : (bx < cx ? bx : cx),\n y0 = ay < by ? (ay < cy ? ay : cy) : (by < cy ? by : cy),\n x1 = ax > bx ? (ax > cx ? ax : cx) : (bx > cx ? bx : cx),\n y1 = ay > by ? (ay > cy ? ay : cy) : (by > cy ? by : cy);\n\n var p = c.next;\n while (p !== a) {\n if (p.x >= x0 && p.x <= x1 && p.y >= y0 && p.y <= y1 &&\n pointInTriangle(ax, ay, bx, by, cx, cy, p.x, p.y) &&\n area(p.prev, p, p.next) >= 0) return false;\n p = p.next;\n }\n\n return true;\n}\n\nfunction isEarHashed(ear, minX, minY, invSize) {\n var a = ear.prev,\n b = ear,\n c = ear.next;\n\n if (area(a, b, c) >= 0) return false; // reflex, can't be an ear\n\n var ax = a.x, bx = b.x, cx = c.x, ay = a.y, by = b.y, cy = c.y;\n\n // triangle bbox; min & max are calculated like this for speed\n var x0 = ax < bx ? (ax < cx ? ax : cx) : (bx < cx ? bx : cx),\n y0 = ay < by ? (ay < cy ? ay : cy) : (by < cy ? by : cy),\n x1 = ax > bx ? (ax > cx ? ax : cx) : (bx > cx ? bx : cx),\n y1 = ay > by ? (ay > cy ? ay : cy) : (by > cy ? by : cy);\n\n // z-order range for the current triangle bbox;\n var minZ = zOrder(x0, y0, minX, minY, invSize),\n maxZ = zOrder(x1, y1, minX, minY, invSize);\n\n var p = ear.prevZ,\n n = ear.nextZ;\n\n // look for points inside the triangle in both directions\n while (p && p.z >= minZ && n && n.z <= maxZ) {\n if (p.x >= x0 && p.x <= x1 && p.y >= y0 && p.y <= y1 && p !== a && p !== c &&\n pointInTriangle(ax, ay, bx, by, cx, cy, p.x, p.y) && area(p.prev, p, p.next) >= 0) return false;\n p = p.prevZ;\n\n if (n.x >= x0 && n.x <= x1 && n.y >= y0 && n.y <= y1 && n !== a && n !== c &&\n pointInTriangle(ax, ay, bx, by, cx, cy, n.x, n.y) && area(n.prev, n, n.next) >= 0) return false;\n n = n.nextZ;\n }\n\n // look for remaining points in decreasing z-order\n while (p && p.z >= minZ) {\n if (p.x >= x0 && p.x <= x1 && p.y >= y0 && p.y <= y1 && p !== a && p !== c &&\n pointInTriangle(ax, ay, bx, by, cx, cy, p.x, p.y) && area(p.prev, p, p.next) >= 0) return false;\n p = p.prevZ;\n }\n\n // look for remaining points in increasing z-order\n while (n && n.z <= maxZ) {\n if (n.x >= x0 && n.x <= x1 && n.y >= y0 && n.y <= y1 && n !== a && n !== c &&\n pointInTriangle(ax, ay, bx, by, cx, cy, n.x, n.y) && area(n.prev, n, n.next) >= 0) return false;\n n = n.nextZ;\n }\n\n return true;\n}\n\n// go through all polygon nodes and cure small local self-intersections\nfunction cureLocalIntersections(start, triangles, dim) {\n var p = start;\n do {\n var a = p.prev,\n b = p.next.next;\n\n if (!equals(a, b) && intersects(a, p, p.next, b) && locallyInside(a, b) && locallyInside(b, a)) {\n\n triangles.push(a.i / dim | 0);\n triangles.push(p.i / dim | 0);\n triangles.push(b.i / dim | 0);\n\n // remove two nodes involved\n removeNode(p);\n removeNode(p.next);\n\n p = start = b;\n }\n p = p.next;\n } while (p !== start);\n\n return filterPoints(p);\n}\n\n// try splitting polygon into two and triangulate them independently\nfunction splitEarcut(start, triangles, dim, minX, minY, invSize) {\n // look for a valid diagonal that divides the polygon into two\n var a = start;\n do {\n var b = a.next.next;\n while (b !== a.prev) {\n if (a.i !== b.i && isValidDiagonal(a, b)) {\n // split the polygon in two by the diagonal\n var c = splitPolygon(a, b);\n\n // filter colinear points around the cuts\n a = filterPoints(a, a.next);\n c = filterPoints(c, c.next);\n\n // run earcut on each half\n earcutLinked(a, triangles, dim, minX, minY, invSize, 0);\n earcutLinked(c, triangles, dim, minX, minY, invSize, 0);\n return;\n }\n b = b.next;\n }\n a = a.next;\n } while (a !== start);\n}\n\n// link every hole into the outer loop, producing a single-ring polygon without holes\nfunction eliminateHoles(data, holeIndices, outerNode, dim) {\n var queue = [],\n i, len, start, end, list;\n\n for (i = 0, len = holeIndices.length; i < len; i++) {\n start = holeIndices[i] * dim;\n end = i < len - 1 ? holeIndices[i + 1] * dim : data.length;\n list = linkedList(data, start, end, dim, false);\n if (list === list.next) list.steiner = true;\n queue.push(getLeftmost(list));\n }\n\n queue.sort(compareX);\n\n // process holes from left to right\n for (i = 0; i < queue.length; i++) {\n outerNode = eliminateHole(queue[i], outerNode);\n }\n\n return outerNode;\n}\n\nfunction compareX(a, b) {\n return a.x - b.x;\n}\n\n// find a bridge between vertices that connects hole with an outer ring and and link it\nfunction eliminateHole(hole, outerNode) {\n var bridge = findHoleBridge(hole, outerNode);\n if (!bridge) {\n return outerNode;\n }\n\n var bridgeReverse = splitPolygon(bridge, hole);\n\n // filter collinear points around the cuts\n filterPoints(bridgeReverse, bridgeReverse.next);\n return filterPoints(bridge, bridge.next);\n}\n\n// David Eberly's algorithm for finding a bridge between hole and outer polygon\nfunction findHoleBridge(hole, outerNode) {\n var p = outerNode,\n hx = hole.x,\n hy = hole.y,\n qx = -Infinity,\n m;\n\n // find a segment intersected by a ray from the hole's leftmost point to the left;\n // segment's endpoint with lesser x will be potential connection point\n do {\n if (hy <= p.y && hy >= p.next.y && p.next.y !== p.y) {\n var x = p.x + (hy - p.y) * (p.next.x - p.x) / (p.next.y - p.y);\n if (x <= hx && x > qx) {\n qx = x;\n m = p.x < p.next.x ? p : p.next;\n if (x === hx) return m; // hole touches outer segment; pick leftmost endpoint\n }\n }\n p = p.next;\n } while (p !== outerNode);\n\n if (!m) return null;\n\n // look for points inside the triangle of hole point, segment intersection and endpoint;\n // if there are no points found, we have a valid connection;\n // otherwise choose the point of the minimum angle with the ray as connection point\n\n var stop = m,\n mx = m.x,\n my = m.y,\n tanMin = Infinity,\n tan;\n\n p = m;\n\n do {\n if (hx >= p.x && p.x >= mx && hx !== p.x &&\n pointInTriangle(hy < my ? hx : qx, hy, mx, my, hy < my ? qx : hx, hy, p.x, p.y)) {\n\n tan = Math.abs(hy - p.y) / (hx - p.x); // tangential\n\n if (locallyInside(p, hole) &&\n (tan < tanMin || (tan === tanMin && (p.x > m.x || (p.x === m.x && sectorContainsSector(m, p)))))) {\n m = p;\n tanMin = tan;\n }\n }\n\n p = p.next;\n } while (p !== stop);\n\n return m;\n}\n\n// whether sector in vertex m contains sector in vertex p in the same coordinates\nfunction sectorContainsSector(m, p) {\n return area(m.prev, m, p.prev) < 0 && area(p.next, m, m.next) < 0;\n}\n\n// interlink polygon nodes in z-order\nfunction indexCurve(start, minX, minY, invSize) {\n var p = start;\n do {\n if (p.z === 0) p.z = zOrder(p.x, p.y, minX, minY, invSize);\n p.prevZ = p.prev;\n p.nextZ = p.next;\n p = p.next;\n } while (p !== start);\n\n p.prevZ.nextZ = null;\n p.prevZ = null;\n\n sortLinked(p);\n}\n\n// Simon Tatham's linked list merge sort algorithm\n// http://www.chiark.greenend.org.uk/~sgtatham/algorithms/listsort.html\nfunction sortLinked(list) {\n var i, p, q, e, tail, numMerges, pSize, qSize,\n inSize = 1;\n\n do {\n p = list;\n list = null;\n tail = null;\n numMerges = 0;\n\n while (p) {\n numMerges++;\n q = p;\n pSize = 0;\n for (i = 0; i < inSize; i++) {\n pSize++;\n q = q.nextZ;\n if (!q) break;\n }\n qSize = inSize;\n\n while (pSize > 0 || (qSize > 0 && q)) {\n\n if (pSize !== 0 && (qSize === 0 || !q || p.z <= q.z)) {\n e = p;\n p = p.nextZ;\n pSize--;\n } else {\n e = q;\n q = q.nextZ;\n qSize--;\n }\n\n if (tail) tail.nextZ = e;\n else list = e;\n\n e.prevZ = tail;\n tail = e;\n }\n\n p = q;\n }\n\n tail.nextZ = null;\n inSize *= 2;\n\n } while (numMerges > 1);\n\n return list;\n}\n\n// z-order of a point given coords and inverse of the longer side of data bbox\nfunction zOrder(x, y, minX, minY, invSize) {\n // coords are transformed into non-negative 15-bit integer range\n x = (x - minX) * invSize | 0;\n y = (y - minY) * invSize | 0;\n\n x = (x | (x << 8)) & 0x00FF00FF;\n x = (x | (x << 4)) & 0x0F0F0F0F;\n x = (x | (x << 2)) & 0x33333333;\n x = (x | (x << 1)) & 0x55555555;\n\n y = (y | (y << 8)) & 0x00FF00FF;\n y = (y | (y << 4)) & 0x0F0F0F0F;\n y = (y | (y << 2)) & 0x33333333;\n y = (y | (y << 1)) & 0x55555555;\n\n return x | (y << 1);\n}\n\n// find the leftmost node of a polygon ring\nfunction getLeftmost(start) {\n var p = start,\n leftmost = start;\n do {\n if (p.x < leftmost.x || (p.x === leftmost.x && p.y < leftmost.y)) leftmost = p;\n p = p.next;\n } while (p !== start);\n\n return leftmost;\n}\n\n// check if a point lies within a convex triangle\nfunction pointInTriangle(ax, ay, bx, by, cx, cy, px, py) {\n return (cx - px) * (ay - py) >= (ax - px) * (cy - py) &&\n (ax - px) * (by - py) >= (bx - px) * (ay - py) &&\n (bx - px) * (cy - py) >= (cx - px) * (by - py);\n}\n\n// check if a diagonal between two polygon nodes is valid (lies in polygon interior)\nfunction isValidDiagonal(a, b) {\n return a.next.i !== b.i && a.prev.i !== b.i && !intersectsPolygon(a, b) && // dones't intersect other edges\n (locallyInside(a, b) && locallyInside(b, a) && middleInside(a, b) && // locally visible\n (area(a.prev, a, b.prev) || area(a, b.prev, b)) || // does not create opposite-facing sectors\n equals(a, b) && area(a.prev, a, a.next) > 0 && area(b.prev, b, b.next) > 0); // special zero-length case\n}\n\n// signed area of a triangle\nfunction area(p, q, r) {\n return (q.y - p.y) * (r.x - q.x) - (q.x - p.x) * (r.y - q.y);\n}\n\n// check if two points are equal\nfunction equals(p1, p2) {\n return p1.x === p2.x && p1.y === p2.y;\n}\n\n// check if two segments intersect\nfunction intersects(p1, q1, p2, q2) {\n var o1 = sign(area(p1, q1, p2));\n var o2 = sign(area(p1, q1, q2));\n var o3 = sign(area(p2, q2, p1));\n var o4 = sign(area(p2, q2, q1));\n\n if (o1 !== o2 && o3 !== o4) return true; // general case\n\n if (o1 === 0 && onSegment(p1, p2, q1)) return true; // p1, q1 and p2 are collinear and p2 lies on p1q1\n if (o2 === 0 && onSegment(p1, q2, q1)) return true; // p1, q1 and q2 are collinear and q2 lies on p1q1\n if (o3 === 0 && onSegment(p2, p1, q2)) return true; // p2, q2 and p1 are collinear and p1 lies on p2q2\n if (o4 === 0 && onSegment(p2, q1, q2)) return true; // p2, q2 and q1 are collinear and q1 lies on p2q2\n\n return false;\n}\n\n// for collinear points p, q, r, check if point q lies on segment pr\nfunction onSegment(p, q, r) {\n return q.x <= Math.max(p.x, r.x) && q.x >= Math.min(p.x, r.x) && q.y <= Math.max(p.y, r.y) && q.y >= Math.min(p.y, r.y);\n}\n\nfunction sign(num) {\n return num > 0 ? 1 : num < 0 ? -1 : 0;\n}\n\n// check if a polygon diagonal intersects any polygon segments\nfunction intersectsPolygon(a, b) {\n var p = a;\n do {\n if (p.i !== a.i && p.next.i !== a.i && p.i !== b.i && p.next.i !== b.i &&\n intersects(p, p.next, a, b)) return true;\n p = p.next;\n } while (p !== a);\n\n return false;\n}\n\n// check if a polygon diagonal is locally inside the polygon\nfunction locallyInside(a, b) {\n return area(a.prev, a, a.next) < 0 ?\n area(a, b, a.next) >= 0 && area(a, a.prev, b) >= 0 :\n area(a, b, a.prev) < 0 || area(a, a.next, b) < 0;\n}\n\n// check if the middle point of a polygon diagonal is inside the polygon\nfunction middleInside(a, b) {\n var p = a,\n inside = false,\n px = (a.x + b.x) / 2,\n py = (a.y + b.y) / 2;\n do {\n if (((p.y > py) !== (p.next.y > py)) && p.next.y !== p.y &&\n (px < (p.next.x - p.x) * (py - p.y) / (p.next.y - p.y) + p.x))\n inside = !inside;\n p = p.next;\n } while (p !== a);\n\n return inside;\n}\n\n// link two polygon vertices with a bridge; if the vertices belong to the same ring, it splits polygon into two;\n// if one belongs to the outer ring and another to a hole, it merges it into a single ring\nfunction splitPolygon(a, b) {\n var a2 = new Node(a.i, a.x, a.y),\n b2 = new Node(b.i, b.x, b.y),\n an = a.next,\n bp = b.prev;\n\n a.next = b;\n b.prev = a;\n\n a2.next = an;\n an.prev = a2;\n\n b2.next = a2;\n a2.prev = b2;\n\n bp.next = b2;\n b2.prev = bp;\n\n return b2;\n}\n\n// create a node and optionally link it with previous one (in a circular doubly linked list)\nfunction insertNode(i, x, y, last) {\n var p = new Node(i, x, y);\n\n if (!last) {\n p.prev = p;\n p.next = p;\n\n } else {\n p.next = last.next;\n p.prev = last;\n last.next.prev = p;\n last.next = p;\n }\n return p;\n}\n\nfunction removeNode(p) {\n p.next.prev = p.prev;\n p.prev.next = p.next;\n\n if (p.prevZ) p.prevZ.nextZ = p.nextZ;\n if (p.nextZ) p.nextZ.prevZ = p.prevZ;\n}\n\nfunction Node(i, x, y) {\n // vertex index in coordinates array\n this.i = i;\n\n // vertex coordinates\n this.x = x;\n this.y = y;\n\n // previous and next vertex nodes in a polygon ring\n this.prev = null;\n this.next = null;\n\n // z-order curve value\n this.z = 0;\n\n // previous and next nodes in z-order\n this.prevZ = null;\n this.nextZ = null;\n\n // indicates whether this is a steiner point\n this.steiner = false;\n}\n\n// return a percentage difference between the polygon area and its triangulation area;\n// used to verify correctness of triangulation\nearcut.deviation = function (data, holeIndices, dim, triangles) {\n var hasHoles = holeIndices && holeIndices.length;\n var outerLen = hasHoles ? holeIndices[0] * dim : data.length;\n\n var polygonArea = Math.abs(signedArea(data, 0, outerLen, dim));\n if (hasHoles) {\n for (var i = 0, len = holeIndices.length; i < len; i++) {\n var start = holeIndices[i] * dim;\n var end = i < len - 1 ? holeIndices[i + 1] * dim : data.length;\n polygonArea -= Math.abs(signedArea(data, start, end, dim));\n }\n }\n\n var trianglesArea = 0;\n for (i = 0; i < triangles.length; i += 3) {\n var a = triangles[i] * dim;\n var b = triangles[i + 1] * dim;\n var c = triangles[i + 2] * dim;\n trianglesArea += Math.abs(\n (data[a] - data[c]) * (data[b + 1] - data[a + 1]) -\n (data[a] - data[b]) * (data[c + 1] - data[a + 1]));\n }\n\n return polygonArea === 0 && trianglesArea === 0 ? 0 :\n Math.abs((trianglesArea - polygonArea) / polygonArea);\n};\n\nfunction signedArea(data, start, end, dim) {\n var sum = 0;\n for (var i = start, j = end - dim; i < end; i += dim) {\n sum += (data[j] - data[i]) * (data[i + 1] + data[j + 1]);\n j = i;\n }\n return sum;\n}\n\n// turn a polygon in a multi-dimensional array form (e.g. as in GeoJSON) into a form Earcut accepts\nearcut.flatten = function (data) {\n var dim = data[0][0].length,\n result = {vertices: [], holes: [], dimensions: dim},\n holeIndex = 0;\n\n for (var i = 0; i < data.length; i++) {\n for (var j = 0; j < data[i].length; j++) {\n for (var d = 0; d < dim; d++) result.vertices.push(data[i][j][d]);\n }\n if (i > 0) {\n holeIndex += data[i - 1].length;\n result.holes.push(holeIndex);\n }\n }\n return result;\n};\n","/**\n * @fileoverview WebGL 渐变对象\n * \n * 本模块提供了 WebGL 渐变功能,支持 GLSL 着色器直接计算渐变色,\n * 无需 textureCanvas,性能更优。\n * \n * 支持的渐变类型:\n * - 线性渐变 (linear)\n * - 径向渐变 (radial)\n * \n * @module lib/webgl/gradient\n * @author jmGraph Team\n */\n\n/** @constant {number} 最大颜色断点数量 */\nconst MAX_STOPS = 16;\n\n/**\n * WebGL 渐变类\n * 支持 GLSL 着色器直接计算渐变色\n * \n * @class WebglGradient\n * @example\n * const gradient = new WebglGradient('linear', { x1: 0, y1: 0, x2: 100, y2: 0 });\n * gradient.addColorStop(0, '#ff0000');\n * gradient.addColorStop(1, '#0000ff');\n */\nclass WebglGradient {\n /**\n * 构造函数\n * @param {string} [type='linear'] 渐变类型:'linear' 或 'radial'\n * @param {Object} params 渐变参数\n * @param {number} [params.x1=0] 起点/内圆中心X坐标\n * @param {number} [params.y1=0] 起点/内圆中心Y坐标\n * @param {number} [params.r1=0] 内圆半径(径向渐变)\n * @param {number} [params.x2=0] 终点/外圆中心X坐标\n * @param {number} [params.y2=0] 终点/外圆中心Y坐标\n * @param {number} [params.r2=0] 外圆半径(径向渐变)\n * @param {Object} [params.bounds] 渐变边界\n * @param {Object} [params.control] 控制器对象\n */\n constructor(type = 'linear', params = {}) {\n /** @type {string} 渐变类型 */\n this.type = type || 'linear';\n\n this.x1 = params.x1 || 0;\n this.y1 = params.y1 || 0;\n this.r1 = params.r1 || 0;\n this.x2 = params.x2 || 0;\n this.y2 = params.y2 || 0;\n this.r2 = params.r2 || 0;\n\n /** @type {Object} 渐变边界 */\n this.bounds = params.bounds || { left: 0, top: 0, width: 0, height: 0 };\n\n this.control = params.control;\n\n /** @type {Array<{offset: number, color: string}>} 颜色断点数组 */\n this.stops = [];\n this._sortedStops = null;\n this._paramsHash = null;\n }\n\n /**\n * 添加颜色断点\n * @param {number} offset 断点位置 (0-1)\n * @param {string} color 颜色值\n */\n addColorStop(offset, color) {\n this.stops.push({\n offset: Math.max(0, Math.min(1, offset)),\n color\n });\n this._sortedStops = null;\n this._paramsHash = null;\n }\n\n /**\n * 获取排序后的断点数组(带解析后的颜色)\n * @private\n * @returns {Array<{offset: number, r: number, g: number, b: number, a: number}>}\n */\n _getSortedStops() {\n if (this._sortedStops) return this._sortedStops;\n\n const utils = this.control && this.control.graph && this.control.graph.utils;\n this._sortedStops = this.stops\n .map(s => {\n let c = s.color;\n if (utils && typeof c === 'string') {\n c = utils.hexToRGBA(c);\n }\n if (typeof c === 'object' && c !== null) {\n const needNormalize = (c.r > 1 || c.g > 1 || c.b > 1) ? 255 : 1;\n return {\n offset: s.offset,\n r: (c.r !== undefined ? c.r : 0) / needNormalize,\n g: (c.g !== undefined ? c.g : 0) / needNormalize,\n b: (c.b !== undefined ? c.b : 0) / needNormalize,\n a: c.a !== undefined ? c.a : 1\n };\n }\n return { offset: s.offset, r: 0, g: 0, b: 0, a: 1 };\n })\n .sort((a, b) => a.offset - b.offset);\n\n return this._sortedStops;\n }\n\n /**\n * 将渐变参数转换为 uniform 格式,传递给着色器\n * @returns {Object} uniform 参数对象\n */\n toUniformParams() {\n const stops = this._getSortedStops();\n const count = Math.min(stops.length, MAX_STOPS);\n\n const flatStops = new Float32Array(count * 5);\n for (let i = 0; i < count; i++) {\n const s = stops[i];\n flatStops[i * 5 + 0] = s.offset;\n flatStops[i * 5 + 1] = s.r;\n flatStops[i * 5 + 2] = s.g;\n flatStops[i * 5 + 3] = s.b;\n flatStops[i * 5 + 4] = s.a;\n }\n\n return {\n gradientType: this.type === 'radial' ? 2 : 1,\n gradientStart: new Float32Array([\n this.x1, this.y1,\n this.type === 'radial' ? Math.max(0, this.r1) : 0,\n 0\n ]),\n gradientEnd: new Float32Array([\n this.x2, this.y2,\n this.type === 'radial' ? Math.max(0, this.r2) : 0,\n 0\n ]),\n stopCount: count,\n stops: flatStops\n };\n }\n\n /** 使缓存失效 */\n invalidateCache() {\n this._sortedStops = null;\n this._paramsHash = null;\n }\n\n /**\n * 转换为渐变的字符串表达\n * @returns {string} 渐变字符串\n */\n toString() {\n let str = this.type + '-gradient(';\n if (this.type == 'linear') {\n str += this.x1 + ' ' + this.y1 + ' ' + this.x2 + ' ' + this.y2;\n }\n else {\n str += this.x1 + ' ' + this.y1 + ' ' + this.r1 + ' ' + this.x2 + ' ' + this.y2 + ' ' + this.r2;\n }\n this.stops.forEach(function(s) {\n str += ',' + s.color + ' ' + s.offset;\n });\n return str + ')';\n }\n}\n\nexport default WebglGradient;\nexport { MAX_STOPS };\n","/**\n * @fileoverview WebGL 着色器管理模块\n * \n * 本模块提供了 WebGL 着色器的创建功能。\n * \n * @module lib/webgl/core/shader\n * @author jmGraph Team\n */\n\n/**\n * 创建 WebGL 着色器\n * @param {WebGLRenderingContext} gl WebGL 渲染上下文\n * @param {number} type 着色器类型:gl.VERTEX_SHADER 或 gl.FRAGMENT_SHADER\n * @param {string} src 着色器源码\n * @returns {WebGLShader} 编译后的着色器对象\n */\nfunction createShader(gl, type, src) {\n const shader = gl.createShader(type);\n gl.shaderSource(shader, src);\n gl.compileShader(shader);\n return shader;\n}\n\nexport {\n createShader\n}","\n/**\n * @fileoverview GLSL 类型大小映射模块\n * \n * 本模块提供了 GLSL 类型到其元素数量的映射。\n * \n * @module lib/webgl/core/mapSize\n * @author jmGraph Team\n */\n\n/**\n * GLSL 类型到元素数量的映射表\n * @constant {Object.<string, number>}\n */\nconst GLSL_TO_SIZE = {\n 'float': 1,\n 'vec2': 2,\n 'vec3': 3,\n 'vec4': 4,\n\n 'int': 1,\n 'ivec2': 2,\n 'ivec3': 3,\n 'ivec4': 4,\n\n 'bool': 1,\n 'bvec2': 2,\n 'bvec3': 3,\n 'bvec4': 4,\n\n 'mat2': 4,\n 'mat3': 9,\n 'mat4': 16,\n\n 'sampler2D': 1\n};\n\n/**\n * 根据 GLSL 类型名获取元素数量\n * @param {string} type GLSL 类型名\n * @returns {number} 元素数量\n */\nconst mapSize = function(type) { \n return GLSL_TO_SIZE[type];\n};\n\nexport {\n mapSize\n}\n","\n/**\n * @fileoverview WebGL 类型到 GLSL 类型映射模块\n * \n * 本模块提供了 WebGL 常量类型到 GLSL 类型名的映射。\n * \n * @module lib/webgl/core/mapType\n * @author jmGraph Team\n */\n\n/** @type {Object.<number, string>|null} 缓存的类型映射表 */\nvar GL_TABLE = null;\n\n/**\n * WebGL 常量到 GLSL 类型的映射表\n * @constant {Object.<string, string>}\n */\nconst GL_TO_GLSL_TYPES = {\n 'FLOAT': 'float',\n 'FLOAT_VEC2': 'vec2',\n 'FLOAT_VEC3': 'vec3',\n 'FLOAT_VEC4': 'vec4',\n\n 'INT': 'int',\n 'INT_VEC2': 'ivec2',\n 'INT_VEC3': 'ivec3',\n 'INT_VEC4': 'ivec4',\n \n 'BOOL': 'bool',\n 'BOOL_VEC2': 'bvec2',\n 'BOOL_VEC3': 'bvec3',\n 'BOOL_VEC4': 'bvec4',\n \n 'FLOAT_MAT2': 'mat2',\n 'FLOAT_MAT3': 'mat3',\n 'FLOAT_MAT4': 'mat4',\n \n 'SAMPLER_2D': 'sampler2D' \n};\n\n/**\n * 将 WebGL 类型常量映射为 GLSL 类型名\n * @param {WebGLRenderingContext} gl WebGL 渲染上下文\n * @param {number} type WebGL 类型常量\n * @returns {string} GLSL 类型名\n */\nconst mapType = function(gl, type) {\n if(!GL_TABLE) {\n const typeNames = Object.keys(GL_TO_GLSL_TYPES);\n GL_TABLE = {};\n for(let i = 0; i < typeNames.length; ++i) {\n const tn = typeNames[i];\n GL_TABLE[ gl[tn] ] = GL_TO_GLSL_TYPES[tn];\n }\n }\n\n return GL_TABLE[type];\n};\n\nexport {\n mapType\n}\n","/**\n * @fileoverview WebGL 着色器程序管理模块\n * \n * 本模块提供了 WebGL 着色器程序的创建和管理功能,包括:\n * - 创建着色器程序\n * - 提取属性和 uniform 变量\n * - 顶点属性绑定\n * \n * @module lib/webgl/core/program\n * @author jmGraph Team\n */\nimport { createShader } from './shader.js';\nimport { mapSize } from './mapSize.js';\nimport { mapType } from './mapType.js';\n\n/**\n * 创建着色器程序\n * @param {WebGLRenderingContext} gl WebGL 渲染上下文\n * @param {string} vertexSrc 顶点着色器源码\n * @param {string} fragmentSrc 片段着色器源码\n * @returns {Object} 程序对象 {program, attrs, uniforms}\n */\nfunction createProgram(gl, vertexSrc, fragmentSrc) {\n const vertexShader = createShader(gl, gl.VERTEX_SHADER, vertexSrc);\n const fragmentShader = createShader(gl, gl.FRAGMENT_SHADER, fragmentSrc);\n\n const program = gl.createProgram();\n gl.attachShader(program, vertexShader);\n gl.attachShader(program, fragmentShader);\n gl.linkProgram(program);\n\n if (!gl.getProgramParameter(program, gl.LINK_STATUS)) {\n console.error('PError: Could not initialize shader.');\n console.error('gl.VALIDATE_STATUS', gl.getProgramParameter(program, gl.VALIDATE_STATUS));\n console.error('gl.getError()', gl.getError());\n\n if (gl.getProgramInfoLog(program) !== '') {\n console.warn('Warning: gl.getProgramInfoLog()', gl.getProgramInfoLog(program));\n }\n\n gl.deleteProgram(program);\n }\n\n useProgram(gl, program);\n\n gl.deleteShader(vertexShader);\n gl.deleteShader(fragmentShader);\n\n const attrs = extractAttributes(gl, program);\n const uniforms = extractUniforms(gl, program);\n \n return { program, attrs, uniforms };\n}\n\n/**\n * 使用指定的着色器程序\n * @param {WebGLRenderingContext} gl WebGL 渲染上下文\n * @param {WebGLProgram} program 着色器程序\n */\nfunction useProgram(gl, program) {\n return gl.useProgram(program);\n}\n\n/**\n * 提取着色器程序中的所有属性\n * @param {WebGLRenderingContext} gl WebGL 渲染上下文\n * @param {WebGLProgram} program 着色器程序\n * @returns {Object} 属性对象字典\n */\nfunction extractAttributes(gl, program) {\n const attributes = {};\n const count = gl.getProgramParameter(program, gl.ACTIVE_ATTRIBUTES);\n\n for (let i = 0; i < count; i++){\n const attribData = gl.getActiveAttrib(program, i);\n const type = mapType(gl, attribData.type);\n attributes[attribData.name] = {\n attribData,\n size: mapSize(type),\n type,\n location: gl.getAttribLocation(program, attribData.name), \n };\n }\n\n return attributes;\n}\n\n/**\n * 提取着色器程序中的所有 uniform 变量\n * @param {WebGLRenderingContext} gl WebGL 渲染上下文\n * @param {WebGLProgram} program 着色器程序\n * @returns {Object} uniform 变量对象字典\n */\nfunction extractUniforms(gl, program) {\n const uniforms = {};\n const count = gl.getProgramParameter(program, gl.ACTIVE_UNIFORMS);\n\n for (let i = 0; i < count; i++) {\n const uniformData = gl.getActiveUniform(program, i);\n const name = uniformData.name.replace(/\\[.*?\\]/, \"\");\n const type = mapType(gl, uniformData.type);\n\n uniforms[name] = {\n uniformData,\n type: type,\n size: uniformData.size,\n location: gl.getUniformLocation(program, name),\n };\n }\n\n return uniforms;\n}\n\n/**\n * 将缓冲区数据写入顶点属性\n * @param {WebGLRenderingContext} gl WebGL 渲染上下文\n * @param {Object} buffer 缓冲区对象\n * @param {Object} attr 属性对象\n * @param {number} [size=2] 每个顶点的分量数(1-4)\n * @param {number} [strip=0] 步长,0 表示紧密排列\n * @param {number} [offset=0] 字节偏移量\n * @param {number} [dataType=gl.FLOAT] 数据类型\n * @returns {Object} 缓冲区对象\n */\nfunction writeVertexAttrib(gl, buffer, attr, size=2, strip=0, offset=0, dataType=gl.FLOAT) {\n gl.bindBuffer(buffer.type, buffer.buffer);\n gl.vertexAttribPointer(\n attr.location,\n size,\n dataType,\n false,\n strip * buffer.unitSize,\n offset\n );\n gl.enableVertexAttribArray(attr.location);\n return buffer;\n}\n\n/**\n * 禁用顶点属性数组\n * @param {WebGLRenderingContext} gl WebGL 渲染上下文\n * @param {Object} attr 属性对象\n */\nfunction disableVertexAttribArray(gl, attr) {\n return gl.disableVertexAttribArray(attr.location);\n}\n\n/**\n * 获取属性位置\n * @param {WebGLRenderingContext} gl WebGL 渲染上下文\n * @param {WebGLProgram} program 着色器程序\n * @param {string} name 属性名\n * @returns {number} 属性位置\n */\nfunction getAttribLocation(gl, program, name) {\n return gl.getAttribLocation(program, name);\n}\n\n/**\n * 获取 uniform 位置\n * @param {WebGLRenderingContext} gl WebGL 渲染上下文\n * @param {WebGLProgram} program 着色器程序\n * @param {string} name uniform 变量名\n * @returns {WebGLUniformLocation} uniform 位置\n */\nfunction getUniformLocation(gl, program, name) {\n return gl.getUniformLocation(program, name);\n}\n\nexport {\n createProgram,\n useProgram,\n getAttribLocation,\n getUniformLocation,\n extractAttributes,\n extractUniforms,\n writeVertexAttrib,\n disableVertexAttribArray\n}","\n/**\n * @fileoverview WebGL 缓冲区管理模块\n * \n * 本模块提供了 WebGL 缓冲区的创建和管理功能,包括:\n * - 创建通用缓冲区\n * - 创建 Float32 类型缓冲区\n * - 创建 Uint16 类型缓冲区\n * - 删除缓冲区\n * \n * @module lib/webgl/core/buffer\n * @author jmGraph Team\n */\n\n/**\n * 创建 WebGL 缓冲区\n * @param {WebGLRenderingContext} gl WebGL 渲染上下文\n * @param {Array|TypedArray} data 缓冲区数据\n * @param {number} [type=gl.ARRAY_BUFFER] 缓冲区类型\n * @param {number} [drawType=gl.STATIC_DRAW] 绘制类型\n * @returns {Object} 缓冲区对象 {type, drawType, buffer, unitSize}\n */\nfunction createBuffer(gl, data, type=gl.ARRAY_BUFFER, drawType=gl.STATIC_DRAW) {\n const buffer = gl.createBuffer();\n if(!buffer) {\n throw Error('创建缓冲区对象失败');\n }\n gl.bindBuffer(type, buffer);\n gl.bufferData(type, data.buffer || data, drawType);\n return {\n type,\n drawType,\n buffer,\n unitSize: data.BYTES_PER_ELEMENT\n };\n}\n\n/**\n * 创建 Float32 类型缓冲区\n * @param {WebGLRenderingContext} gl WebGL 渲染上下文\n * @param {Array} data 数据数组\n * @param {number} [type=gl.ARRAY_BUFFER] 缓冲区类型\n * @param {number} [drawType=gl.STATIC_DRAW] 绘制类型\n * @returns {Object} 缓冲区对象\n */\nfunction createFloat32Buffer(gl, data, type=gl.ARRAY_BUFFER, drawType=gl.STATIC_DRAW) {\n const vertices = new Float32Array(data);\n const buffer = createBuffer(gl, vertices, type, drawType);\n return buffer;\n}\n\n/**\n * 创建 Uint16 类型缓冲区\n * @param {WebGLRenderingContext} gl WebGL 渲染上下文\n * @param {Array} data 数据数组\n * @param {number} [type=gl.ARRAY_BUFFER] 缓冲区类型\n * @param {number} [drawType=gl.STATIC_DRAW] 绘制类型\n * @returns {Object} 缓冲区对象\n */\nfunction createUint16Buffer(gl, data, type=gl.ARRAY_BUFFER, drawType=gl.STATIC_DRAW) {\n const vertices = new Uint16Array(data);\n const buffer = createBuffer(gl, vertices, type, drawType);\n return buffer;\n}\n\n/**\n * 删除缓冲区\n * @param {WebGLRenderingContext} gl WebGL 渲染上下文\n * @param {Object|WebGLBuffer} buffer 缓冲区对象或 WebGL 缓冲区\n */\nfunction deleteBuffer(gl, buffer) {\n gl.deleteBuffer(buffer.buffer || buffer);\n}\n\nexport {\n createBuffer,\n createUint16Buffer,\n createFloat32Buffer,\n deleteBuffer,\n}","\n/**\n * @fileoverview WebGL 纹理管理模块\n * \n * 本模块提供了 WebGL 纹理的创建和管理功能,包括:\n * - 创建 2D 纹理\n * - 创建图片纹理\n * - 创建数据纹理\n * - 删除纹理\n * \n * @module lib/webgl/core/texture\n * @author jmGraph Team\n */\n\n/**\n * 创建 2D 纹理\n * @param {WebGLRenderingContext} gl WebGL 渲染上下文\n * @returns {WebGLTexture} 纹理对象\n */\nfunction create2DTexture(gl) {\n const texture = gl.createTexture();\n gl.pixelStorei(gl.UNPACK_FLIP_Y_WEBGL, 1);\n gl.activeTexture(gl.TEXTURE0);\n gl.bindTexture(gl.TEXTURE_2D, texture);\n \n gl.texParameterf(gl.TEXTURE_2D, gl.TEXTURE_MAG_FILTER, gl.NEAREST);\n gl.texParameterf(gl.TEXTURE_2D, gl.TEXTURE_MIN_FILTER, gl.NEAREST);\n gl.texParameterf(gl.TEXTURE_2D, gl.TEXTURE_WRAP_S, gl.CLAMP_TO_EDGE);\n gl.texParameterf(gl.TEXTURE_2D, gl.TEXTURE_WRAP_T, gl.CLAMP_TO_EDGE);\n \n return texture;\n}\n\n/**\n * 创建图片纹理\n * @param {WebGLRenderingContext} gl WebGL 渲染上下文\n * @param {Image|HTMLImageElement} img 图像对象\n * @returns {Object} 纹理对象 {texture}\n */\nfunction createImgTexture(gl, img) {\n const texture = create2DTexture(gl);\n gl.texImage2D(gl.TEXTURE_2D, 0, gl.RGBA, gl.RGBA, gl.UNSIGNED_BYTE, img);\n return { texture };\n}\n\n/**\n * 根据像素数据创建纹理\n * @param {WebGLRenderingContext} gl WebGL 渲染上下文\n * @param {ImageData|Object} pixels 像素数据 {data, width, height}\n * @returns {Object} 纹理对象 {texture}\n */\nfunction createDataTexture(gl, pixels) {\n const data = new Uint8Array(pixels.data || pixels);\n const texture = create2DTexture(gl);\n\n gl.texImage2D(\n gl.TEXTURE_2D,\n 0,\n gl.RGBA,\n pixels.width || 1,\n pixels.height || 1,\n 0,\n gl.RGBA,\n gl.UNSIGNED_BYTE,\n data\n );\n return { texture };\n}\n\n/**\n * 删除纹理\n * @param {WebGLRenderingContext} gl WebGL 渲染上下文\n * @param {WebGLTexture} texture 纹理对象\n */\nfunction deleteTexture(gl, texture) {\n return gl.deleteTexture(texture);\n}\n\nexport {\n create2DTexture,\n createImgTexture,\n createDataTexture,\n deleteTexture\n}","\n/**\n * @fileoverview WebGL 基础渲染类\n * \n * 本模块提供了 WebGL 渲染的核心功能,包括:\n * - 着色器程序管理\n * - 缓冲区管理\n * - 纹理管理\n * - 变换矩阵操作\n * - 多边形三角化(使用 earcut 算法)\n * - 渐变支持\n * \n * @module lib/webgl/base\n * @author jmGraph Team\n */\nimport earcut from '../earcut.js';\nimport webglGradient, { MAX_STOPS } from './gradient.js';\nimport {\n createProgram,\n useProgram,\n writeVertexAttrib,\n disableVertexAttribArray\n} from './core/program.js';\n\nimport {\n createFloat32Buffer,\n createUint16Buffer,\n deleteBuffer,\n} from './core/buffer.js';\n\nimport {\n create2DTexture,\n createImgTexture,\n createDataTexture,\n deleteTexture\n} from './core/texture.js';\n\n// 把canvas坐标转为webgl坐标系\nconst convertPointSource = `\n vec4 translatePosition(vec4 point, float x, float y) {\n point.x = (point.x-x)/x;\n point.y = (y-point.y)/y;\n return point;\n }`;\n// 把纹理的canvas坐标转为纹理的坐标系\nconst convertTexturePosition = `\n vec2 translateTexturePosition(in vec2 point, vec4 bounds) {\n point.x = (point.x-bounds.x)/bounds.z; // 离左上角位置的X长比上纹理宽 0-1\n point.y = 1.0-(point.y-bounds.y)/bounds.w; // 离左上角位置的Y长比上高,因为纹理坐标是左下角起,所以要用1-\n return point;\n }`;\n\n// path顶点着色器源码\nconst pathVertexSource = `\n attribute vec4 a_position;\n attribute vec4 a_color;\n attribute vec2 a_text_coord;\n uniform vec2 a_center_point; // 当前canvas的中心位置\n uniform float a_point_size; // 点的大小\n uniform int a_type;\n varying vec4 v_color;\n varying vec2 v_text_coord;\n varying float v_type;\n\n ${convertPointSource}\n\n void main() {\n gl_PointSize = a_point_size == 0.0? 1.0 : a_point_size;\n v_type = float(a_type);\n vec4 pos = translatePosition(a_position, a_center_point.x, a_center_point.y);\n gl_Position = pos;\n v_color = a_color;\n if(a_type == 2 || a_type == 5) {\n v_text_coord = a_position.xy;\n }\n }\n`;\n// path 片段着色器源码\nconst pathFragmentSource = `\n precision mediump float;\n uniform sampler2D u_sample;\n uniform vec4 v_texture_bounds; // 纹理的左上坐标和大小 x,y,z,w\n uniform vec4 v_single_color;\n // GLSL 渐变 uniforms\n uniform int u_gradient_type; // 0=无 1=线性 2=径向\n uniform vec4 u_gradient_start; // 线性:{x1,y1,0,0} 径向:{cx,cy,r1,0}\n uniform vec4 u_gradient_end; // 线性:{x2,y2,0,0} 径向:{cx,cy,r2,0}\n uniform int u_gradient_stop_count;\n uniform float u_gradient_offsets[${MAX_STOPS}];\n uniform vec4 u_gradient_colors[${MAX_STOPS}]; // {r, g, b, a} 0~1 范围\n varying float v_type;\n varying vec4 v_color;\n varying vec2 v_text_coord;\n\n ${convertTexturePosition}\n\n // 在 sorted stops 中按 t 值采样颜色\n // 兼容 GLSL ES 1.0:循环仅与常量比较,无 break/continue\n vec4 sampleGradient(float t) {\n t = clamp(t, 0.0, 1.0);\n // 正向扫描:始终遍历 MAX_STOPS-1 次,找到 t 所在段并覆盖结果\n float localT = 0.0;\n vec4 c0 = u_gradient_colors[0];\n vec4 c1 = u_gradient_colors[0];\n for(int i = 0; i < ${MAX_STOPS - 1}; i++) {\n float s0 = u_gradient_offsets[i];\n float s1 = u_gradient_offsets[i + 1];\n if(t >= s0) {\n float range = s1 - s0;\n localT = range > 0.0001 ? clamp((t - s0) / range, 0.0, 1.0) : 0.0;\n c0 = u_gradient_colors[i];\n c1 = u_gradient_colors[i + 1];\n }\n }\n return mix(c0, c1, localT);\n }\n\n void main() {\n // 如果是fill,则直接填充颜色\n if(v_type == 1.0) {\n gl_FragColor = v_single_color;\n }\n // 渐变色 (旧方式,顶点颜色插值)\n else if(v_type == 3.0) {\n gl_FragColor = v_color;\n }\n // GLSL 渐变填充 (type=5)\n else if(v_type == 5.0) {\n float t;\n if(u_gradient_type == 2) {\n // 径向渐变\n vec2 d = v_text_coord - u_gradient_start.xy;\n float dist = length(d);\n float r1 = u_gradient_start.z;\n float r2 = u_gradient_end.z;\n float range = r2 - r1;\n t = range > 0.001 ? (dist - r1) / range : 0.0;\n } else {\n // 线性渐变\n vec2 dir = u_gradient_end.xy - u_gradient_start.xy;\n float lenSq = dot(dir, dir);\n if(lenSq > 0.001) {\n vec2 pos = v_text_coord - u_gradient_start.xy;\n t = dot(pos, dir) / lenSq;\n } else {\n t = 0.0;\n }\n }\n gl_FragColor = sampleGradient(t) * v_single_color.a;\n }\n else if(v_type == 2.0) {\n vec2 pos = translateTexturePosition(v_text_coord, v_texture_bounds);\n gl_FragColor = texture2D(u_sample, pos);\n }\n else {\n float r = distance(gl_PointCoord, vec2(0.5, 0.5));\n //根据距离设置片元\n if(r <= 0.5){\n // 方形区域片元距离几何中心半径小于0.5,像素颜色设置红色\n gl_FragColor = v_single_color;\n }else {\n // 方形区域距离几何中心半径不小于0.5的片元剪裁舍弃掉:\n discard;\n }\n }\n }\n`;\n\n/**\n * WebGL 基础渲染类\n * 提供 WebGL 渲染的核心功能,包括着色器、缓冲区、纹理管理等\n * \n * @class WeblBase\n * @example\n * const base = new WeblBase(graph, { mode: 'webgl' });\n * base.setStyle({ fillStyle: '#ff0000' });\n */\nclass WeblBase {\n /**\n * 构造函数\n * @param {jmGraph} graph jmGraph 实例\n * @param {Object} option 配置选项\n */\n constructor(graph, option) {\n this.graph = graph;\n this.option = option || {};\n this.style = {\n globalAlpha: 1\n };\n this.stateStack = [];\n /** @type {number[]} 2D 变换矩阵 [a, b, c, d, tx, ty] */\n this.transformMatrix = [1, 0, 0, 1, 0, 0];\n }\n\n /** @returns {WebGLRenderingContext} WebGL 渲染上下文 */\n get context() {\n if(this.graph) return this.graph.context;\n }\n\n /** 保存当前状态到状态栈 */\n save() {\n this.stateStack.push({\n transformMatrix: [...this.transformMatrix],\n style: { ...this.style }\n });\n }\n\n /** 从状态栈恢复上一个状态 */\n restore() {\n if (this.stateStack.length > 0) {\n const state = this.stateStack.pop();\n this.transformMatrix = state.transformMatrix;\n this.style = state.style;\n }\n }\n\n /**\n * 平移变换\n * @param {number} x X 轴平移量\n * @param {number} y Y 轴平移量\n */\n translate(x, y) {\n this.transformMatrix[4] += x * this.transformMatrix[0] + y * this.transformMatrix[2];\n this.transformMatrix[5] += x * this.transformMatrix[1] + y * this.transformMatrix[3];\n }\n\n /**\n * 缩放变换\n * @param {number} sx X 轴缩放比例\n * @param {number} sy Y 轴缩放比例\n */\n scale(sx, sy) {\n this.transformMatrix[0] *= sx;\n this.transformMatrix[1] *= sx;\n this.transformMatrix[2] *= sy;\n this.transformMatrix[3] *= sy;\n }\n\n /**\n * 旋转变换\n * @param {number} angle 旋转角度(弧度)\n */\n rotate(angle) {\n const cos = Math.cos(angle);\n const sin = Math.sin(angle);\n const [a, b, c, d] = this.transformMatrix;\n this.transformMatrix[0] = a * cos - b * sin;\n this.transformMatrix[1] = a * sin + b * cos;\n this.transformMatrix[2] = c * cos - d * sin;\n this.transformMatrix[3] = c * sin + d * cos;\n }\n\n /**\n * 矩阵变换\n * @param {number} a 水平缩放\n * @param {number} b 垂直倾斜\n * @param {number} c 水平倾斜\n * @param {number} d 垂直缩放\n * @param {number} e 水平移动\n * @param {number} f 垂直移动\n */\n transform(a, b, c, d, e, f) {\n const [currentA, currentB, currentC, currentD, currentE, currentF] = this.transformMatrix;\n this.transformMatrix[0] = a * currentA + b * currentC;\n this.transformMatrix[1] = a * currentB + b * currentD;\n this.transformMatrix[2] = c * currentA + d * currentC;\n this.transformMatrix[3] = c * currentB + d * currentD;\n this.transformMatrix[4] = e * currentA + f * currentC + currentE;\n this.transformMatrix[5] = e * currentB + f * currentD + currentF;\n }\n\n /**\n * 应用变换到点\n * @param {Object} point 点坐标 {x, y}\n * @returns {Object} 变换后的点坐标 {x, y}\n */\n applyTransform(point) {\n const [a, b, c, d, tx, ty] = this.transformMatrix;\n return {\n x: a * point.x + c * point.y + tx,\n y: b * point.x + d * point.y + ty\n };\n }\n\n /**\n * 文本测量用的离屏 canvas context\n * @private\n * @returns {CanvasRenderingContext2D|null}\n */\n get _measureCtx() {\n if(!this.__measureCtx) {\n try {\n if(typeof document !== 'undefined') {\n const c = document.createElement('canvas');\n c.width = c.height = 1;\n this.__measureCtx = c.getContext('2d');\n }\n } catch(e) {\n this.__measureCtx = null;\n }\n }\n return this.__measureCtx;\n }\n\n /**\n * 获取当前着色器程序\n * @returns {Object} 着色器程序对象\n */\n get program() {\n return this.graph.context.pathProgram || (this.graph.context.pathProgram=this.createProgram(pathVertexSource, pathFragmentSource));\n }\n\n /**\n * 设置样式\n * @param {Object|string} style 样式对象或样式属性名\n * @param {string} [value] 样式值(当 style 为字符串时使用)\n */\n setStyle(style = this.style, value = '') {\n if(typeof style === 'string') {\n const obj = {};\n obj[style] = value;\n style = obj;\n }\n this.style = {\n ...this.style,\n ...style\n }\n }\n\n /**\n * 将颜色转换为 WebGL 可识别的格式\n * @param {string|Object} color 颜色值\n * @returns {Object} RGBA 对象 {r, g, b, a},范围 0-1\n */\n convertColor(color) {\n if(this.isGradient(color)) return color;\n if(typeof color === 'string') {\n color = this.graph.utils.hexToRGBA(color);\n if(typeof color === 'string') {\n color = this.__parseCSSColor(color);\n }\n }\n if(typeof color === 'object' && color.r !== undefined) {\n return this.graph.utils.rgbToDecimal(color);\n }\n return color;\n }\n\n /**\n * 利用离屏 canvas 解析任意 CSS 颜色\n * @private\n * @param {string} colorStr CSS 颜色字符串\n * @returns {Object} RGBA 对象 {r, g, b, a}\n */\n __parseCSSColor(colorStr) {\n const ctx = this._measureCtx;\n if(!ctx) return { r: 0, g: 0, b: 0, a: 0 };\n try {\n ctx.clearRect(0, 0, 1, 1);\n ctx.fillStyle = '#000000';\n ctx.fillStyle = colorStr;\n ctx.fillRect(0, 0, 1, 1);\n const [r, g, b, a] = ctx.getImageData(0, 0, 1, 1).data;\n if(ctx.fillStyle === '#000000' && colorStr !== '#000000' && colorStr !== 'black') {\n return { r: 0, g: 0, b: 0, a: 0 };\n }\n return { r, g, b, a: a / 255 };\n } catch(e) {\n return { r: 0, g: 0, b: 0, a: 0 };\n }\n }\n\n /**\n * 创建着色器程序\n * @param {string} vertexSrc 顶点着色器源码\n * @param {string} fragmentSrc 片段着色器源码\n * @returns {Object} 着色器程序对象\n */\n createProgram(vertexSrc, fragmentSrc) { \n return createProgram(this.context, vertexSrc, fragmentSrc);\n }\n\n /**\n * 使用指定的着色器程序\n * @param {Object} [program] 着色器程序,默认使用当前程序\n * @returns {Object} 着色器程序\n */\n useProgram(program=this.program) {\n program = program.program || program;\n if(this.context.__curent_program === program) return program;\n useProgram(this.context, program.program || program);\n this.context.__curent_program = program;\n return program;\n }\n\n /**\n * 获取属性位置\n * @param {string} name 属性名\n * @returns {number} 属性位置\n */\n getAttribLocation(name) {\n return this.context.getAttribLocation(this.program.program, name);\n }\n \n /**\n * 获取 uniform 位置\n * @param {string} name uniform 变量名\n * @returns {WebGLUniformLocation} uniform 位置\n */\n getUniformLocation(name) {\n return this.context.getUniformLocation(this.program.program, name);\n }\n\n /**\n * 将缓冲区数据写入顶点属性\n * @param {Object} buffer 缓冲区对象\n * @param {Object} attr 属性对象\n * @param {number} [size=2] 每个顶点的分量数(1-4)\n * @param {number} [strip=0] 步长,0 表示紧密排列\n * @param {number} [offset=0] 字节偏移量\n * @param {number} [dataType=FLOAT] 数据类型\n * @returns {Object} 缓冲区对象\n */\n writeVertexAttrib(buffer, attr, size=2, strip=0, offset=0, dataType=this.context.FLOAT) {\n buffer.attr = attr;\n return writeVertexAttrib(this.context, buffer, attr, size, strip, offset, dataType);\n }\n\n /**\n * 禁用顶点属性数组\n * @param {Object} attr 属性对象\n * @returns {Object} 属性对象\n */\n disableVertexAttribArray(attr) {\n try{\n if(!attr) return attr;\n return disableVertexAttribArray(this.context, attr);\n }\n catch(e) {\n console.error(e);\n }\n return attr;\n }\n\n /**\n * 创建 Float32 缓冲区\n * @param {Array} data 数据数组\n * @param {number} [type=ARRAY_BUFFER] 缓冲区类型\n * @param {number} [drawType=STATIC_DRAW] 绘制类型\n * @returns {Object} 缓冲区对象\n */\n createFloat32Buffer(data, type=this.context.ARRAY_BUFFER, drawType=this.context.STATIC_DRAW) {\n const buffer = createFloat32Buffer(this.context, data, type, drawType);\n return { data, ...buffer };\n }\n\n /**\n * 创建 Uint16 缓冲区\n * @param {Array} data 数据数组\n * @param {number} [type=ARRAY_BUFFER] 缓冲区类型\n * @param {number} [drawType=STATIC_DRAW] 绘制类型\n * @returns {Object} 缓冲区对象\n */\n createUint16Buffer(data, type=this.context.ARRAY_BUFFER, drawType=this.context.STATIC_DRAW) {\n const buffer = createUint16Buffer(this.context, data, type, drawType);\n return { data, ...buffer };\n }\n\n /**\n * 删除缓冲区\n * @param {Object} buffer 缓冲区对象\n * @returns {Object} 缓冲区对象\n */\n deleteBuffer(buffer) {\n try {\n if(!buffer) return;\n const bufferHandler = buffer.buffer || buffer;\n if(bufferHandler) return deleteBuffer(this.context, bufferHandler);\n }\n catch(e) {\n console.log(buffer);\n console.error(e);\n }\n return buffer;\n }\n\n /** @returns {WebGLTexture} 2D 纹理对象 */\n create2DTexture() { \n return create2DTexture(this.context);\n }\n\n /**\n * 创建图片纹理\n * @param {Image|HTMLImageElement} img 图像对象\n * @returns {Object} 纹理对象\n */\n createImgTexture(img) {\n return createImgTexture(this.context, img);\n }\n\n /**\n * 根据像素数据创建纹理\n * @param {ImageData|Uint8Array} data 像素数据\n * @returns {Object} 纹理对象\n */\n createDataTexture(data) {\n return createDataTexture(this.context, data);\n }\n\n /**\n * 删除纹理\n * @param {Object} texture 纹理对象\n * @returns {Object} 纹理对象\n */\n deleteTexture(texture) {\n try {\n return deleteTexture(this.context, texture.texture || texture);\n }\n catch(e) {\n console.error(e);\n }\n return texture;\n }\n\n /**\n * 多边形三角化,得到三角形顶点索引数组\n * @param {Array<Object>} points 多边形顶点数组\n * @returns {Array<number>} 三角形顶点索引数组\n */\n earCutPoints(points) {\n const arr = this.pointsToArray(points);\n const ps = earcut(arr);\n return ps;\n }\n\n /**\n * 多边形三角化,得到三角形顶点数组\n * @param {Array<Object>} points 多边形顶点数组\n * @returns {Array<Array<Object>>} 三角形数组,每个三角形包含3个顶点\n */\n earCutPointsToTriangles(points) {\n this.earCutCache = this.earCutCache || (this.earCutCache = {});\n const len = points.length;\n const key = len + '_' + points[0].x + '_' + points[0].y + '_' + points[len-1].x + '_' + points[len-1].y;\n if (this.earCutCache[key]) return this.earCutCache[key];\n\n const ps = this.earCutPoints(points);\n const triangles = [];\n for(let i=0;i<ps.length; i+=3) {\n const p1 = points[ps[i]];\n const p2 = points[ps[i+1]];\n const p3 = points[ps[i+2]];\n triangles.push([p1, p2, p3]);\n }\n \n this.earCutCache[key] = triangles;\n return triangles;\n }\n\n /**\n * 点坐标数组转为一维数组\n * @param {Array<Object>} points 点数组 [{x, y}, ...]\n * @returns {Array<number>} 一维数组 [x1, y1, x2, y2, ...]\n */\n pointsToArray(points) {\n return [].concat(...points.map(p=>[p.x,p.y]));\n }\n\n /**\n * 一维数组转为点坐标数组\n * @param {Array<number>} arr 一维数组 [x1, y1, x2, y2, ...]\n * @returns {Array<Object>} 点数组 [{x, y}, ...]\n */\n arrayToPoints(arr) {\n const points = [];\n for(let i=0;i<arr.length; i+=2) {\n points.push({\n x: arr[i],\n y: arr[i+1]\n });\n }\n return points;\n }\n\n /**\n * 创建线性渐变\n * @param {number} x1 起点X坐标\n * @param {number} y1 起点Y坐标\n * @param {number} x2 终点X坐标\n * @param {number} y2 终点Y坐标\n * @param {Object} bounds 渐变边界\n * @returns {WebglGradient} 渐变对象\n */\n createLinearGradient(x1, y1, x2, y2, bounds) {\n return new webglGradient('linear', {\n x1, y1, x2, y2, bounds,\n control: this\n });\n }\n\n /**\n * 创建径向渐变\n * @param {number} x1 内圆中心X坐标\n * @param {number} y1 内圆中心Y坐标\n * @param {number} r1 内圆半径\n * @param {number} x2 外圆中心X坐标\n * @param {number} y2 外圆中心Y坐标\n * @param {number} r2 外圆半径\n * @param {Object} bounds 渐变边界\n * @returns {WebglGradient} 渐变对象\n */\n createRadialGradient(x1, y1, r1, x2, y2, r2, bounds) {\n return new webglGradient('radial', {\n x1, y1, r1,\n x2, y2, r2,\n bounds,\n control: this\n });\n }\n\n /**\n * 判断是否为渐变对象\n * @param {Object} obj 待检测对象\n * @returns {boolean} 是否为渐变对象\n */\n isGradient(obj) {\n return obj && obj instanceof webglGradient;\n }\n\n\t/**\n\t * 测试获取文本所占大小\n\t *\n\t * @method testSize\n\t * @return {object} 含文本大小的对象\n\t */\n\ttestSize(text, style=this.style) {\n\t\tconst ctx = this._measureCtx;\n\t\tif(!ctx) return { width: 15, height: style.fontSize || 15 };\n\n\t\tctx.save && ctx.save();\n\t\tif(style.font || style.fontSize) ctx.font = style.font || (style.fontSize + 'px ' + style.fontFamily);\n\t\tconst size = ctx.measureText ? ctx.measureText(text) : { width: 15 };\n ctx.restore && ctx.restore();\n\t\tsize.height = style.fontSize ? parseInt(style.fontSize) : 15;\n\t\treturn size;\n\t}\n}\n\nexport default WeblBase;\nexport { pathVertexSource, pathFragmentSource, MAX_STOPS };\n","/**\n * @fileoverview WebGL 路径绘制类\n * \n * 本模块提供了 WebGL 路径绘制功能,包括:\n * - 线条绘制(stroke)\n * - 填充绘制(fill)\n * - 纹理填充\n * - 渐变填充\n * - 文本绘制\n * - 多边形三角化\n * \n * @module lib/webgl/path\n * @author jmGraph Team\n */\nimport WebglBase, { MAX_STOPS } from './base.js';\nimport earcut from '../earcut.js';\n\n/**\n * WebGL 路径绘制类\n * 继承自 WeblBase,提供路径绘制功能\n * \n * @class WebglPath\n * @extends WeblBase\n * @example\n * const path = new WebglPath(graph, { isRegular: false, needCut: true });\n * path.draw(points);\n * path.stroke(points, '#ff0000', 2);\n */\nclass WebglPath extends WebglBase {\n /**\n * 构造函数\n * @param {jmGraph} graph jmGraph 实例\n * @param {Object} option 配置选项\n * @param {boolean} [option.isRegular=false] 是否为规则图形(凸多边形)\n * @param {boolean} [option.needCut=false] 是否需要切割处理\n * @param {Object} [option.control] 控制器对象\n */\n constructor(graph, option) {\n super(graph, option);\n /** @type {boolean} 是否为规则图形(凸多边形),规则图形处理更高效 */\n this.isRegular = option.isRegular || false;\n /** @type {boolean} 是否需要切割处理 */\n this.needCut = option.needCut || false;\n this.control = option.control;\n /** @type {Array<Object>} 路径点数组 */\n this.points = [];\n /** @type {Array} 缓存的缓冲区,避免每帧创建/销毁 */\n this.__cachedBuffers = [];\n /** @type {Object} 缓存的纹理 */\n this.__cachedTexture = null;\n /** @type {string} 缓存纹理的 key */\n this.__cachedTextureKey = null;\n }\n\n /** 释放缓存的 WebGL 资源 */\n dispose() {\n for(const buf of this.__cachedBuffers) {\n this.deleteBuffer(buf);\n }\n this.__cachedBuffers = [];\n if(this.__cachedTexture) {\n this.deleteTexture(this.__cachedTexture);\n this.__cachedTexture = null;\n this.__cachedTextureKey = null;\n }\n }\n\n /**\n * 获取或创建缓冲区,优先复用缓存\n * @param {Array} data 数据数组\n * @param {Object} attr 属性对象\n * @returns {Object} 缓冲区对象\n */\n getOrCreateBuffer(data, attr) {\n let buffer = this.__cachedBuffers.find(b => b.attr === attr);\n if(buffer) {\n const gl = this.context;\n const float32 = new Float32Array(data);\n gl.bindBuffer(gl.ARRAY_BUFFER, buffer.buffer);\n gl.bufferData(gl.ARRAY_BUFFER, float32, gl.DYNAMIC_DRAW);\n buffer.data = data;\n return buffer;\n }\n buffer = this.createFloat32Buffer(data);\n buffer.attr = attr;\n this.__cachedBuffers.push(buffer);\n return buffer;\n }\n\n /**\n * 应用变换到点\n * @param {Object} point 点坐标 {x, y}\n * @returns {Object} 变换后的点坐标\n */\n applyTransform(point) {\n return super.applyTransform(point);\n }\n\n /**\n * 设置父级边界\n * @param {Object} [parentBounds] 父级边界 {left, top, width, height}\n */\n setParentBounds(parentBounds = this.parentAbsoluteBounds) {\n\n //this.useProgram();\n\n if(parentBounds) this.parentAbsoluteBounds = parentBounds;\n // 缓存中心点值,只在变化时才更新 uniform\n const cx = this.graph.width / 2;\n const cy = this.graph.height / 2;\n if(this.__lastCenterX !== cx || this.__lastCenterY !== cy) {\n this.context.uniform2f(this.program.uniforms.a_center_point.location, cx, cy);\n this.__lastCenterX = cx;\n this.__lastCenterY = cy;\n }\n }\n\n setFragColor(color) {\n \n if(!Array.isArray(color)) {\n color = this.convertColor(color);\n if(typeof color.a === 'undefined') color.a = 1;\n this.context.uniform4f(this.program.uniforms.v_single_color.location, color.r, color.g, color.b, color.a * this.style.globalAlpha);\n return null;\n }\n\n const colorData = [];\n for(let c of color) {\n c = this.convertColor(c);\n if(typeof c.a === 'undefined') c.a = 1;\n colorData.push(c.r, c.g, c.b, c.a * this.style.globalAlpha);\n }\n \n const colorBuffer = this.createFloat32Buffer(colorData); \n this.writeVertexAttrib(colorBuffer, this.program.attrs.a_color, 4, 0, 0);\n colorBuffer.attr = this.program.attrs.a_color;\n return colorBuffer;\n }\n\n beginDraw() {\n this.useProgram();\n }\n\n // 开始绘制\n draw(points, parentBounds = this.parentAbsoluteBounds) {\n //this.useProgram();\n\n this.setParentBounds(parentBounds);\n \n this.points = points;\n }\n\n endDraw() {\n if(this.points) delete this.points;\n if(this.pathPoints) delete this.pathPoints;\n this.needClose = false;\n // 缓存的纹理保留到下次绘制(渐变可能不变)\n }\n\n /**\n * 标记路径需要闭合(不修改原始 points 数组)\n * 闭合逻辑由 stroke/fill 绘制方法自行处理\n */\n closePath() {\n this.needClose = true;\n }\n\n // 绘制点数组(使用 DYNAMIC_DRAW 复用 buffer,避免每帧 create/delete)\n writePoints(points, attr = this.program.attrs.a_position) {\n const fixedPoints = [];\n const [a, b, c, d, tx, ty] = this.transformMatrix;\n const isIdentity = (a === 1 && b === 0 && c === 0 && d === 1 && tx === 0 && ty === 0);\n const offsetLeft = this.parentAbsoluteBounds.left;\n const offsetTop = this.parentAbsoluteBounds.top;\n\n if(isIdentity) {\n // 单位矩阵时直接加偏移,避免逐点调用 applyTransform\n for(let i = 0; i < points.length; i++) {\n fixedPoints.push(points[i].x + offsetLeft, points[i].y + offsetTop);\n }\n } else {\n for(const p of points) {\n const transformedPoint = this.applyTransform(p);\n fixedPoints.push(\n transformedPoint.x + offsetLeft,\n transformedPoint.y + offsetTop\n );\n }\n }\n const float32 = new Float32Array(fixedPoints);\n const gl = this.context;\n\n // 复用已有 buffer 或创建新的\n if(this.__cachedBuffers.length > 0) {\n // 找一个同 attr 的 buffer 复用\n let buffer = this.__cachedBuffers.find(b => b.attr === attr);\n if(buffer) {\n gl.bindBuffer(gl.ARRAY_BUFFER, buffer.buffer);\n gl.bufferData(gl.ARRAY_BUFFER, float32, gl.DYNAMIC_DRAW);\n buffer.data = fixedPoints;\n this.writeVertexAttrib(buffer, attr, 2, 0, 0);\n return buffer;\n }\n }\n const vertexBuffer = this.createFloat32Buffer(float32, gl.ARRAY_BUFFER, gl.DYNAMIC_DRAW); \n this.writeVertexAttrib(vertexBuffer, attr, 2, 0, 0);\n vertexBuffer.attr = attr;\n this.__cachedBuffers.push(vertexBuffer);\n return vertexBuffer;\n }\n\n // 连接二个点\n genLinePoints(start, end) {\n const points = [start];\n const dx = end.x - start.x;\n const dy = end.y - start.y;\n if(dx !== 0 || dy !== 0) {\n const len = Math.sqrt(Math.pow(dx, 2) + Math.pow(dy, 2));\n const cos = dx / len;\n const sin = dy / len;\n const step = 0.5;\n for(let l=step; l<len; l+=step) {\n const x = start.x + cos * l;\n const y = start.y + sin * l;\n points.push({\n x, \n y\n });\n }\n }\n points.push(end);\n return points;\n }\n\n // 把path坐标集合分解成一个个点,并且处理moveTo线段能力\n pathToPoints(points=this.points) {\n let start = null;\n const res = [];\n for(let i=0; i<points.length; i++) {\n const p = points[i];\n if(start && !p.m) {\n const linePoints = this.genLinePoints(start, p);\n res.push(...linePoints);\n }\n else if(start && !res.includes(start)) {\n res.push(start);\n }\n start = p;\n }\n if(!res.includes(start)) res.push(start);\n return res;\n }\n // 二点是否重合\n equalPoint(p1, p2) {\n return p1.x === p2.x && p1.y === p2.y;\n }\n\n // 将带 moveTo 标记的点集拆分为外轮廓和多个洞\n splitSubPaths(points) {\n const subPaths = [];\n let current = [];\n for(let i = 0; i < points.length; i++) {\n const p = points[i];\n if(p.m && current.length > 0) {\n subPaths.push(current);\n current = [];\n }\n current.push(p);\n }\n if(current.length > 0) subPaths.push(current);\n\n // 面积最大的作为外轮廓,其余作为洞\n let maxArea = -1;\n let outerIdx = 0;\n for(let i = 0; i < subPaths.length; i++) {\n const area = Math.abs(this.polygonArea(subPaths[i]));\n if(area > maxArea) {\n maxArea = area;\n outerIdx = i;\n }\n }\n\n const outerPoints = subPaths[outerIdx];\n const holes = [];\n for(let i = 0; i < subPaths.length; i++) {\n if(i !== outerIdx) holes.push(subPaths[i]);\n }\n return { outerPoints, holes };\n }\n\n // 计算多边形面积(Shoelace 公式)\n polygonArea(points) {\n let area = 0;\n const n = points.length;\n for(let i = 0; i < n; i++) {\n const j = (i + 1) % n;\n area += points[i].x * points[j].y;\n area -= points[j].x * points[i].y;\n }\n return area / 2;\n }\n\n // 使用 earcut 带 holes 填充多边形\n fillWithHoles(outerPoints, holes, isTexture = false) {\n // 将所有点合并:外轮廓 + 各个洞,并记录洞的起始索引\n const allPoints = [...outerPoints];\n const holeIndices = [];\n for(const hole of holes) {\n holeIndices.push(allPoints.length);\n allPoints.push(...hole);\n }\n\n const dim = 2;\n const vertexData = [];\n for(const p of allPoints) {\n vertexData.push(p.x, p.y);\n }\n\n // 用 earcut 进行带洞三角化\n const indices = earcut(vertexData, holeIndices, dim);\n\n if(!indices || indices.length < 3) return;\n\n // 构建 GPU 顶点数据\n const allVertices = [];\n const allTexCoords = [];\n for(let i = 0; i < indices.length; i++) {\n const p = allPoints[indices[i]];\n allVertices.push(p.x, p.y);\n if(isTexture) allTexCoords.push(p.x, p.y);\n }\n\n const gl = this.context;\n const vertexArr = new Float32Array(allVertices);\n\n let posBuffer = this.__cachedBuffers.find(b => b.attr === this.program.attrs.a_position);\n if(!posBuffer) {\n posBuffer = this.createFloat32Buffer(vertexArr, gl.ARRAY_BUFFER, gl.DYNAMIC_DRAW);\n posBuffer.attr = this.program.attrs.a_position;\n this.__cachedBuffers.push(posBuffer);\n } else {\n gl.bindBuffer(gl.ARRAY_BUFFER, posBuffer.buffer);\n gl.bufferData(gl.ARRAY_BUFFER, vertexArr, gl.DYNAMIC_DRAW);\n }\n this.writeVertexAttrib(posBuffer, this.program.attrs.a_position, 2, 0, 0);\n\n if(isTexture && allTexCoords.length) {\n const texData = new Float32Array(allTexCoords);\n let texBuffer = this.__cachedBuffers.find(b => b.attr === this.program.attrs.a_text_coord);\n if(!texBuffer) {\n texBuffer = this.createFloat32Buffer(texData, gl.ARRAY_BUFFER, gl.DYNAMIC_DRAW);\n texBuffer.attr = this.program.attrs.a_text_coord;\n this.__cachedBuffers.push(texBuffer);\n } else {\n gl.bindBuffer(gl.ARRAY_BUFFER, texBuffer.buffer);\n gl.bufferData(gl.ARRAY_BUFFER, texData, gl.DYNAMIC_DRAW);\n }\n this.writeVertexAttrib(texBuffer, this.program.attrs.a_text_coord, 2, 0, 0);\n }\n\n gl.drawArrays(gl.TRIANGLES, 0, allVertices.length / 2);\n }\n // 把path坐标集合转为线段集\n pathToLines(points) {\n let start = null;\n const res = [];\n for(let i=0; i<points.length; i++) {\n const p = points[i];\n // 不重合的二个点,组成线段\n if(start && !p.m && !(start.x == p.x && start.y == p.y)) {\n const line = {\n start,\n end: p,\n };\n res.push(line);\n }\n start = p;\n }\n return res;\n }\n\n // 裁剪线段,如果二段线段有交点,则分割成四段, 端头相交的线段不用分割\n cutLines(lines, index1=0, index2=0) {\n if(lines && lines.length < 3) return lines;\n \n index2 = Math.max(index1 + 1, index2); //如果指定了比下一个更大的索引,则用更大的,说明前面的已经处理过了,不需要重复\n\n // 找出线段相交的点,并切割线段\n while(index1 < lines.length) {\n const line1 = lines[index1];\n\n while(index2 < lines.length) {\n const line2 = lines[index2];\n // 如果二条线顶点有重合,则不用处理\n if(this.equalPoint(line1.start, line2.start) || this.equalPoint(line1.end, line2.end) || \n this.equalPoint(line1.start, line2.end) || this.equalPoint(line1.end, line2.start)) {\n index2++;\n continue;\n }\n let cuted = false;\n const intersection = this.getIntersection(line1, line2);// 计算交点\n if(intersection) {\n // 如果交点不是线段的端点,则分割成二条线段\n if(!this.equalPoint(line1.start, intersection) && !this.equalPoint(line1.end, intersection)) {\n const sub1 = {\n start: line1.start,\n end: intersection\n };\n const sub2 = {\n start: intersection,\n end: line1.end\n };\n // 从原数组中删除当前线段,替换成新的线段\n lines.splice(index1, 1, sub1, sub2);\n // 当前线段被重新替换,需要重新从它开始处理\n cuted = true;\n index2 ++;// 因为多加入了一个线段,则对比线索引需要加1\n }\n // 如果交点不是线段的端点,则分割成二条线段\n if(!this.equalPoint(line2.start, intersection) && !this.equalPoint(line2.end, intersection)) {\n const sub1 = {\n start: line2.start,\n end: intersection\n };\n const sub2 = {\n start: intersection,\n end: line2.end\n };\n // 从原数组中删除当前线段,替换成新的线段\n lines.splice(index2, 1, sub1, sub2);\n index2 ++; // 线段2也切成了二段,对比索引要继续加1\n }\n }\n index2++;\n // 如果已经分割了起始线段,则第一个子线段开始,重新对比后面还未对比完的。直接所有对比完成返回\n if(cuted) return this.cutLines(lines, index1, index2);\n }\n index1++;\n index2 = index1 + 1;\n }\n return lines;\n }\n\n // 计算二个线段的交点\n getIntersection(line1, line2) {\n // 如果首尾相接,也认为是有交点\n if(this.equalPoint(line1.start, line2.start) || this.equalPoint(line1.start, line2.end)) return line1.start;\n if(this.equalPoint(line1.end, line2.start) || this.equalPoint(line1.end, line2.end)) return line1.end;\n\n // 三角形abc 面积的2倍\n const area_abc = (line1.start.x - line2.start.x) * (line1.end.y - line2.start.y) - (line1.start.y - line2.start.y) * (line1.end.x - line2.start.x);\n \n // 三角形abd 面积的2倍\n const area_abd = (line1.start.x - line2.end.x) * (line1.end.y - line2.end.y) - (line1.start.y - line2.end.y) * (line1.end.x - line2.end.x);\n \n // 面积符号相同则两点在线段同侧,不相交 (=0表示在线段顶点上);\n if (area_abc * area_abd > 0) {\n return null;\n }\n \n // 三角形cda 面积的2倍\n const area_cda = (line2.start.x - line1.start.x) * (line2.end.y - line1.start.y) - (line2.start.y - line1.start.y) * (line2.end.x - line1.start.x);\n // 三角形cdb 面积的2倍\n // 注意: 这里有一个小优化.不需要再用公式计算面积,而是通过已知的三个面积加减得出.\n const area_cdb = area_cda + area_abc - area_abd ;\n if(area_cda * area_cdb > 0) {\n return null ;\n }\n if(area_abd === area_abc) return null;\n\n //计算交点坐标\n const t = area_cda / (area_abd - area_abc);\n const dx= t * (line1.end.x - line1.start.x);\n const dy= t * (line1.end.y - line1.start.y);\n\n return { \n x: line1.start.x + dx, \n y: line1.start.y + dy\n };\n }\n\n // 找出跟当前线段尾部相交的所有线段\n getIntersectionLines(line, lines, index, point=line.end, points=[], root=null) {\n const res = {\n line,\n polygons: []\n };\n \n points.push(point);\n \n if(root && this.equalPoint(root.line.start, point)) {\n points.unshift(root.line.start); // 把起始地址加入进去\n root.polygons.push(points);\n return res;\n }\n\n for(;index<lines.length; index++) {\n const l = lines[index];\n if(this.equalPoint(point, l.start)) { \n if(points.includes(l.end)) continue; \n this.getIntersectionLines(l, lines, index+1, l.end, [...points], root||res);\n }\n else if(this.equalPoint(point, l.end)) {\n if(points.includes(l.start)) continue; \n this.getIntersectionLines(l, lines, index+1, l.start, [...points], root||res);\n }\n }\n return res;\n }\n\n // 根据路径点坐标,切割出封闭的多边形\n getPolygon(points) {\n let polygons = [];\n let lines = this.pathToLines(points); // 分解得到线段\n if(lines && lines.length > 2) {\n lines = this.cutLines(lines); // 把所有相交点切割线段找出来\n for(let i=0; i<lines.length-1; i++) {\n const line1 = lines[i];\n let polygon = [];// 当前图形\n\n const treeLine = this.getIntersectionLines(line1, lines, i+1);\n \n if(treeLine.polygons.length) polygons.push(...treeLine.polygons);\n continue;\n let lastLine = line1; // 下一个还在连接状态的线\n for(let j=i+1; j<lines.length; j++) {\n const line2 = lines[j];\n // 如果跟下一条线相接,则表示还在形成图形中\n if(this.equalPoint(lastLine.end, line2.start)) {\n polygon.push(lastLine.end);\n lastLine = line2;\n if(i === j+1) continue; //下一条相连 则不需要处理相交情况\n }\n else {\n polygon = [];\n } \n // 因为前面进行了分割线段,则里只有处理端点相连的情况\n const intersection = this.equalPoint(line1.start, line2.end)? line1.start: null;//this.getIntersection(line1, line2);// 计算交点\n if(intersection) {\n polygon.push(intersection);// 交叉点为图形顶点\n // 如果上一个连接线不是当前交叉线,则表示重新开始闭合\n // 如果上一个连接线是当前交叉线,形成了封闭的图形\n if(lastLine === line2 && polygon.length > 1) {\n polygons.push(polygon);\n \n // 封闭后,下一个起始线条就是从交点开始计算起\n /*lastLine = {\n start: intersection,\n end: line2.end\n };*/\n polygon = [];// 重新开始新一轮找图形\n\n /*\n // 如果交点是上一条线的终点,则新图形为空\n if(this.equalPoint(line2.end, intersection)) {\n polygon = [];// 重新开始新一轮找图形\n }\n else {\n // 同时交点也要加到上一个图形中第一个点,形成封闭\n polygon.unshift(intersection);\n\n polygon = [ intersection ];// 重新开始新一轮找图形\n }*/\n }\n else {\n lastLine = line2;\n }\n }\n }\n }\n }\n \n // 当有多个封闭图形时,再弟归一下,里面是不是有封闭图形内还有子封闭图形\n /*if(polygons.length > 1) {\n const newPolygons = [];\n for(const polygon of polygons) {\n // 只有大于4才有可能有子封闭图形\n if(polygon.length > 4) {\n const childPolygons = this.getPolygon(polygon);\n // 当有多个子图形时,表示它不是最终封闭图形,跳过,\n // 因为它的子图形之前有加入的,不需要重复加入\n if(childPolygons.length > 1) {\n //newPolygons.push(...childPolygons);\n continue;\n }\n }\n newPolygons.push(polygon);\n }\n polygons = newPolygons;\n }*/\n return polygons;\n }\n\n // 分割成一个个规则的三角形,不规则的多边形不全割的话纹理就会没法正确覆盖\n getTriangles(points) {\n this.trianglesCache = this.trianglesCache||(this.trianglesCache={});\n // 快速缓存 key:用长度和首尾点坐标(比 JSON.stringify 快几个数量级)\n const len = points.length;\n const key = len + '_' + points[0].x + '_' + points[0].y + '_' + points[len-1].x + '_' + points[len-1].y;\n if(this.trianglesCache[key]) return this.trianglesCache[key];\n\n const res = [];\n const polygons = this.getPolygon(points); \n if(polygons.length) { \n for(const polygon of polygons) {\n // 需要分割三角形,不然填充会有问题\n const triangles = this.earCutPointsToTriangles(polygon);\n res.push(...triangles);\n } \n }\n this.trianglesCache[key] = res;\n return res;\n }\n\n // 画线条\n stroke(points = this.points, color = this.style.strokeStyle, lineWidth = this.style.lineWidth) {\n if(!points || !points.length) return;\n // this.useProgram();\n\n let colorBuffer = null;\n if(color) {\n colorBuffer = this.setFragColor(color);\n }\n // 线宽\n if(lineWidth) {\n this.context.uniform1f(this.program.uniforms.a_point_size.location, lineWidth);// * this.graph.devicePixelRatio\n }\n // 标注为stroke\n if(this.program.uniforms.a_type) {\n // 4表示单画一个圆点,1表示方块形成的线条\n this.context.uniform1i(this.program.uniforms.a_type.location, points.length === 1? 4 :1);\n }\n if(points && points.length) {\n const regular = lineWidth <= 1.2;\n const hasMoveTo = points.some && points.some(p => p.m);\n const isRing = !hasMoveTo && this.needCut; // 空心形状(jmHArc close=true 时无 m 标记)\n if(regular && (hasMoveTo || isRing)) {\n // 有 moveTo 标记或空心形状时,分段绘制每个子路径的 LINE_LOOP\n // 避免 LINE_LOOP 把不同子路径的点连起来产生拉扯线\n if(hasMoveTo) {\n let subPath = [];\n for(let i = 0; i < points.length; i++) {\n if(points[i].m && subPath.length > 0) {\n const buffer = this.writePoints(subPath);\n this.context.drawArrays(this.context.LINE_LOOP, 0, subPath.length);\n subPath = [];\n }\n subPath.push(points[i]);\n }\n if(subPath.length > 1) {\n const buffer = this.writePoints(subPath);\n this.context.drawArrays(this.context.LINE_LOOP, 0, subPath.length);\n }\n }\n else if(isRing) {\n // 空心形状:前半段为内弧,后半段为外弧(反向),各自 LINE_LOOP\n const mid = Math.floor(points.length / 2);\n const inner = points.slice(0, mid);\n const outer = points.slice(mid);\n if(inner.length > 1) {\n this.writePoints(inner);\n this.context.drawArrays(this.context.LINE_LOOP, 0, inner.length);\n }\n if(outer.length > 1) {\n this.writePoints(outer);\n this.context.drawArrays(this.context.LINE_LOOP, 0, outer.length);\n }\n }\n }\n else {\n points = regular? points : this.pathToPoints(points);\n const buffer = this.writePoints(points);\n this.context.drawArrays(regular? this.context.LINE_LOOP: this.context.POINTS, 0, points.length);\n }\n // buffer 由 endDraw 统一清理\n }\n colorBuffer && this.disableVertexAttribArray(colorBuffer && colorBuffer.attr);\n }\n\n // 填充图形\n fill(bounds = {left: 0, top: 0, width: 0, height: 0}, type = 1) {\n \n if(this.points && this.points.length) { \n // 如果是颜色rgba\n if(this.style.fillStyle) { \n this.fillColor(this.style.fillStyle, this.points, bounds, type);\n }\n if(this.style.fillImage) { \n this.fillImage(this.style.fillImage, this.points, bounds, type); \n }\n }\n }\n\n fillColor(color, points, bounds, type=1) {\n \n // 如果是渐变色,使用 GLSL 着色器直接计算\n if(this.isGradient(color)) {\n return this.fillGradient(color, points, bounds);\n }\n \n // 标注为fill\n this.context.uniform1i(this.program.uniforms.a_type.location, type);\n const colorBuffer = this.setFragColor(color);\n\n this.fillPolygons(points); \n\n colorBuffer && this.disableVertexAttribArray(colorBuffer && colorBuffer.attr);\n\n }\n\n /**\n * 使用 GLSL 着色器渲染渐变填充\n * 无需 textureCanvas,直接通过 uniform 传递渐变参数给 GPU\n */\n fillGradient(gradient, points, bounds) {\n const params = gradient.toUniformParams();\n if(!params) return;\n\n // 标注为 GLSL 渐变 (type=5)\n this.context.uniform1i(this.program.uniforms.a_type.location, 5);\n\n // 设置 globalAlpha(通过 v_single_color.a 传递给着色器)\n this.context.uniform4f(this.program.uniforms.v_single_color.location, 1.0, 1.0, 1.0, this.style.globalAlpha);\n\n // 设置渐变类型\n if(this.program.uniforms.u_gradient_type) {\n this.context.uniform1i(this.program.uniforms.u_gradient_type.location, params.gradientType);\n }\n\n // 设置渐变起点/终点\n if(this.program.uniforms.u_gradient_start) {\n this.context.uniform4fv(this.program.uniforms.u_gradient_start.location, params.gradientStart);\n }\n if(this.program.uniforms.u_gradient_end) {\n this.context.uniform4fv(this.program.uniforms.u_gradient_end.location, params.gradientEnd);\n }\n\n // 设置颜色断点数量\n if(this.program.uniforms.u_gradient_stop_count) {\n this.context.uniform1i(this.program.uniforms.u_gradient_stop_count.location, params.stopCount);\n }\n\n // 设置每个 stop 的 offset\n // 关键:必须填充完整的 MAX_STOPS 长度数组,否则未初始化元素默认为 0\n // 会导致着色器循环中 t >= 0 始终为 true,返回黑色\n if(this.program.uniforms.u_gradient_offsets) {\n const offsets = new Float32Array(MAX_STOPS);\n for(let i = 0; i < params.stopCount; i++) {\n offsets[i] = params.stops[i * 5];\n }\n // 用 2.0 填充剩余项,使 t(0~1) >= 2.0 为 false,不会被匹配\n for(let i = params.stopCount; i < MAX_STOPS; i++) {\n offsets[i] = 2.0;\n }\n this.context.uniform1fv(this.program.uniforms.u_gradient_offsets.location, offsets);\n }\n\n // 设置每个 stop 的颜色 (rgba)\n if(this.program.uniforms.u_gradient_colors) {\n const colors = new Float32Array(MAX_STOPS * 4);\n for(let i = 0; i < params.stopCount; i++) {\n colors[i * 4 + 0] = params.stops[i * 5 + 1]; // r\n colors[i * 4 + 1] = params.stops[i * 5 + 2]; // g\n colors[i * 4 + 2] = params.stops[i * 5 + 3]; // b\n colors[i * 4 + 3] = params.stops[i * 5 + 4]; // a\n }\n // 用最后一个 stop 的颜色填充剩余项,确保不会返回黑色\n if(params.stopCount > 0) {\n const lastR = params.stops[(params.stopCount - 1) * 5 + 1];\n const lastG = params.stops[(params.stopCount - 1) * 5 + 2];\n const lastB = params.stops[(params.stopCount - 1) * 5 + 3];\n const lastA = params.stops[(params.stopCount - 1) * 5 + 4];\n for(let i = params.stopCount; i < MAX_STOPS; i++) {\n colors[i * 4 + 0] = lastR;\n colors[i * 4 + 1] = lastG;\n colors[i * 4 + 2] = lastB;\n colors[i * 4 + 3] = lastA;\n }\n }\n this.context.uniform4fv(this.program.uniforms.u_gradient_colors.location, colors);\n }\n\n // 填充多边形(需要纹理坐标来计算渐变位置)\n this.fillPolygons(points, true);\n this.disableVertexAttribArray(this.program.attrs.a_text_coord);\n }\n\n // 区域填充图片\n // points绘制的图形顶点\n // 图片整体绘制区域\n fillImage(img, points, bounds) {\n if(!img) return;\n\n // 对于 ImageData,生成缓存 key(基于渐变参数或 bounds),复用纹理\n let texture = null;\n if(img instanceof ImageData) {\n const key = `${img.width}_${img.height}_${bounds.width}_${bounds.height}_${bounds.left}_${bounds.top}`;\n if(this.__cachedTexture && this.__cachedTextureKey === key) {\n texture = this.__cachedTexture;\n } else {\n texture = this.createDataTexture(img);\n // 释放旧纹理\n if(this.__cachedTexture) {\n this.deleteTexture(this.__cachedTexture);\n }\n this.__cachedTexture = texture;\n this.__cachedTextureKey = key;\n }\n } else {\n texture = this.createImgTexture(img);\n }\n this.context.uniform1i(this.program.uniforms.u_sample.location, 0); // 纹理单元传递给着色器\n\n // 指定纹理区域尺寸\n this.context.uniform4f(this.program.uniforms.v_texture_bounds.location, \n bounds.left + this.parentAbsoluteBounds.left,\n bounds.top + this.parentAbsoluteBounds.top,\n bounds.width,\n bounds.height,\n ); // 纹理单元传递给着色器\n\n this.fillTexture(points);\n \n // 仅对非缓存纹理(非 ImageData)立即删除\n if(!(img instanceof ImageData)) {\n this.deleteTexture(texture);\n }\n }\n\n fillTexture(points) { \n if(points && points.length) { // 标注为纹理对象\n this.context.uniform1i(this.program.uniforms.a_type.location, 2); \n // 纹理坐标\n //const coordBuffer = this.writePoints(points, this.program.attrs.a_text_coord);\n this.fillPolygons(points, true);\n //this.deleteBuffer(coordBuffer); \n this.disableVertexAttribArray(this.program.attrs.a_text_coord); \n } \n }\n\n // 进行多边形填充\n fillPolygons(points, isTexture = false) { \n if(points.length <= 3) {\n // 3个点以下的三角形直接画\n const buffer = this.writePoints(points);\n const coordBuffer = isTexture? this.writePoints(points, this.program.attrs.a_text_coord): null;\n this.context.drawArrays(this.context.TRIANGLE_FAN, 0, points.length);\n return;\n }\n\n // 规则图形(凸多边形,如圆):直接用 TRIANGLE_FAN 一次性绘制,无需 earcut\n if(this.isRegular) {\n // 检查是否有 moveTo 标记,如果有说明路径包含多个子路径(如空心圆弧 jmHArc)\n const hasMoveTo = points.some && points.some(p => p.m);\n if(hasMoveTo) {\n // 有 m 标记:按 m 标记拆分子路径\n const { outerPoints, holes } = this.splitSubPaths(points);\n this.fillWithHoles(outerPoints, holes, isTexture);\n return;\n }\n // 无 m 标记但 needCut=true 表示空心形状(如 jmHArc close=true)\n // 前半段为内弧,后半段为外弧(反向),按中点拆分\n if(this.needCut && points.length >= 6) {\n const mid = Math.floor(points.length / 2);\n const inner = points.slice(0, mid);\n const outer = points.slice(mid);\n const innerArea = Math.abs(this.polygonArea(inner));\n const outerArea = Math.abs(this.polygonArea(outer));\n if(outerArea >= innerArea) {\n this.fillWithHoles(outer, [inner], isTexture);\n } else {\n this.fillWithHoles(inner, [outer], isTexture);\n }\n return;\n }\n const buffer = this.writePoints(points);\n const coordBuffer = isTexture? this.writePoints(points, this.program.attrs.a_text_coord): null;\n this.context.drawArrays(this.context.TRIANGLE_FAN, 0, points.length);\n return;\n }\n\n // 不规则图形:需要 earcut 三角化后,合并为一个大的顶点缓冲区,单次 drawArrays\n const triangles = this.needCut? this.earCutPointsToTriangles(points): this.getTriangles(points);\n if(!triangles.length) return;\n\n // 合并所有三角形的顶点到一个数组\n const allVertices = [];\n const allTexCoords = [];\n for(const triangle of triangles) {\n for(const p of triangle) {\n allVertices.push(p.x, p.y);\n if(isTexture) allTexCoords.push(p.x, p.y);\n }\n }\n\n // 一次性上传所有数据并绘制\n const vertexData = new Float32Array(allVertices);\n const gl = this.context;\n\n // 复用或创建 position buffer\n let posBuffer = this.__cachedBuffers.find(b => b.attr === this.program.attrs.a_position);\n if(!posBuffer) {\n posBuffer = this.createFloat32Buffer(vertexData, gl.ARRAY_BUFFER, gl.DYNAMIC_DRAW);\n posBuffer.attr = this.program.attrs.a_position;\n this.__cachedBuffers.push(posBuffer);\n } else {\n gl.bindBuffer(gl.ARRAY_BUFFER, posBuffer.buffer);\n gl.bufferData(gl.ARRAY_BUFFER, vertexData, gl.DYNAMIC_DRAW);\n }\n this.writeVertexAttrib(posBuffer, this.program.attrs.a_position, 2, 0, 0);\n\n if(isTexture && allTexCoords.length) {\n const texData = new Float32Array(allTexCoords);\n let texBuffer = this.__cachedBuffers.find(b => b.attr === this.program.attrs.a_text_coord);\n if(!texBuffer) {\n texBuffer = this.createFloat32Buffer(texData, gl.ARRAY_BUFFER, gl.DYNAMIC_DRAW);\n texBuffer.attr = this.program.attrs.a_text_coord;\n this.__cachedBuffers.push(texBuffer);\n } else {\n gl.bindBuffer(gl.ARRAY_BUFFER, texBuffer.buffer);\n gl.bufferData(gl.ARRAY_BUFFER, texData, gl.DYNAMIC_DRAW);\n }\n this.writeVertexAttrib(texBuffer, this.program.attrs.a_text_coord, 2, 0, 0);\n }\n\n gl.drawArrays(gl.TRIANGLES, 0, allVertices.length / 2);\n }\n\n // 填充图形\n drawImage(img, left=0, top=0, width=img.width, height=img.height) {\n width = width || img.width;\n height = height || img.height;\n\n this.fillImage(img, this.points, {\n left,\n top,\n width, \n height\n });\n }\n\n drawText(text, x, y, bounds) {\n // 文本渲染仍需要 2D canvas 绘制字形,然后作为纹理上传\n // 使用临时 canvas,不依赖共享的 textureCanvas\n if(!bounds.width || !bounds.height) return null;\n if(typeof document === 'undefined') return null;\n\n let canvas = this.__textCanvas;\n if(!canvas) {\n canvas = document.createElement('canvas');\n this.__textCanvas = canvas;\n }\n canvas.width = bounds.width;\n canvas.height = bounds.height;\n\n const ctx = canvas.getContext('2d', { willReadFrequently: true });\n ctx.clearRect(0, 0, canvas.width, canvas.height);\n\n // 修改字体\n ctx.font = this.style.font || (this.style.fontSize + 'px ' + this.style.fontFamily);\n\n x -= bounds.left;\n y -= bounds.top;\n\n // 设置文本样式\n if(this.style.fillStyle) {\n ctx.fillStyle = this.graph.utils.toColor(this.style.fillStyle);\n }\n if(this.style.strokeStyle) {\n ctx.strokeStyle = this.graph.utils.toColor(this.style.strokeStyle);\n }\n if(this.style.shadowColor) {\n ctx.shadowColor = this.graph.utils.toColor(this.style.shadowColor);\n }\n if(this.style.shadowBlur) {\n ctx.shadowBlur = this.style.shadowBlur;\n }\n if(this.style.shadowOffsetX !== undefined) {\n ctx.shadowOffsetX = this.style.shadowOffsetX;\n }\n if(this.style.shadowOffsetY !== undefined) {\n ctx.shadowOffsetY = this.style.shadowOffsetY;\n }\n if(this.style.textAlign) {\n ctx.textAlign = this.style.textAlign;\n }\n if(this.style.textBaseline) {\n ctx.textBaseline = this.style.textBaseline;\n }\n\n if(this.style.fillStyle && ctx.fillText) {\n if(this.style.maxWidth) {\n ctx.fillText(text, x, y, this.style.maxWidth);\n }\n else {\n ctx.fillText(text, x, y);\n }\n }\n if(this.style.strokeStyle && ctx.strokeText) {\n if(this.style.maxWidth) {\n ctx.strokeText(text, x, y, this.style.maxWidth);\n }\n else {\n ctx.strokeText(text, x, y);\n }\n }\n\n // 用纹理图片代替文字\n const data = ctx.getImageData(0, 0, canvas.width, canvas.height);\n this.fillImage(data, this.points, bounds);\n }\n}\n\nexport default WebglPath;","\n/**\n * @fileoverview jmGraph 控件基类\n * \n * jmControl 是 jmGraph 库中所有可视化控件的基类,继承自 jmProperty。\n * 提供了完整的控件生命周期管理:\n * - 样式系统:支持填充、描边、阴影、渐变、滤镜等\n * - 变换系统:支持平移、旋转、缩放\n * - 事件系统:支持鼠标、键盘、触摸事件\n * - 渲染系统:支持 Canvas 2D 和 WebGL 双渲染模式\n * - 层级管理:支持 zIndex 排序和父子关系\n * - 碰撞检测:支持点击测试和命中区域\n * \n * @module jmControl\n * @extends jmProperty\n * @author jmGraph Team\n * @license MIT\n */\n\nimport {jmUtils} from \"./jmUtils.js\";\nimport {jmList} from \"./jmList.js\";\nimport {jmGradient} from \"./jmGradient.js\";\nimport {jmShadow} from \"./jmShadow.js\";\nimport {jmFilter} from \"./jmFilter.js\";\nimport {jmProperty} from \"./jmProperty.js\";\nimport WebglPath from \"../lib/webgl/path.js\";\n\n/**\n * 样式名称映射表\n * \n * 将简化的样式名称映射到 Canvas API 的标准属性名。\n * 例如:'fill' -> 'fillStyle', 'stroke' -> 'strokeStyle'\n * \n * @constant {Object.<string, string>}\n * @private\n */\nconst jmStyleMap = {\n\t'fill':'fillStyle', // 填充颜色\n\t'fillImage':'fillImage', // 填充图片\n\t'stroke':'strokeStyle', // 描边颜色\n\t'shadow.blur':'shadowBlur', // 阴影模糊度\n\t'shadow.x':'shadowOffsetX', // 阴影X偏移\n\t'shadow.y':'shadowOffsetY', // 阴影Y偏移\n\t'shadow.color':'shadowColor', // 阴影颜色\n\t'lineWidth' : 'lineWidth', // 线宽\n\t'miterLimit': 'miterLimit', // 斜接限制\n\t'fillStyle' : 'fillStyle', // 填充样式\n\t'strokeStyle' : 'strokeStyle',// 描边样式\n\t'font' : 'font', // 字体\n\t'opacity' : 'globalAlpha', // 透明度\n\t'textAlign' : 'textAlign', // 文本对齐\n\t'textBaseline' : 'textBaseline', // 文本基线\n\t'shadowBlur' : 'shadowBlur', // 阴影模糊\n\t'shadowOffsetX' : 'shadowOffsetX', // 阴影X偏移\n\t'shadowOffsetY' : 'shadowOffsetY', // 阴影Y偏移\n\t'shadowColor' : 'shadowColor', // 阴影颜色\n\t'lineJoin': 'lineJoin', // 线条连接样式\n\t'lineCap':'lineCap', // 线条端点样式\n\t'lineDashOffset': 'lineDashOffset', // 虚线偏移\n\t'globalCompositeOperation': 'globalCompositeOperation' // 合成操作\n};\n\n/**\n * jmGraph 控件基类\n * \n * jmControl 是所有可视化图形控件的基类,提供了完整的图形渲染和交互能力。\n * \n * **核心功能:**\n * \n * 1. **样式系统**\n * - 支持填充色、描边色、渐变、图片填充\n * - 支持阴影、滤镜、混合模式\n * - 支持虚线、线宽、线帽等线条样式\n * \n * 2. **变换系统**\n * - 支持 translate(平移)\n * - 支持 rotation(旋转)\n * - 支持 transform(矩阵变换)\n * \n * 3. **事件系统**\n * - 鼠标事件:mousedown, mouseup, mousemove, click, dblclick\n * - 触摸事件:touchstart, touchmove, touchend\n * - 焦点事件:mouseover, mouseleave, touchover, touchleave\n * - 自定义事件:支持任意事件类型\n * \n * 4. **渲染系统**\n * - 自动选择 Canvas 2D 或 WebGL 渲染器\n * - 支持脏矩形优化\n * - 支持层级排序(zIndex)\n * \n * 5. **碰撞检测**\n * - 支持点在多边形内判断\n * - 支持自定义命中区域\n * - 支持旋转后的碰撞检测\n * \n * @class jmControl\n * @extends jmProperty\n * \n * @example\n * // 创建自定义控件\n * class MyShape extends jmControl {\n * constructor(params) {\n * super(params, 'myShape');\n * }\n * \n * // 重写绘制方法\n * draw() {\n * // 自定义绘制逻辑\n * }\n * }\n * \n * // 使用控件\n * const shape = new MyShape({\n * position: { x: 100, y: 100 },\n * width: 50,\n * height: 50,\n * style: {\n * fill: 'red',\n * stroke: 'black',\n * lineWidth: 2\n * }\n * });\n * graph.children.add(shape);\n */\nexport default class jmControl extends jmProperty {\n\n\t/**\n\t * 构造函数\n\t * \n\t * 创建一个新的控件实例。子类应该调用 super(params, 'typeName') 来设置类型名称。\n\t * \n\t * @constructor\n\t * @param {Object} [params] - 控件初始化参数\n\t * @param {Object} [params.style] - 样式对象,包含填充、描边等属性\n\t * @param {number} [params.width=0] - 控件宽度\n\t * @param {number} [params.height=0] - 控件高度\n\t * @param {Object} [params.position] - 控件位置 {x, y}\n\t * @param {jmGraph} [params.graph] - 所属画布实例\n\t * @param {number} [params.zIndex=0] - 层级顺序\n\t * @param {boolean} [params.interactive=false] - 是否响应交互事件\n\t * @param {Object} [params.hitArea] - 自定义命中区域 {x, y, width, height}\n\t * @param {boolean} [params.isRegular] - 是否为规则图形(WebGL优化)\n\t * @param {boolean} [params.needCut] - 是否需要裁剪(WebGL)\n\t * @param {string} [t] - 控件类型名称,默认使用类名\n\t * \n\t * @example\n\t * // 创建矩形控件\n\t * const rect = new jmControl({\n\t * position: { x: 10, y: 10 },\n\t * width: 100,\n\t * height: 50,\n\t * style: {\n\t * fill: '#ff0000',\n\t * stroke: '#000000',\n\t * lineWidth: 2\n\t * },\n\t * interactive: true\n\t * }, 'jmRect');\n\t */\n\tconstructor(params, t) {\n\t\tparams = params||{};\n\t\tsuper(params);\n\t\t// 设置控件类型标识\n\t\tthis.property('type', t || new.target.name);\n\t\t// 初始化样式对象\n\t\tthis.style = params && params.style ? params.style : {};\n\t\t// 设置尺寸\n\t\tthis.width = params.width || 0;\n\t\tthis.height = params.height || 0;\n\t\t// 自定义命中区域(用于点击测试)\n\t\tthis.hitArea = params.hitArea || null;\n\n\t\t// 设置位置\n\t\tif(params.position) {\n\t\t\tthis.position = params.position;\n\t\t}\n\n\t\t// 关联画布\n\t\tthis.graph = params.graph || null;\n\t\t// 层级顺序(用于排序)\n\t\tthis.zIndex = params.zIndex || 0;\n\t\t// 是否响应交互事件\n\t\tthis.interactive = typeof params.interactive == 'undefined'? false : params.interactive;\n\n\t\t// WebGL 模式下创建对应的渲染控制器\n\t\tif(this.mode === 'webgl') {\n\t\t\tthis.webglControl = new WebglPath(this.graph, {\n\t\t\t\tstyle: this.style,\n\t\t\t\tcontrol: this,\n\t\t\t\tisRegular: params.isRegular,\n\t\t\t\tneedCut: params.needCut\n\t\t\t});\n\t\t}\n\n\t\t// 执行初始化\n\t\tthis.initializing();\n\t\t\n\t\t// 别名:on 等同于 bind\n\t\tthis.on = this.bind;\n\t\t\n\t\t// 保存原始参数\n\t\tthis.option = params;\n\t}\n\n\t/**\n\t * 控件类型标识\n\t * \n\t * 用于类型检查和调试,由构造函数自动设置。\n\t * \n\t * @type {string}\n\t * @readonly\n\t * \n\t * @example\n\t * console.log(rect.type); // 'jmRect'\n\t * if(control.type === 'jmCircle') { ... }\n\t */\n\tget type() {\n\t\treturn this.property('type');\n\t}\n\n\t/**\n\t * 绘图上下文\n\t * \n\t * 获取当前控件的 Canvas 2D 或 WebGL 渲染上下文。\n\t * 如果控件本身不是 jmGraph,会返回所属 graph 的上下文。\n\t * \n\t * @type {CanvasRenderingContext2D|WebGLRenderingContext}\n\t * @readonly\n\t * \n\t * @example\n\t * // 获取上下文并绘制\n\t * const ctx = control.context;\n\t * ctx.fillStyle = 'red';\n\t * ctx.fillRect(0, 0, 100, 100);\n\t */\n\tget context() {\n\t\tlet s = this.property('context');\n\t\tif(s) return s;\n\t\telse if(this.is('jmGraph') && this.canvas && this.canvas.getContext) {\n\t\t\treturn this.context = this.canvas.getContext(this.mode || '2d');\n\t\t}\n\t\tconst g = this.graph;\n\t\tif(g) return g.context;\n\t\treturn g.canvas.getContext(this.mode || '2d');\n\t}\n\tset context(v) {\n\t\treturn this.property('context', v);\n\t}\n\n\t/**\n\t * 样式对象\n\t * \n\t * 控件的视觉样式配置,包括:\n\t * - fill: 填充颜色或渐变\n\t * - stroke: 描边颜色\n\t * - lineWidth: 线宽\n\t * - shadow: 阴影配置\n\t * - font: 字体(文本控件)\n\t * - opacity: 透明度\n\t * \n\t * 设置新样式会触发 needUpdate。\n\t * \n\t * @type {Object}\n\t * \n\t * @example\n\t * // 设置样式\n\t * control.style = {\n\t * fill: '#ff0000',\n\t * stroke: '#000000',\n\t * lineWidth: 2,\n\t * shadow: {\n\t * blur: 10,\n\t * x: 5,\n\t * y: 5,\n\t * color: 'rgba(0,0,0,0.5)'\n\t * }\n\t * };\n\t */\n\tget style() {\n\t\tlet s = this.property('style');\n\t\tif(!s) s = this.property('style', {});\n\t\treturn s;\n\t}\n\tset style(v) {\n\t\tthis.needUpdate = true;\n\t\treturn this.property('style', v);\n\t}\n\n\t/**\n\t * 是否可见\n\t * \n\t * 控制控件是否参与渲染和事件响应。\n\t * 不可见的控件不会被绘制,也不会响应鼠标/触摸事件。\n\t * \n\t * @type {boolean}\n\t * @default true\n\t * \n\t * @example\n\t * // 隐藏控件\n\t * control.visible = false;\n\t * \n\t * // 显示控件\n\t * control.visible = true;\n\t */\n\tget visible() {\n\t\tlet s = this.property('visible');\n\t\tif(typeof s == 'undefined') s = this.property('visible', true);\n\t\treturn s;\n\t}\n\tset visible(v) {\n\t\tthis.needUpdate = true;\n\t\treturn this.property('visible', v);\n\t}\n\n\t/**\n\t * 是否响应交互事件\n\t * \n\t * 设置为 true 时,控件会响应鼠标和触摸事件。\n\t * 设置为 false 时,事件会穿透到下层控件。\n\t * \n\t * @type {boolean}\n\t * @default false\n\t * \n\t * @example\n\t * // 启用交互\n\t * control.interactive = true;\n\t * control.bind('click', (evt) => {\n\t * console.log('clicked!');\n\t * });\n\t */\n\tget interactive() {\n\t\tconst s = this.property('interactive');\n\t\treturn s;\n\t}\n\tset interactive(v) {\n\t\treturn this.property('interactive', v);\n\t}\n\n\t/**\n\t * 自定义命中区域\n\t * \n\t * 用于点击测试的自定义区域,格式为 {x, y, width, height}。\n\t * 如果设置,点击测试会使用此区域而非实际图形边界。\n\t * \n\t * @type {Object|null}\n\t * \n\t * @example\n\t * // 设置更大的点击区域\n\t * control.hitArea = {\n\t * x: -10,\n\t * y: -10,\n\t * width: control.width + 20,\n\t * height: control.height + 20\n\t * };\n\t */\n\tget hitArea() {\n\t\tconst s = this.property('hitArea');\n\t\treturn s;\n\t}\n\tset hitArea(v) {\n\t\treturn this.property('hitArea', v);\n\t}\n\t\t\n\t/**\n\t * 子控件列表\n\t * \n\t * 当前控件的所有子控件。子控件会按 zIndex 排序后绘制。\n\t * 添加子控件时会自动建立父子关系。\n\t * \n\t * @type {jmList}\n\t * \n\t * @example\n\t * // 添加子控件\n\t * parent.children.add(child);\n\t * \n\t * // 移除子控件\n\t * parent.children.remove(child);\n\t * \n\t * // 遍历子控件\n\t * parent.children.each((i, child) => {\n\t * console.log(child);\n\t * });\n\t */\n\tget children() {\n\t\tlet s = this.property('children');\n\t\tif(!s) s = this.property('children', new jmList());\n\t\treturn s;\n\t}\n\tset children(v) {\n\t\tthis.needUpdate = true;\n\t\treturn this.property('children', v);\n\t}\n\n\t/**\n\t * 控件宽度\n\t * \n\t * 可以是具体数值或百分比字符串(如 '50%')。\n\t * 百分比会相对于父容器宽度计算。\n\t * \n\t * @type {number|string}\n\t * \n\t * @example\n\t * // 设置固定宽度\n\t * control.width = 100;\n\t * \n\t * // 设置百分比宽度\n\t * control.width = '50%';\n\t */\n\tget width() {\n\t\tlet s = this.property('width');\n\t\tif(typeof s == 'undefined') s = this.property('width', 0);\n\t\treturn s;\n\t}\n\tset width(v) {\n\t\tthis.needUpdate = true;\n\t\treturn this.property('width', v);\n\t}\n\n\t/**\n\t * 控件高度\n\t * \n\t * 可以是具体数值或百分比字符串(如 '50%')。\n\t * 百分比会相对于父容器高度计算。\n\t * \n\t * @type {number|string}\n\t * \n\t * @example\n\t * // 设置固定高度\n\t * control.height = 100;\n\t * \n\t * // 设置百分比高度\n\t * control.height = '50%';\n\t */\n\tget height() {\n\t\tlet s = this.property('height');\n\t\tif(typeof s == 'undefined') s = this.property('height', 0);\n\t\treturn s;\n\t}\n\tset height(v) {\n\t\tthis.needUpdate = true;\n\t\treturn this.property('height', v);\n\t}\n\n\t/**\n\t * 层级顺序\n\t * \n\t * 控制控件的绘制顺序,值越大越靠上。\n\t * 设置 zIndex 会触发子控件重新排序。\n\t * \n\t * @type {number}\n\t * @default 0\n\t * \n\t * @example\n\t * // 将控件置于最上层\n\t * control.zIndex = 100;\n\t * \n\t * // 将控件置于最下层\n\t * control.zIndex = -1;\n\t */\n\tget zIndex() {\n\t\tlet s = this.property('zIndex');\n\t\tif(!s) s = this.property('zIndex', 0);\n\t\treturn s;\n\t}\n\tset zIndex(v) {\n\t\tthis.property('zIndex', v);\n\t\tthis.children.sort();\n\t\tthis.needUpdate = true;\n\t\treturn v;\n\t}\n\n\t/**\n\t * 鼠标样式\n\t * \n\t * 鼠标悬停在控件上时显示的光标样式。\n\t * 常用值:'default', 'pointer', 'move', 'text', 'crosshair'\n\t * \n\t * @type {string}\n\t * \n\t * @example\n\t * // 设置为手型指针\n\t * control.cursor = 'pointer';\n\t * \n\t * // 设置为移动样式\n\t * control.cursor = 'move';\n\t */\n\tset cursor(cur) {\n\t\tconst graph = this.graph;\n\t\tif(graph) {\n\t\t\tgraph.css('cursor',cur);\n\t\t}\n\t}\n\tget cursor() {\n\t\tconst graph = this.graph;\n\t\tif(graph) {\n\t\t\treturn graph.css('cursor');\n\t\t}\n\t}\n\n\t/**\n\t * 初始化控件\n\t * \n\t * 在构造函数末尾调用,用于设置子控件管理逻辑。\n\t * 重写了 children 的 add、remove、sort、clear 方法,\n\t * 实现自动的父子关系维护和脏标记传播。\n\t * \n\t * @method initializing\n\t * @protected\n\t */\n\tinitializing() {\n\n\t\tconst self = this;\n\t\tthis.children = this.children || new jmList();\n\t\tconst oadd = this.children.add;\n\t\t\n\t\t/**\n\t\t * 重写 add 方法,自动建立父子关系\n\t\t * @param {jmControl} obj - 要添加的子控件\n\t\t * @returns {jmControl} 添加的子控件\n\t\t */\n\t\tthis.children.add = function(obj) {\n\t\t\tif(typeof obj === 'object') {\n\t\t\t\t// 如果对象已有父级,先从原父级移除\n\t\t\t\tif(obj.parent && obj.parent != self && obj.parent.children) {\n\t\t\t\t\tobj.parent.children.remove(obj);\n\t\t\t\t}\n\t\t\t\tobj.parent = self;\n\t\t\t\t// 如果已存在,先移除再添加\n\t\t\t\tif(this.contain(obj)) {\n\t\t\t\t\tthis.oremove(obj);\n\t\t\t\t}\n\t\t\t\toadd.call(this, obj);\n\t\t\t\tobj.emit('add', obj);\n\n\t\t\t\tself.needUpdate = true;\n\t\t\t\t// 传播 graph 引用\n\t\t\t\tif(self.graph) obj.graph = self.graph;\n\t\t\t\tthis.sort();\n\t\t\t\treturn obj;\n\t\t\t}\n\t\t};\n\t\tthis.children.oremove= this.children.remove;\n\t\t\n\t\t/**\n\t\t * 重写 remove 方法,清理父子关系\n\t\t * @param {jmControl} obj - 要移除的子控件\n\t\t */\n\t\tthis.children.remove = function(obj) {\n\t\t\tif(typeof obj === 'object') {\n\t\t\t\tobj.parent = null;\n\t\t\t\tobj.graph = null;\n\t\t\t\tobj.remove(true);\n\t\t\t\tthis.oremove(obj);\n\t\t\t\tself.needUpdate = true;\n\t\t\t}\n\t\t};\n\t\t\n\t\t/**\n\t\t * 按 zIndex 排序子控件\n\t\t */\n\t\tthis.children.sort = function() {\n\t\t\tconst levelItems = {};\n\t\t\tthis.each(function(i, obj) {\n\t\t\t\tif(!obj) return;\n\t\t\t\tlet zindex = obj.zIndex;\n\t\t\t\tif(!zindex && obj.style && obj.style.zIndex) {\n\t\t\t\t\tzindex = Number(obj.style.zIndex);\n\t\t\t\t\tif(isNaN(zindex)) zindex=obj.style.zIndex||0;\n\t\t\t\t}\n\t\t\t\tlet items = levelItems[zindex] || (levelItems[zindex] = []);\n\t\t\t\titems.push(obj);\n\t\t\t});\n\n\t\t\tthis.splice(0, this.length);\n\t\t\t\n\t\t\tfor(let index in levelItems) {\n\t\t\t\toadd.call(this, levelItems[index]);\n\t\t\t}\n\t\t}\n\t\t\n\t\t/**\n\t\t * 清空所有子控件\n\t\t */\n\t\tthis.children.clear = function() {\n\t\t\tthis.each(function(i,obj) {\n\t\t\t\tthis.remove(obj);\n\t\t\t},true);\n\t\t}\n\t\tthis.needUpdate = true;\n\t} \n\n\t/**\n\t * 设置控件样式到绘图上下文\n\t * \n\t * 将样式对象应用到 Canvas 上下文,支持:\n\t * - 基础样式:fill, stroke, lineWidth, opacity 等\n\t * - 阴影效果:shadow.blur, shadow.x, shadow.y, shadow.color\n\t * - 渐变填充:支持线性渐变和径向渐变\n\t * - 变换效果:rotation(旋转)、translate(平移)、transform(矩阵变换)\n\t * - 高级效果:lineDash(虚线)、filter(滤镜)、clipPath(裁剪)、mask(遮罩)\n\t * \n\t * @method setStyle\n\t * @param {Object} [style] - 要应用的样式对象,默认使用 this.style\n\t * \n\t * @example\n\t * // 应用样式\n\t * control.setStyle({\n\t * fill: '#ff0000',\n\t * stroke: '#000000',\n\t * lineWidth: 2,\n\t * shadow: {\n\t * blur: 10,\n\t * x: 5,\n\t * y: 5,\n\t * color: 'rgba(0,0,0,0.5)'\n\t * }\n\t * });\n\t * \n\t * // 使用渐变\n\t * control.setStyle({\n\t * fill: 'linear-gradient(0,0,100,0,#ff0000,#0000ff)'\n\t * });\n\t */\n\tsetStyle(style) {\n\t\tif(!style) {\n\t\t\tstyle = this.style;\n\t\t}\n\t\tif(!style) return;\n\n\t\t/**\n\t\t * 内部样式设置函数\n\t\t * @param {*} styleValue - 样式值\n\t\t * @param {string} name - 样式名称\n\t\t * @param {string} [mpkey] - 映射键名\n\t\t * @private\n\t\t */\n\t\tconst __setStyle = (style, name, mpkey) => {\n\t\t\tif(style) {\n\t\t\t\tlet styleValue = style;\n\t\t\t\t// 支持函数形式的样式值\n\t\t\t\tif(typeof styleValue === 'function') {\n\t\t\t\t\ttry {\n\t\t\t\t\t\tstyleValue = styleValue.call(this);\n\t\t\t\t\t}\n\t\t\t\t\tcatch(e) {\n\t\t\t\t\t\tconsole.warn(e);\n\t\t\t\t\t\treturn;\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\tlet t = typeof styleValue;\n\t\t\t\tlet mpname = jmStyleMap[mpkey || name];\n\n\t\t\t\t// 处理渐变\n\t\t\t\tif((styleValue instanceof jmGradient) || (t == 'string' && styleValue.indexOf('-gradient') > -1)) {\n\t\t\t\t\tif(t == 'string' && styleValue.indexOf('-gradient') > -1) {\n\t\t\t\t\t\tstyleValue = new jmGradient(styleValue);\n\t\t\t\t\t}\n\t\t\t\t\t__setStyle(styleValue.toGradient(this), mpname||name);\n\t\t\t\t}\n\t\t\t\t// 处理标准样式映射\n\t\t\t\telse if(mpname) {\n\t\t\t\t\tif(this.webglControl) {\n\t\t\t\t\t\tthis.webglControl.setStyle(mpname, styleValue);\n\t\t\t\t\t}\n\t\t\t\t\telse {\n\t\t\t\t\t\tif(t == 'string' && ['fillStyle', 'strokeStyle', 'shadowColor'].indexOf(mpname) > -1) {\n\t\t\t\t\t\t\tstyleValue = jmUtils.toColor(styleValue);\n\t\t\t\t\t\t}\n\t\t\t\t\t\tthis.context[mpname] = styleValue;\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\t// 处理特殊样式\n\t\t\t\telse {\n\t\t\t\t\tswitch(name) {\n\t\t\t\t\t\t// 阴影样式\n\t\t\t\t\t\tcase 'shadow' : {\n\t\t\t\t\t\t\tif(t == 'string') {\n\t\t\t\t\t\t\t\t__setStyle(new jmShadow(styleValue), name);\n\t\t\t\t\t\t\t\tbreak;\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\tfor(let k in styleValue) {\n\t\t\t\t\t\t\t\t__setStyle(styleValue[k], k, name + '.' + k);\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\tbreak;\n\t\t\t\t\t\t}\n\t\t\t\t\t\t// 平移变换\n\t\t\t\t\t\tcase 'translate' : {\n\t\t\t\t\t\t\tbreak;\n\t\t\t\t\t\t}\n\t\t\t\t\t\t// 旋转变换\n\t\t\t\t\t\tcase 'rotation' : {\n\t\t\t\t\t\t\tif(typeof styleValue.angle === 'undefined' || isNaN(styleValue.angle)) break;\n\t\t\t\t\t\t\tstyleValue = this.getRotation(styleValue);\n\t\t\t\t\t\t\t\n\t\t\t\t\t\t\tthis.__translateAbsolutePosition = this.toAbsolutePoint({\n\t\t\t\t\t\t\t\tx: styleValue.x,\n\t\t\t\t\t\t\t\ty: styleValue.y\n\t\t\t\t\t\t\t});\n\t\t\t\t\t\t\tthis.context.translate && this.context.translate(this.__translateAbsolutePosition.x, this.__translateAbsolutePosition.y);\n\t\t\t\t\t\t\tthis.context.rotate && this.context.rotate(styleValue.angle);\n\t\t\t\t\t\t\tthis.context.translate && this.context.translate(-this.__translateAbsolutePosition.x, -this.__translateAbsolutePosition.y);\n\t\t\t\t\t\t\tbreak;\n\t\t\t\t\t\t}\n\t\t\t\t\t\t// 矩阵变换\n\t\t\t\t\t\tcase 'transform' : {\n\t\t\t\t\t\t\tif(!this.context.transform) break;\n\t\t\t\t\t\t\tif(Array.isArray(styleValue)) {\n\t\t\t\t\t\t\t\tthis.context.transform.apply(this.context, styleValue);\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\telse if(typeof styleValue == 'object') {\n\t\t\t\t\t\t\t\tthis.context.transform(\n\t\t\t\t\t\t\t\t\tstyleValue.scaleX || 1,\n\t\t\t\t\t\t\t\t\tstyleValue.skewX || 0,\n\t\t\t\t\t\t\t\t\tstyleValue.skewY || 0,\n\t\t\t\t\t\t\t\t\tstyleValue.scaleY || 1,\n\t\t\t\t\t\t\t\t\tstyleValue.offsetX || 0,\n\t\t\t\t\t\t\t\t\tstyleValue.offsetY || 0\n\t\t\t\t\t\t\t\t);\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\tbreak;\n\t\t\t\t\t\t}\n\t\t\t\t\t\t// 鼠标样式\n\t\t\t\t\t\tcase 'cursor' : {\n\t\t\t\t\t\t\tthis.cursor = styleValue;\n\t\t\t\t\t\t\tbreak;\n\t\t\t\t\t\t}\n\t\t\t\t\t\t// ===== 新增样式特性 =====\n\n\t\t\t\t\t\t/**\n\t\t\t\t\t\t * 虚线样式\n\t\t\t\t\t\t * 支持数组格式 [5, 3, 2] 或字符串格式 \"5,3,2\"\n\t\t\t\t\t\t * @example\n\t\t\t\t\t\t * style: { lineDash: [5, 3] } // 5px实线,3px空白\n\t\t\t\t\t\t */\n\t\t\t\t\t\tcase 'lineDash' : {\n\t\t\t\t\t\t\tif(!this.context.setLineDash) break;\n\t\t\t\t\t\t\tlet dash;\n\t\t\t\t\t\t\tif(typeof styleValue === 'string') {\n\t\t\t\t\t\t\t\tdash = styleValue.split(',').map(v => parseFloat(v.trim())).filter(v => !isNaN(v));\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\telse if(Array.isArray(styleValue)) {\n\t\t\t\t\t\t\t\tdash = styleValue.map(v => parseFloat(v)).filter(v => !isNaN(v));\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\tif(dash && dash.length) {\n\t\t\t\t\t\t\t\tthis.context.setLineDash(dash);\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\telse {\n\t\t\t\t\t\t\t\tthis.context.setLineDash([]);\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\tbreak;\n\t\t\t\t\t\t}\n\t\t\t\t\t\t// 虚线偏移量\n\t\t\t\t\t\tcase 'lineDashOffset' : {\n\t\t\t\t\t\t\tif(!this.context.setLineDash) break;\n\t\t\t\t\t\t\tthis.context.lineDashOffset = Number(styleValue) || 0;\n\t\t\t\t\t\t\tbreak;\n\t\t\t\t\t\t}\n\t\t\t\t\t\t/**\n\t\t\t\t\t\t * CSS滤镜效果\n\t\t\t\t\t\t * 支持 blur, grayscale, sepia, brightness, contrast, saturate, hue-rotate, invert, opacity\n\t\t\t\t\t\t * @example\n\t\t\t\t\t\t * style: { filter: 'blur(5px) grayscale(50%)' }\n\t\t\t\t\t\t * // 或使用对象\n\t\t\t\t\t\t * style: { filter: { blur: 5, grayscale: 0.5 } }\n\t\t\t\t\t\t */\n\t\t\t\t\t\tcase 'filter' : {\n\t\t\t\t\t\t\tif(this.context.filter === undefined) break;\n\t\t\t\t\t\t\tif(styleValue instanceof jmFilter) {\n\t\t\t\t\t\t\t\tthis.context.filter = styleValue.toCanvasFilter();\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\telse if(typeof styleValue === 'string') {\n\t\t\t\t\t\t\t\tthis.context.filter = styleValue || 'none';\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\telse if(typeof styleValue === 'object') {\n\t\t\t\t\t\t\t\tthis.context.filter = (new jmFilter(styleValue)).toCanvasFilter();\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\tbreak;\n\t\t\t\t\t\t}\n\t\t\t\t\t\t/**\n\t\t\t\t\t\t * 混合模式\n\t\t\t\t\t\t * 常用值:source-over, multiply, screen, overlay, darken, lighten\n\t\t\t\t\t\t * @example\n\t\t\t\t\t\t * style: { globalCompositeOperation: 'multiply' }\n\t\t\t\t\t\t */\n\t\t\t\t\t\tcase 'globalCompositeOperation' : {\n\t\t\t\t\t\t\tif(!this.context.globalCompositeOperation) break;\n\t\t\t\t\t\t\tthis.context.globalCompositeOperation = styleValue;\n\t\t\t\t\t\t\tbreak;\n\t\t\t\t\t\t}\n\t\t\t\t\t\t/**\n\t\t\t\t\t\t * 裁剪路径\n\t\t\t\t\t\t * 通过 canvas clip 实现裁剪效果\n\t\t\t\t\t\t * @example\n\t\t\t\t\t\t * style: { clipPath: clipShape } // clipShape 是一个图形控件\n\t\t\t\t\t\t */\n\t\t\t\t\t\tcase 'clipPath' : {\n\t\t\t\t\t\t\tif(!this.context.clip) break;\n\t\t\t\t\t\t\t// clipPath可以是一个图形控件实例\n\t\t\t\t\t\t\tif(styleValue && styleValue.points && styleValue.points.length > 0) {\n\t\t\t\t\t\t\t\tconst bounds = this.parent && this.parent.absoluteBounds ? this.parent.absoluteBounds : this.absoluteBounds;\n\t\t\t\t\t\t\t\tthis.context.beginPath();\n\t\t\t\t\t\t\t\tthis.context.moveTo(styleValue.points[0].x + (bounds ? bounds.left : 0), styleValue.points[0].y + (bounds ? bounds.top : 0));\n\t\t\t\t\t\t\t\tfor(let i = 1; i < styleValue.points.length; i++) {\n\t\t\t\t\t\t\t\t\tif(styleValue.points[i].m) {\n\t\t\t\t\t\t\t\t\t\tthis.context.moveTo(styleValue.points[i].x + (bounds ? bounds.left : 0), styleValue.points[i].y + (bounds ? bounds.top : 0));\n\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t\telse {\n\t\t\t\t\t\t\t\t\t\tthis.context.lineTo(styleValue.points[i].x + (bounds ? bounds.left : 0), styleValue.points[i].y + (bounds ? bounds.top : 0));\n\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\tif(styleValue.style && styleValue.style.close) {\n\t\t\t\t\t\t\t\t\tthis.context.closePath();\n\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\tthis.context.clip();\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\tbreak;\n\t\t\t\t\t\t}\n\t\t\t\t\t\t/**\n\t\t\t\t\t\t * 遮罩效果\n\t\t\t\t\t\t * 通过 globalCompositeOperation + destination-in 实现\n\t\t\t\t\t\t * @example\n\t\t\t\t\t\t * style: { mask: maskShape } // maskShape 是一个图形控件\n\t\t\t\t\t\t */\n\t\t\t\t\t\tcase 'mask' : {\n\t\t\t\t\t\t\tif(!this.context.globalCompositeOperation) break;\n\t\t\t\t\t\t\t// mask是一个图形控件实例,在绘制前需要先应用mask\n\t\t\t\t\t\t\t// 这里只是标记,实际绘制在paint流程中处理\n\t\t\t\t\t\t\tthis.__mask = styleValue;\n\t\t\t\t\t\t\tbreak;\n\t\t\t\t\t\t}\n\t\t\t\t\t\t// 阴影相关样式(WebGL兼容)\n\t\t\t\t\t\tcase 'shadowColor' : {\n\t\t\t\t\t\t\tif(this.webglControl) {\n\t\t\t\t\t\t\t\tthis.webglControl.setStyle('shadowColor', styleValue);\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\telse {\n\t\t\t\t\t\t\t\tthis.context.shadowColor = jmUtils.toColor(styleValue);\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\tbreak;\n\t\t\t\t\t\t}\n\t\t\t\t\t\tcase 'shadowBlur' : {\n\t\t\t\t\t\t\tif(this.webglControl) {\n\t\t\t\t\t\t\t\tthis.webglControl.setStyle('shadowBlur', styleValue);\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\telse {\n\t\t\t\t\t\t\t\tthis.context.shadowBlur = Number(styleValue) || 0;\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\tbreak;\n\t\t\t\t\t\t}\n\t\t\t\t\t\tcase 'shadowOffsetX' : {\n\t\t\t\t\t\t\tif(this.webglControl) {\n\t\t\t\t\t\t\t\tthis.webglControl.setStyle('shadowOffsetX', styleValue);\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\telse {\n\t\t\t\t\t\t\t\tthis.context.shadowOffsetX = Number(styleValue) || 0;\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\tbreak;\n\t\t\t\t\t\t}\n\t\t\t\t\t\tcase 'shadowOffsetY' : {\n\t\t\t\t\t\t\tif(this.webglControl) {\n\t\t\t\t\t\t\t\tthis.webglControl.setStyle('shadowOffsetY', styleValue);\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\telse {\n\t\t\t\t\t\t\t\tthis.context.shadowOffsetY = Number(styleValue) || 0;\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\tbreak;\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\t// 应用平移变换\n\t\tif(this.translate) {\n\t\t\t__setStyle(this.translate, 'translate');\n\t\t}\n\t\t// 应用矩阵变换\n\t\tif(this.transform) {\n\t\t\t__setStyle(this.transform, 'transform');\n\t\t}\n\t\t// 遍历应用所有样式\n\t\tfor(let k in style) {\n\t\t\tif(k === 'constructor') continue;\n\t\t\tlet t = typeof style[k];\n\t\t\t// 自动转换渐变字符串\n\t\t\tif(t == 'string' && style[k].indexOf('-gradient') > -1) {\n\t\t\t\tstyle[k] = new jmGradient(style[k]);\n\t\t\t}\n\t\t\t// 自动转换阴影字符串\n\t\t\telse if(t == 'string' && k == 'shadow') {\n\t\t\t\tstyle[k] = new jmShadow(style[k]);\n\t\t\t}\n\t\t\t// 自动转换滤镜字符串\n\t\t\telse if(t == 'string' && k == 'filter') {\n\t\t\t\tstyle[k] = new jmFilter(style[k]);\n\t\t\t}\n\t\t\t__setStyle(style[k], k);\n\t\t}\n\t}\n\n\t/**\n\t * 获取当前控件的边界矩形\n\t * \n\t * 通过分析控件的描点或位置加宽高得到边界矩形。\n\t * 对于 jmGraph,边界为画布尺寸。\n\t * 对于有 points 的控件,边界为所有点的最小包围矩形。\n\t * \n\t * @method getBounds\n\t * @param {boolean} [isReset=false] - 是否强制重新计算(忽略缓存)\n\t * @returns {Object} 边界对象\n\t * @returns {number} returns.left - 左边界 X 坐标\n\t * @returns {number} returns.top - 上边界 Y 坐标\n\t * @returns {number} returns.right - 右边界 X 坐标\n\t * @returns {number} returns.bottom - 下边界 Y 坐标\n\t * @returns {number} returns.width - 宽度\n\t * @returns {number} returns.height - 高度\n\t * \n\t * @example\n\t * // 获取边界\n\t * const bounds = control.getBounds();\n\t * console.log(`宽: ${bounds.width}, 高: ${bounds.height}`);\n\t * \n\t * // 强制重新计算\n\t * const newBounds = control.getBounds(true);\n\t */\n\tgetBounds(isReset) {\n\t\t//如果当次计算过,则不重复计算\n\t\tif(this.bounds && !isReset) return this.bounds;\n\n\t\tconst rect = {}; // left top\n\t\t//jmGraph,特殊处理\n\t\tif(this.type == 'jmGraph' && this.canvas) {\n\t\t\tif(typeof this.canvas.width === 'function') {\n\t\t\t\trect.right = this.canvas.width(); \n\t\t\t}\n\t\t\telse if(this.width) {\n\t\t\t\trect.right = this.width;\n\t\t\t}\n\t\t\t\n\t\t\tif(typeof this.canvas.height === 'function') {\n\t\t\t\trect.bottom = this.canvas.height(); \n\t\t\t}\n\t\t\telse if(this.height) {\n\t\t\t\trect.bottom = this.height;\n\t\t\t}\n\t\t}\n\t\t// 根据 points 计算边界\n\t\telse if(this.points && this.points.length > 0) {\t\t\n\t\t\tfor(const p of this.points) {\n\t\t\t\tif(typeof rect.left === 'undefined' || rect.left > p.x) {\n\t\t\t\t\trect.left = p.x;\n\t\t\t\t}\n\t\t\t\tif(typeof rect.top === 'undefined' || rect.top > p.y) {\n\t\t\t\t\trect.top = p.y;\n\t\t\t\t}\n\n\t\t\t\tif(typeof rect.right === 'undefined' || rect.right < p.x) {\n\t\t\t\t\trect.right = p.x;\n\t\t\t\t}\n\t\t\t\tif(typeof rect.bottom === 'undefined' || rect.bottom < p.y) {\n\t\t\t\t\trect.bottom = p.y;\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t\t// 根据位置和尺寸计算边界\n\t\telse if(this.getLocation) {\n\t\t\tlet p = this.getLocation();\n\t\t\tif(p) {\n\t\t\t\trect.left = p.left;\n\t\t\t\trect.top = p.top;\n\t\t\t\trect.right = p.left + p.width;\n\t\t\t\trect.bottom = p.top + p.height;\n\t\t\t}\t\t\n\t\t}\n\t\tif(rect.left === undefined) rect.left = 0; \n\t\tif(rect.top === undefined) rect.top = 0; \n\t\tif(rect.right === undefined) rect.right = 0; \n\t\tif(rect.bottom === undefined) rect.bottom = 0; \n\t\trect.width = rect.right - rect.left;\n\t\trect.height = rect.bottom - rect.top;\n\t\t\n\t\treturn this.bounds=rect;\n\t}\n\n\t/**\n\t * 获取旋转后的边界矩形\n\t * \n\t * 计算控件旋转后的最小包围矩形。\n\t * 当控件有旋转变换时,实际占据的空间会发生变化。\n\t * \n\t * @method getRotationBounds\n\t * @param {Object} [rotation] - 旋转参数,默认使用 style.rotation\n\t * @param {number} rotation.x - 旋转中心 X(相对于控件)\n\t * @param {number} rotation.y - 旋转中心 Y(相对于控件)\n\t * @param {number} rotation.angle - 旋转角度(弧度)\n\t * @param {Object} [bounds] - 基础边界,默认使用 getBounds()\n\t * @returns {Object} 旋转后的边界对象\n\t * \n\t * @example\n\t * // 获取旋转后的边界\n\t * const bounds = control.getRotationBounds();\n\t * console.log(`旋转后宽度: ${bounds.width}`);\n\t */\n\tgetRotationBounds(rotation=null) {\n\t\trotation = rotation || this.getRotation();\n\t\tconst bounds = this.getBounds();\n\t\tif(!rotation || !rotation.angle) return bounds;\n\n\t\tconst rect = {\n\t\t\twidth: 0,\n\t\t\theight: 0,\n\t\t\toldBounds: bounds\n\t\t}; // left top\n\t\tlet points = [];\n\t\tif(this.points && this.points.length > 0) {\t\n\t\t\tpoints = jmUtils.clone(this.points, true); // 深度拷贝\t\t\t\n\t\t}\n\t\telse if(this.getLocation) {\n\t\t\tconst local = this.getLocation();\n\t\t\tif(local) {\n\t\t\t\tpoints.push({\n\t\t\t\t\tx: local.left,\n\t\t\t\t\ty: local.top\n\t\t\t\t},{\n\t\t\t\t\tx: local.left + local.width,\n\t\t\t\t\ty: local.top\n\t\t\t\t},{\n\t\t\t\t\tx: local.left + local.width,\n\t\t\t\t\ty: local.top + local.height\n\t\t\t\t},{\n\t\t\t\t\tx: local.left,\n\t\t\t\t\ty: local.top + local.height\n\t\t\t\t});\n\t\t\t}\t\t\n\t\t}\n\t\tpoints = jmUtils.rotatePoints(points, {\n\t\t\tx: rotation.x + bounds.left,\n\t\t\ty: rotation.y + bounds.top\n\t\t}, rotation.angle);// 对现在点进行旋转\n\n\t\tfor(const p of points) {\n\t\t\tif(typeof rect.left === 'undefined' || rect.left > p.x) {\n\t\t\t\trect.left = p.x;\n\t\t\t}\n\t\t\tif(typeof rect.top === 'undefined' || rect.top > p.y) {\n\t\t\t\trect.top = p.y;\n\t\t\t}\n\n\t\t\tif(typeof rect.right === 'undefined' || rect.right < p.x) {\n\t\t\t\trect.right = p.x;\n\t\t\t}\n\t\t\tif(typeof rect.bottom === 'undefined' || rect.bottom < p.y) {\n\t\t\t\trect.bottom = p.y;\n\t\t\t}\n\t\t}\n\n\t\tif(!rect.left) rect.left = 0; \n\t\tif(!rect.top) rect.top = 0; \n\t\tif(!rect.right) rect.right = 0; \n\t\tif(!rect.bottom) rect.bottom = 0; \n\n\t\trect.width = rect.right - rect.left;\n\t\trect.height = rect.bottom - rect.top;\n\n\t\treturn rect;\n\t}\n\n\t/**\n\t * 获取当前控件的位置参数\n\t * \n\t * 解析百分比和 margin 参数,返回标准化的位置信息。\n\t * 支持百分比定位(如 '50%')和 margin 偏移。\n\t * \n\t * @method getLocation\n\t * @returns {Object} 位置参数对象\n\t * @returns {number} returns.left - 左边距\n\t * @returns {number} returns.top - 上边距\n\t * @returns {number} returns.width - 宽度\n\t * @returns {number} returns.height - 高度\n\t * @returns {Object} [returns.position] - 位置对象 {x, y}\n\t * @returns {Object} [returns.center] - 中心点\n\t * @returns {Object} [returns.start] - 起点(线条类)\n\t * @returns {Object} [returns.end] - 终点(线条类)\n\t * @returns {number} [returns.radius] - 半径(圆形类)\n\t * \n\t * @example\n\t * const loc = control.getLocation();\n\t * console.log(`位置: (${loc.left}, ${loc.top})`);\n\t */\n\tgetLocation() {\n\t\t//如果已经计算过则直接返回\n\t\t//在开画之前会清空此对象\n\t\t//if(reset !== true && this.location) return this.location;\n\n\t\tlet local = this.location = {left: 0,top: 0,width: 0,height: 0};\n\n\t\t// 检查是否有百分比参数需要解析,没有则直接引用避免克隆开销\n\t\tconst needResolve = this.parent && (jmUtils.checkPercent(this.width) || jmUtils.checkPercent(this.height) ||\n\t\t\t(this.position && jmUtils.checkPercent(this.position.x)) || (this.position && jmUtils.checkPercent(this.position.y)));\n\t\tlocal.position = typeof this.position == 'function'? this.position(): (needResolve? jmUtils.clone(this.position) : this.position);\t\n\t\tlocal.center = this.center && typeof this.center === 'function'?this.center(): (needResolve? jmUtils.clone(this.center) : this.center);//中心\n\t\tlocal.start = this.start && typeof this.start === 'function'?this.start(): (needResolve? jmUtils.clone(this.start) : this.start);//起点\n\t\tlocal.end = this.end && typeof this.end === 'function'?this.end(): (needResolve? jmUtils.clone(this.end) : this.end);//起点\n\t\tlocal.radius = this.radius;//半径\n\t\tlocal.width = this.width;\n\t\tlocal.height = this.height;\n\n\t\tconst margin = this.style.margin;\n\t\tconst marginObj = needResolve && margin ? jmUtils.clone(margin, {}) : (margin || {});\n\t\tmarginObj.left = (marginObj.left || 0);\n\t\tmarginObj.top = (marginObj.top || 0);\n\t\tmarginObj.right = (marginObj.right || 0);\n\t\tmarginObj.bottom = (marginObj.bottom || 0);\n\t\t\n\t\t//如果没有指定位置,但指定了margin。则位置取margin偏移量\n\t\tif(local.position) {\n\t\t\tlocal.left = local.position.x;\n\t\t\tlocal.top = local.position.y;\n\t\t}\n\t\telse {\n\t\t\tlocal.left = marginObj.left;\n\t\t\tlocal.top = marginObj.top;\n\t\t}\n\n\t\tif(this.parent) {\n\t\t\tconst parentBounds = this.parent.getBounds();\t\n\n\t\t\t//处理百分比参数\n\t\t\tif(jmUtils.checkPercent(local.left)) {\n\t\t\t\tlocal.left = jmUtils.percentToNumber(local.left) * parentBounds.width;\n\t\t\t}\n\t\t\tif(jmUtils.checkPercent(local.top)) {\n\t\t\t\tlocal.top = jmUtils.percentToNumber(local.top) * parentBounds.height;\n\t\t\t}\n\t\t\t\n\t\t\t//如果没有指定宽度或高度,则按百分之百计算其父宽度或高度\n\t\t\tif(jmUtils.checkPercent(local.width)) {\n\t\t\t\tlocal.width = jmUtils.percentToNumber(local.width) * parentBounds.width;\n\t\t\t}\n\t\t\tif(jmUtils.checkPercent(local.height)) {\n\t\t\t\tlocal.height = jmUtils.percentToNumber(local.height) * parentBounds.height;\n\t\t\t}\n\t\t\t//处理中心点\n\t\t\tif(local.center) {\n\t\t\t\t//处理百分比参数\n\t\t\t\tif(jmUtils.checkPercent(local.center.x)) {\n\t\t\t\t\tlocal.center.x = jmUtils.percentToNumber(local.center.x) * parentBounds.width;\n\t\t\t\t}\n\t\t\t\tif(jmUtils.checkPercent(local.center.y)) {\n\t\t\t\t\tlocal.center.y = jmUtils.percentToNumber(local.center.y) * parentBounds.height;\n\t\t\t\t}\n\t\t\t}\n\t\t\tif(local.radius) {\n\t\t\t\t//处理百分比参数\n\t\t\t\tif(jmUtils.checkPercent(local.radius)) {\n\t\t\t\t\tlocal.radius = jmUtils.percentToNumber(local.radius) * Math.min(parentBounds.width, parentBounds.height);\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t\treturn local;\n\t}\n\n\t/**\n\t * 获取当前控件的旋转信息\n\t * \n\t * 解析旋转参数,支持百分比形式的旋转中心。\n\t * 如果控件本身没有旋转,会继承父级的旋转。\n\t * \n\t * @method getRotation\n\t * @param {Object} [rotation] - 旋转参数,默认使用 style.rotation\n\t * @param {Object} [bounds] - 基础边界\n\t * @returns {Object} 旋转信息\n\t * @returns {number} returns.x - 旋转中心 X(相对于控件)\n\t * @returns {number} returns.y - 旋转中心 Y(相对于控件)\n\t * @returns {number} returns.angle - 旋转角度(弧度)\n\t * @returns {Object} returns.bounds - 控件边界\n\t * \n\t * @example\n\t * // 获取旋转信息\n\t * const rot = control.getRotation();\n\t * if(rot.angle) {\n\t * console.log(`旋转角度: ${rot.angle} 弧度`);\n\t * }\n\t */\n\tgetRotation(rotation, bounds = null) {\n\t\trotation = rotation || jmUtils.clone(this.style.rotation);\n\n\t\tif(!rotation) {\n\t\t\t//如果本身没有,则可以继承父级的\n\t\t\trotation = this.parent && this.parent.getRotation?this.parent.getRotation():null;\n\t\t\t//如果父级有旋转,则把坐标转换为当前控件区域\n\t\t\tif(rotation) {\n\t\t\t\tbounds = bounds || this.getBounds();\n\t\t\t\trotation.x -= bounds.left;\n\t\t\t\trotation.y -= bounds.top;\n\t\t\t}\n\t\t}\n\t\telse {\n\t\t\tbounds = bounds || this.getBounds();\n\t\t\tif(typeof rotation.x === 'undefined') rotation.x = '50%';\n\t\t\tif(typeof rotation.y === 'undefined') rotation.y = '50%';\n\t\t\tif(jmUtils.checkPercent(rotation.x)) {\n\t\t\t\trotation.x = jmUtils.percentToNumber(rotation.x) * bounds.width;\n\t\t\t}\n\t\t\tif(jmUtils.checkPercent(rotation.y)) {\n\t\t\t\trotation.y = jmUtils.percentToNumber(rotation.y) * bounds.height;\n\t\t\t}\n\t\t}\n\t\treturn {\n\t\t\t...rotation,\n\t\t\tbounds\n\t\t};\n\n\t}\n\n\t/**\n\t * 计算位移偏移量\n\t * \n\t * 解析 translate 样式,支持百分比形式。\n\t * \n\t * @method getTranslate\n\t * @param {Object} [translate] - 平移参数,默认使用 style.translate\n\t * @param {Object} [bounds] - 参考边界\n\t * @returns {Object} 平移信息 {x, y}\n\t * \n\t * @example\n\t * const trans = control.getTranslate();\n\t * console.log(`平移: (${trans.x}, ${trans.y})`);\n\t */\n\tgetTranslate(translate, bounds = null) {\n\t\ttranslate = translate || this.style.translate;\n\t\tif(!translate) return {x: 0, y: 0};\n\t\tconst result = {\n\t\t\tx: translate.x || 0,\n\t\t\ty: translate.y || 0\n\t\t}\n\t\t\n\t\tif(jmUtils.checkPercent(result.x)) {\n\t\t\tif(!bounds && this.parent) bounds = this.parent.getBounds();\n\t\t\tresult.x = jmUtils.percentToNumber(result.x) * bounds.width;\n\t\t}\n\t\tif(jmUtils.checkPercent(result.y)) {\n\t\t\tif(!bounds && this.parent) bounds = this.parent.getBounds();\n\t\t\tresult.y = jmUtils.percentToNumber(result.y) * bounds.height;\n\t\t}\n\t\treturn result;\n\t}\n\n\t/**\n\t * 移除当前控件\n\t * \n\t * 从父控件的子控件列表中移除当前控件。\n\t * 移除后会触发 needUpdate 重绘。\n\t * \n\t * @method remove\n\t * \n\t * @example\n\t * // 移除控件\n\t * control.remove();\n\t */\n\tremove() {\t\n\t\tif(this.parent) {\n\t\t\tthis.parent.children.remove(this);\n\t\t}\n\t}\n\n\t/**\n\t * 对控件进行平移\n\t * \n\t * 遍历控件所有描点或位置,设置其偏移量。\n\t * 支持移动 position、center、start、end、points 等属性。\n\t * \n\t * @method offset\n\t * @param {number} x - X 轴偏移量\n\t * @param {number} y - Y 轴偏移量\n\t * @param {boolean} [trans=true] - 是否传递给监听者\n\t * @param {Object} [evt] - 如果是事件触发,传递 move 事件参数\n\t * \n\t * @example\n\t * // 向右移动 10px,向下移动 5px\n\t * control.offset(10, 5);\n\t */\n\toffset(x, y, trans, evt) {\n\t\ttrans = trans === false?false:true;\t\n\t\tlet local = this.getLocation(true);\t\t\n\t\tlet offseted = false;\n\t\t\n\t\tif(local.position) {\n\t\t\tlocal.left += x;\n\t\t\tlocal.top += y;\n\t\t\t// 由于local是clone出来的对象,为了保留位移,则要修改原属性\n\t\t\tthis.position.x = local.left;\n\t\t\tthis.position.y = local.top;\n\t\t\toffseted = true;\n\t\t}\n\n\t\tif(local.center) {\t\t\n\t\t\tthis.center.x = local.center.x + x;\n\t\t\tthis.center.y = local.center.y + y;\n\t\t\toffseted = true;\n\t\t}\n\n\t\tif(local.start && typeof local.start == 'object') {\t\n\t\t\tthis.start.x = local.start.x + x;\n\t\t\tthis.start.y = local.start.y + y;\n\t\t\toffseted = true;\n\t\t}\n\n\t\tif(local.end && typeof local.end == 'object') {\t\t\n\t\t\tthis.end.x = local.end.x + x;\n\t\t\tthis.end.y = local.end.y + y;\n\t\t\toffseted = true;\n\t\t}\n\n\n\t\tif(offseted == false && this.cpoints) {\n\t\t\tlet p = typeof this.cpoints == 'function'?this.cpoints:this.cpoints;\n\t\t\tif(p) {\t\t\t\n\t\t\t\tlet len = p.length;\n\t\t\t\tfor(let i=0; i < len;i++) {\n\t\t\t\t\tp[i].x += x;\n\t\t\t\t\tp[i].y += y;\n\t\t\t\t}\t\t\n\t\t\t\toffseted = true;\n\t\t\t}\t\t\t\n\t\t}\n\t\t\n\t\tif(offseted == false && this.points) {\n\t\t\tlet len = this.points.length;\n\t\t\tfor(let i=0; i < len;i++) {\n\t\t\t\tthis.points[i].x += x;\n\t\t\t\tthis.points[i].y += y;\n\t\t\t}\n\t\t\toffseted = true;\n\t\t}\n\t\t\n\t\t//触发控件移动事件\t\n\t\tthis.emit('move',{\n\t\t\toffsetX: x,\n\t\t\toffsetY: y,\n\t\t\ttrans: trans,\n\t\t\tevt: evt\n\t\t});\n\n\t\tthis.needUpdate = true;\n\t}\n\n\t/**\n\t * 获取控件相对于画布的绝对边界\n\t * \n\t * 与 getBounds 不同的是:getBounds 获取的是相对于父容器的边界,\n\t * 而 getAbsoluteBounds 获取的是相对于画布的边界。\n\t * \n\t * @method getAbsoluteBounds\n\t * @returns {Object} 绝对边界对象\n\t * \n\t * @example\n\t * const absBounds = control.getAbsoluteBounds();\n\t * console.log(`画布上的位置: (${absBounds.left}, ${absBounds.top})`);\n\t */\n\tgetAbsoluteBounds() {\n\t\t//当前控件的边界,\n\t\tlet rec = this.getBounds();\n\t\tif(this.parent && this.parent.absoluteBounds) {\n\t\t\t//父容器的绝对边界\n\t\t\tlet prec = this.parent.absoluteBounds || this.parent.getAbsoluteBounds();\n\t\t\t\n\t\t\treturn {\n\t\t\t\tleft : prec.left + rec.left,\n\t\t\t\ttop : prec.top + rec.top,\n\t\t\t\tright : prec.left + rec.right,\n\t\t\t\tbottom : prec.top + rec.bottom,\n\t\t\t\twidth : rec.width,\n\t\t\t\theight : rec.height\n\t\t\t};\n\t\t}\n\t\treturn rec;\n\t}\n\n\t/**\n\t * 把当前控件内部坐标转为画布绝对坐标\n\t * \n\t * @method toAbsolutePoint\n\t * @param {Object} point - 内部坐标 {x, y}\n\t * @returns {Object} 绝对坐标\n\t * \n\t * @example\n\t * const absPoint = control.toAbsolutePoint({x: 10, y: 10});\n\t */\n\ttoAbsolutePoint(point) {\n\t\tif(point.x || point.y) {\n\t\t\tconst bounds = this.absoluteBounds?this.absoluteBounds:this.getAbsoluteBounds();\n\t\t\t\n\t\t\tpoint.x = (point.x||0) + bounds.left;\n\t\t\tpoint.y = (point.y||0) + bounds.top;\t\n\t\t}\n\t\treturn point;\n\t}\n\n\t/**\n\t * 把画布绝对坐标转为当前控件坐标系内\n\t * \n\t * @method toLocalPosition\n\t * @param {Object} point - 绝对坐标\n\t * @returns {Object|false} 相对坐标,如果无法转换返回 false\n\t * \n\t * @example\n\t * const localPoint = control.toLocalPosition({x: 100, y: 100});\n\t */\n\ttoLocalPosition(point) {\n\t\t\n\t\tconst bounds = this.absoluteBounds?this.absoluteBounds:this.getAbsoluteBounds();\n\t\tif(!bounds) return false;\t\n\t\treturn { \n\t\t\tx: point.x - bounds.left,\n\t\t\ty: point.y - bounds.top\n\t\t};\n\t}\n\n\t/**\n\t * 画控件前初始化\n\t * \n\t * 执行 beginPath 开始控件的绘制路径。\n\t * 重置位置信息缓存,确保使用最新的位置数据。\n\t * \n\t * @method beginDraw\n\t * @protected\n\t * \n\t * @example\n\t * // 子类重写时需要调用父类方法\n\t * class MyShape extends jmControl {\n\t * beginDraw() {\n\t * super.beginDraw();\n\t * // 自定义初始化逻辑\n\t * }\n\t * }\n\t */\n\tbeginDraw() {\t\n\t\tthis.getLocation(true);//重置位置信息\n\t\tthis.context.beginPath && this.context.beginPath();\t\t\n\t\tif(this.webglControl && this.webglControl.beginDraw) this.webglControl.beginDraw();\n\t}\n\n\t/**\n\t * 结束控件绘制\n\t * \n\t * 根据样式执行 fill 或 stroke 操作。\n\t * 如果设置了 close 样式,会先闭合路径。\n\t * \n\t * @method endDraw\n\t * @protected\n\t * \n\t * @example\n\t * // 绘制流程\n\t * control.beginDraw();\n\t * control.draw();\n\t * control.endDraw();\n\t */\n\tendDraw() {\n\t\t//如果当前为封闭路径\n\t\tif(this.style.close) {\n\t\t\tif(this.webglControl) this.webglControl.closePath();\n\t\t\tthis.context.closePath && this.context.closePath();\n\t\t}\n\n\t\t// 根据渲染模式选择不同的绘制路径\n\t\tif(this.webglControl) {\n\t\t\t// WebGL 模式:使用 WebGL 绘制\n\t\t\tconst fill = this.style['fill'] || this.style['fillStyle'];\n\t\t\tif(fill) {\n\t\t\t\tconst bounds = this.getBounds();\n\t\t\t\tthis.webglControl.fill(bounds);\n\t\t\t}\n\t\t\tif(this.style['stroke'] || (!fill && !this.is('jmGraph'))) {\n\t\t\t\tthis.webglControl.stroke();\n\t\t\t}\n\t\t\tif(this.webglControl.endDraw) this.webglControl.endDraw();\n\t\t}\n\t\telse {\n\t\t\t// 2D 模式:使用 Canvas 2D API 绘制\n\t\t\tconst fill = this.style['fill'] || this.style['fillStyle'];\n\t\t\tif(fill) {\n\t\t\t\tthis.context.fill && this.context.fill();\n\t\t\t}\n\t\t\tif(this.style['stroke'] || (!fill && !this.is('jmGraph'))) {\n\t\t\t\tthis.context.stroke && this.context.stroke();\n\t\t\t}\n\t\t}\n\n\t\tthis.needUpdate = false;\n\t}\n\n\t/**\n\t * 绘制控件路径\n\t * \n\t * 在画布上绘制控件的路径点。\n\t * 子类应该重写此方法实现自定义绘制逻辑。\n\t * \n\t * @method draw\n\t * @protected\n\t * \n\t * @example\n\t * // 子类重写绘制方法\n\t * class MyShape extends jmControl {\n\t * draw() {\n\t * const ctx = this.context;\n\t * ctx.moveTo(0, 0);\n\t * ctx.lineTo(100, 100);\n\t * // ... 更多绘制逻辑\n\t * }\n\t * }\n\t */\n\tdraw() {\t\n\t\tif(this.points && this.points.length > 0) {\n\t\t\t//获取当前控件的绝对位置\n\t\t\tconst bounds = this.parent && this.parent.absoluteBounds?this.parent.absoluteBounds:this.absoluteBounds;\n\t\t\tif(this.webglControl) {\n\t\t\t\tthis.webglControl.setParentBounds(bounds);\n\t\t\t\tthis.webglControl.draw(this.points);\n\t\t\t}\n\t\t\telse if(this.context && this.context.moveTo) {\n\t\t\t\tthis.context.moveTo(this.points[0].x + bounds.left,this.points[0].y + bounds.top);\n\t\t\t\tlet len = this.points.length;\t\t\t\n\t\t\t\tfor(let i=1; i < len;i++) {\n\t\t\t\t\tlet p = this.points[i];\n\t\t\t\t\t//移至当前坐标\n\t\t\t\t\tif(p.m) {\n\t\t\t\t\t\tthis.context.moveTo(p.x + bounds.left,p.y + bounds.top);\n\t\t\t\t\t}\n\t\t\t\t\telse {\n\t\t\t\t\t\tthis.context.lineTo(p.x+ bounds.left,p.y + bounds.top);\n\t\t\t\t\t}\t\t\t\n\t\t\t\t}\t\n\t\t\t}\t\n\t\t}\t\n\t}\n\n\t/**\n\t * 绘制当前控件及其子控件\n\t * \n\t * 协调控件的绘制流程:\n\t * 1. 检查可见性\n\t * 2. 初始化点数据\n\t * 3. 计算边界\n\t * 4. 应用样式\n\t * 5. 绘制自身\n\t * 6. 绘制子控件\n\t * 7. 触发事件\n\t * \n\t * @method paint\n\t * @param {boolean} [v] - 是否可见,false 时跳过绘制\n\t * \n\t * @example\n\t * // 手动触发重绘\n\t * control.paint();\n\t */\n\tpaint(v) {\n\t\tif(v !== false && this.visible !== false) {\t\t\n\t\t\tif(this.initPoints) this.initPoints();\n\t\t\t//计算当前边界\n\t\t\tthis.bounds = null;\n\t\t\tthis.absoluteBounds = this.getAbsoluteBounds();\n\t\t\tlet needDraw = true;//是否需要绘制\n\t\t\tif(!this.is('jmGraph') && this.graph) {\n\t\t\t\tif(this.absoluteBounds.left >= this.graph.width) needDraw = false;\n\t\t\t\telse if(this.absoluteBounds.top >= this.graph.height) needDraw = false;\n\t\t\t\telse if(this.absoluteBounds.right <= 0) needDraw = false;\n\t\t\t\telse if(this.absoluteBounds.bottom <= 0) needDraw = false;\n\t\t\t}\n\t\t\t\n\t\t\tthis.context.save && this.context.save();\n\n\t\t\tthis.emit('beginDraw', this);\n\t\t\t\n\t\t\tthis.setStyle();//设定样式\n\n\t\t\t// 应用mask遮罩效果:在mask区域内绘制当前控件\n\t\t\t// 使用 destination-in 合成模式,只保留mask区域内的内容\n\t\t\tconst maskStyle = this.style.mask || this.__mask;\n\t\t\tif(maskStyle && maskStyle.points && this.context.globalCompositeOperation) {\n\t\t\t\t// 先绘制当前控件\n\t\t\t\tif(needDraw && this.beginDraw) this.beginDraw();\n\t\t\t\tif(needDraw && this.draw) this.draw();\t\n\t\t\t\tif(needDraw && this.endDraw) this.endDraw();\n\n\t\t\t\t// 再应用mask裁剪\n\t\t\t\tthis.context.globalCompositeOperation = 'destination-in';\n\t\t\t\tif(maskStyle.initPoints) maskStyle.initPoints();\n\t\t\t\tconst mBounds = maskStyle.parent && maskStyle.parent.absoluteBounds ? maskStyle.parent.absoluteBounds : this.absoluteBounds;\n\t\t\t\tthis.context.beginPath();\n\t\t\t\tif(maskStyle.points && maskStyle.points.length > 0) {\n\t\t\t\t\tthis.context.moveTo(maskStyle.points[0].x + (mBounds ? mBounds.left : 0), maskStyle.points[0].y + (mBounds ? mBounds.top : 0));\n\t\t\t\t\tfor(let i = 1; i < maskStyle.points.length; i++) {\n\t\t\t\t\t\tif(maskStyle.points[i].m) {\n\t\t\t\t\t\t\tthis.context.moveTo(maskStyle.points[i].x + (mBounds ? mBounds.left : 0), maskStyle.points[i].y + (mBounds ? mBounds.top : 0));\n\t\t\t\t\t\t}\n\t\t\t\t\t\telse {\n\t\t\t\t\t\t\tthis.context.lineTo(maskStyle.points[i].x + (mBounds ? mBounds.left : 0), maskStyle.points[i].y + (mBounds ? mBounds.top : 0));\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t\tif(maskStyle.style && maskStyle.style.close) {\n\t\t\t\t\t\tthis.context.closePath();\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\tthis.context.fillStyle = '#ffffff';\n\t\t\t\tthis.context.fill();\n\t\t\t\t// 恢复合成模式\n\t\t\t\tthis.context.globalCompositeOperation = 'source-over';\n\t\t\t}\n\t\t\telse {\n\t\t\t\tif(needDraw && this.beginDraw) this.beginDraw();\n\t\t\t\tif(needDraw && this.draw) this.draw();\t\n\t\t\t\tif(needDraw && this.endDraw) this.endDraw();\n\t\t\t}\n\n\t\t\tif(this.children) {\n\t\t\t\tthis.children.each(function(i,item) {\n\t\t\t\t\tif(item && item.paint) item.paint();\n\t\t\t\t});\n\t\t\t}\n\n\t\t\tthis.emit('endDraw',this);\t\n\t\t\tthis.context.restore && this.context.restore();\n\t\t\t\n\t\t\tthis.needUpdate = false;\n\t\t}\n\t}\n\n\t/**\n\t * 获取指定事件的监听器集合\n\t * \n\t * 返回绑定到指定事件名称的所有事件处理函数。\n\t * \n\t * @method getEvent\n\t * @param {string} name - 事件名称(如 'click', 'mousedown')\n\t * @returns {jmList|null} 事件处理函数集合,不存在则返回 null\n\t * \n\t * @example\n\t * const handlers = control.getEvent('click');\n\t * if(handlers) {\n\t * console.log(`有 ${handlers.count()} 个点击事件处理器`);\n\t * }\n\t */\n\tgetEvent(name) {\t\t\n\t\treturn this.__events?this.__events[name]:null;\n\t}\n\n\t/**\n\t * 绑定控件事件\n\t * \n\t * 为控件添加事件监听器。支持同时绑定多个事件(用空格分隔)。\n\t * 同一个处理函数不会被重复添加。\n\t * \n\t * @method bind\n\t * @param {string} name - 事件名称,多个事件用空格分隔\n\t * @param {Function} handle - 事件处理函数\n\t * @returns {void}\n\t * \n\t * @example\n\t * // 绑定单个事件\n\t * control.bind('click', (evt) => {\n\t * console.log('被点击了', evt);\n\t * });\n\t * \n\t * // 绑定多个事件\n\t * control.bind('mousedown mouseup', (evt) => {\n\t * console.log('鼠标事件', evt);\n\t * });\n\t * \n\t * // 使用 on 别名\n\t * control.on('mousemove', (evt) => {\n\t * console.log('鼠标移动', evt.position);\n\t * });\n\t */\n\tbind(name, handle) {\t\n\t\tif(name && name.indexOf(' ') > -1) {\n\t\t\tname = name.split(' ');\n\t\t\tfor(let n of name) {\n\t\t\t\tn && this.bind(n, handle);\n\t\t\t}\n\t\t\treturn;\n\t\t}\t\n\t\t/**\n\t\t * 添加事件的集合\n\t\t *\n\t\t * @method _setEvent\n\t\t * @private\n\t\t */\n\t\tfunction _setEvent(name, events) {\n\t\t\tif(!this.__events) this.__events = {};\n\t\t\treturn this.__events[name] = events;\n\t\t}\n\t\tlet eventCollection = this.getEvent(name) || _setEvent.call(this, name, new jmList());\n\t\tif(!eventCollection.contain(handle)) {\n\t\t\teventCollection.add(handle);\n\t\t}\n\t}\n\n\t/**\n\t * 移除控件事件\n\t * \n\t * 移除已绑定的事件处理函数。如果不指定处理函数,则移除该事件的所有处理函数。\n\t * \n\t * @method unbind\n\t * @param {string} name - 事件名称,多个事件用空格分隔\n\t * @param {Function} [handle] - 要移除的事件处理函数,不指定则移除所有\n\t * \n\t * @example\n\t * // 移除特定处理函数\n\t * control.unbind('click', myHandler);\n\t * \n\t * // 移除所有点击事件\n\t * control.unbind('click');\n\t * \n\t * // 移除多个事件\n\t * control.unbind('mousedown mouseup');\n\t */\n\tunbind(name, handle) {\t\n\t\tif(name && name.indexOf(' ') > -1) {\n\t\t\tname = name.split(' ');\n\t\t\tfor(let n of name) {\n\t\t\t\tn && this.unbind(n, handle);\n\t\t\t}\n\t\t\treturn;\n\t\t}\t\n\t\tlet eventCollection = this.getEvent(name) ;\t\t\n\t\tif(eventCollection) {\n\t\t\tif(handle) eventCollection.remove(handle);\n\t\t\telse eventCollection.clear();\n\t\t}\n\t}\n\n\n\t/**\n\t * 触发事件\n\t * \n\t * 执行指定事件的所有监听器。\n\t * 支持传递多个参数给事件处理函数。\n\t * \n\t * @method emit\n\t * @param {string} name - 事件名称\n\t * @param {...*} args - 传递给事件处理函数的参数\n\t * @returns {jmControl} 返回 this 以支持链式调用\n\t * \n\t * @example\n\t * // 触发自定义事件\n\t * control.emit('customEvent', { data: 'value' });\n\t * \n\t * // 触发带多个参数的事件\n\t * control.emit('dataChange', oldValue, newValue);\n\t */\n\temit(...args) {\t\t\t\n\t\t// 避免每帧 args.slice(1) 分配临时数组\n\t\t// runEventHandle 内部会把非数组参数包装成数组\n\t\tif(args.length > 2) {\n\t\t\tthis.runEventHandle(args[0], args.slice(1));\n\t\t} else if(args.length === 2) {\n\t\t\tthis.runEventHandle(args[0], [args[1]]);\n\t\t} else {\n\t\t\tthis.runEventHandle(args[0], []);\n\t\t}\n\t\treturn this;\n\t}\n\n\t/**\n\t * 执行事件处理函数\n\t * \n\t * 内部方法,用于执行指定事件的所有监听器。\n\t * 如果任一处理函数返回 false,会设置 args.cancel = true。\n\t * \n\t * @method runEventHandle\n\t * @param {string} name - 事件名称\n\t * @param {Array|Object} args - 事件参数\n\t * @returns {boolean} 是否被取消\n\t * @protected\n\t */\n\trunEventHandle(name, args) {\n\t\tlet events = this.getEvent(name);\t\t\n\t\tif(events) {\n\t\t\t\n\t\tif(name === 'mousemove' && this.type == 'jmResize') {\n\t\t\tconsole.log('resize mousemove', args, events);\n\t\t}\n\t\t\tvar self = this;\n\t\t\tif(!Array.isArray(args)) args = [args];\t\n\t\t\tevents.each(function(i, handle) {\n\t\t\t\t//只要有一个事件被阻止,则不再处理同级事件,并设置冒泡被阻断\n\t\t\t\tif(false === handle.apply(self, args)) {\n\t\t\t\t\targs.cancel = true;\n\t\t\t\t}\n\t\t\t});\t\t\n\t\t}\t\n\t\treturn args.cancel;\n\t}\n\n\t/**\n\t * 检查坐标是否落在当前控件区域中\n\t * \n\t * 用于点击测试和碰撞检测。\n\t * 支持旋转后的碰撞检测,以及自定义命中区域。\n\t * \n\t * @method checkPoint\n\t * @param {Object} p - 要检测的点坐标\n\t * @param {number} p.x - X 坐标\n\t * @param {number} p.y - Y 坐标\n\t * @param {number} [pad] - 容差范围,默认使用 lineWidth 或 1\n\t * @returns {boolean} 点是否在控件区域内\n\t * \n\t * @example\n\t * // 检查点击位置\n\t * graph.bind('click', (evt) => {\n\t * if(control.checkPoint(evt.position)) {\n\t * console.log('点击了控件');\n\t * }\n\t * });\n\t */\n\tcheckPoint(p, pad) {\n\t\t//jmGraph 需要判断dom位置\n\t\tif(this.type == 'jmGraph') {\n\t\t\t//获取dom位置\n\t\t\tconst position = this.getPosition();\n\t\t\tif(p.pageX > position.right || p.pageX < position.left) {\n\t\t\t\treturn false;\n\t\t\t}\n\t\t\tif(p.pageY > position.bottom || p.pageY < position.top) {\n\t\t\t\treturn false;\n\t\t\t}\t\n\t\t\treturn true;\n\t\t}\n\t\t\n\t\tconst bounds = this.getBounds();\t\n\t\t// 如果指定了合中区域,则以命中区域为准\n\t\tif(this.hitArea) {\n\t\t\tconst hitArea = {\n\t\t\t\tleft: this.hitArea.x + bounds.left,\n\t\t\t\ttop: this.hitArea.y + bounds.top,\n\t\t\t\tright: this.hitArea.width + bounds.left,\n\t\t\t\tbottom: this.hitArea.height + bounds.top,\n\t\t\t};\n\t\t\tif(p.x > hitArea.right || p.x < hitArea.left) {\n\t\t\t\treturn false;\n\t\t\t}\n\t\t\tif(p.y > hitArea.bottom || p.y < hitArea.top) {\n\t\t\t\treturn false;\n\t\t\t}\n\t\t\treturn true;\n\t\t}\n\t\t\n\t\tlet ps = this.points;\n\t\t//如果不是路径组成,则采用边界做为顶点\n\t\tif(!ps || !ps.length) {\n\t\t\tps = [];\n\t\t\tps.push({x: bounds.left, y: bounds.top}); //左上角\n\t\t\tps.push({x: bounds.right, y: bounds.top});//右上角\n\t\t\tps.push({x: bounds.right, y: bounds.bottom});//右下角\n\t\t\tps.push({x: bounds.left, y: bounds.bottom}); //左下\n\t\t\tps.push({x: bounds.left, y: bounds.top}); //左上角 //闭合\n\t\t}\n\t\t//如果有指定padding 表示接受区域加宽,命中更易\n\t\tpad = Number(pad || this.style['touchPadding'] || this.style['lineWidth'] || 1);\n\t\tif(ps && ps.length) {\n\t\t\tconst rotation = this.getRotation(null, bounds);//获取当前旋转参数\n\t\t\t//如果有旋转参数,则需要转换坐标再处理\n\t\t\tif(rotation && rotation.angle) {\n\t\t\t\tps = jmUtils.clone(ps, true);//拷贝一份数据\n\t\t\t\t//rotateX ,rotateY 是相对当前控件的位置\n\t\t\t\tps = jmUtils.rotatePoints(ps, {\n\t\t\t\t\tx: rotation.x + bounds.left,\n\t\t\t\t\ty: rotation.y + bounds.top\n\t\t\t\t}, rotation.angle || 0);\n\t\t\t}\n\t\t\t//如果当前路径不是实心的\n\t\t\t//就只用判断点是否在边上即可\t\n\t\t\tif(ps.length > 2 && (!this.style['fill'] || this.style['stroke'])) {\n\t\t\t\tlet i = 0;\n\t\t\t\tconst count = ps.length;\n\t\t\t\tfor(let j = i+1; j <= count; j = (++i + 1)) {\n\t\t\t\t\t//如果j超出最后一个\n\t\t\t\t\t//则当为封闭图形时跟第一点连线处理.否则直接返回false\n\t\t\t\t\tif(j == count) {\n\t\t\t\t\t\tif(this.style.close) {\n\t\t\t\t\t\t\tconst r = jmUtils.pointInPolygon(p,[ps[i],ps[0]], pad);\n\t\t\t\t\t\t\tif(r) return true;\n\t\t\t\t\t\t}\n\t\t\t\t\t} \n\t\t\t\t\telse {\n\t\t\t\t\t\t//判断是否在点i,j连成的线上\n\t\t\t\t\t\tconst s = jmUtils.pointInPolygon(p,[ps[i],ps[j]], pad);\n\t\t\t\t\t\tif(s) return true;\n\t\t\t\t\t}\t\t\t\n\t\t\t\t}\n\t\t\t\t//不是封闭的图形,则直接返回\n\t\t\t\tif(!this.style['fill']) return false;\n\t\t\t}\n\n\t\t\tconst r = jmUtils.pointInPolygon(p,ps, pad);\t\t\n\t\t\treturn r;\n\t\t}\n\n\t\tif(p.x > bounds.right || p.x < bounds.left) {\n\t\t\treturn false;\n\t\t}\n\t\tif(p.y > bounds.bottom || p.y < bounds.top) {\n\t\t\treturn false;\n\t\t}\n\t\t\n\t\treturn true;\n\t}\n\n\n\t/**\n\t * 触发控件事件并执行事件冒泡\n\t * \n\t * 组合事件参数,按控件层级关系执行事件冒泡。\n\t * 事件从最上层的子控件开始触发,向上冒泡到父控件。\n\t * \n\t * @method raiseEvent\n\t * @param {string} name - 事件名称\n\t * @param {Object} args - 原生事件对象\n\t * @returns {boolean} 如果事件被阻止冒泡则返回 false,否则返回 true\n\t * \n\t * @example\n\t * // 通常由框架内部调用,用户一般不需要直接调用\n\t * // 框架会自动处理鼠标/触摸事件\n\t */\n\traiseEvent(name, args) {\n\t\tif(this.visible === false) return ;//如果不显示则不响应事件\t\n\t\t\n\t\tif(!args.position) {\t\t\n\t\t\tconst graph = this.graph;\n\t\t\targs.isWXMiniApp = graph.isWXMiniApp;\n\n\t\t\tconst srcElement = args.srcElement || args.target;\t\t\t\n\t\t\t\n\t\t\tconst position = jmUtils.getEventPosition(args);//初始化事件位置\n\t\t\n\t\t\targs = {\n\t\t\t\tposition: position,\n\t\t\t\tbutton: args.button == 0 || position.isTouch? 1: args.button,\n\t\t\t\tkeyCode: args.keyCode || args.charCode || args.which,\n\t\t\t\tctrlKey: args.ctrlKey,\n\t\t\t\tcancel : false,\n\t\t\t\tevent: args, // 原生事件\n\t\t\t\tsrcElement : srcElement,\n\t\t\t\tisWXMiniApp: graph.isWXMiniApp,\n\t\t\t};\t\t\n\t\t}\n\t\targs.path = args.path||[]; //事件冒泡路径\n\n\t\t//先执行子元素事件,如果事件没有被阻断,则向上冒泡\n\t\tlet stoped = false;\n\t\tif(this.children) {\n\t\t\tthis.children.each(function(j, el) {\n\t\t\t\t//未被阻止才执行\t\t\t\n\t\t\t\tif(args.cancel !== true) {\n\t\t\t\t\t//如果被阻止冒泡,\n\t\t\t\t\tstoped = el.raiseEvent(name, args) === false? true: stoped;\n\t\t\t\t\t// 不再响应其它元素\n\t\t\t\t\tif(stoped) return false;\n\t\t\t\t}\n\t\t\t}, true);//按逆序处理\n\t\t}\n\t\t// 如果已被阻止,不再响应上级事件\n\t\tif(stoped) return false;\n\t\t\n\t\t//获取当前对象的父元素绝对位置\n\t\t//生成当前坐标对应的父级元素的相对位置\n\t\tlet abounds = this.parent && this.parent.absoluteBounds?this.parent.absoluteBounds : this.absoluteBounds;\n\t\tif(!abounds) return false;\t\n\t\t//args = jmUtils.clone(args);//参数副本\n\t\targs.position.x = args.position.offsetX - abounds.left;\n\t\targs.position.y = args.position.offsetY - abounds.top;\n\n\t\t// 是否在当前控件内操作\n\t\tconst inpos = this.interactive !== false && this.checkPoint(args.position);\n\n\t\tif(name === 'mousemove' && this.type == 'jmGraph' && !inpos) {\n\t\t\tconsole.log('mousemove out', args.position, abounds);\n\t\t}\n\t\t\n\t\t//事件发生在边界内或健盘事件发生在画布中才触发\n\t\tif(inpos) {\n\t\t\t//如果没有指定触发对象,则认为当前为第一触发对象\n\t\t\tif(!args.target) {\n\t\t\t\targs.target = this;\n\t\t\t}\n\t\t\t\n\t\t\tthis.runEventAndPopEvent(name, args);\n\n\t\t\tif(!this.focused && (name === 'mousemove' || name === 'touchmove')) {\n\t\t\t\tthis.focused = true;//表明当前焦点在此控件中\n\t\t\t\tthis.raiseEvent(name === 'mousemove'? 'mouseover': 'touchover', args);\n\t\t\t}\t\n\t\t}\n\t\telse {\n\t\t\t//如果焦点不在,且原焦点在,则触发mouseleave事件\n\t\t\tif(this.interactive !== false && !inpos &&\n\t\t\t\tthis.focused && \n\t\t\t\t(name === 'mousemove' || name === 'touchmove')) {\n\n\t\t\t\tthis.focused = false;//表明当前焦点离开\n\t\t\t\tthis.runEventHandle(name === 'mousemove'? 'mouseleave' : 'touchleave', args);//执行事件\t\n\t\t\t}\t\n\t\t}\n\t\t\t\n\t\treturn args.cancel === false;//如果被阻止则返回false,否则返回true\n\t}\n\n\t/**\n\t * 执行事件并进行冒泡\n\t * \n\t * 内部方法,用于执行事件处理并添加到事件路径。\n\t * \n\t * @method runEventAndPopEvent\n\t * @param {string} name - 事件名称\n\t * @param {Object} args - 事件参数\n\t * @protected\n\t */\n\trunEventAndPopEvent(name, args) {\t\n\n\t\tif(args.cancel !== true) {\n\t\t\t// 添加到触发路径\n\t\t\targs.path.push(this);\n\n\t\t\t//如果返回true则阻断冒泡\n\t\t\tthis.runEventHandle(name, args);//执行事件\n\n\t\t\t// // 向父节点冒泡事件\t\t\n\t\t\t// if(args.cancel !== true && this.parent && this.parent.runEventAndPopEvent) {\n\t\t\t// \t// 相对位置需要改为父节点的\n\t\t\t// \tif(args.position) {\n\t\t\t// \t\tlet bounds = this.parent.getBounds();\n\t\t\t// \t\targs.position.x += bounds.left;\n\t\t\t// \t\targs.position.y += bounds.top;\n\t\t\t// \t}\n\t\t\t// \tthis.parent.runEventAndPopEvent(name, args);\n\t\t\t// }\t\t\n\t\t}\n\t}\n\n\t/**\n\t * 清空控件指定事件\n\t * \n\t * 移除指定事件名称下的所有事件处理函数。\n\t * \n\t * @method clearEvents\n\t * @param {string} name - 需要清除的事件名称\n\t * \n\t * @example\n\t * // 清除所有点击事件\n\t * control.clearEvents('click');\n\t */\n\tclearEvents(name) {\n\t\tvar eventCollection = this.getEvent(name);\t\t\n\t\tif(eventCollection) {\n\t\t\teventCollection.clear();\n\t\t}\n\t}\n\n\t/**\n\t * 查找指定类型的父级控件\n\t * \n\t * 沿着父级链向上查找,直到找到指定类型的控件或到达最顶级。\n\t * \n\t * @method findParent\n\t * @param {string|Function} type - 类型名称(字符串)或类构造函数\n\t * @returns {jmControl|null} 找到的父级控件实例,未找到返回 null\n\t * \n\t * @example\n\t * // 查找 jmGraph 实例\n\t * const graph = control.findParent('jmGraph');\n\t * \n\t * // 查找特定类的实例\n\t * const parent = control.findParent(MyCustomControl);\n\t */\n\tfindParent(type) {\n\t\t//如果为类型名称,则返回名称相同的类型对象\n\t\tif(typeof type === 'string') {\n\t\t\tif(this.type == type)\n\t\t\t\treturn this;\n\t\t}\n\t\telse if(this.is(type)) {\n\t\t\treturn this;\n\t\t}\n\t\tif(this.parent) {\n\t\t\treturn this.parent.findParent(type);\n\t\t}\n\t\treturn null;\n\t}\n\n\t/**\n\t * 设置控件是否可拖动\n\t * \n\t * 启用或禁用控件的拖动功能。\n\t * 拖动时会触发 movestart、move、moveend 事件。\n\t * \n\t * @method canMove\n\t * @param {boolean} m - true 启用拖动,false 禁用拖动\n\t * @param {jmGraph} [graph] - 画布实例,如果控件已添加到画布可省略\n\t * @returns {jmControl} 返回 this 以支持链式调用\n\t * \n\t * @example\n\t * // 启用拖动\n\t * control.canMove(true);\n\t * \n\t * // 禁用拖动\n\t * control.canMove(false);\n\t * \n\t * // 监听拖动事件\n\t * control.on('movestart', (evt) => console.log('开始拖动'));\n\t * control.on('moveend', (evt) => console.log('结束拖动'));\n\t */\n\tcanMove(m, graph) {\n\t\tif(!this.__mvMonitor) {\n\t\t\t/**\n\t\t\t * 控制控件移动对象\n\t\t\t * \n\t\t\t * @property __mvMonitor\n\t\t\t * @private\n\t\t\t */\n\t\t\tthis.__mvMonitor = {};\n\t\t\tthis.__mvMonitor.mouseDown = false;\n\t\t\tthis.__mvMonitor.curposition={x:0,y:0};\n\t\t\tvar self = this;\n\t\t\t/**\n\t\t\t * 控件移动鼠标事件\n\t\t\t *\n\t\t\t * @method mv\n\t\t\t * @private\n\t\t\t */\n\t\t\tthis.__mvMonitor.mv = function(evt) {\n\t\t\t\tlet _this = self;\n\t\t\t\t//如果鼠标经过当前可移动控件,则显示可移动指针\n\t\t\t\t//if(evt.path && evt.path.indexOf(_this)>-1) {\n\t\t\t\t//\t_this.cursor('move');\t\n\t\t\t\t//}\n\t\t\t\tif(_this.__mvMonitor.mouseDown) {\n\t\t\t\t\t_this.parent.bounds = null;\n\t\t\t\t\t//let parentbounds = _this.parent.getAbsoluteBounds();\t\t\n\t\t\t\t\tlet offsetx = evt.position.offsetX - _this.__mvMonitor.curposition.x;\n\t\t\t\t\tlet offsety = evt.position.offsetY - _this.__mvMonitor.curposition.y;\t\t\t\t\n\t\t\t\t\t//console.log(offsetx + ',' + offsety);\n\t\t\t\t\t//如果锁定边界\n\t\t\t\t\tif(_this.option.lockSide) {\n\t\t\t\t\t\tlet thisbounds = _this.bounds || _this.getAbsoluteBounds();\t\t\t\t\t\n\t\t\t\t\t\t//检查边界出界\n\t\t\t\t\t\tlet outside = jmUtils.checkOutSide(_this.option.lockSide, thisbounds, { x: offsetx, y: offsety });\n\t\t\t\t\t\tif(outside.left < 0 && offsetx < 0) {\n\t\t\t\t\t\t\t//offsetx -= outside.left;\n\t\t\t\t\t\t\toffsetx = 0;\n\t\t\t\t\t\t}\n\t\t\t\t\t\telse if(outside.right > 0 && offsetx > 0) {\n\t\t\t\t\t\t\t//offsetx -= outside.right;\n\t\t\t\t\t\t\toffsetx = 0;\n\t\t\t\t\t\t}\n\t\t\t\t\t\tif(outside.top < 0 && offsety < 0) {\n\t\t\t\t\t\t\t//offsety -= outside.top;\n\t\t\t\t\t\t\toffsety = 0;\n\t\t\t\t\t\t}\n\t\t\t\t\t\telse if(outside.bottom > 0 && offsety > 0) {\n\t\t\t\t\t\t\t//offsety -= outside.bottom;\n\t\t\t\t\t\t\toffsety = 0;\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t\t\n\t\t\t\t\tif(offsetx || offsety) {\n\t\t\t\t\t\t_this.offset(offsetx, offsety, true, evt);\n\t\t\t\t\t\tif(offsetx) _this.__mvMonitor.curposition.x = evt.position.offsetX;\n\t\t\t\t\t\tif(offsety) _this.__mvMonitor.curposition.y = evt.position.offsetY;\t\n\t\t\t\t\t\t//console.log('mouse move',offsetx + '.' + offsety);\n\t\t\t\t\t}\n\t\t\t\t\treturn false;\n\t\t\t\t}\n\t\t\t}\n\t\t\t/**\n\t\t\t * 控件移动鼠标松开事件\n\t\t\t *\n\t\t\t * @method mu\n\t\t\t * @private\n\t\t\t */\n\t\t\tthis.__mvMonitor.mu = function(evt) {\n\t\t\t\tlet _this = self;\n\t\t\t\tif(_this.__mvMonitor.mouseDown) {\n\t\t\t\t\t_this.__mvMonitor.mouseDown = false;\n\t\t\t\t\t//_this.cursor('default');\n\t\t\t\t\t_this.emit('moveend',{position:_this.__mvMonitor.curposition});\t\n\t\t\t\t\t//return false;\n\t\t\t\t}\t\t\t\n\t\t\t}\n\t\t\t/**\n\t\t\t * 控件移动鼠标离开事件\n\t\t\t *\n\t\t\t * @method ml\n\t\t\t * @private\n\t\t\t */\n\t\t\tthis.__mvMonitor.ml = function() {\n\t\t\t\tlet _this = self;\n\t\t\t\tif(_this.__mvMonitor.mouseDown) {\n\t\t\t\t\t_this.__mvMonitor.mouseDown = false;\n\t\t\t\t\t//_this.cursor('default');\t\n\t\t\t\t\t_this.emit('moveend',{position:_this.__mvMonitor.curposition});\n\t\t\t\t\treturn false;\n\t\t\t\t}\t\n\t\t\t}\n\t\t\t/**\n\t\t\t * 控件移动鼠标按下事件\n\t\t\t *\n\t\t\t * @method md\n\t\t\t * @private\n\t\t\t */\n\t\t\tthis.__mvMonitor.md = function(evt) {\n\t\t\t\t\n\t\t\t\tif(this.__mvMonitor.mouseDown) return;\n\t\t\t\tif(evt.button == 0 || evt.button == 1) {\n\t\t\t\t\tthis.__mvMonitor.mouseDown = true;\n\t\t\t\t\t//this.cursor('move');\n\t\t\t\t\t//var parentbounds = this.parent.absoluteBounds || this.parent.getAbsoluteBounds();\t\n\t\t\t\t\tthis.__mvMonitor.curposition.x = evt.position.offsetX;//evt.position.x + parentbounds.left;\n\t\t\t\t\tthis.__mvMonitor.curposition.y = evt.position.offsetY;//evt.position.y + parentbounds.top;\n\t\t\t\t\t//触发控件移动事件\n\t\t\t\t\tthis.emit('movestart',{position:this.__mvMonitor.curposition});\n\t\t\t\t\t\n\t\t\t\t\tevt.cancel = true;\n\t\t\t\t\treturn false;\n\t\t\t\t}\t\t\t\n\t\t\t}\n\t\t}\n\t\tgraph = graph || this.graph ;//获取最顶级元素画布\n\t\t\n\t\tif(m !== false) {\t\t\t\n\t\t\tgraph.bind('mousemove',this.__mvMonitor.mv);\n\t\t\tgraph.bind('mouseup',this.__mvMonitor.mu);\n\t\t\tgraph.bind('mouseleave',this.__mvMonitor.ml);\n\t\t\tthis.bind('mousedown',this.__mvMonitor.md);\n\t\t\tgraph.bind('touchmove',this.__mvMonitor.mv);\n\t\t\tgraph.bind('touchend',this.__mvMonitor.mu);\n\t\t\tthis.bind('touchstart',this.__mvMonitor.md);\n\t\t}\n\t\telse {\t\t\t\n\t\t\tgraph.unbind('mousemove',this.__mvMonitor.mv);\n\t\t\tgraph.unbind('mouseup',this.__mvMonitor.mu);\n\t\t\tgraph.unbind('mouseleave',this.__mvMonitor.ml);\n\t\t\tthis.unbind('mousedown',this.__mvMonitor.md);\n\t\t\tgraph.unbind('touchmove',this.__mvMonitor.mv);\n\t\t\tgraph.unbind('touchend',this.__mvMonitor.mu);\n\t\t\tthis.unbind('touchstart',this.__mvMonitor.md);\t\n\t\t}\n\n\t\tthis.interactive = true;// 如果可以移动,则响应事件\n\t\treturn this;\n\t}\n};\n\nexport { jmControl };","/**\n * @fileoverview jmPath 路径基类\n * \n * jmPath 是大部分图形的基类,提供了基于点序列的路径绘制能力。\n * 所有需要通过点序列定义形状的图形(如多边形、线条、贝塞尔曲线等)\n * 都可以继承此类。\n * \n * 主要功能:\n * - 点序列管理(points 属性)\n * - SVG 导出支持(toSVG 方法)\n * - 路径闭合控制\n * \n * @module jmPath\n * @author jmGraph Team\n * @license MIT\n */\n\nimport {jmControl} from \"./jmControl.js\";\n\n/**\n * 基础路径类\n * \n * 大部分图形的基类,通过指定一系列点来画出图形。\n * 支持开放路径和闭合路径,支持 SVG 导出。\n * \n * @class jmPath\n * @extends jmControl\n * \n * @param {Object} params 路径参数\n * @param {Array<Object>} [params.points] 点序列,每个点格式:{x:0, y:0, m:false}\n * @param {string} [t='jmPath'] 类型标识\n * \n * @example\n * // 创建自定义路径\n * const path = new jmPath({\n * points: [\n * {x: 0, y: 0},\n * {x: 100, y: 0},\n * {x: 100, y: 100},\n * {x: 0, y: 100}\n * ],\n * style: {\n * fill: '#ff0000',\n * stroke: '#000000',\n * close: true // 闭合路径\n * }\n * });\n */\nexport default class jmPath extends jmControl {\t\n\n\tconstructor(params, t='jmPath') {\n\t\tsuper(params, t);\t\t\n\t\tthis.points = params && params.points ? params.points : [];\t\n\t}\n\t\n\t/**\n\t * 描点集合\n\t * point格式:{x:0,y:0,m:true}\n\t * @property points\n\t * @type {array}\n\t */\n\tget points() {\n\t\tlet s = this.property('points');\n\t\treturn s;\n\t}\n\tset points(v) {\n\t\tthis.needUpdate = true;\n\t\treturn this.property('points', v);\n\t}\n\n\t/**\n\t * 转换为SVG路径\n\t * \n\t * @method toSVG\n\t * @return {string} SVG路径字符串\n\t */\n\ttoSVG() {\n\t\tif(!this.points || this.points.length === 0) return '';\n\t\t\n\t\tlet pathData = '';\n\t\tconst points = this.points;\n\t\t\n\t\t// 移动到起点\n\t\tpathData += `M ${points[0].x} ${points[0].y}`;\n\t\t\n\t\t// 绘制路径\n\t\tfor(let i = 1; i < points.length; i++) {\n\t\t\tconst p = points[i];\n\t\t\tif(p.m) {\n\t\t\t\t// 移动到新位置\n\t\t\t\tpathData += ` M ${p.x} ${p.y}`;\n\t\t\t} else {\n\t\t\t\t// 直线到\n\t\t\t\tpathData += ` L ${p.x} ${p.y}`;\n\t\t\t}\n\t\t}\n\t\t\n\t\t// 如果是封闭路径\n\t\tif(this.style && this.style.close) {\n\t\t\tpathData += ' Z';\n\t\t}\n\t\t\n\t\t// 构建SVG元素\n\t\tlet svg = '<path d=\"' + pathData + '\"';\n\t\t\n\t\t// 添加样式\n\t\tif(this.style) {\n\t\t\tif(this.style.fill) {\n\t\t\t\tsvg += ' fill=\"' + this.style.fill + '\"';\n\t\t\t}\n\t\t\tif(this.style.stroke) {\n\t\t\t\tsvg += ' stroke=\"' + this.style.stroke + '\"';\n\t\t\t}\n\t\t\tif(this.style.lineWidth) {\n\t\t\t\tsvg += ' stroke-width=\"' + this.style.lineWidth + '\"';\n\t\t\t}\n\t\t\tif(this.style.opacity) {\n\t\t\t\tsvg += ' opacity=\"' + this.style.opacity + '\"';\n\t\t\t}\n\t\t}\n\t\t\n\t\tsvg += '/>';\n\t\treturn svg;\n\t}\t\n\t\n}\n\nexport { jmPath };\n","/**\n * @fileoverview jmGraph 主画布类\n * \n * jmGraph 是 jmGraph 库的核心类,代表一个完整的画布实例。\n * 它继承自 jmControl,提供了完整的图形渲染、事件处理、缩放平移等功能。\n * \n * 主要功能:\n * - Canvas/WebGL 双渲染模式支持\n * - 图形创建与管理(createShape, createLine, createPath 等)\n * - 渐变和阴影效果(createLinearGradient, createRadialGradient, createShadow)\n * - 缩放和平移(setZoom, pan, resetTransform)\n * - 导出功能(toDataURL, exportToPNG, exportToJPEG, exportToSVG)\n * - 自动刷新动画循环(autoRefresh)\n * - 微信小程序支持\n * \n * @module jmGraph\n * @author jmGraph Team\n * @license MIT\n */\n\nimport {jmUtils} from \"./jmUtils.js\";\nimport {jmList} from \"./jmList.js\";\nimport {jmProperty} from './jmProperty.js';\nimport {jmShadow} from \"./jmShadow.js\";\nimport {jmGradient} from \"./jmGradient.js\";\nimport {jmFilter} from \"./jmFilter.js\";\nimport {jmEvents} from \"./jmEvents.js\";\nimport {jmControl} from \"./jmControl.js\";\nimport {jmPath} from \"./jmPath.js\";\n\n/**\n * jmGraph 画图类\n * \n * 对 Canvas 画图 API 进行二次封装,使其更易调用,省去很多重复的工作。\n * 支持多种图形的创建、渲染、交互和导出。\n * \n * @class jmGraph\n * @extends jmControl\n * \n * @param {HTMLElement|string} canvas Canvas 元素或元素 ID\n * @param {Object} [option] 配置选项\n * @param {number} [option.width] 画布宽度\n * @param {number} [option.height] 画布高度\n * @param {string} [option.mode='2d'] 渲染模式:'2d' 或 'webgl'\n * @param {boolean} [option.autoRefresh=false] 是否自动刷新\n * @param {Object} [option.shapes] 自定义图形类型映射\n * @param {function} [callback] 初始化完成后的回调函数\n * \n * @example\n * // 创建画布实例\n * const graph = new jmGraph('canvasId', {\n * width: 800,\n * height: 600,\n * mode: '2d'\n * });\n * \n * // 创建一个矩形\n * const rect = graph.createShape('rect', {\n * x: 100, y: 100,\n * width: 200, height: 150,\n * style: { fill: '#ff0000' }\n * });\n * graph.children.add(rect);\n * graph.refresh();\n */\nexport default class jmGraph extends jmControl {\n\n\tconstructor(canvas, option, callback) {\n\t\tif(typeof option == 'function') {\n\t\t\tcallback = option;\n\t\t\toption = {};\n\t\t}\n\t\n\t\toption = option || {};\n\t\t//option.mode = '2d'; // webgl | 2d 暂不支持webgl\n\t\toption.interactive = true;\n\t\toption.isRegular = true;// 规则的\n\n\t\tsuper(option, 'jmGraph');\n\n\t\tthis.option = option || {};\n\t\t\n\t\tthis.devicePixelRatio = 1; // 根据屏幕的缩放倍数\n\n\t\t/**\n\t\t * 工具类\n\t\t * @property utils/util\n\t\t * @type {jmUtils}\n\t\t */\n\t\tthis.util = this.utils = jmUtils;\t\n\t\t// 模式 webgl | 2d\n\t\tthis.mode = option.mode || '2d';\n\n\t\t// 缩放和平移相关\n\t\tthis.scaleFactor = 1;\n\t\tthis.translation = {x: 0, y: 0};\n\n\t\t//如果是小程序\n\t\tif(typeof wx != 'undefined' && wx.canIUse && wx.canIUse('canvas')) {\t\t\t\n\t\t\tif(typeof canvas === 'string') canvas = wx.createSelectorQuery().select('#' + canvas);\n\t\t\tthis.isWXMiniApp = true;// 微信小程序平台\n\t\t\tthis.container = canvas;\n\t\t}\n\t\telse {\n\t\t\tif(typeof canvas === 'string' && typeof document != 'undefined') {\n\t\t\t\tcanvas = document.getElementById(canvas);\n\t\t\t}\n\t\t\telse if(canvas.length) {\n\t\t\t\tcanvas = canvas[0];\n\t\t\t}\n\n\t\t\tif(!canvas.getContext && typeof document != 'undefined') {\n\t\t\t\tthis.container = canvas;\n\t\t\t\tlet cn = document.createElement('canvas');\n\t\t\t\tcanvas.appendChild(cn);\n\t\t\t\tcn.width = canvas.offsetWidth||canvas.clientWidth;\n\t\t\t\tcn.height = canvas.offsetHeight||canvas.clientHeight;\n\t\t\t\tcanvas = cn;\n\t\t\t}\t\n\t\t\telse {\n\t\t\t\tthis.container = canvas.parentElement;\n\t\t\t}\n\t\t}\t\n\t\tthis.canvas = canvas;\t\n\t\t// Create context with preserveDrawingBuffer for webgl to prevent flickering\n\t\tif(this.mode === 'webgl') {\n\t\t\tthis.context = canvas.getContext(this.mode, { preserveDrawingBuffer: true });\n\t\t}\n\t\telse {\n\t\t\tthis.context = canvas.getContext(this.mode);\n\t\t}\n\t\t\n\t\t// webgl模式\n\t\tif(this.mode === 'webgl') {\n\n\t\t\tthis.context.enable(this.context.BLEND);// 开启混合功能:(注意,它不可和gl.DEPTH_TEST一起使用)\n\t\t\tthis.context.blendFunc(this.context.SRC_ALPHA, this.context.ONE_MINUS_SRC_ALPHA); // 指定混合函数:\n\t\t\t// webglcontextlost webglcontextrestored\n\t\t\tjmUtils.bindEvent(canvas, 'webglcontextlost', (e)=> {\n\t\t\t\tconsole.log('canvas webglcontextlost', e);\n\t\t\t\tthis.emit('webglcontextlost', e);\n\t\t\t});\n\t\t\tjmUtils.bindEvent(canvas, 'webglcontextrestored', (e)=> {\n\t\t\t\tconsole.log('canvas webglcontextrestored', e);\n\t\t\t\tthis.emit('webglcontextrestored', e);\n\t\t\t});\n\t\t} \n\t\tthis.__init(callback);\n\t}\n\n\t/**\n\t * 初始化画布\n\t * @method init\n\t */\n\t__init(callback) {\n\t\t/**\n\t\t * 当前所有图形类型\n\t\t * @property shapes\n\t\t * @type {object}\n\t\t */\n\t\tthis.shapes = Object.assign({\n\t\t\t\"path\": jmPath,\n\t\t}, this.option.shapes);\n\t\t\n\t\t/**\n\t\t * 画控件前初始化\n\t\t * 为了解决一像素线条问题\n\t\t */\n\t\tthis.on('beginDraw', function() { \n\t\t\tthis.context.translate && this.context.translate(0.5, 0.5);\n\t\t\t// 应用缩放和平移变换\n\t\t\tif(this.context.translate && this.context.scale) {\n\t\t\t\tthis.context.translate(this.translation.x, this.translation.y);\n\t\t\t\tthis.context.scale(this.scaleFactor, this.scaleFactor);\n\t\t\t}\n\t\t});\n\t\t/**\n\t\t * 结束控件绘制 为了解决一像素线条问题\n\t\t */\n\t\tthis.on('endDraw', function() { \n\t\t\tthis.context.translate && this.context.translate(-0.5, -0.5);\n\t\t\t// 恢复缩放和平移变换\n\t\t\tif(this.context.translate && this.context.scale) {\n\t\t\t\tthis.context.scale(1/this.scaleFactor, 1/this.scaleFactor);\n\t\t\t\tthis.context.translate(-this.translation.x, -this.translation.y);\n\t\t\t}\n\t\t});\n\n\t\t// devicePixelRatio初始化\n\t\tlet dpr = typeof window != 'undefined' && window.devicePixelRatio > 1? window.devicePixelRatio : 1;\n\t\tif(this.isWXMiniApp) {\n\t\t\tdpr = wx.getWindowInfo().pixelRatio || 1;\n\t\t}\t\t\n\t\tthis.devicePixelRatio = dpr;\n\t\t// 为了解决锯齿问题,先放大canvas再缩放\n\t\tthis.dprScaleSize = this.devicePixelRatio > 1? this.devicePixelRatio : 2;\n\t\t\n\t\tif(this.option.width > 0) this.width = this.option.width;\n\t\tif(this.option.height > 0) this.height = this.option.height;\t\n\t\tthis.resize();\t\t\n\n\t\t//绑定事件\n\t\tthis.eventHandler = new jmEvents(this, this.canvas.canvas || this.canvas);\t\n\n\t\t//如果指定了自动刷新\n\t\tif(this.option.autoRefresh) {\n\t\t\tthis.autoRefresh();\n\t\t}\n\n\t\tif(callback) callback(this);\t\t\n\t}\n\n\t// 重置canvas大小,并判断高清屏,画图先放大二倍\n\tresize(w, h) {\n\t\tif(!this.canvas) return;\n\n\t\tthis.__normalSize = this.__normalSize || { width: 0, height: 0};\n\t\tw = w || this.__normalSize.width || this.width, h = h || this.__normalSize.height || this.height;\n\n\t\tif(w) this.__normalSize.width = w;\n\t\tif(h) this.__normalSize.height = h;\n\t\n\t\tthis.css('width', w + \"px\");\n\t\tthis.css('height', h + \"px\");\n\t\tif(this.mode === '2d') {\n\t\t\tthis.canvas.height = h * this.dprScaleSize;\n\t\t\tthis.canvas.width = w * this.dprScaleSize;\n\t\t\tif(this.dprScaleSize !== 1) this.context.scale && this.context.scale(this.dprScaleSize, this.dprScaleSize);\t\n\t\t}\n\t\telse {\n\t\t\tthis.canvas.width = w;\n\t\t\tthis.canvas.height = h;\n\t\t}\n\n\t\tthis.context.viewport && this.context.viewport(0, 0, w, h);\n\t\tthis.needUpdate = true;\n\t}\n\n\t/**\n\t * 宽度\n\t * @property width\n\t * @type {number}\n\t */\n\tget width() {\n\t\tif(this.__normalSize && this.__normalSize.width) return this.__normalSize.width;\n\t\tif(this.canvas) return this.canvas.width;\n\t\treturn 0;\n\t}\n\tset width(v) {\n\t\tthis.needUpdate = true;\n\t\tif(this.canvas) {\n\t\t\tthis.resize(v);\n\t\t}\t\n\t\treturn v;\n\t}\n\n\t/**\n\t * 高度\n\t * @property height\n\t * @type {number}\n\t */\n\tget height() {\n\t\tif(this.__normalSize && this.__normalSize.height) return this.__normalSize.height;\n\t\tif(this.canvas) return this.canvas.height;\n\t\treturn 0;\n\t}\n\tset height(v) {\n\t\tthis.needUpdate = true;\n\t\tif(this.canvas) {\n\t\t\tthis.resize(0, v);\n\t\t}\n\t\treturn v;\n\t}\n\n\t/**\n\t * 创建jmGraph的静态对象\n\t *\n\t * @method create\n\t * @return {jmGraph} jmGraph实例对象\n\t */\n\tstatic create(...args) {\n\t\treturn new jmGraph(...args);\n\t}\n\n\t/**\n\t * 获取当前画布在浏览器中的绝对定位\n\t *\n\t * @method getPosition\n\t * @return {postion} 返回定位坐标\n\t */\n\tgetPosition() {\n\t\tconst p = this.isWXMiniApp? {\n\t\t\tleft: 0,\n\t\t\ttop: 0\n\t\t} :jmUtils.getElementPosition(this.canvas.canvas || this.canvas);\n\t\t\n\t\tp.width = this.width;\n\t\tp.height = this.height;\n\t\tp.right = p.left + p.width;\n\t\tp.bottom = p.top + p.height;\n\t\treturn p;\n\t}\n\n\t/**\n\t * 注册图形类型,图形类型必需有统一的构造函数。参数为画布句柄和参数对象。\n\t *\n\t * @method registerShape \n\t * @param {string} name 控件图形名称\n\t * @param {class} shape 图形控件类型\n\t */\n\tregisterShape(name, shape) {\n\t\tthis.shapes[name] = shape;\n\t}\n\n\t/**\n\t * 从已注册的图形类创建图形\n\t * 简单直观创建对象\n\t *\n\t * @method createShape \n\t * @param {string} shape 注册控件的名称 也可以直接是控件类型\n\t * @param {object} args 实例化控件的参数\n\t * @return {object} 已实例化控件的对象\n\t */\n\tcreateShape(shape, args) {\n\t\tif(typeof shape === 'string') {\n\t\t\tshape = this.shapes[shape];\n\t\t}\n\t\tif(shape) {\n\t\t\tif(!args) args = {};\n\t\t\targs.graph = this;\n\t\t\tconst obj = new shape(args);\n\t\t\treturn obj;\n\t\t}\n\t}\n\n\t/**\n\t * 生成阴影对象\n\t *\n\t * @method createShadow\n\t * @param {number} x x偏移量\n\t * @param {number} y y偏移量\n\t * @param {number} blur 模糊值\n\t * @param {string} color 颜色\n\t * @return {jmShadow} 阴影对象\n\t */\n\tcreateShadow(x, y, blur, color) {\n\t\tconst sh = new jmShadow(x, y, blur, color);\n\t\treturn sh;\n\t}\n\n\t/**\n\t * 生成线性渐变对象\n\t *\n\t * @method createLinearGradient\n\t * @param {number} x1 线性渐变起始点X坐标\n\t * @param {number} y1 线性渐变起始点Y坐标\n\t * @param {number} x2 线性渐变结束点X坐标\n\t * @param {number} y2 线性渐变结束点Y坐标\n\t * @return {jmGradient} 线性渐变对象\n\t */\n\tcreateLinearGradient(x1, y1, x2, y2, stops=[]) {\n\t\tconst gradient = new jmGradient({\n\t\t\ttype:'linear',\n\t\t\tx1: x1,\n\t\t\ty1: y1,\n\t\t\tx2: x2,\n\t\t\ty2: y2,\n\t\t\tstops\n\t\t});\n\t\treturn gradient;\n\t}\n\n\t/**\n\t * 生成放射渐变对象\n\t *\n\t * @method createRadialGradient\n\t * @param {number} x1 放射渐变小圆中心X坐标\n\t * @param {number} y1 放射渐变小圆中心Y坐标\n\t * @param {number} r1 放射渐变小圆半径\n\t * @param {number} x2 放射渐变大圆中心X坐标\n\t * @param {number} y2 放射渐变大圆中心Y坐标\n\t * @param {number} r2 放射渐变大圆半径\n\t * @return {jmGradient} 放射渐变对象\n\t */\n\tcreateRadialGradient(x1, y1, r1, x2, y2, r2, stops=[]) {\t\n\t\tconst gradient = new jmGradient({\n\t\t\ttype:'radial',\n\t\t\tx1: x1,\n\t\t\ty1: y1,\n\t\t\tr1: r1,\n\t\t\tx2: x2,\n\t\t\ty2: y2,\n\t\t\tr2: r2,\n\t\t\tstops\n\t\t});\n\t\treturn gradient;\n\t}\n\n\t/**\n\t * 重新刷新整个画板\n\t * 以加入动画事件触发延时10毫秒刷新,保存最尽的调用只刷新一次,加强性能的效果。\n\t *\n\t * @method refresh\n\t */\n\trefresh() {\t\n\t\t//加入动画,触发redraw,会导致多次refresh只redraw一次\n\t\t/*this.animate(function() {\n\t\t\treturn false;\n\t\t},100,'jmgraph_refresh');*/\n\t\tthis.redraw();\n\t}\n\n\t/**\n\t * 重新刷新整个画板\n\t * 此方法直接重画,与refresh效果类似\n\t *\n\t * @method redraw\n\t * @param {number} [w] 清除画布的宽度\n\t * @param {number} [h] 清除画布的高度\n\t */\n\tredraw(w, h) {\t\n\t\tthis.clear(w||this.width, h||this.height);\n\t\tthis.paint();\n\t}\n\n\t/**\n\t * 清除画布\n\t * \n\t * @method clear\n\t * @param {number} [w] 清除画布的宽度\n\t * @param {number} [h] 清除画布的高度\n\t */\n\tclear(w, h) {\n\t\tif(!w || !h) {\n\t\t\tw = this.width;\n\t\t\th = this.height;\n\t\t\t/*if(this.scaleSize) {\n\t\t\t\tw = w / this.scaleSize.x;\n\t\t\t\th = h / this.scaleSize.y;\n\t\t\t}*/\n\t\t}\n\t\t\n\t\tif(this.context.clearRect) {\n\t\t\tif(this.style && this.style.fill) {\n\t\t\t\tthis.points = [\n\t\t\t\t\t{x:0, y:0},\n\t\t\t\t\t{x:w, y:0},\n\t\t\t\t\t{x:w, y:h},\n\t\t\t\t\t{x:0, y:h}\n\t\t\t\t];\n\t\t\t\tthis.style.close = true;// 封闭填充\n\t\t\t}\n\n\t\t\tthis.context.clearRect(0, 0, w, h);\n\t\t}\n\t\telse if(this.mode === 'webgl' && this.context.clear) {\n\t\t\t// 缓存 clearColor 对象,避免每帧创建\n\t\t\tif(this.style && this.style.fill) {\n\t\t\t\tconst color = this.utils.hexToRGBA(this.style.fill);\n\t\t\t\tthis.__lastClearColor = color;\n\t\t\t\tthis.context.clearColor(color.r, color.g, color.b, color.a);\n\t\t\t}\n\t\t\telse if(!this.__lastClearColor) {\n\t\t\t\tthis.__lastClearColor = { r: 0, g: 0, b: 0, a: 0 };\n\t\t\t\tthis.context.clearColor(0, 0, 0, 0);\n\t\t\t}\n\t\t\telse {\n\t\t\t\tthis.context.clearColor(this.__lastClearColor.r, this.__lastClearColor.g, this.__lastClearColor.b, this.__lastClearColor.a);\n\t\t\t}\n \tthis.context.clear(this.context.COLOR_BUFFER_BIT); // 清空颜色缓冲区,也就是清空画布\n\t\t}\n\t}\n\n\t/**\n\t* 设置画布样式,此处只是设置其css样式\n\t*\n\t* @method css\n\t* @param {string} name 样式名\n\t* @param {string} value 样式值\n\t*/\n\tcss(name, value) {\n\t\tif(this.canvas && this.canvas.style) {\n\t\t\tif(typeof value != 'undefined') this.canvas.style[name] = value;\n\t\t\treturn this.canvas.style[name];\n\t\t}\n\t}\n\n\t/**\n\t * 生成路径对象\n\t *\n\t * @method createPath\n\t * @param {array} points 路径中的描点集合\n\t * @param {style} style 当前路径的样式\n\t * @return {jmPath} 路径对象jmPath\n\t */\n\tcreatePath(points, style, option={}) {\n\t\tconst path = this.createShape('path',{\n\t\t\tpoints: points,\n\t\t\tstyle: style,\n\t\t\t...option\n\t\t});\n\t\treturn path;\n\t}\n\n\t/**\n\t * 生成直线\n\t * \n\t * @method createLine\n\t * @param {point} start 直线的起点\n\t * @param {point} end 直线的终点\n\t * @param {style} 直线的样式\n\t * @return {jmLine} 直线对象\n\t */\n\tcreateLine(start, end, style) {\n\t\tconst line = this.createShape('line', {\n\t\t\tstart: start,\n\t\t\tend: end,\n\t\t\tstyle: style\n\t\t});\n\t\treturn line;\n\t}\n\n\t/**\n\t * 缩小整个画布按比例0.9\n\t * \n\t * @method zoomOut\n\t */\n\tzoomOut() {\n\t\tthis.scale(0.9 ,0.9);\n\t}\n\n\t/**\n\t * 放大 每次增大0.1的比例\n\t * \n\t * @method zoomIn\n\t */\n\tzoomIn() {\t\t\n\t\tthis.scale(1.1 ,1.1);\n\t}\n\n\t/**\n\t * 大小复原\n\t * \n\t * @method zoomActual\n\t */\n\tzoomActual() {\n\t\tif(this.scaleSize) {\n\t\t\tthis.scale(1 / this.scaleSize.x ,1 / this.scaleSize.y);\t\n\t\t}\n\t\telse {\n\t\t\tthis.scale(1 ,1);\t\n\t\t}\t\n\t}\n\n\t/**\n\t * 放大缩小画布\n\t * \n\t * @method scale\n\t * @param {number} dx 缩放X轴比例\n\t * @param {number} dy 缩放Y轴比例\n\t */\n\tscale(dx, dy) {\n\t\tif(!this.normalSize) {\n\t\t\tthis.normalSize = {\n\t\t\t\twidth: this.canvas.width,\n\t\t\t\theight: this.canvas.height\n\t\t\t};\n\t\t}\n\t\t\n\t\t//this.context.scale && this.context.scale(dx,dy);\n\t\tif(!this.scaleSize) {\n\t\t\tthis.scaleSize = {x: 1,y: 1};\n\t\t}\n\t\telse {\n\t\t\tthis.scaleSize = {x: dx * this.scaleSize.x, y: dy * this.scaleSize.y};\n\t\t}\n\t\tthis.canvas.style && (this.canvas.style.transform = `scale(${this.scaleSize.x}, ${this.scaleSize.y})`);\n\t}\n\n\t/**\n\t * 设置缩放因子\n\t * 支持以指定点为中心进行缩放,保持该点在屏幕上的位置不变\n\t * \n\t * @method setZoom\n\t * @param {number} zoom 缩放因子(建议范围:0.1 - 10)\n\t * @param {number} [x] 缩放中心X坐标(画布坐标)\n\t * @param {number} [y] 缩放中心Y坐标(画布坐标)\n\t * @return {jmGraph} 返回当前实例,支持链式调用\n\t */\n\tsetZoom(zoom, x, y) {\n\t\t// 参数验证\n\t\tif(typeof zoom !== 'number' || isNaN(zoom)) {\n\t\t\tconsole.warn('jmGraph: setZoom - 无效的缩放因子');\n\t\t\treturn this;\n\t\t}\n\t\t\n\t\t// 限制缩放范围,防止过度缩放导致性能问题或显示异常\n\t\tconst minZoom = 0.1; // 最小缩放到10%\n\t\tconst maxZoom = 10; // 最大放大到10倍\n\t\tzoom = Math.max(minZoom, Math.min(maxZoom, zoom));\n\t\t\n\t\tif (x !== undefined && y !== undefined) {\n\t\t\t// 计算缩放前后的坐标偏移\n\t\t\t// 保持缩放中心点在屏幕上的位置不变\n\t\t\tconst oldZoom = this.scaleFactor;\n\t\t\tconst newZoom = zoom;\n\t\t\t\n\t\t\t// 调整平移量以保持缩放中心位置不变\n\t\t\tthis.translation.x = x - (x - this.translation.x) * (newZoom / oldZoom);\n\t\t\tthis.translation.y = y - (y - this.translation.y) * (newZoom / oldZoom);\n\t\t}\n\t\t\n\t\tthis.scaleFactor = zoom;\n\t\tthis.needUpdate = true;\n\t\tthis.redraw();\n\t\t\n\t\treturn this; // 支持链式调用\n\t}\n\n\t/**\n\t * 平移画布\n\t * 移动画布视图,改变可视区域\n\t * \n\t * @method pan\n\t * @param {number} dx X轴平移量(像素)\n\t * @param {number} dy Y轴平移量(像素)\n\t * @return {jmGraph} 返回当前实例,支持链式调用\n\t */\n\tpan(dx, dy) {\n\t\t// 参数验证\n\t\tif(typeof dx !== 'number' || typeof dy !== 'number' || isNaN(dx) || isNaN(dy)) {\n\t\t\tconsole.warn('jmGraph: pan - 无效的平移参数');\n\t\t\treturn this;\n\t\t}\n\t\t\n\t\tthis.translation.x += dx;\n\t\tthis.translation.y += dy;\n\t\tthis.needUpdate = true;\n\t\tthis.redraw();\n\t\t\n\t\treturn this; // 支持链式调用\n\t}\n\n\t/**\n\t * 重置缩放和平移\n\t * 恢复画布到初始状态(缩放为1,平移为0)\n\t * \n\t * @method resetTransform\n\t * @return {jmGraph} 返回当前实例,支持链式调用\n\t */\n\tresetTransform() {\n\t\tthis.scaleFactor = 1;\n\t\tthis.translation = {x: 0, y: 0};\n\t\tthis.needUpdate = true;\n\t\tthis.redraw();\n\t\t\n\t\treturn this; // 支持链式调用\n\t}\n\n\t/**\n\t * 保存为base64图形数据\n\t * \n\t * @method toDataURL\n\t * @return {string} 当前画布图的base64字符串\n\t */\n\ttoDataURL() {\n\t\tlet data = this.canvas.toDataURL?this.canvas.toDataURL():'';\n\t\treturn data;\n\t}\n\n\t/**\n\t * 导出为PNG图片\n\t * 使用Canvas的toDataURL方法导出当前画布内容\n\t * \n\t * @method exportToPNG\n\t * @param {string} [fileName='jmgraph-export'] 文件名(不含扩展名)\n\t * @param {string} [format='image/png'] 图片格式,支持image/png和image/jpeg\n\t * @param {number} [quality=0.9] 图片质量(0-1之间,仅对JPEG格式有效)\n\t */\n\texportToPNG(fileName = 'jmgraph-export', format = 'image/png', quality = 0.9) {\n\t\ttry {\n\t\t\t// 确保画布已渲染\n\t\t\tthis.redraw();\n\t\t\t\n\t\t\tconst dataURL = this.canvas.toDataURL(format, quality);\n\t\t\tthis.downloadFile(dataURL, fileName, 'png');\n\t\t} catch(error) {\n\t\t\tconsole.error('jmGraph: exportToPNG - 导出失败', error);\n\t\t}\n\t}\n\n\t/**\n\t * 导出为JPEG图片\n\t * \n\t * @method exportToJPEG\n\t * @param {string} [fileName='jmgraph-export'] 文件名(不含扩展名)\n\t * @param {number} [quality=0.9] 图片质量(0-1之间)\n\t */\n\texportToJPEG(fileName = 'jmgraph-export', quality = 0.9) {\n\t\tthis.exportToPNG(fileName, 'image/jpeg', quality);\n\t}\n\n\t/**\n\t * 导出为SVG文件\n\t * 将当前画布内容转换为SVG格式\n\t * 注意:只有实现了toSVG方法的形状才能被导出\n\t * \n\t * @method exportToSVG\n\t * @param {string} [fileName='jmgraph-export'] 文件名(不含扩展名)\n\t */\n\texportToSVG(fileName = 'jmgraph-export') {\n\t\ttry {\n\t\t\tconst svg = this.toSVG();\n\t\t\tconst blob = new Blob([svg], { type: 'image/svg+xml;charset=utf-8' });\n\t\t\tconst url = URL.createObjectURL(blob);\n\t\t\tthis.downloadFile(url, fileName, 'svg');\n\t\t\t\n\t\t\t// 释放URL对象,避免内存泄漏\n\t\t\tsetTimeout(() => URL.revokeObjectURL(url), 100);\n\t\t} catch(error) {\n\t\t\tconsole.error('jmGraph: exportToSVG - 导出失败', error);\n\t\t}\n\t}\n\n\t/**\n\t * 遍历所有形状,生成SVG标记\n\t *\n\t * @method toSVG\n\t * @return {string} SVG字符串\n\t */\n\ttoSVG() {\n\t\t// SVG头部,包含命名空间和画布尺寸\n\t\tlet svg = `<svg width=\"${this.width}\" height=\"${this.height}\" xmlns=\"http://www.w3.org/2000/svg\" viewBox=\"0 0 ${this.width} ${this.height}\">`;\n\n\t\t// 添加背景色(如果有)\n\t\tif(this.style && this.style.fill) {\n\t\t\tsvg += `<rect width=\"100%\" height=\"100%\" fill=\"${this.style.fill}\"/>`;\n\t\t}\n\n\t\t// 遍历所有直接添加的形状\n\t\tthis.children.each((i, shape) => {\n\t\t\tif(shape.toSVG) {\n\t\t\t\tsvg += shape.toSVG();\n\t\t\t}\n\t\t});\n\n\t\tsvg += '</svg>';\n\t\treturn svg;\n\t}\n\n\t/**\n\t * 下载文件\n\t * 创建临时链接元素触发浏览器下载\n\t * \n\t * @method downloadFile\n\t * @private\n\t * @param {string} url 文件URL或Data URL\n\t * @param {string} fileName 文件名(不含扩展名)\n\t * @param {string} extension 文件扩展名\n\t */\n\tdownloadFile(url, fileName, extension) {\n\t\t// 创建临时链接元素\n\t\tconst link = document.createElement('a');\n\t\tlink.href = url;\n\t\tlink.download = `${fileName}.${extension}`;\n\t\t\n\t\t// 添加到DOM并触发点击\n\t\tdocument.body.appendChild(link);\n\t\tlink.click();\n\t\t\n\t\t// 清理DOM\n\t\tdocument.body.removeChild(link);\n\t}\n\n\t/** \n\t * 自动刷新画版\n\t * @param {function} callback 执行回调\n\t */\n\tautoRefresh(callback) {\n\t\tif(this.___isAutoRefreshing) return;\n\t\tconst self = this;\n\t\tthis.___isAutoRefreshing = true;\n\t\t\n\t\tconst refreshStartTime = Date.now();\n\t\tfunction update() {\n\t\t\tif(self.destroyed) {\n\t\t\t\tself.___isAutoRefreshing = false;\n\t\t\t\treturn;// 已销毁\n\t\t\t}\n\t\t\tif(self.needUpdate) self.redraw();\n\n\t\t\tconst time = Date.now() - refreshStartTime;\n\t\t\t// 触发刷新事件\n\t\t\tself.emit('update', time);\n\n\t\t\t// 直接 requestAnimationFrame,无需先 cancel\n\t\t\tself.__requestAnimationFrameFunHandler = self.requestAnimationFrame(update);\n\t\t\tif(callback) callback();\n\t\t}\n\t\tself.__requestAnimationFrameFunHandler && this.cancelAnimationFrame(self.__requestAnimationFrameFunHandler);\n\t\tself.__requestAnimationFrameFunHandler = this.requestAnimationFrame(update);\n\t\treturn this;\n\t}\n\n\t// 销毁当前对象\n\tdestroy() {\n\t\tthis.eventHandler.destroy();\n\t\tthis.destroyed = true;// 标记已销毁\n\t}\n}\n\nexport {\n\tjmGraph,\n\tjmUtils,\n\tjmList,\n\tjmProperty,\n\tjmShadow,\n\tjmGradient,\n\tjmFilter,\n\tjmEvents,\n\tjmControl,\n\tjmPath,\n };\n"],"names":["jmList","Array","ps","arg","length","isArray","i","push","option","type","obj","this","includes","_typeof","removeAt","index","splice","removeHandler","call","find","cb","inverse","len","handler","count","colorKeywords","aliceblue","antiquewhite","aqua","aquamarine","azure","beige","bisque","black","blanchedalmond","blue","blueviolet","brown","burlywood","cadetblue","chartreuse","chocolate","coral","cornflowerblue","cornsilk","crimson","cyan","darkblue","darkcyan","darkgoldenrod","darkgray","darkgreen","darkkhaki","darkmagenta","darkolivegreen","darkorange","darkorchid","darkred","darksalmon","darkseagreen","darkslateblue","darkslategray","darkslategrey","darkturquoise","darkviolet","deeppink","deepskyblue","dimgray","dimgrey","dodgerblue","firebrick","floralwhite","forestgreen","fuchsia","gainsboro","ghostwhite","gold","goldenrod","gray","green","greenyellow","grey","honeydew","hotpink","indianred","indigo","ivory","khaki","lavender","lavenderblush","lawngreen","lemonchiffon","lightblue","lightcoral","lightcyan","lightgoldenrodyellow","lightgrey","lightgreen","lightpink","lightsalmon","lightseagreen","lightskyblue","lightslategray","lightslategrey","lightsteelblue","lightyellow","lime","limegreen","linen","magenta","maroon","mediumaquamarine","mediumblue","mediumorchid","mediumpurple","mediumseagreen","mediumslateblue","mediumspringgreen","mediumturquoise","mediumvioletred","midnightblue","mintcream","mistyrose","moccasin","navajowhite","navy","oldlace","olive","olivedrab","orange","orangered","orchid","palegoldenrod","palegreen","paleturquoise","palevioletred","papayawhip","peachpuff","peru","pink","plum","powderblue","purple","red","rebeccapurple","rosybrown","royalblue","saddlebrown","salmon","sandybrown","seagreen","seashell","sienna","silver","skyblue","slateblue","slategray","slategrey","snow","springgreen","steelblue","tan","teal","thistle","tomato","turquoise","violet","wheat","white","whitesmoke","yellow","yellowgreen","transparent","activeborder","activecaption","appworkspace","background","buttonface","buttonhighlight","buttonshadow","buttontext","captiontext","graytext","highlight","highlighttext","inactiveborder","inactivecaption","inactivecaptiontext","infobackground","infotext","menu","menutext","scrollbar","threeddarkshadow","threedface","threedhighlight","threedlightshadow","threedshadow","window","windowframe","windowtext","jmUtils","source","target","deep","copyHandler","deepIndex","cloned","WeakMap","undefined","has","get","isType","dest","set","clone","slice","tagName","getContext","emit","__proto__","Object","keys","concat","getOwnPropertySymbols","v","k","name","fun","opt","indexOf","ns","split","bindEvent","attachEvent","addEventListener","removeEventListener","detachEvent","el","pos","offsetParent","top","offsetTop","left","offsetLeft","x","y","evt","scale","isWXMiniApp","event","isTouch","touches","changedTouches","targetTouches","srcElement","px","pageX","clientX","document","documentElement","scrollLeft","body","py","pageY","clientY","scrollTop","ox","offsetX","oy","offsetY","p","getElementPosition","layerX","layerY","screenX","screenY","constructor","pt","polygon","offset","n","Math","abs","pointOnLine","rayCasting","p1","p2","minX","min","maxX","max","minY","maxY","f","l","sqrt","inside","testY","testX","j","yi","yj","xi","xj","parentBounds","targetBounds","result","right","bottom","rp","r","cos","sin","x1","y1","c","sc","substring","trimStart","trimEnd","per","trim","tmp","checkPercent","h","toLowerCase","iv","floor","hex","__hexToRGBA_Cache","m","res","color","a","substr","g","b","Number","hexToNumber","toFixed","match","byteToDecimal","hexToRGBA","callback","win","requestAnimationFrame","setTimeout","cancelAnimationFrame","clearTimeout","control_id_counter","jmObject","graph","id","is","arguments","animateHandles","params","add","millisec","handle","self","dispatcher","_this","overduehandles","curTimes","Date","now","each","ani","times","apply","e","remove","animate","PROPERTY_KEY","Symbol","jmProperty","mode","pars","pros","value","args","oldValue","newValue","property","needUpdate","findParent","canvas","jmShadow","blur","fromString","s","ms","test","jmGradient","stops","control","gradient","context","bounds","absoluteBounds","getAbsoluteBounds","x2","y2","location","getLocation","d","radius","width","height","num","percentToNumber","parseFloat","isNaN","sx1","sy1","sx2","sy2","webglControl","createLinearGradient","key","toString","r1","r2","createRadialGradient","createCircularGradient","toColor","addColorStop","content","colorCount","gradientMatch","console","warn","splitIndex","_findSplitIndex","colorPart","_parseLinearParams","_parseRadialParams","_parseColorStops","depth","char","_angle","coords","trimmed","startsWith","direction","dir","_directionToAngle","angle","_hasAngleUnit","_parseAngle","_angleToCoords","parts","shape","position","atMatch","shapePart","posPart","_parseRadialShape","_parseRadialPosition","sizeMatch","sizes","rx","ry","_splitColorStops","lastOffset","finalOffset","stop","parsed","_parseSingleColorStop","_isValidColor","_normalizeOffset","nextOffset","_findNextOffset","addStop","current","hexMatch","rgbaMatch","hslaMatch","namedMatch","currentIndex","endsWith","str","angleStr","PI","round","directions","keywordMatch","mainDir","secDir","replace","combined","jmFilter","filters","addFilter","normalized","existing","regex","exec","valueStr","map","join","some","findIndex","jmEvents","container","mouseHandler","jmMouseEvent","keyHandler","jmKeyEvent","eventName","raiseEvent","destroy","instance","eventEvents","init","doc","preventDefault","touchStart","passive","touchMove","touchEnd","touchCancel","removeEvent","checkKeyEvent","earcut","data","holeIndices","dim","invSize","hasHoles","outerLen","outerNode","linkedList","triangles","next","prev","start","list","queue","end","steiner","leftmost","getLeftmost","sort","compareX","hole","bridge","hx","hy","qx","Infinity","mx","my","tanMin","pointInTriangle","locallyInside","area","sectorContainsSector","findHoleBridge","bridgeReverse","splitPolygon","filterPoints","eliminateHole","eliminateHoles","earcutLinked","clockwise","last","signedArea","insertNode","equals","removeNode","again","ear","pass","z","zOrder","prevZ","nextZ","q","tail","numMerges","pSize","qSize","inSize","sortLinked","indexCurve","ax","bx","cx","ay","by","cy","x0","y0","minZ","maxZ","isEarHashed","isEar","intersects","cureLocalIntersections","intersectsPolygon","middleInside","isValidDiagonal","splitEarcut","q1","q2","o1","sign","o2","o3","o4","onSegment","a2","Node","b2","an","bp","sum","deviation","polygonArea","trianglesArea","flatten","vertices","holes","dimensions","holeIndex","WebglGradient","_sortedStops","_paramsHash","utils","needNormalize","_getSortedStops","flatStops","Float32Array","gradientType","gradientStart","gradientEnd","stopCount","forEach","createShader","gl","src","shader","shaderSource","compileShader","GLSL_TO_SIZE","mapSize","GL_TABLE","GL_TO_GLSL_TYPES","mapType","typeNames","tn","createProgram","vertexSrc","fragmentSrc","vertexShader","VERTEX_SHADER","fragmentShader","FRAGMENT_SHADER","program","attachShader","linkProgram","getProgramParameter","LINK_STATUS","error","VALIDATE_STATUS","getError","getProgramInfoLog","deleteProgram","useProgram","deleteShader","attrs","attributes","ACTIVE_ATTRIBUTES","attribData","getActiveAttrib","size","getAttribLocation","extractAttributes","uniforms","ACTIVE_UNIFORMS","uniformData","getActiveUniform","getUniformLocation","extractUniforms","createBuffer","ARRAY_BUFFER","drawType","STATIC_DRAW","buffer","Error","bindBuffer","bufferData","unitSize","BYTES_PER_ELEMENT","create2DTexture","texture","createTexture","pixelStorei","UNPACK_FLIP_Y_WEBGL","activeTexture","TEXTURE0","bindTexture","TEXTURE_2D","texParameterf","TEXTURE_MAG_FILTER","NEAREST","TEXTURE_MIN_FILTER","TEXTURE_WRAP_S","CLAMP_TO_EDGE","TEXTURE_WRAP_T","pathVertexSource","pathFragmentSource","MAX_STOPS","WeblBase","style","globalAlpha","stateStack","transformMatrix","state","pop","sx","sy","currentA","currentB","currentC","currentD","currentE","currentF","point","tx","ty","__measureCtx","createElement","pathProgram","isGradient","__parseCSSColor","rgbToDecimal","colorStr","ctx","_measureCtx","clearRect","fillStyle","fillRect","getImageData","__curent_program","attr","strip","dataType","FLOAT","vertexAttribPointer","enableVertexAttribArray","writeVertexAttrib","disableVertexAttribArray","createFloat32Buffer","Uint16Array","createUint16Buffer","bufferHandler","deleteBuffer","log","img","texImage2D","RGBA","UNSIGNED_BYTE","pixels","Uint8Array","deleteTexture","points","pointsToArray","earCutCache","earCutPoints","p3","arr","webglGradient","text","fontSize","save","font","fontFamily","measureText","restore","parseInt","WebglPath","WebglBase","isRegular","needCut","__cachedBuffers","__cachedTexture","__cachedTextureKey","buf","float32","DYNAMIC_DRAW","parentAbsoluteBounds","__lastCenterX","__lastCenterY","uniform2f","a_center_point","convertColor","uniform4f","v_single_color","colorData","colorBuffer","a_color","setParentBounds","pathPoints","needClose","a_position","fixedPoints","transformedPoint","applyTransform","vertexBuffer","dx","dy","pow","linePoints","genLinePoints","subPaths","maxArea","outerIdx","outerPoints","isTexture","allPoints","vertexData","indices","allVertices","allTexCoords","vertexArr","posBuffer","_this2","texData","texBuffer","a_text_coord","drawArrays","TRIANGLES","lines","index1","index2","line1","line2","equalPoint","sub1","cuted","intersection","getIntersection","sub2","cutLines","area_abc","area_abd","area_cda","t","line","root","polygons","unshift","getIntersectionLines","pathToLines","treeLine","trianglesCache","getPolygon","earCutPointsToTriangles","strokeStyle","lineWidth","setFragColor","uniform1f","a_point_size","a_type","uniform1i","regular","hasMoveTo","isRing","subPath","writePoints","LINE_LOOP","mid","inner","outer","pathToPoints","POINTS","fillColor","fillImage","fillGradient","fillPolygons","toUniformParams","u_gradient_type","u_gradient_start","uniform4fv","u_gradient_end","u_gradient_stop_count","u_gradient_offsets","offsets","uniform1fv","u_gradient_colors","colors","lastR","lastG","lastB","lastA","ImageData","createDataTexture","createImgTexture","u_sample","v_texture_bounds","fillTexture","TRIANGLE_FAN","splitSubPaths","fillWithHoles","getTriangles","_this3","__textCanvas","willReadFrequently","shadowColor","shadowBlur","shadowOffsetX","shadowOffsetY","textAlign","textBaseline","fillText","maxWidth","strokeText","jmStyleMap","jmControl","hitArea","zIndex","interactive","initializing","on","bind","children","css","cur","oadd","parent","contain","oremove","levelItems","zindex","clear","__setStyle","mpkey","styleValue","dash","mpname","toGradient","setStyle","getRotation","__translateAbsolutePosition","toAbsolutePoint","translate","rotate","transform","scaleX","skewX","skewY","scaleY","cursor","setLineDash","filter","lineDashOffset","toCanvasFilter","globalCompositeOperation","clip","beginPath","moveTo","lineTo","close","closePath","__mask","isReset","rect","rotation","getBounds","local","oldBounds","rotatePoints","needResolve","center","margin","marginObj","trans","offseted","cpoints","rec","prec","beginDraw","fill","stroke","endDraw","draw","visible","initPoints","needDraw","maskStyle","mask","mBounds","item","paint","__events","eventCollection","getEvent","events","unbind","runEventHandle","cancel","pad","getPosition","pointInPolygon","getEventPosition","button","keyCode","charCode","which","ctrlKey","path","stoped","abounds","inpos","checkPoint","runEventAndPopEvent","focused","__mvMonitor","mouseDown","curposition","mv","outside","offsetx","offsety","lockSide","thisbounds","checkOutSide","mu","ml","md","jmPath","pathData","svg","opacity","jmGraph","devicePixelRatio","util","scaleFactor","translation","wx","canIUse","createSelectorQuery","select","getElementById","parentElement","cn","appendChild","offsetWidth","clientWidth","offsetHeight","clientHeight","preserveDrawingBuffer","enable","BLEND","blendFunc","SRC_ALPHA","ONE_MINUS_SRC_ALPHA","__init","shapes","assign","dpr","getWindowInfo","pixelRatio","dprScaleSize","resize","eventHandler","autoRefresh","w","__normalSize","viewport","redraw","__lastClearColor","clearColor","COLOR_BUFFER_BIT","createShape","scaleSize","normalSize","zoom","oldZoom","newZoom","toDataURL","fileName","format","quality","dataURL","downloadFile","exportToPNG","toSVG","blob","Blob","url","URL","createObjectURL","revokeObjectURL","extension","link","href","download","click","removeChild","___isAutoRefreshing","refreshStartTime","__requestAnimationFrameFunHandler","update","time","destroyed"],"mappings":"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"}
|