diff --git a/.babelrc b/.babelrc new file mode 100644 index 000000000..ff5e0c4f9 --- /dev/null +++ b/.babelrc @@ -0,0 +1,9 @@ +{ + "presets": [ + "es2015-loose-rollup", + "stage-0" + ], + "plugins": [ + "external-helpers" + ] +} diff --git a/.editorconfig b/.editorconfig new file mode 100644 index 000000000..a2f217c26 --- /dev/null +++ b/.editorconfig @@ -0,0 +1,20 @@ +# EditorConfig is awesome: http://EditorConfig.org + +# top-most EditorConfig file +root = true + +# Unix-style newlines with a newline ending every file +[*] +end_of_line = lf +charset = utf-8 +insert_final_newline = true +trim_trailing_whitespace = true +indent_style = space +indent_size = 2 + +[Makefile] +indent_style = tab +indent_size = 1 + +[*.md] +trim_trailing_whitespace = false \ No newline at end of file diff --git a/.eslintignore b/.eslintignore new file mode 100644 index 000000000..af04a1961 --- /dev/null +++ b/.eslintignore @@ -0,0 +1,4 @@ +build/ +dist/ +mocks/ +node_modules/ diff --git a/.eslintrc b/.eslintrc index fa91992b8..2a2eebe71 100644 --- a/.eslintrc +++ b/.eslintrc @@ -1,23 +1,21 @@ { - "extends": "airbnb/legacy", + "extends": [ + "egg" + ], + "parser": "babel-eslint", + "parserOptions": { + "sourceType": "module" + }, "rules": { - "no-console": [ + "no-bitwise": [ 0 ], - "space-before-function-paren": [ + "experimentalDecorators": [ 0 ], - "comma-dangle": [2, "never"], - "vars-on-top": 0, - "no-param-reassign": 0, - "max-len": 0, - "new-cap": 0, - "func-names": 0, - "no-unused-expressions": 0, - "dot-notation": [2, {"allowKeywords": false}], - "quote-props": 0, - "no-nested-ternary": 0, - "no-new": 0, - "no-cond-assign": 0 + "comma-dangle": [ + "error", + "never" + ] } } diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml new file mode 100644 index 000000000..d07fd81b0 --- /dev/null +++ b/.gitlab-ci.yml @@ -0,0 +1,11 @@ +before_script: + - Xvfb :99 & + - export DISPLAY=:99.0; + - echo $PATH +test: + image: reg.docker.alibaba-inc.com/dockerlab/macaca-electron:0.2.0 + script: + - time tnpm i --no-cache + - time tnpm run ci + tags: + - swarm diff --git a/.npmignore b/.npmignore new file mode 100644 index 000000000..18a56b66e --- /dev/null +++ b/.npmignore @@ -0,0 +1,68 @@ +# Logs +logs +*.log +npm-debug.log* +yarn-debug.log* +yarn-error.log* + +# lock +package-lock.json + +# Runtime data +pids +*.pid +*.seed +*.pid.lock + +# Directory for instrumented libs generated by jscoverage/JSCover +lib-cov + +# Coverage directory used by tools like istanbul +coverage + +# nyc test coverage +.nyc_output + +# Grunt intermediate storage (http://gruntjs.com/creating-plugins#storing-task-files) +.grunt + +# Bower dependency directory (https://bower.io/) +bower_components + +# node-waf configuration +.lock-wscript + +# Compiled binary addons (http://nodejs.org/api/addons.html) +build/Release + +# Dependency directories +node_modules/ +jspm_packages/ + +# Typescript v1 declaration files +typings/ + +# Optional npm cache directory +.npm + +# Optional eslint cache +.eslintcache + +# Optional REPL history +.node_repl_history + +# Output of 'npm pack' +*.tgz + +# Yarn Integrity file +.yarn-integrity + +# dotenv environment variables file +.env + +build +.DS_Store + +# npmignore - content above this line is automatically generated and modifications may be omitted +# see npmjs.com/npmignore for more details. +test diff --git a/build/g.js b/build/g.js new file mode 100644 index 000000000..51e7d540a --- /dev/null +++ b/build/g.js @@ -0,0 +1,13586 @@ +(function (global, factory) { + typeof exports === 'object' && typeof module !== 'undefined' ? module.exports = factory() : + typeof define === 'function' && define.amd ? define(factory) : + (global.G = factory()); +}(this, (function () { 'use strict'; + +/** + * @fileOverview 基础工具类 + * @author hankaiai@126.com + * @author dxq613@gmail.com + */ + +var objectPrototype = Object.prototype; +var toString = objectPrototype.toString; + + +var MAX_LEVEL = 5; + +function deepMix(dst, src, level) { + level = level || 0; + for (var k in src) { + if (src.hasOwnProperty(k)) { + var value = src[k]; + if (value !== null && Util.isObject(value)) { + if (!Util.isObject(dst[k])) { + dst[k] = {}; + } + if (level < MAX_LEVEL) { + deepMix(dst[k], src[k], level + 1); + } else { + dst[k] = src[k]; + } + } else if (Util.isArray(value)) { + //if(!Util.isArray(dst[k])){ + dst[k] = []; + //} + dst[k] = dst[k].concat(value); + } else if (value !== undefined) { + dst[k] = src[k]; + } + } + } +} + +/** + * @class Util + * @singleton + * 绘图的工具类 + */ +var Util = { + + /** + * 替换字符串中的字段. + * @param {String} str 模版字符串 + * @param {Object} o json data + * @param {RegExp} [regexp] 匹配字符串的正则表达式 + */ + + substitute: function(str, o) { + if (!str || !o) { + return str; + } + return str.replace(/\\?\{([^{}]+)\}/g, function(match, name) { + if (match.charAt(0) === '\\') { + return match.slice(1); + } + return (o[name] === undefined) ? '' : o[name]; + }); + }, + /** + * 使第一个字母变成大写 + * @param {String} s 字符串 + * @return {String} 首字母大写后的字符串 + */ + ucfirst: function(s) { + s += ''; + return s.charAt(0).toUpperCase() + s.substring(1); + }, + /** + * 判断是否是字符串 + * @return {Boolean} 是否是字符串 + */ + isString: function(value) { + return typeof value === 'string'; + }, + /** + * 判断是否数字 + * @return {Boolean} 是否数字 + */ + isNumber: function(value) { + return typeof value === 'number'; + }, + /** + * 判断是否数字或者数字字符串,由于$.isNumberic方法会把 '123'认为数字 + * @return {Boolean} 是否数字 + */ + isNumeric: function(value) { + return !isNaN(parseFloat(value)) && isFinite(value); + }, + /** + * 是否是布尔类型 + * + * @param {Object} value 测试的值 + * @return {Boolean} + */ + isBoolean: function(value) { + return typeof value === 'boolean'; + }, + /** + * 是否为函数 + * @param {*} fn 对象 + * @return {Boolean} 是否函数 + */ + isFunction: function(fn) { + return typeof(fn) === 'function'; + }, + /** + * 是否数组 + * @method + * @param {*} obj 是否数组 + * @return {Boolean} 是否数组 + */ + isArray: ('isArray' in Array) ? Array.isArray : function(value) { + return toString.call(value) === '[object Array]'; + }, + + /** + * 是否日期 + * @param {*} value 对象 + * @return {Boolean} 是否日期 + */ + isDate: function(value) { + return toString.call(value) === '[object Date]'; + }, + /** + * 对象是否为空 + * @param {*} o 对象 + * @return {Boolean} 是否不存在 + */ + isNull: function(o) { + return o === undefined || o === null; + }, + /** + * 对象是否为空 + * @param {*} o 对象 + * @return {Boolean} 是否存在 + */ + notNull: function(o) { + return !Util.isNull(o); + }, + /** + * 对象或数组是否为没有元素的空的 + * + */ + isBlank: function(o) { + if (Util.isArray(o)) { + return o.length === 0; + } + + if (Util.isObject(o)) { + var n = 0; + Util.each(o, function(key, value) { + n++; + }); + return n === 0; + } + + return false; + }, + /** + * 是否是javascript对象 + * @param {Object} value The value to test + * @return {Boolean} + * @method + */ + isObject: (toString.call(null) === '[object Object]') ? + function(value) { + // check ownerDocument here as well to exclude DOM nodes + return value !== null && value !== undefined && toString.call(value) === '[object Object]' && value.ownerDocument === undefined; + } : function(value) { + return toString.call(value) === '[object Object]'; + }, + /** + * 实现类的继承,通过父类生成子类 + * @param {Function} subclass + * @param {Function} superclass 父类构造函数 + * @param {Object} overrides 子类的属性或者方法 + * @return {Function} 返回的子类构造函数 + * 示例: + * @example + * //父类 + * function base(){ + * + * } + * + * function sub(){ + * + * } + * //子类 + * Util.extend(sub,base,{ + * method : function(){ + * + * } + * }); + * + * //或者 + * var sub = Util.extend(base,{}); + */ + extend: function(subclass, superclass, overrides, staticOverrides) { + //如果只提供父类构造函数,则自动生成子类构造函数 + if (!Util.isFunction(superclass)) { + overrides = superclass; + superclass = subclass; + subclass = function() {}; + } + + var create = Object.create ? + function(proto, c) { + return Object.create(proto, { + constructor: { + value: c + } + }); + } : + function(proto, c) { + function F() {} + + F.prototype = proto; + + var o = new F(); + o.constructor = c; + return o; + }; + + var superObj = create(superclass.prototype, subclass); //new superclass(),//实例化父类作为子类的prototype + subclass.prototype = Util.mix(superObj, subclass.prototype); //指定子类的prototype + subclass.superclass = create(superclass.prototype, superclass); + Util.mix(superObj, overrides); + Util.mix(subclass, staticOverrides); + return subclass; + }, + /** + * 复制到原型链上 + * @param {Function} c 类 + * @param {Object} obj 对象 + */ + augment: function(c) { + + var args = Util.toArray(arguments); + for (var i = 1; i < args.length; i++) { + var obj = args[i]; + if (Util.isFunction(obj)) { + obj = obj.prototype; + } + Util.mix(c.prototype, obj); + } + }, + /** + * 转换成数组 + * @param {*} value 需要转换的对象 + * @return {Array} 数组 + */ + toArray: function(value) { + if (!value || !value.length) { + return []; + } + return Array.prototype.slice.call(value); + }, + /** + * 合并数据 + * @return {Object} 将数据合并到第一个 + */ + mix: function() { + var args = Util.toArray(arguments), + obj = args[0]; + if (obj === true) { + obj = args[1]; + for (var i = 2; i < args.length; i++) { + var source = args[i]; + deepMix(obj, source); + } + } else { + for (var i = 1; i < args.length; i++) { + var source = args[i]; + for (var k in source) { + if (source.hasOwnProperty(k) && k !== 'constructor') { + obj[k] = source[k]; + } + } + } + } + return obj; + }, + + /** + * 遍历数组或者对象 + * @param {Object|Array} element/Object 数组中的元素或者对象的值 + * @param {Function} func 遍历的函数 function(elememt,index){} 或者 function(value,key){} + */ + each: function(elements, func) { + if (!elements) { + return; + } + if (Util.isObject(elements)) { + for (var k in elements) { + if (elements.hasOwnProperty(k)) { + var rst = func(elements[k], k); + if (rst === false) { + break; + } + } + } + } else if (elements.length) { + for (var i = 0; i < elements.length; i++) { + var rst = func(elements[i], i); + if (rst === false) { + break; + } + } + } + }, + requestAnimationFrame: function(fn) { + var method = window.requestAnimationFrame || window.webkitRequestAnimationFrame || function(fn) { + return setTimeout(fn, 16); + }; + + return method(fn); + }, + cancelAnimationFrame: function(id) { + var method = window.cancelAnimationFrame || window.webkitCancelAnimationFrame || function(id) { + return clearTimeout(id); + }; + return method(id); + } +}; + + +var util$2 = Util; + +var index$6 = util$2; + +//将数值逼近到指定的数 +function tryFixed(v, base) { + var str = base.toString(); + var index = str.indexOf('.'); + if (index === -1) { + return Math.round(v); + } + var length = str.substr(index + 1).length; + if (length > 20) { + length = 20; + } + return parseFloat(v.toFixed(length)); +} + +function _mix(dist, obj) { + for (var k in obj) { + if (obj.hasOwnProperty(k) && k !== 'constructor' && obj[k] !== undefined) { + dist[k] = obj[k]; + } + } +} + + +/** + * @class Util + * @singleton + * 绘图的工具类 + */ +index$6.mix(index$6, { + + mixin: function(c, mixins) { + if (c && mixins) { + c._mixins = mixins; + c.ATTRS = c.ATTRS || {}; + var temp = {}; + index$6.each(mixins, function(mixin) { + index$6.augment(c, mixin); + var attrs = mixin.ATTRS; + if (attrs) { + index$6.mix(temp, attrs); + } + }); + + c.ATTRS = index$6.mix(temp, c.ATTRS); + } + }, + /** + * map 数组 + * @param {Array} arr 数组 + * @return {Array} map后的数组 + */ + map: function(arr, func) { + var result = []; + index$6.each(arr, function(value, index) { + result.push(func(value, index)); + }); + return result; + }, + /** + * 过滤数组 + * @param {Object|Array} element/Object 数组中的元素或者对象的值 + * @param {Function} func 遍历的函数 function(elememt,index){} 或者 function(value,key){},如果返回true则添加到结果集 + * @return {Array} 过滤的结果集 + */ + filter: function(array, func) { + var result = []; + index$6.each(array, function(value, index) { + if (func(value, index)) { + result.push(value); + } + }); + return result; + }, + /** + * 生成唯一的Id + * @method + * @param {String} prefix 前缀 + * @return {String} 唯一的编号 + */ + guid: (function() { + var map = {}; + return function(prefix) { + prefix = prefix || 'g'; + if (!map[prefix]) { + map[prefix] = 1; + } else { + map[prefix] += 1; + } + return prefix + map[prefix]; + }; + })(), + /** + * 数组中是否存在元素 + * @param {Array} arr 数组 + * @param {*} obj 查找的元素 + * @return {Boolean} 是否存在 + */ + inArray: function(arr, value) { + return index$6.indexOf(arr, value) !== -1; + }, + /** + * 查找元素在数组中的位置,如果不存在则返回-1 + * @param {Array} arr 数组 + * @param {*} obj 查找的元素 + * @return {Number} 位置 + */ + indexOf: function(arr, obj) { + var m = Array.prototype.indexOf; + if (m) { + return m.call(arr, obj); + } + var index = -1; + + for (var i = 0; i < arr.length; i++) { + if (arr[i] === obj) { + index = i; + break; + } + } + return index; + }, + /** + * 删除 + */ + remove: function(arr, obj) { + var index = index$6.indexOf(arr, obj); + if (index !== -1) { + arr.splice(index, 1); + } + }, + /** + * 清空 + * @param {Array} array 数组 + */ + empty: function(array) { + if (!(array instanceof(Array))) { + for (var i = array.length - 1; i >= 0; i--) { + delete array[i]; + } + } + array.length = 0; + }, + /** + * 2个数组是否等同 + * @param {Array} a1 数组1 + * @param {Array} a2 数组2 + * @return {Boolean} 2个数组相等或者内部元素是否相等 + */ + equalsArray: function(a1, a2) { + if (a1 === a2) { + return true; + } + if (!a1 || !a2) { + return false; + } + + if (a1.length !== a2.length) { + return false; + } + var rst = true; + for (var i = 0; i < a1.length; i++) { + if (a1[i] !== a2[i]) { + rst = false; + break; + } + } + return rst; + }, + /** + * 封装事件,便于使用上下文this,和便于解除事件时使用 + * @protected + * @param {Object} self 对象 + * @param {String} action 事件名称 + */ + wrapBehavior: function(self, action) { + var method = function(e) { + self[action](e); + }; + self['_wrap_' + action] = method; + return method; + }, + /** + * 获取封装的事件 + * @protected + * @param {Object} self 对象 + * @param {String} action 事件名称 + */ + getWrapBehavior: function(self, action) { + return self['_wrap_' + action]; + }, + /** + * 将value的小数位长度和base保持一致 + * @param {Number} value 值 + * @param {Number} base 基准值 + * @return {Number} fixed后的数字 + */ + fixedBase: function(value, base) { + return tryFixed(value, base); + }, + /** + * 返回集合对象的长度,如果是数组则返回数组的长度,如果是对象则返回对象中的属性个数 + * @param {Array or Object} set 集合对象 + * @return {Number} 集合对象的长度 + */ + length: function(set) { + if (index$6.isArray(set)) { + return set.length; + } + if (index$6.isObject(set)) { + var length = 0; + index$6.each(set, function() { + length++; + }); + return length; + } + return 0; + }, + clone: function(obj) { + if (typeof obj !== 'object' || obj === null) { + return obj; + } + var rst; + if (index$6.isArray(obj)) { + rst = []; + for (var i = 0, l = obj.length; i < l; i++) { + if (typeof obj[i] === 'object' && obj[i] != null) { + rst[i] = index$6.clone(obj[i]); + } else { + rst[i] = obj[i]; + } + } + } else { + rst = {}; + for (var k in obj) { + if (typeof obj[k] === 'object' && obj[k] != null) { + rst[k] = index$6.clone(obj[k]); + } else { + rst[k] = obj[k]; + } + } + } + + return rst; + }, + simpleMix: function(dist, obj1, obj2, obj3) { + if (obj1) { + _mix(dist, obj1); + } + + if (obj2) { + _mix(dist, obj2); + } + + if (obj3) { + _mix(dist, obj3); + } + return dist; + } +}); + +var util = index$6; + +var index$4 = util; + +/* + * Paths + */ + +var spaces = "\x09\x0a\x0b\x0c\x0d\x20\xa0\u1680\u180e\u2000\u2001\u2002\u2003\u2004\u2005\u2006\u2007\u2008\u2009\u200a\u202f\u205f\u3000\u2028\u2029"; +var pathCommand = new RegExp("([a-z])[" + spaces + ",]*((-?\\d*\\.?\\d*(?:e[\\-+]?\\d+)?[" + spaces + "]*,?[" + spaces + "]*)+)", "ig"); +var pathValues = new RegExp("(-?\\d*\\.?\\d*(?:e[\\-+]?\\d+)?)[" + spaces + "]*,?[" + spaces + "]*", "ig"); + +// Parses given path string into an array of arrays of path segments +var parsePathString = function(pathString) { + if (!pathString) { + return null; + } + + if (typeof pathString === typeof []) { + return pathString; + } else { + var paramCounts = { + a: 7, + c: 6, + o: 2, + h: 1, + l: 2, + m: 2, + r: 4, + q: 4, + s: 4, + t: 2, + v: 1, + u: 3, + z: 0 + }, + data = []; + + String(pathString).replace(pathCommand, function(a, b, c) { + var params = [], + name = b.toLowerCase(); + c.replace(pathValues, function(a, b) { + b && params.push(+b); + }); + if (name == "m" && params.length > 2) { + data.push([b].concat(params.splice(0, 2))); + name = "l"; + b = b == "m" ? "l" : "L"; + } + if (name == "o" && params.length == 1) { + data.push([b, params[0]]); + } + if (name == "r") { + data.push([b].concat(params)); + } else + while (params.length >= paramCounts[name]) { + data.push([b].concat(params.splice(0, paramCounts[name]))); + if (!paramCounts[name]) { + break; + } + } + }); + + return data; + } +}; + + +// http://schepers.cc/getting-to-the-point +var catmullRom2bezier = function(crp, z) { + var d = []; + for (var i = 0, iLen = crp.length; iLen - 2 * !z > i; i += 2) { + var p = [{ + x: +crp[i - 2], + y: +crp[i - 1] + }, { + x: +crp[i], + y: +crp[i + 1] + }, { + x: +crp[i + 2], + y: +crp[i + 3] + }, { + x: +crp[i + 4], + y: +crp[i + 5] + }]; + if (z) { + if (!i) { + p[0] = { + x: +crp[iLen - 2], + y: +crp[iLen - 1] + }; + } else if (iLen - 4 == i) { + p[3] = { + x: +crp[0], + y: +crp[1] + }; + } else if (iLen - 2 == i) { + p[2] = { + x: +crp[0], + y: +crp[1] + }; + p[3] = { + x: +crp[2], + y: +crp[3] + }; + } + } else { + if (iLen - 4 == i) { + p[3] = p[2]; + } else if (!i) { + p[0] = { + x: +crp[i], + y: +crp[i + 1] + }; + } + } + d.push(["C", + (-p[0].x + 6 * p[1].x + p[2].x) / 6, + (-p[0].y + 6 * p[1].y + p[2].y) / 6, + (p[1].x + 6 * p[2].x - p[3].x) / 6, + (p[1].y + 6 * p[2].y - p[3].y) / 6, + p[2].x, + p[2].y + ]); + } + + return d; + +}; + +var ellipsePath = function(x, y, rx, ry, a) { + if (a == null && ry == null) { + ry = rx; + } + x = +x; + y = +y; + rx = +rx; + ry = +ry; + if (a != null) { + var rad = Math.PI / 180, + x1 = x + rx * Math.cos(-ry * rad), + x2 = x + rx * Math.cos(-a * rad), + y1 = y + rx * Math.sin(-ry * rad), + y2 = y + rx * Math.sin(-a * rad), + res = [ + ["M", x1, y1], + ["A", rx, rx, 0, +(a - ry > 180), 0, x2, y2] + ]; + } else { + res = [ + ["M", x, y], + ["m", 0, -ry], + ["a", rx, ry, 0, 1, 1, 0, 2 * ry], + ["a", rx, ry, 0, 1, 1, 0, -2 * ry], + ["z"] + ]; + } + return res; +}; + +var pathToAbsolute = function(pathArray) { + pathArray = parsePathString(pathArray); + + if (!pathArray || !pathArray.length) { + return [ + ["M", 0, 0] + ]; + } + var res = [], + x = 0, + y = 0, + mx = 0, + my = 0, + start = 0, + pa0; + if (pathArray[0][0] == "M") { + x = +pathArray[0][1]; + y = +pathArray[0][2]; + mx = x; + my = y; + start++; + res[0] = ["M", x, y]; + } + var crz = pathArray.length == 3 && + pathArray[0][0] == "M" && + pathArray[1][0].toUpperCase() == "R" && + pathArray[2][0].toUpperCase() == "Z"; + for (var r, pa, i = start, ii = pathArray.length; i < ii; i++) { + res.push(r = []); + pa = pathArray[i]; + pa0 = pa[0]; + if (pa0 != pa0.toUpperCase()) { + r[0] = pa0.toUpperCase(); + switch (r[0]) { + case "A": + r[1] = pa[1]; + r[2] = pa[2]; + r[3] = pa[3]; + r[4] = pa[4]; + r[5] = pa[5]; + r[6] = +pa[6] + x; + r[7] = +pa[7] + y; + break; + case "V": + r[1] = +pa[1] + y; + break; + case "H": + r[1] = +pa[1] + x; + break; + case "R": + var dots = [x, y].concat(pa.slice(1)); + for (var j = 2, jj = dots.length; j < jj; j++) { + dots[j] = +dots[j] + x; + dots[++j] = +dots[j] + y; + } + res.pop(); + res = res.concat(catmullRom2bezier(dots, crz)); + break; + case "O": + res.pop(); + dots = ellipsePath(x, y, pa[1], pa[2]); + dots.push(dots[0]); + res = res.concat(dots); + break; + case "U": + res.pop(); + res = res.concat(ellipsePath(x, y, pa[1], pa[2], pa[3])); + r = ["U"].concat(res[res.length - 1].slice(-2)); + break; + case "M": + mx = +pa[1] + x; + my = +pa[2] + y; + default: + for (j = 1, jj = pa.length; j < jj; j++) { + r[j] = +pa[j] + ((j % 2) ? x : y); + } + } + } else if (pa0 == "R") { + dots = [x, y].concat(pa.slice(1)); + res.pop(); + res = res.concat(catmullRom2bezier(dots, crz)); + r = ["R"].concat(pa.slice(-2)); + } else if (pa0 == "O") { + res.pop(); + dots = ellipsePath(x, y, pa[1], pa[2]); + dots.push(dots[0]); + res = res.concat(dots); + } else if (pa0 == "U") { + res.pop(); + res = res.concat(ellipsePath(x, y, pa[1], pa[2], pa[3])); + r = ["U"].concat(res[res.length - 1].slice(-2)); + } else { + for (var k = 0, kk = pa.length; k < kk; k++) { + r[k] = pa[k]; + } + } + pa0 = pa0.toUpperCase(); + if (pa0 != "O") { + switch (r[0]) { + case "Z": + x = +mx; + y = +my; + break; + case "H": + x = r[1]; + break; + case "V": + y = r[1]; + break; + case "M": + mx = r[r.length - 2]; + my = r[r.length - 1]; + default: + x = r[r.length - 2]; + y = r[r.length - 1]; + } + } + } + + return res; +}; + + +var l2c = function(x1, y1, x2, y2) { + return [x1, y1, x2, y2, x2, y2]; +}; +var q2c = function(x1, y1, ax, ay, x2, y2) { + var _13 = 1 / 3, + _23 = 2 / 3; + return [ + _13 * x1 + _23 * ax, + _13 * y1 + _23 * ay, + _13 * x2 + _23 * ax, + _13 * y2 + _23 * ay, + x2, + y2 + ]; +}; +var a2c = function(x1, y1, rx, ry, angle, large_arc_flag, sweep_flag, x2, y2, recursive) { + // for more information of where this math came from visit: + // http://www.w3.org/TR/SVG11/implnote.html#ArcImplementationNotes + if(rx === ry) rx += 1; + var _120 = Math.PI * 120 / 180, + rad = Math.PI / 180 * (+angle || 0), + res = [], + xy, + rotate = function(x, y, rad) { + var X = x * Math.cos(rad) - y * Math.sin(rad), + Y = x * Math.sin(rad) + y * Math.cos(rad); + return { + x: X, + y: Y + }; + }; + if (!recursive) { + xy = rotate(x1, y1, -rad); + x1 = xy.x; + y1 = xy.y; + xy = rotate(x2, y2, -rad); + x2 = xy.x; + y2 = xy.y; + if(x1 === x2 && y1 === y2) { // 若弧的起始点和终点重叠则错开一点 + x2 += 1; + y2 += 1; + } + var cos = Math.cos(Math.PI / 180 * angle), + sin = Math.sin(Math.PI / 180 * angle), + x = (x1 - x2) / 2, + y = (y1 - y2) / 2; + var h = (x * x) / (rx * rx) + (y * y) / (ry * ry); + if (h > 1) { + h = Math.sqrt(h); + rx = h * rx; + ry = h * ry; + } + var rx2 = rx * rx, + ry2 = ry * ry, + k = (large_arc_flag == sweep_flag ? -1 : 1) * + Math.sqrt(Math.abs((rx2 * ry2 - rx2 * y * y - ry2 * x * x) / (rx2 * y * y + ry2 * x * x))), + cx = k * rx * y / ry + (x1 + x2) / 2, + cy = k * -ry * x / rx + (y1 + y2) / 2, + f1 = Math.asin(((y1 - cy) / ry).toFixed(9)), + f2 = Math.asin(((y2 - cy) / ry).toFixed(9)); + + f1 = x1 < cx ? Math.PI - f1 : f1; + f2 = x2 < cx ? Math.PI - f2 : f2; + f1 < 0 && (f1 = Math.PI * 2 + f1); + f2 < 0 && (f2 = Math.PI * 2 + f2); + if (sweep_flag && f1 > f2) { + f1 = f1 - Math.PI * 2; + } + if (!sweep_flag && f2 > f1) { + f2 = f2 - Math.PI * 2; + } + } else { + f1 = recursive[0]; + f2 = recursive[1]; + cx = recursive[2]; + cy = recursive[3]; + } + var df = f2 - f1; + if (Math.abs(df) > _120) { + var f2old = f2, + x2old = x2, + y2old = y2; + f2 = f1 + _120 * (sweep_flag && f2 > f1 ? 1 : -1); + x2 = cx + rx * Math.cos(f2); + y2 = cy + ry * Math.sin(f2); + res = a2c(x2, y2, rx, ry, angle, 0, sweep_flag, x2old, y2old, [f2, f2old, cx, cy]); + } + df = f2 - f1; + var c1 = Math.cos(f1), + s1 = Math.sin(f1), + c2 = Math.cos(f2), + s2 = Math.sin(f2), + t = Math.tan(df / 4), + hx = 4 / 3 * rx * t, + hy = 4 / 3 * ry * t, + m1 = [x1, y1], + m2 = [x1 + hx * s1, y1 - hy * c1], + m3 = [x2 + hx * s2, y2 - hy * c2], + m4 = [x2, y2]; + m2[0] = 2 * m1[0] - m2[0]; + m2[1] = 2 * m1[1] - m2[1]; + if (recursive) { + return [m2, m3, m4].concat(res); + } else { + res = [m2, m3, m4].concat(res).join().split(","); + var newres = []; + for (var i = 0, ii = res.length; i < ii; i++) { + newres[i] = i % 2 ? rotate(res[i - 1], res[i], rad).y : rotate(res[i], res[i + 1], rad).x; + } + return newres; + } +}; + +var path2curve = function(path, path2) { + var p = pathToAbsolute(path), + p2 = path2 && pathToAbsolute(path2), + attrs = { + x: 0, + y: 0, + bx: 0, + by: 0, + X: 0, + Y: 0, + qx: null, + qy: null + }, + attrs2 = { + x: 0, + y: 0, + bx: 0, + by: 0, + X: 0, + Y: 0, + qx: null, + qy: null + }, + processPath = function(path, d, pcom) { + var nx, ny; + if (!path) { + return ["C", d.x, d.y, d.x, d.y, d.x, d.y]; + }!(path[0] in { + T: 1, + Q: 1 + }) && (d.qx = d.qy = null); + switch (path[0]) { + case "M": + d.X = path[1]; + d.Y = path[2]; + break; + case "A": + path = ["C"].concat(a2c.apply(0, [d.x, d.y].concat(path.slice(1)))); + break; + case "S": + if (pcom == "C" || pcom == "S") { // In "S" case we have to take into account, if the previous command is C/S. + nx = d.x * 2 - d.bx; // And reflect the previous + ny = d.y * 2 - d.by; // command's control point relative to the current point. + } else { // or some else or nothing + nx = d.x; + ny = d.y; + } + path = ["C", nx, ny].concat(path.slice(1)); + break; + case "T": + if (pcom == "Q" || pcom == "T") { // In "T" case we have to take into account, if the previous command is Q/T. + d.qx = d.x * 2 - d.qx; // And make a reflection similar + d.qy = d.y * 2 - d.qy; // to case "S". + } else { // or something else or nothing + d.qx = d.x; + d.qy = d.y; + } + path = ["C"].concat(q2c(d.x, d.y, d.qx, d.qy, path[1], path[2])); + break; + case "Q": + d.qx = path[1]; + d.qy = path[2]; + path = ["C"].concat(q2c(d.x, d.y, path[1], path[2], path[3], path[4])); + break; + case "L": + path = ["C"].concat(l2c(d.x, d.y, path[1], path[2])); + break; + case "H": + path = ["C"].concat(l2c(d.x, d.y, path[1], d.y)); + break; + case "V": + path = ["C"].concat(l2c(d.x, d.y, d.x, path[1])); + break; + case "Z": + path = ["C"].concat(l2c(d.x, d.y, d.X, d.Y)); + break; + } + return path; + }, + fixArc = function(pp, i) { + if (pp[i].length > 7) { + pp[i].shift(); + var pi = pp[i]; + while (pi.length) { + pcoms1[i] = "A"; // if created multiple C:s, their original seg is saved + p2 && (pcoms2[i] = "A"); // the same as above + pp.splice(i++, 0, ["C"].concat(pi.splice(0, 6))); + } + pp.splice(i, 1); + ii = Math.max(p.length, p2 && p2.length || 0); + } + }, + fixM = function(path1, path2, a1, a2, i) { + if (path1 && path2 && path1[i][0] == "M" && path2[i][0] != "M") { + path2.splice(i, 0, ["M", a2.x, a2.y]); + a1.bx = 0; + a1.by = 0; + a1.x = path1[i][1]; + a1.y = path1[i][2]; + ii = Math.max(p.length, p2 && p2.length || 0); + } + }, + pcoms1 = [], // path commands of original path p + pcoms2 = [], // path commands of original path p2 + pfirst = "", // temporary holder for original path command + pcom = ""; // holder for previous path command of original path + for (var i = 0, ii = Math.max(p.length, p2 && p2.length || 0); i < ii; i++) { + p[i] && (pfirst = p[i][0]); // save current path command + + if (pfirst != "C") { // C is not saved yet, because it may be result of conversion + pcoms1[i] = pfirst; // Save current path command + i && (pcom = pcoms1[i - 1]); // Get previous path command pcom + } + p[i] = processPath(p[i], attrs, pcom); // Previous path command is inputted to processPath + + if (pcoms1[i] != "A" && pfirst == "C") pcoms1[i] = "C"; // A is the only command + // which may produce multiple C:s + // so we have to make sure that C is also C in original path + + fixArc(p, i); // fixArc adds also the right amount of A:s to pcoms1 + + if (p2) { // the same procedures is done to p2 + p2[i] && (pfirst = p2[i][0]); + if (pfirst != "C") { + pcoms2[i] = pfirst; + i && (pcom = pcoms2[i - 1]); + } + p2[i] = processPath(p2[i], attrs2, pcom); + + if (pcoms2[i] != "A" && pfirst == "C") { + pcoms2[i] = "C"; + } + + fixArc(p2, i); + } + fixM(p, p2, attrs, attrs2, i); + fixM(p2, p, attrs2, attrs, i); + var seg = p[i], + seg2 = p2 && p2[i], + seglen = seg.length, + seg2len = p2 && seg2.length; + attrs.x = seg[seglen - 2]; + attrs.y = seg[seglen - 1]; + attrs.bx = parseFloat(seg[seglen - 4]) || attrs.x; + attrs.by = parseFloat(seg[seglen - 3]) || attrs.y; + attrs2.bx = p2 && (parseFloat(seg2[seg2len - 4]) || attrs2.x); + attrs2.by = p2 && (parseFloat(seg2[seg2len - 3]) || attrs2.y); + attrs2.x = p2 && seg2[seg2len - 2]; + attrs2.y = p2 && seg2[seg2len - 1]; + } + + return p2 ? [p, p2] : p; +}; + +var p2s = /,?([a-z]),?/gi; +var path2string = function(path) { + return path.join(',').replace(p2s, "$1"); +}; + +var PathUtil = { + toArray: parsePathString, + toString: path2string, + toCurve: path2curve, + toAbsolute: pathToAbsolute, + catmullRomToBezier: catmullRom2bezier +}; + +var index$2 = PathUtil; + +var commonjsGlobal = typeof window !== 'undefined' ? window : typeof global !== 'undefined' ? global : typeof self !== 'undefined' ? self : {}; + + + + + +function createCommonjsModule(fn, module) { + return module = { exports: {} }, fn(module, module.exports), module.exports; +} + +/** Detect free variable `global` from Node.js. */ +var freeGlobal = typeof commonjsGlobal == 'object' && commonjsGlobal && commonjsGlobal.Object === Object && commonjsGlobal; + +var _freeGlobal = freeGlobal; + +/** Detect free variable `self`. */ +var freeSelf = typeof self == 'object' && self && self.Object === Object && self; + +/** Used as a reference to the global object. */ +var root = _freeGlobal || freeSelf || Function('return this')(); + +var _root = root; + +/** Built-in value references. */ +var Symbol = _root.Symbol; + +var _Symbol = Symbol; + +/** Used for built-in method references. */ +var objectProto = Object.prototype; + +/** Used to check objects for own properties. */ +var hasOwnProperty = objectProto.hasOwnProperty; + +/** + * Used to resolve the + * [`toStringTag`](http://ecma-international.org/ecma-262/7.0/#sec-object.prototype.tostring) + * of values. + */ +var nativeObjectToString = objectProto.toString; + +/** Built-in value references. */ +var symToStringTag$1 = _Symbol ? _Symbol.toStringTag : undefined; + +/** + * A specialized version of `baseGetTag` which ignores `Symbol.toStringTag` values. + * + * @private + * @param {*} value The value to query. + * @returns {string} Returns the raw `toStringTag`. + */ +function getRawTag(value) { + var isOwn = hasOwnProperty.call(value, symToStringTag$1), + tag = value[symToStringTag$1]; + + try { + value[symToStringTag$1] = undefined; + var unmasked = true; + } catch (e) {} + + var result = nativeObjectToString.call(value); + if (unmasked) { + if (isOwn) { + value[symToStringTag$1] = tag; + } else { + delete value[symToStringTag$1]; + } + } + return result; +} + +var _getRawTag = getRawTag; + +/** Used for built-in method references. */ +var objectProto$1 = Object.prototype; + +/** + * Used to resolve the + * [`toStringTag`](http://ecma-international.org/ecma-262/7.0/#sec-object.prototype.tostring) + * of values. + */ +var nativeObjectToString$1 = objectProto$1.toString; + +/** + * Converts `value` to a string using `Object.prototype.toString`. + * + * @private + * @param {*} value The value to convert. + * @returns {string} Returns the converted string. + */ +function objectToString(value) { + return nativeObjectToString$1.call(value); +} + +var _objectToString = objectToString; + +/** `Object#toString` result references. */ +var nullTag = '[object Null]'; +var undefinedTag = '[object Undefined]'; + +/** Built-in value references. */ +var symToStringTag = _Symbol ? _Symbol.toStringTag : undefined; + +/** + * The base implementation of `getTag` without fallbacks for buggy environments. + * + * @private + * @param {*} value The value to query. + * @returns {string} Returns the `toStringTag`. + */ +function baseGetTag(value) { + if (value == null) { + return value === undefined ? undefinedTag : nullTag; + } + return (symToStringTag && symToStringTag in Object(value)) + ? _getRawTag(value) + : _objectToString(value); +} + +var _baseGetTag = baseGetTag; + +/** + * Checks if `value` is the + * [language type](http://www.ecma-international.org/ecma-262/7.0/#sec-ecmascript-language-types) + * of `Object`. (e.g. arrays, functions, objects, regexes, `new Number(0)`, and `new String('')`) + * + * @static + * @memberOf _ + * @since 0.1.0 + * @category Lang + * @param {*} value The value to check. + * @returns {boolean} Returns `true` if `value` is an object, else `false`. + * @example + * + * _.isObject({}); + * // => true + * + * _.isObject([1, 2, 3]); + * // => true + * + * _.isObject(_.noop); + * // => true + * + * _.isObject(null); + * // => false + */ +function isObject(value) { + var type = typeof value; + return value != null && (type == 'object' || type == 'function'); +} + +var isObject_1 = isObject; + +/** `Object#toString` result references. */ +var asyncTag = '[object AsyncFunction]'; +var funcTag = '[object Function]'; +var genTag = '[object GeneratorFunction]'; +var proxyTag = '[object Proxy]'; + +/** + * Checks if `value` is classified as a `Function` object. + * + * @static + * @memberOf _ + * @since 0.1.0 + * @category Lang + * @param {*} value The value to check. + * @returns {boolean} Returns `true` if `value` is a function, else `false`. + * @example + * + * _.isFunction(_); + * // => true + * + * _.isFunction(/abc/); + * // => false + */ +function isFunction(value) { + if (!isObject_1(value)) { + return false; + } + // The use of `Object#toString` avoids issues with the `typeof` operator + // in Safari 9 which returns 'object' for typed arrays and other constructors. + var tag = _baseGetTag(value); + return tag == funcTag || tag == genTag || tag == asyncTag || tag == proxyTag; +} + +var isFunction_1 = isFunction; + +/** + * Checks if `value` is object-like. A value is object-like if it's not `null` + * and has a `typeof` result of "object". + * + * @static + * @memberOf _ + * @since 4.0.0 + * @category Lang + * @param {*} value The value to check. + * @returns {boolean} Returns `true` if `value` is object-like, else `false`. + * @example + * + * _.isObjectLike({}); + * // => true + * + * _.isObjectLike([1, 2, 3]); + * // => true + * + * _.isObjectLike(_.noop); + * // => false + * + * _.isObjectLike(null); + * // => false + */ +function isObjectLike(value) { + return value != null && typeof value == 'object'; +} + +var isObjectLike_1 = isObjectLike; + +/** `Object#toString` result references. */ +var boolTag = '[object Boolean]'; + +/** + * Checks if `value` is classified as a boolean primitive or object. + * + * @static + * @memberOf _ + * @since 0.1.0 + * @category Lang + * @param {*} value The value to check. + * @returns {boolean} Returns `true` if `value` is a boolean, else `false`. + * @example + * + * _.isBoolean(false); + * // => true + * + * _.isBoolean(null); + * // => false + */ +function isBoolean(value) { + return value === true || value === false || + (isObjectLike_1(value) && _baseGetTag(value) == boolTag); +} + +var isBoolean_1 = isBoolean; + +/** + * Checks if `value` is `null` or `undefined`. + * + * @static + * @memberOf _ + * @since 4.0.0 + * @category Lang + * @param {*} value The value to check. + * @returns {boolean} Returns `true` if `value` is nullish, else `false`. + * @example + * + * _.isNil(null); + * // => true + * + * _.isNil(void 0); + * // => true + * + * _.isNil(NaN); + * // => false + */ +function isNil(value) { + return value == null; +} + +var isNil_1 = isNil; + +/** + * Checks if `value` is classified as an `Array` object. + * + * @static + * @memberOf _ + * @since 0.1.0 + * @category Lang + * @param {*} value The value to check. + * @returns {boolean} Returns `true` if `value` is an array, else `false`. + * @example + * + * _.isArray([1, 2, 3]); + * // => true + * + * _.isArray(document.body.children); + * // => false + * + * _.isArray('abc'); + * // => false + * + * _.isArray(_.noop); + * // => false + */ +var isArray = Array.isArray; + +var isArray_1 = isArray; + +/** `Object#toString` result references. */ +var stringTag = '[object String]'; + +/** + * Checks if `value` is classified as a `String` primitive or object. + * + * @static + * @since 0.1.0 + * @memberOf _ + * @category Lang + * @param {*} value The value to check. + * @returns {boolean} Returns `true` if `value` is a string, else `false`. + * @example + * + * _.isString('abc'); + * // => true + * + * _.isString(1); + * // => false + */ +function isString(value) { + return typeof value == 'string' || + (!isArray_1(value) && isObjectLike_1(value) && _baseGetTag(value) == stringTag); +} + +var isString_1 = isString; + +/** Used for built-in method references. */ +var objectProto$4 = Object.prototype; + +/** + * Checks if `value` is likely a prototype object. + * + * @private + * @param {*} value The value to check. + * @returns {boolean} Returns `true` if `value` is a prototype, else `false`. + */ +function isPrototype(value) { + var Ctor = value && value.constructor, + proto = (typeof Ctor == 'function' && Ctor.prototype) || objectProto$4; + + return value === proto; +} + +var _isPrototype = isPrototype; + +/** + * Creates a unary function that invokes `func` with its argument transformed. + * + * @private + * @param {Function} func The function to wrap. + * @param {Function} transform The argument transform. + * @returns {Function} Returns the new function. + */ +function overArg(func, transform) { + return function(arg) { + return func(transform(arg)); + }; +} + +var _overArg = overArg; + +/* Built-in method references for those with the same name as other `lodash` methods. */ +var nativeKeys = _overArg(Object.keys, Object); + +var _nativeKeys = nativeKeys; + +/** Used for built-in method references. */ +var objectProto$3 = Object.prototype; + +/** Used to check objects for own properties. */ +var hasOwnProperty$2 = objectProto$3.hasOwnProperty; + +/** + * The base implementation of `_.keys` which doesn't treat sparse arrays as dense. + * + * @private + * @param {Object} object The object to query. + * @returns {Array} Returns the array of property names. + */ +function baseKeys(object) { + if (!_isPrototype(object)) { + return _nativeKeys(object); + } + var result = []; + for (var key in Object(object)) { + if (hasOwnProperty$2.call(object, key) && key != 'constructor') { + result.push(key); + } + } + return result; +} + +var _baseKeys = baseKeys; + +/** Used to detect overreaching core-js shims. */ +var coreJsData = _root['__core-js_shared__']; + +var _coreJsData = coreJsData; + +/** Used to detect methods masquerading as native. */ +var maskSrcKey = (function() { + var uid = /[^.]+$/.exec(_coreJsData && _coreJsData.keys && _coreJsData.keys.IE_PROTO || ''); + return uid ? ('Symbol(src)_1.' + uid) : ''; +}()); + +/** + * Checks if `func` has its source masked. + * + * @private + * @param {Function} func The function to check. + * @returns {boolean} Returns `true` if `func` is masked, else `false`. + */ +function isMasked(func) { + return !!maskSrcKey && (maskSrcKey in func); +} + +var _isMasked = isMasked; + +/** Used for built-in method references. */ +var funcProto$1 = Function.prototype; + +/** Used to resolve the decompiled source of functions. */ +var funcToString$1 = funcProto$1.toString; + +/** + * Converts `func` to its source code. + * + * @private + * @param {Function} func The function to convert. + * @returns {string} Returns the source code. + */ +function toSource(func) { + if (func != null) { + try { + return funcToString$1.call(func); + } catch (e) {} + try { + return (func + ''); + } catch (e) {} + } + return ''; +} + +var _toSource = toSource; + +/** + * Used to match `RegExp` + * [syntax characters](http://ecma-international.org/ecma-262/7.0/#sec-patterns). + */ +var reRegExpChar = /[\\^$.*+?()[\]{}|]/g; + +/** Used to detect host constructors (Safari). */ +var reIsHostCtor = /^\[object .+?Constructor\]$/; + +/** Used for built-in method references. */ +var funcProto = Function.prototype; +var objectProto$5 = Object.prototype; + +/** Used to resolve the decompiled source of functions. */ +var funcToString = funcProto.toString; + +/** Used to check objects for own properties. */ +var hasOwnProperty$3 = objectProto$5.hasOwnProperty; + +/** Used to detect if a method is native. */ +var reIsNative = RegExp('^' + + funcToString.call(hasOwnProperty$3).replace(reRegExpChar, '\\$&') + .replace(/hasOwnProperty|(function).*?(?=\\\()| for .+?(?=\\\])/g, '$1.*?') + '$' +); + +/** + * The base implementation of `_.isNative` without bad shim checks. + * + * @private + * @param {*} value The value to check. + * @returns {boolean} Returns `true` if `value` is a native function, + * else `false`. + */ +function baseIsNative(value) { + if (!isObject_1(value) || _isMasked(value)) { + return false; + } + var pattern = isFunction_1(value) ? reIsNative : reIsHostCtor; + return pattern.test(_toSource(value)); +} + +var _baseIsNative = baseIsNative; + +/** + * Gets the value at `key` of `object`. + * + * @private + * @param {Object} [object] The object to query. + * @param {string} key The key of the property to get. + * @returns {*} Returns the property value. + */ +function getValue(object, key) { + return object == null ? undefined : object[key]; +} + +var _getValue = getValue; + +/** + * Gets the native function at `key` of `object`. + * + * @private + * @param {Object} object The object to query. + * @param {string} key The key of the method to get. + * @returns {*} Returns the function if it's native, else `undefined`. + */ +function getNative(object, key) { + var value = _getValue(object, key); + return _baseIsNative(value) ? value : undefined; +} + +var _getNative = getNative; + +/* Built-in method references that are verified to be native. */ +var DataView = _getNative(_root, 'DataView'); + +var _DataView = DataView; + +/* Built-in method references that are verified to be native. */ +var Map = _getNative(_root, 'Map'); + +var _Map = Map; + +/* Built-in method references that are verified to be native. */ +var Promise = _getNative(_root, 'Promise'); + +var _Promise = Promise; + +/* Built-in method references that are verified to be native. */ +var Set = _getNative(_root, 'Set'); + +var _Set = Set; + +/* Built-in method references that are verified to be native. */ +var WeakMap = _getNative(_root, 'WeakMap'); + +var _WeakMap = WeakMap; + +/** `Object#toString` result references. */ +var mapTag$1 = '[object Map]'; +var objectTag = '[object Object]'; +var promiseTag = '[object Promise]'; +var setTag$1 = '[object Set]'; +var weakMapTag = '[object WeakMap]'; + +var dataViewTag = '[object DataView]'; + +/** Used to detect maps, sets, and weakmaps. */ +var dataViewCtorString = _toSource(_DataView); +var mapCtorString = _toSource(_Map); +var promiseCtorString = _toSource(_Promise); +var setCtorString = _toSource(_Set); +var weakMapCtorString = _toSource(_WeakMap); + +/** + * Gets the `toStringTag` of `value`. + * + * @private + * @param {*} value The value to query. + * @returns {string} Returns the `toStringTag`. + */ +var getTag = _baseGetTag; + +// Fallback for data views, maps, sets, and weak maps in IE 11 and promises in Node.js < 6. +if ((_DataView && getTag(new _DataView(new ArrayBuffer(1))) != dataViewTag) || + (_Map && getTag(new _Map) != mapTag$1) || + (_Promise && getTag(_Promise.resolve()) != promiseTag) || + (_Set && getTag(new _Set) != setTag$1) || + (_WeakMap && getTag(new _WeakMap) != weakMapTag)) { + getTag = function(value) { + var result = _baseGetTag(value), + Ctor = result == objectTag ? value.constructor : undefined, + ctorString = Ctor ? _toSource(Ctor) : ''; + + if (ctorString) { + switch (ctorString) { + case dataViewCtorString: return dataViewTag; + case mapCtorString: return mapTag$1; + case promiseCtorString: return promiseTag; + case setCtorString: return setTag$1; + case weakMapCtorString: return weakMapTag; + } + } + return result; + }; +} + +var _getTag = getTag; + +/** `Object#toString` result references. */ +var argsTag = '[object Arguments]'; + +/** + * The base implementation of `_.isArguments`. + * + * @private + * @param {*} value The value to check. + * @returns {boolean} Returns `true` if `value` is an `arguments` object, + */ +function baseIsArguments(value) { + return isObjectLike_1(value) && _baseGetTag(value) == argsTag; +} + +var _baseIsArguments = baseIsArguments; + +/** Used for built-in method references. */ +var objectProto$6 = Object.prototype; + +/** Used to check objects for own properties. */ +var hasOwnProperty$4 = objectProto$6.hasOwnProperty; + +/** Built-in value references. */ +var propertyIsEnumerable = objectProto$6.propertyIsEnumerable; + +/** + * Checks if `value` is likely an `arguments` object. + * + * @static + * @memberOf _ + * @since 0.1.0 + * @category Lang + * @param {*} value The value to check. + * @returns {boolean} Returns `true` if `value` is an `arguments` object, + * else `false`. + * @example + * + * _.isArguments(function() { return arguments; }()); + * // => true + * + * _.isArguments([1, 2, 3]); + * // => false + */ +var isArguments = _baseIsArguments(function() { return arguments; }()) ? _baseIsArguments : function(value) { + return isObjectLike_1(value) && hasOwnProperty$4.call(value, 'callee') && + !propertyIsEnumerable.call(value, 'callee'); +}; + +var isArguments_1 = isArguments; + +/** Used as references for various `Number` constants. */ +var MAX_SAFE_INTEGER = 9007199254740991; + +/** + * Checks if `value` is a valid array-like length. + * + * **Note:** This method is loosely based on + * [`ToLength`](http://ecma-international.org/ecma-262/7.0/#sec-tolength). + * + * @static + * @memberOf _ + * @since 4.0.0 + * @category Lang + * @param {*} value The value to check. + * @returns {boolean} Returns `true` if `value` is a valid length, else `false`. + * @example + * + * _.isLength(3); + * // => true + * + * _.isLength(Number.MIN_VALUE); + * // => false + * + * _.isLength(Infinity); + * // => false + * + * _.isLength('3'); + * // => false + */ +function isLength(value) { + return typeof value == 'number' && + value > -1 && value % 1 == 0 && value <= MAX_SAFE_INTEGER; +} + +var isLength_1 = isLength; + +/** + * Checks if `value` is array-like. A value is considered array-like if it's + * not a function and has a `value.length` that's an integer greater than or + * equal to `0` and less than or equal to `Number.MAX_SAFE_INTEGER`. + * + * @static + * @memberOf _ + * @since 4.0.0 + * @category Lang + * @param {*} value The value to check. + * @returns {boolean} Returns `true` if `value` is array-like, else `false`. + * @example + * + * _.isArrayLike([1, 2, 3]); + * // => true + * + * _.isArrayLike(document.body.children); + * // => true + * + * _.isArrayLike('abc'); + * // => true + * + * _.isArrayLike(_.noop); + * // => false + */ +function isArrayLike(value) { + return value != null && isLength_1(value.length) && !isFunction_1(value); +} + +var isArrayLike_1 = isArrayLike; + +/** + * This method returns `false`. + * + * @static + * @memberOf _ + * @since 4.13.0 + * @category Util + * @returns {boolean} Returns `false`. + * @example + * + * _.times(2, _.stubFalse); + * // => [false, false] + */ +function stubFalse() { + return false; +} + +var stubFalse_1 = stubFalse; + +var isBuffer_1 = createCommonjsModule(function (module, exports) { +/** Detect free variable `exports`. */ +var freeExports = 'object' == 'object' && exports && !exports.nodeType && exports; + +/** Detect free variable `module`. */ +var freeModule = freeExports && 'object' == 'object' && module && !module.nodeType && module; + +/** Detect the popular CommonJS extension `module.exports`. */ +var moduleExports = freeModule && freeModule.exports === freeExports; + +/** Built-in value references. */ +var Buffer = moduleExports ? _root.Buffer : undefined; + +/* Built-in method references for those with the same name as other `lodash` methods. */ +var nativeIsBuffer = Buffer ? Buffer.isBuffer : undefined; + +/** + * Checks if `value` is a buffer. + * + * @static + * @memberOf _ + * @since 4.3.0 + * @category Lang + * @param {*} value The value to check. + * @returns {boolean} Returns `true` if `value` is a buffer, else `false`. + * @example + * + * _.isBuffer(new Buffer(2)); + * // => true + * + * _.isBuffer(new Uint8Array(2)); + * // => false + */ +var isBuffer = nativeIsBuffer || stubFalse_1; + +module.exports = isBuffer; +}); + +/** `Object#toString` result references. */ +var argsTag$1 = '[object Arguments]'; +var arrayTag = '[object Array]'; +var boolTag$1 = '[object Boolean]'; +var dateTag = '[object Date]'; +var errorTag = '[object Error]'; +var funcTag$1 = '[object Function]'; +var mapTag$2 = '[object Map]'; +var numberTag = '[object Number]'; +var objectTag$1 = '[object Object]'; +var regexpTag = '[object RegExp]'; +var setTag$2 = '[object Set]'; +var stringTag$1 = '[object String]'; +var weakMapTag$1 = '[object WeakMap]'; + +var arrayBufferTag = '[object ArrayBuffer]'; +var dataViewTag$1 = '[object DataView]'; +var float32Tag = '[object Float32Array]'; +var float64Tag = '[object Float64Array]'; +var int8Tag = '[object Int8Array]'; +var int16Tag = '[object Int16Array]'; +var int32Tag = '[object Int32Array]'; +var uint8Tag = '[object Uint8Array]'; +var uint8ClampedTag = '[object Uint8ClampedArray]'; +var uint16Tag = '[object Uint16Array]'; +var uint32Tag = '[object Uint32Array]'; + +/** Used to identify `toStringTag` values of typed arrays. */ +var typedArrayTags = {}; +typedArrayTags[float32Tag] = typedArrayTags[float64Tag] = +typedArrayTags[int8Tag] = typedArrayTags[int16Tag] = +typedArrayTags[int32Tag] = typedArrayTags[uint8Tag] = +typedArrayTags[uint8ClampedTag] = typedArrayTags[uint16Tag] = +typedArrayTags[uint32Tag] = true; +typedArrayTags[argsTag$1] = typedArrayTags[arrayTag] = +typedArrayTags[arrayBufferTag] = typedArrayTags[boolTag$1] = +typedArrayTags[dataViewTag$1] = typedArrayTags[dateTag] = +typedArrayTags[errorTag] = typedArrayTags[funcTag$1] = +typedArrayTags[mapTag$2] = typedArrayTags[numberTag] = +typedArrayTags[objectTag$1] = typedArrayTags[regexpTag] = +typedArrayTags[setTag$2] = typedArrayTags[stringTag$1] = +typedArrayTags[weakMapTag$1] = false; + +/** + * The base implementation of `_.isTypedArray` without Node.js optimizations. + * + * @private + * @param {*} value The value to check. + * @returns {boolean} Returns `true` if `value` is a typed array, else `false`. + */ +function baseIsTypedArray(value) { + return isObjectLike_1(value) && + isLength_1(value.length) && !!typedArrayTags[_baseGetTag(value)]; +} + +var _baseIsTypedArray = baseIsTypedArray; + +/** + * The base implementation of `_.unary` without support for storing metadata. + * + * @private + * @param {Function} func The function to cap arguments for. + * @returns {Function} Returns the new capped function. + */ +function baseUnary(func) { + return function(value) { + return func(value); + }; +} + +var _baseUnary = baseUnary; + +var _nodeUtil = createCommonjsModule(function (module, exports) { +/** Detect free variable `exports`. */ +var freeExports = 'object' == 'object' && exports && !exports.nodeType && exports; + +/** Detect free variable `module`. */ +var freeModule = freeExports && 'object' == 'object' && module && !module.nodeType && module; + +/** Detect the popular CommonJS extension `module.exports`. */ +var moduleExports = freeModule && freeModule.exports === freeExports; + +/** Detect free variable `process` from Node.js. */ +var freeProcess = moduleExports && _freeGlobal.process; + +/** Used to access faster Node.js helpers. */ +var nodeUtil = (function() { + try { + return freeProcess && freeProcess.binding && freeProcess.binding('util'); + } catch (e) {} +}()); + +module.exports = nodeUtil; +}); + +/* Node.js helper references. */ +var nodeIsTypedArray = _nodeUtil && _nodeUtil.isTypedArray; + +/** + * Checks if `value` is classified as a typed array. + * + * @static + * @memberOf _ + * @since 3.0.0 + * @category Lang + * @param {*} value The value to check. + * @returns {boolean} Returns `true` if `value` is a typed array, else `false`. + * @example + * + * _.isTypedArray(new Uint8Array); + * // => true + * + * _.isTypedArray([]); + * // => false + */ +var isTypedArray = nodeIsTypedArray ? _baseUnary(nodeIsTypedArray) : _baseIsTypedArray; + +var isTypedArray_1 = isTypedArray; + +/** `Object#toString` result references. */ +var mapTag = '[object Map]'; +var setTag = '[object Set]'; + +/** Used for built-in method references. */ +var objectProto$2 = Object.prototype; + +/** Used to check objects for own properties. */ +var hasOwnProperty$1 = objectProto$2.hasOwnProperty; + +/** + * Checks if `value` is an empty object, collection, map, or set. + * + * Objects are considered empty if they have no own enumerable string keyed + * properties. + * + * Array-like values such as `arguments` objects, arrays, buffers, strings, or + * jQuery-like collections are considered empty if they have a `length` of `0`. + * Similarly, maps and sets are considered empty if they have a `size` of `0`. + * + * @static + * @memberOf _ + * @since 0.1.0 + * @category Lang + * @param {*} value The value to check. + * @returns {boolean} Returns `true` if `value` is empty, else `false`. + * @example + * + * _.isEmpty(null); + * // => true + * + * _.isEmpty(true); + * // => true + * + * _.isEmpty(1); + * // => true + * + * _.isEmpty([1, 2, 3]); + * // => false + * + * _.isEmpty({ 'a': 1 }); + * // => false + */ +function isEmpty(value) { + if (value == null) { + return true; + } + if (isArrayLike_1(value) && + (isArray_1(value) || typeof value == 'string' || typeof value.splice == 'function' || + isBuffer_1(value) || isTypedArray_1(value) || isArguments_1(value))) { + return !value.length; + } + var tag = _getTag(value); + if (tag == mapTag || tag == setTag) { + return !value.size; + } + if (_isPrototype(value)) { + return !_baseKeys(value).length; + } + for (var key in value) { + if (hasOwnProperty$1.call(value, key)) { + return false; + } + } + return true; +} + +var isEmpty_1 = isEmpty; + +/** + * A specialized version of `_.map` for arrays without support for iteratee + * shorthands. + * + * @private + * @param {Array} [array] The array to iterate over. + * @param {Function} iteratee The function invoked per iteration. + * @returns {Array} Returns the new mapped array. + */ +function arrayMap(array, iteratee) { + var index = -1, + length = array == null ? 0 : array.length, + result = Array(length); + + while (++index < length) { + result[index] = iteratee(array[index], index, array); + } + return result; +} + +var _arrayMap = arrayMap; + +/** `Object#toString` result references. */ +var symbolTag = '[object Symbol]'; + +/** + * Checks if `value` is classified as a `Symbol` primitive or object. + * + * @static + * @memberOf _ + * @since 4.0.0 + * @category Lang + * @param {*} value The value to check. + * @returns {boolean} Returns `true` if `value` is a symbol, else `false`. + * @example + * + * _.isSymbol(Symbol.iterator); + * // => true + * + * _.isSymbol('abc'); + * // => false + */ +function isSymbol(value) { + return typeof value == 'symbol' || + (isObjectLike_1(value) && _baseGetTag(value) == symbolTag); +} + +var isSymbol_1 = isSymbol; + +/** Used as references for various `Number` constants. */ +var INFINITY = 1 / 0; + +/** Used to convert symbols to primitives and strings. */ +var symbolProto = _Symbol ? _Symbol.prototype : undefined; +var symbolToString = symbolProto ? symbolProto.toString : undefined; + +/** + * The base implementation of `_.toString` which doesn't convert nullish + * values to empty strings. + * + * @private + * @param {*} value The value to process. + * @returns {string} Returns the string. + */ +function baseToString(value) { + // Exit early for strings to avoid a performance hit in some environments. + if (typeof value == 'string') { + return value; + } + if (isArray_1(value)) { + // Recursively convert values (susceptible to call stack limits). + return _arrayMap(value, baseToString) + ''; + } + if (isSymbol_1(value)) { + return symbolToString ? symbolToString.call(value) : ''; + } + var result = (value + ''); + return (result == '0' && (1 / value) == -INFINITY) ? '-0' : result; +} + +var _baseToString = baseToString; + +/** + * Converts `value` to a string. An empty string is returned for `null` + * and `undefined` values. The sign of `-0` is preserved. + * + * @static + * @memberOf _ + * @since 4.0.0 + * @category Lang + * @param {*} value The value to convert. + * @returns {string} Returns the converted string. + * @example + * + * _.toString(null); + * // => '' + * + * _.toString(-0); + * // => '-0' + * + * _.toString([1, 2, 3]); + * // => '1,2,3' + */ +function toString$1(value) { + return value == null ? '' : _baseToString(value); +} + +var toString_1 = toString$1; + +/** Used to generate unique IDs. */ +var idCounter = 0; + +/** + * Generates a unique ID. If `prefix` is given, the ID is appended to it. + * + * @static + * @since 0.1.0 + * @memberOf _ + * @category Util + * @param {string} [prefix=''] The value to prefix the ID with. + * @returns {string} Returns the unique ID. + * @example + * + * _.uniqueId('contact_'); + * // => 'contact_104' + * + * _.uniqueId(); + * // => '105' + */ +function uniqueId(prefix) { + var id = ++idCounter; + return toString_1(prefix) + id; +} + +var uniqueId_1 = uniqueId; + +/** + * Removes all key-value entries from the list cache. + * + * @private + * @name clear + * @memberOf ListCache + */ +function listCacheClear() { + this.__data__ = []; + this.size = 0; +} + +var _listCacheClear = listCacheClear; + +/** + * Performs a + * [`SameValueZero`](http://ecma-international.org/ecma-262/7.0/#sec-samevaluezero) + * comparison between two values to determine if they are equivalent. + * + * @static + * @memberOf _ + * @since 4.0.0 + * @category Lang + * @param {*} value The value to compare. + * @param {*} other The other value to compare. + * @returns {boolean} Returns `true` if the values are equivalent, else `false`. + * @example + * + * var object = { 'a': 1 }; + * var other = { 'a': 1 }; + * + * _.eq(object, object); + * // => true + * + * _.eq(object, other); + * // => false + * + * _.eq('a', 'a'); + * // => true + * + * _.eq('a', Object('a')); + * // => false + * + * _.eq(NaN, NaN); + * // => true + */ +function eq(value, other) { + return value === other || (value !== value && other !== other); +} + +var eq_1 = eq; + +/** + * Gets the index at which the `key` is found in `array` of key-value pairs. + * + * @private + * @param {Array} array The array to inspect. + * @param {*} key The key to search for. + * @returns {number} Returns the index of the matched value, else `-1`. + */ +function assocIndexOf(array, key) { + var length = array.length; + while (length--) { + if (eq_1(array[length][0], key)) { + return length; + } + } + return -1; +} + +var _assocIndexOf = assocIndexOf; + +/** Used for built-in method references. */ +var arrayProto = Array.prototype; + +/** Built-in value references. */ +var splice = arrayProto.splice; + +/** + * Removes `key` and its value from the list cache. + * + * @private + * @name delete + * @memberOf ListCache + * @param {string} key The key of the value to remove. + * @returns {boolean} Returns `true` if the entry was removed, else `false`. + */ +function listCacheDelete(key) { + var data = this.__data__, + index = _assocIndexOf(data, key); + + if (index < 0) { + return false; + } + var lastIndex = data.length - 1; + if (index == lastIndex) { + data.pop(); + } else { + splice.call(data, index, 1); + } + --this.size; + return true; +} + +var _listCacheDelete = listCacheDelete; + +/** + * Gets the list cache value for `key`. + * + * @private + * @name get + * @memberOf ListCache + * @param {string} key The key of the value to get. + * @returns {*} Returns the entry value. + */ +function listCacheGet(key) { + var data = this.__data__, + index = _assocIndexOf(data, key); + + return index < 0 ? undefined : data[index][1]; +} + +var _listCacheGet = listCacheGet; + +/** + * Checks if a list cache value for `key` exists. + * + * @private + * @name has + * @memberOf ListCache + * @param {string} key The key of the entry to check. + * @returns {boolean} Returns `true` if an entry for `key` exists, else `false`. + */ +function listCacheHas(key) { + return _assocIndexOf(this.__data__, key) > -1; +} + +var _listCacheHas = listCacheHas; + +/** + * Sets the list cache `key` to `value`. + * + * @private + * @name set + * @memberOf ListCache + * @param {string} key The key of the value to set. + * @param {*} value The value to set. + * @returns {Object} Returns the list cache instance. + */ +function listCacheSet(key, value) { + var data = this.__data__, + index = _assocIndexOf(data, key); + + if (index < 0) { + ++this.size; + data.push([key, value]); + } else { + data[index][1] = value; + } + return this; +} + +var _listCacheSet = listCacheSet; + +/** + * Creates an list cache object. + * + * @private + * @constructor + * @param {Array} [entries] The key-value pairs to cache. + */ +function ListCache(entries) { + var index = -1, + length = entries == null ? 0 : entries.length; + + this.clear(); + while (++index < length) { + var entry = entries[index]; + this.set(entry[0], entry[1]); + } +} + +// Add methods to `ListCache`. +ListCache.prototype.clear = _listCacheClear; +ListCache.prototype['delete'] = _listCacheDelete; +ListCache.prototype.get = _listCacheGet; +ListCache.prototype.has = _listCacheHas; +ListCache.prototype.set = _listCacheSet; + +var _ListCache = ListCache; + +/** + * Removes all key-value entries from the stack. + * + * @private + * @name clear + * @memberOf Stack + */ +function stackClear() { + this.__data__ = new _ListCache; + this.size = 0; +} + +var _stackClear = stackClear; + +/** + * Removes `key` and its value from the stack. + * + * @private + * @name delete + * @memberOf Stack + * @param {string} key The key of the value to remove. + * @returns {boolean} Returns `true` if the entry was removed, else `false`. + */ +function stackDelete(key) { + var data = this.__data__, + result = data['delete'](key); + + this.size = data.size; + return result; +} + +var _stackDelete = stackDelete; + +/** + * Gets the stack value for `key`. + * + * @private + * @name get + * @memberOf Stack + * @param {string} key The key of the value to get. + * @returns {*} Returns the entry value. + */ +function stackGet(key) { + return this.__data__.get(key); +} + +var _stackGet = stackGet; + +/** + * Checks if a stack value for `key` exists. + * + * @private + * @name has + * @memberOf Stack + * @param {string} key The key of the entry to check. + * @returns {boolean} Returns `true` if an entry for `key` exists, else `false`. + */ +function stackHas(key) { + return this.__data__.has(key); +} + +var _stackHas = stackHas; + +/* Built-in method references that are verified to be native. */ +var nativeCreate = _getNative(Object, 'create'); + +var _nativeCreate = nativeCreate; + +/** + * Removes all key-value entries from the hash. + * + * @private + * @name clear + * @memberOf Hash + */ +function hashClear() { + this.__data__ = _nativeCreate ? _nativeCreate(null) : {}; + this.size = 0; +} + +var _hashClear = hashClear; + +/** + * Removes `key` and its value from the hash. + * + * @private + * @name delete + * @memberOf Hash + * @param {Object} hash The hash to modify. + * @param {string} key The key of the value to remove. + * @returns {boolean} Returns `true` if the entry was removed, else `false`. + */ +function hashDelete(key) { + var result = this.has(key) && delete this.__data__[key]; + this.size -= result ? 1 : 0; + return result; +} + +var _hashDelete = hashDelete; + +/** Used to stand-in for `undefined` hash values. */ +var HASH_UNDEFINED = '__lodash_hash_undefined__'; + +/** Used for built-in method references. */ +var objectProto$7 = Object.prototype; + +/** Used to check objects for own properties. */ +var hasOwnProperty$5 = objectProto$7.hasOwnProperty; + +/** + * Gets the hash value for `key`. + * + * @private + * @name get + * @memberOf Hash + * @param {string} key The key of the value to get. + * @returns {*} Returns the entry value. + */ +function hashGet(key) { + var data = this.__data__; + if (_nativeCreate) { + var result = data[key]; + return result === HASH_UNDEFINED ? undefined : result; + } + return hasOwnProperty$5.call(data, key) ? data[key] : undefined; +} + +var _hashGet = hashGet; + +/** Used for built-in method references. */ +var objectProto$8 = Object.prototype; + +/** Used to check objects for own properties. */ +var hasOwnProperty$6 = objectProto$8.hasOwnProperty; + +/** + * Checks if a hash value for `key` exists. + * + * @private + * @name has + * @memberOf Hash + * @param {string} key The key of the entry to check. + * @returns {boolean} Returns `true` if an entry for `key` exists, else `false`. + */ +function hashHas(key) { + var data = this.__data__; + return _nativeCreate ? (data[key] !== undefined) : hasOwnProperty$6.call(data, key); +} + +var _hashHas = hashHas; + +/** Used to stand-in for `undefined` hash values. */ +var HASH_UNDEFINED$1 = '__lodash_hash_undefined__'; + +/** + * Sets the hash `key` to `value`. + * + * @private + * @name set + * @memberOf Hash + * @param {string} key The key of the value to set. + * @param {*} value The value to set. + * @returns {Object} Returns the hash instance. + */ +function hashSet(key, value) { + var data = this.__data__; + this.size += this.has(key) ? 0 : 1; + data[key] = (_nativeCreate && value === undefined) ? HASH_UNDEFINED$1 : value; + return this; +} + +var _hashSet = hashSet; + +/** + * Creates a hash object. + * + * @private + * @constructor + * @param {Array} [entries] The key-value pairs to cache. + */ +function Hash(entries) { + var index = -1, + length = entries == null ? 0 : entries.length; + + this.clear(); + while (++index < length) { + var entry = entries[index]; + this.set(entry[0], entry[1]); + } +} + +// Add methods to `Hash`. +Hash.prototype.clear = _hashClear; +Hash.prototype['delete'] = _hashDelete; +Hash.prototype.get = _hashGet; +Hash.prototype.has = _hashHas; +Hash.prototype.set = _hashSet; + +var _Hash = Hash; + +/** + * Removes all key-value entries from the map. + * + * @private + * @name clear + * @memberOf MapCache + */ +function mapCacheClear() { + this.size = 0; + this.__data__ = { + 'hash': new _Hash, + 'map': new (_Map || _ListCache), + 'string': new _Hash + }; +} + +var _mapCacheClear = mapCacheClear; + +/** + * Checks if `value` is suitable for use as unique object key. + * + * @private + * @param {*} value The value to check. + * @returns {boolean} Returns `true` if `value` is suitable, else `false`. + */ +function isKeyable(value) { + var type = typeof value; + return (type == 'string' || type == 'number' || type == 'symbol' || type == 'boolean') + ? (value !== '__proto__') + : (value === null); +} + +var _isKeyable = isKeyable; + +/** + * Gets the data for `map`. + * + * @private + * @param {Object} map The map to query. + * @param {string} key The reference key. + * @returns {*} Returns the map data. + */ +function getMapData(map, key) { + var data = map.__data__; + return _isKeyable(key) + ? data[typeof key == 'string' ? 'string' : 'hash'] + : data.map; +} + +var _getMapData = getMapData; + +/** + * Removes `key` and its value from the map. + * + * @private + * @name delete + * @memberOf MapCache + * @param {string} key The key of the value to remove. + * @returns {boolean} Returns `true` if the entry was removed, else `false`. + */ +function mapCacheDelete(key) { + var result = _getMapData(this, key)['delete'](key); + this.size -= result ? 1 : 0; + return result; +} + +var _mapCacheDelete = mapCacheDelete; + +/** + * Gets the map value for `key`. + * + * @private + * @name get + * @memberOf MapCache + * @param {string} key The key of the value to get. + * @returns {*} Returns the entry value. + */ +function mapCacheGet(key) { + return _getMapData(this, key).get(key); +} + +var _mapCacheGet = mapCacheGet; + +/** + * Checks if a map value for `key` exists. + * + * @private + * @name has + * @memberOf MapCache + * @param {string} key The key of the entry to check. + * @returns {boolean} Returns `true` if an entry for `key` exists, else `false`. + */ +function mapCacheHas(key) { + return _getMapData(this, key).has(key); +} + +var _mapCacheHas = mapCacheHas; + +/** + * Sets the map `key` to `value`. + * + * @private + * @name set + * @memberOf MapCache + * @param {string} key The key of the value to set. + * @param {*} value The value to set. + * @returns {Object} Returns the map cache instance. + */ +function mapCacheSet(key, value) { + var data = _getMapData(this, key), + size = data.size; + + data.set(key, value); + this.size += data.size == size ? 0 : 1; + return this; +} + +var _mapCacheSet = mapCacheSet; + +/** + * Creates a map cache object to store key-value pairs. + * + * @private + * @constructor + * @param {Array} [entries] The key-value pairs to cache. + */ +function MapCache(entries) { + var index = -1, + length = entries == null ? 0 : entries.length; + + this.clear(); + while (++index < length) { + var entry = entries[index]; + this.set(entry[0], entry[1]); + } +} + +// Add methods to `MapCache`. +MapCache.prototype.clear = _mapCacheClear; +MapCache.prototype['delete'] = _mapCacheDelete; +MapCache.prototype.get = _mapCacheGet; +MapCache.prototype.has = _mapCacheHas; +MapCache.prototype.set = _mapCacheSet; + +var _MapCache = MapCache; + +/** Used as the size to enable large array optimizations. */ +var LARGE_ARRAY_SIZE = 200; + +/** + * Sets the stack `key` to `value`. + * + * @private + * @name set + * @memberOf Stack + * @param {string} key The key of the value to set. + * @param {*} value The value to set. + * @returns {Object} Returns the stack cache instance. + */ +function stackSet(key, value) { + var data = this.__data__; + if (data instanceof _ListCache) { + var pairs = data.__data__; + if (!_Map || (pairs.length < LARGE_ARRAY_SIZE - 1)) { + pairs.push([key, value]); + this.size = ++data.size; + return this; + } + data = this.__data__ = new _MapCache(pairs); + } + data.set(key, value); + this.size = data.size; + return this; +} + +var _stackSet = stackSet; + +/** + * Creates a stack cache object to store key-value pairs. + * + * @private + * @constructor + * @param {Array} [entries] The key-value pairs to cache. + */ +function Stack(entries) { + var data = this.__data__ = new _ListCache(entries); + this.size = data.size; +} + +// Add methods to `Stack`. +Stack.prototype.clear = _stackClear; +Stack.prototype['delete'] = _stackDelete; +Stack.prototype.get = _stackGet; +Stack.prototype.has = _stackHas; +Stack.prototype.set = _stackSet; + +var _Stack = Stack; + +/** + * A specialized version of `_.forEach` for arrays without support for + * iteratee shorthands. + * + * @private + * @param {Array} [array] The array to iterate over. + * @param {Function} iteratee The function invoked per iteration. + * @returns {Array} Returns `array`. + */ +function arrayEach(array, iteratee) { + var index = -1, + length = array == null ? 0 : array.length; + + while (++index < length) { + if (iteratee(array[index], index, array) === false) { + break; + } + } + return array; +} + +var _arrayEach = arrayEach; + +var defineProperty = (function() { + try { + var func = _getNative(Object, 'defineProperty'); + func({}, '', {}); + return func; + } catch (e) {} +}()); + +var _defineProperty = defineProperty; + +/** + * The base implementation of `assignValue` and `assignMergeValue` without + * value checks. + * + * @private + * @param {Object} object The object to modify. + * @param {string} key The key of the property to assign. + * @param {*} value The value to assign. + */ +function baseAssignValue(object, key, value) { + if (key == '__proto__' && _defineProperty) { + _defineProperty(object, key, { + 'configurable': true, + 'enumerable': true, + 'value': value, + 'writable': true + }); + } else { + object[key] = value; + } +} + +var _baseAssignValue = baseAssignValue; + +/** Used for built-in method references. */ +var objectProto$9 = Object.prototype; + +/** Used to check objects for own properties. */ +var hasOwnProperty$7 = objectProto$9.hasOwnProperty; + +/** + * Assigns `value` to `key` of `object` if the existing value is not equivalent + * using [`SameValueZero`](http://ecma-international.org/ecma-262/7.0/#sec-samevaluezero) + * for equality comparisons. + * + * @private + * @param {Object} object The object to modify. + * @param {string} key The key of the property to assign. + * @param {*} value The value to assign. + */ +function assignValue(object, key, value) { + var objValue = object[key]; + if (!(hasOwnProperty$7.call(object, key) && eq_1(objValue, value)) || + (value === undefined && !(key in object))) { + _baseAssignValue(object, key, value); + } +} + +var _assignValue = assignValue; + +/** + * Copies properties of `source` to `object`. + * + * @private + * @param {Object} source The object to copy properties from. + * @param {Array} props The property identifiers to copy. + * @param {Object} [object={}] The object to copy properties to. + * @param {Function} [customizer] The function to customize copied values. + * @returns {Object} Returns `object`. + */ +function copyObject(source, props, object, customizer) { + var isNew = !object; + object || (object = {}); + + var index = -1, + length = props.length; + + while (++index < length) { + var key = props[index]; + + var newValue = customizer + ? customizer(object[key], source[key], key, object, source) + : undefined; + + if (newValue === undefined) { + newValue = source[key]; + } + if (isNew) { + _baseAssignValue(object, key, newValue); + } else { + _assignValue(object, key, newValue); + } + } + return object; +} + +var _copyObject = copyObject; + +/** + * The base implementation of `_.times` without support for iteratee shorthands + * or max array length checks. + * + * @private + * @param {number} n The number of times to invoke `iteratee`. + * @param {Function} iteratee The function invoked per iteration. + * @returns {Array} Returns the array of results. + */ +function baseTimes(n, iteratee) { + var index = -1, + result = Array(n); + + while (++index < n) { + result[index] = iteratee(index); + } + return result; +} + +var _baseTimes = baseTimes; + +/** Used as references for various `Number` constants. */ +var MAX_SAFE_INTEGER$1 = 9007199254740991; + +/** Used to detect unsigned integer values. */ +var reIsUint = /^(?:0|[1-9]\d*)$/; + +/** + * Checks if `value` is a valid array-like index. + * + * @private + * @param {*} value The value to check. + * @param {number} [length=MAX_SAFE_INTEGER] The upper bounds of a valid index. + * @returns {boolean} Returns `true` if `value` is a valid index, else `false`. + */ +function isIndex(value, length) { + length = length == null ? MAX_SAFE_INTEGER$1 : length; + return !!length && + (typeof value == 'number' || reIsUint.test(value)) && + (value > -1 && value % 1 == 0 && value < length); +} + +var _isIndex = isIndex; + +/** Used for built-in method references. */ +var objectProto$10 = Object.prototype; + +/** Used to check objects for own properties. */ +var hasOwnProperty$8 = objectProto$10.hasOwnProperty; + +/** + * Creates an array of the enumerable property names of the array-like `value`. + * + * @private + * @param {*} value The value to query. + * @param {boolean} inherited Specify returning inherited property names. + * @returns {Array} Returns the array of property names. + */ +function arrayLikeKeys(value, inherited) { + var isArr = isArray_1(value), + isArg = !isArr && isArguments_1(value), + isBuff = !isArr && !isArg && isBuffer_1(value), + isType = !isArr && !isArg && !isBuff && isTypedArray_1(value), + skipIndexes = isArr || isArg || isBuff || isType, + result = skipIndexes ? _baseTimes(value.length, String) : [], + length = result.length; + + for (var key in value) { + if ((inherited || hasOwnProperty$8.call(value, key)) && + !(skipIndexes && ( + // Safari 9 has enumerable `arguments.length` in strict mode. + key == 'length' || + // Node.js 0.10 has enumerable non-index properties on buffers. + (isBuff && (key == 'offset' || key == 'parent')) || + // PhantomJS 2 has enumerable non-index properties on typed arrays. + (isType && (key == 'buffer' || key == 'byteLength' || key == 'byteOffset')) || + // Skip index properties. + _isIndex(key, length) + ))) { + result.push(key); + } + } + return result; +} + +var _arrayLikeKeys = arrayLikeKeys; + +/** + * Creates an array of the own enumerable property names of `object`. + * + * **Note:** Non-object values are coerced to objects. See the + * [ES spec](http://ecma-international.org/ecma-262/7.0/#sec-object.keys) + * for more details. + * + * @static + * @since 0.1.0 + * @memberOf _ + * @category Object + * @param {Object} object The object to query. + * @returns {Array} Returns the array of property names. + * @example + * + * function Foo() { + * this.a = 1; + * this.b = 2; + * } + * + * Foo.prototype.c = 3; + * + * _.keys(new Foo); + * // => ['a', 'b'] (iteration order is not guaranteed) + * + * _.keys('hi'); + * // => ['0', '1'] + */ +function keys(object) { + return isArrayLike_1(object) ? _arrayLikeKeys(object) : _baseKeys(object); +} + +var keys_1 = keys; + +/** + * The base implementation of `_.assign` without support for multiple sources + * or `customizer` functions. + * + * @private + * @param {Object} object The destination object. + * @param {Object} source The source object. + * @returns {Object} Returns `object`. + */ +function baseAssign(object, source) { + return object && _copyObject(source, keys_1(source), object); +} + +var _baseAssign = baseAssign; + +/** + * This function is like + * [`Object.keys`](http://ecma-international.org/ecma-262/7.0/#sec-object.keys) + * except that it includes inherited enumerable properties. + * + * @private + * @param {Object} object The object to query. + * @returns {Array} Returns the array of property names. + */ +function nativeKeysIn(object) { + var result = []; + if (object != null) { + for (var key in Object(object)) { + result.push(key); + } + } + return result; +} + +var _nativeKeysIn = nativeKeysIn; + +/** Used for built-in method references. */ +var objectProto$11 = Object.prototype; + +/** Used to check objects for own properties. */ +var hasOwnProperty$9 = objectProto$11.hasOwnProperty; + +/** + * The base implementation of `_.keysIn` which doesn't treat sparse arrays as dense. + * + * @private + * @param {Object} object The object to query. + * @returns {Array} Returns the array of property names. + */ +function baseKeysIn(object) { + if (!isObject_1(object)) { + return _nativeKeysIn(object); + } + var isProto = _isPrototype(object), + result = []; + + for (var key in object) { + if (!(key == 'constructor' && (isProto || !hasOwnProperty$9.call(object, key)))) { + result.push(key); + } + } + return result; +} + +var _baseKeysIn = baseKeysIn; + +/** + * Creates an array of the own and inherited enumerable property names of `object`. + * + * **Note:** Non-object values are coerced to objects. + * + * @static + * @memberOf _ + * @since 3.0.0 + * @category Object + * @param {Object} object The object to query. + * @returns {Array} Returns the array of property names. + * @example + * + * function Foo() { + * this.a = 1; + * this.b = 2; + * } + * + * Foo.prototype.c = 3; + * + * _.keysIn(new Foo); + * // => ['a', 'b', 'c'] (iteration order is not guaranteed) + */ +function keysIn$1(object) { + return isArrayLike_1(object) ? _arrayLikeKeys(object, true) : _baseKeysIn(object); +} + +var keysIn_1 = keysIn$1; + +/** + * The base implementation of `_.assignIn` without support for multiple sources + * or `customizer` functions. + * + * @private + * @param {Object} object The destination object. + * @param {Object} source The source object. + * @returns {Object} Returns `object`. + */ +function baseAssignIn(object, source) { + return object && _copyObject(source, keysIn_1(source), object); +} + +var _baseAssignIn = baseAssignIn; + +var _cloneBuffer = createCommonjsModule(function (module, exports) { +/** Detect free variable `exports`. */ +var freeExports = 'object' == 'object' && exports && !exports.nodeType && exports; + +/** Detect free variable `module`. */ +var freeModule = freeExports && 'object' == 'object' && module && !module.nodeType && module; + +/** Detect the popular CommonJS extension `module.exports`. */ +var moduleExports = freeModule && freeModule.exports === freeExports; + +/** Built-in value references. */ +var Buffer = moduleExports ? _root.Buffer : undefined, + allocUnsafe = Buffer ? Buffer.allocUnsafe : undefined; + +/** + * Creates a clone of `buffer`. + * + * @private + * @param {Buffer} buffer The buffer to clone. + * @param {boolean} [isDeep] Specify a deep clone. + * @returns {Buffer} Returns the cloned buffer. + */ +function cloneBuffer(buffer, isDeep) { + if (isDeep) { + return buffer.slice(); + } + var length = buffer.length, + result = allocUnsafe ? allocUnsafe(length) : new buffer.constructor(length); + + buffer.copy(result); + return result; +} + +module.exports = cloneBuffer; +}); + +/** + * Copies the values of `source` to `array`. + * + * @private + * @param {Array} source The array to copy values from. + * @param {Array} [array=[]] The array to copy values to. + * @returns {Array} Returns `array`. + */ +function copyArray(source, array) { + var index = -1, + length = source.length; + + array || (array = Array(length)); + while (++index < length) { + array[index] = source[index]; + } + return array; +} + +var _copyArray = copyArray; + +/** + * A specialized version of `_.filter` for arrays without support for + * iteratee shorthands. + * + * @private + * @param {Array} [array] The array to iterate over. + * @param {Function} predicate The function invoked per iteration. + * @returns {Array} Returns the new filtered array. + */ +function arrayFilter(array, predicate) { + var index = -1, + length = array == null ? 0 : array.length, + resIndex = 0, + result = []; + + while (++index < length) { + var value = array[index]; + if (predicate(value, index, array)) { + result[resIndex++] = value; + } + } + return result; +} + +var _arrayFilter = arrayFilter; + +/** + * This method returns a new empty array. + * + * @static + * @memberOf _ + * @since 4.13.0 + * @category Util + * @returns {Array} Returns the new empty array. + * @example + * + * var arrays = _.times(2, _.stubArray); + * + * console.log(arrays); + * // => [[], []] + * + * console.log(arrays[0] === arrays[1]); + * // => false + */ +function stubArray() { + return []; +} + +var stubArray_1 = stubArray; + +/** Used for built-in method references. */ +var objectProto$12 = Object.prototype; + +/** Built-in value references. */ +var propertyIsEnumerable$1 = objectProto$12.propertyIsEnumerable; + +/* Built-in method references for those with the same name as other `lodash` methods. */ +var nativeGetSymbols = Object.getOwnPropertySymbols; + +/** + * Creates an array of the own enumerable symbols of `object`. + * + * @private + * @param {Object} object The object to query. + * @returns {Array} Returns the array of symbols. + */ +var getSymbols = !nativeGetSymbols ? stubArray_1 : function(object) { + if (object == null) { + return []; + } + object = Object(object); + return _arrayFilter(nativeGetSymbols(object), function(symbol) { + return propertyIsEnumerable$1.call(object, symbol); + }); +}; + +var _getSymbols = getSymbols; + +/** + * Copies own symbols of `source` to `object`. + * + * @private + * @param {Object} source The object to copy symbols from. + * @param {Object} [object={}] The object to copy symbols to. + * @returns {Object} Returns `object`. + */ +function copySymbols(source, object) { + return _copyObject(source, _getSymbols(source), object); +} + +var _copySymbols = copySymbols; + +/** + * Appends the elements of `values` to `array`. + * + * @private + * @param {Array} array The array to modify. + * @param {Array} values The values to append. + * @returns {Array} Returns `array`. + */ +function arrayPush(array, values) { + var index = -1, + length = values.length, + offset = array.length; + + while (++index < length) { + array[offset + index] = values[index]; + } + return array; +} + +var _arrayPush = arrayPush; + +/** Built-in value references. */ +var getPrototype = _overArg(Object.getPrototypeOf, Object); + +var _getPrototype = getPrototype; + +/* Built-in method references for those with the same name as other `lodash` methods. */ +var nativeGetSymbols$1 = Object.getOwnPropertySymbols; + +/** + * Creates an array of the own and inherited enumerable symbols of `object`. + * + * @private + * @param {Object} object The object to query. + * @returns {Array} Returns the array of symbols. + */ +var getSymbolsIn = !nativeGetSymbols$1 ? stubArray_1 : function(object) { + var result = []; + while (object) { + _arrayPush(result, _getSymbols(object)); + object = _getPrototype(object); + } + return result; +}; + +var _getSymbolsIn = getSymbolsIn; + +/** + * Copies own and inherited symbols of `source` to `object`. + * + * @private + * @param {Object} source The object to copy symbols from. + * @param {Object} [object={}] The object to copy symbols to. + * @returns {Object} Returns `object`. + */ +function copySymbolsIn(source, object) { + return _copyObject(source, _getSymbolsIn(source), object); +} + +var _copySymbolsIn = copySymbolsIn; + +/** + * The base implementation of `getAllKeys` and `getAllKeysIn` which uses + * `keysFunc` and `symbolsFunc` to get the enumerable property names and + * symbols of `object`. + * + * @private + * @param {Object} object The object to query. + * @param {Function} keysFunc The function to get the keys of `object`. + * @param {Function} symbolsFunc The function to get the symbols of `object`. + * @returns {Array} Returns the array of property names and symbols. + */ +function baseGetAllKeys(object, keysFunc, symbolsFunc) { + var result = keysFunc(object); + return isArray_1(object) ? result : _arrayPush(result, symbolsFunc(object)); +} + +var _baseGetAllKeys = baseGetAllKeys; + +/** + * Creates an array of own enumerable property names and symbols of `object`. + * + * @private + * @param {Object} object The object to query. + * @returns {Array} Returns the array of property names and symbols. + */ +function getAllKeys(object) { + return _baseGetAllKeys(object, keys_1, _getSymbols); +} + +var _getAllKeys = getAllKeys; + +/** + * Creates an array of own and inherited enumerable property names and + * symbols of `object`. + * + * @private + * @param {Object} object The object to query. + * @returns {Array} Returns the array of property names and symbols. + */ +function getAllKeysIn(object) { + return _baseGetAllKeys(object, keysIn_1, _getSymbolsIn); +} + +var _getAllKeysIn = getAllKeysIn; + +/** Used for built-in method references. */ +var objectProto$13 = Object.prototype; + +/** Used to check objects for own properties. */ +var hasOwnProperty$10 = objectProto$13.hasOwnProperty; + +/** + * Initializes an array clone. + * + * @private + * @param {Array} array The array to clone. + * @returns {Array} Returns the initialized clone. + */ +function initCloneArray(array) { + var length = array.length, + result = array.constructor(length); + + // Add properties assigned by `RegExp#exec`. + if (length && typeof array[0] == 'string' && hasOwnProperty$10.call(array, 'index')) { + result.index = array.index; + result.input = array.input; + } + return result; +} + +var _initCloneArray = initCloneArray; + +/** Built-in value references. */ +var Uint8Array = _root.Uint8Array; + +var _Uint8Array = Uint8Array; + +/** + * Creates a clone of `arrayBuffer`. + * + * @private + * @param {ArrayBuffer} arrayBuffer The array buffer to clone. + * @returns {ArrayBuffer} Returns the cloned array buffer. + */ +function cloneArrayBuffer(arrayBuffer) { + var result = new arrayBuffer.constructor(arrayBuffer.byteLength); + new _Uint8Array(result).set(new _Uint8Array(arrayBuffer)); + return result; +} + +var _cloneArrayBuffer = cloneArrayBuffer; + +/** + * Creates a clone of `dataView`. + * + * @private + * @param {Object} dataView The data view to clone. + * @param {boolean} [isDeep] Specify a deep clone. + * @returns {Object} Returns the cloned data view. + */ +function cloneDataView(dataView, isDeep) { + var buffer = isDeep ? _cloneArrayBuffer(dataView.buffer) : dataView.buffer; + return new dataView.constructor(buffer, dataView.byteOffset, dataView.byteLength); +} + +var _cloneDataView = cloneDataView; + +/** + * Adds the key-value `pair` to `map`. + * + * @private + * @param {Object} map The map to modify. + * @param {Array} pair The key-value pair to add. + * @returns {Object} Returns `map`. + */ +function addMapEntry(map, pair) { + // Don't return `map.set` because it's not chainable in IE 11. + map.set(pair[0], pair[1]); + return map; +} + +var _addMapEntry = addMapEntry; + +/** + * A specialized version of `_.reduce` for arrays without support for + * iteratee shorthands. + * + * @private + * @param {Array} [array] The array to iterate over. + * @param {Function} iteratee The function invoked per iteration. + * @param {*} [accumulator] The initial value. + * @param {boolean} [initAccum] Specify using the first element of `array` as + * the initial value. + * @returns {*} Returns the accumulated value. + */ +function arrayReduce(array, iteratee, accumulator, initAccum) { + var index = -1, + length = array == null ? 0 : array.length; + + if (initAccum && length) { + accumulator = array[++index]; + } + while (++index < length) { + accumulator = iteratee(accumulator, array[index], index, array); + } + return accumulator; +} + +var _arrayReduce = arrayReduce; + +/** + * Converts `map` to its key-value pairs. + * + * @private + * @param {Object} map The map to convert. + * @returns {Array} Returns the key-value pairs. + */ +function mapToArray(map) { + var index = -1, + result = Array(map.size); + + map.forEach(function(value, key) { + result[++index] = [key, value]; + }); + return result; +} + +var _mapToArray = mapToArray; + +/** Used to compose bitmasks for cloning. */ +var CLONE_DEEP_FLAG$1 = 1; + +/** + * Creates a clone of `map`. + * + * @private + * @param {Object} map The map to clone. + * @param {Function} cloneFunc The function to clone values. + * @param {boolean} [isDeep] Specify a deep clone. + * @returns {Object} Returns the cloned map. + */ +function cloneMap(map, isDeep, cloneFunc) { + var array = isDeep ? cloneFunc(_mapToArray(map), CLONE_DEEP_FLAG$1) : _mapToArray(map); + return _arrayReduce(array, _addMapEntry, new map.constructor); +} + +var _cloneMap = cloneMap; + +/** Used to match `RegExp` flags from their coerced string values. */ +var reFlags = /\w*$/; + +/** + * Creates a clone of `regexp`. + * + * @private + * @param {Object} regexp The regexp to clone. + * @returns {Object} Returns the cloned regexp. + */ +function cloneRegExp(regexp) { + var result = new regexp.constructor(regexp.source, reFlags.exec(regexp)); + result.lastIndex = regexp.lastIndex; + return result; +} + +var _cloneRegExp = cloneRegExp; + +/** + * Adds `value` to `set`. + * + * @private + * @param {Object} set The set to modify. + * @param {*} value The value to add. + * @returns {Object} Returns `set`. + */ +function addSetEntry(set, value) { + // Don't return `set.add` because it's not chainable in IE 11. + set.add(value); + return set; +} + +var _addSetEntry = addSetEntry; + +/** + * Converts `set` to an array of its values. + * + * @private + * @param {Object} set The set to convert. + * @returns {Array} Returns the values. + */ +function setToArray(set) { + var index = -1, + result = Array(set.size); + + set.forEach(function(value) { + result[++index] = value; + }); + return result; +} + +var _setToArray = setToArray; + +/** Used to compose bitmasks for cloning. */ +var CLONE_DEEP_FLAG$2 = 1; + +/** + * Creates a clone of `set`. + * + * @private + * @param {Object} set The set to clone. + * @param {Function} cloneFunc The function to clone values. + * @param {boolean} [isDeep] Specify a deep clone. + * @returns {Object} Returns the cloned set. + */ +function cloneSet(set, isDeep, cloneFunc) { + var array = isDeep ? cloneFunc(_setToArray(set), CLONE_DEEP_FLAG$2) : _setToArray(set); + return _arrayReduce(array, _addSetEntry, new set.constructor); +} + +var _cloneSet = cloneSet; + +/** Used to convert symbols to primitives and strings. */ +var symbolProto$1 = _Symbol ? _Symbol.prototype : undefined; +var symbolValueOf = symbolProto$1 ? symbolProto$1.valueOf : undefined; + +/** + * Creates a clone of the `symbol` object. + * + * @private + * @param {Object} symbol The symbol object to clone. + * @returns {Object} Returns the cloned symbol object. + */ +function cloneSymbol(symbol) { + return symbolValueOf ? Object(symbolValueOf.call(symbol)) : {}; +} + +var _cloneSymbol = cloneSymbol; + +/** + * Creates a clone of `typedArray`. + * + * @private + * @param {Object} typedArray The typed array to clone. + * @param {boolean} [isDeep] Specify a deep clone. + * @returns {Object} Returns the cloned typed array. + */ +function cloneTypedArray(typedArray, isDeep) { + var buffer = isDeep ? _cloneArrayBuffer(typedArray.buffer) : typedArray.buffer; + return new typedArray.constructor(buffer, typedArray.byteOffset, typedArray.length); +} + +var _cloneTypedArray = cloneTypedArray; + +/** `Object#toString` result references. */ +var boolTag$3 = '[object Boolean]'; +var dateTag$2 = '[object Date]'; +var mapTag$4 = '[object Map]'; +var numberTag$2 = '[object Number]'; +var regexpTag$2 = '[object RegExp]'; +var setTag$4 = '[object Set]'; +var stringTag$3 = '[object String]'; +var symbolTag$2 = '[object Symbol]'; + +var arrayBufferTag$2 = '[object ArrayBuffer]'; +var dataViewTag$3 = '[object DataView]'; +var float32Tag$2 = '[object Float32Array]'; +var float64Tag$2 = '[object Float64Array]'; +var int8Tag$2 = '[object Int8Array]'; +var int16Tag$2 = '[object Int16Array]'; +var int32Tag$2 = '[object Int32Array]'; +var uint8Tag$2 = '[object Uint8Array]'; +var uint8ClampedTag$2 = '[object Uint8ClampedArray]'; +var uint16Tag$2 = '[object Uint16Array]'; +var uint32Tag$2 = '[object Uint32Array]'; + +/** + * Initializes an object clone based on its `toStringTag`. + * + * **Note:** This function only supports cloning values with tags of + * `Boolean`, `Date`, `Error`, `Number`, `RegExp`, or `String`. + * + * @private + * @param {Object} object The object to clone. + * @param {string} tag The `toStringTag` of the object to clone. + * @param {Function} cloneFunc The function to clone values. + * @param {boolean} [isDeep] Specify a deep clone. + * @returns {Object} Returns the initialized clone. + */ +function initCloneByTag(object, tag, cloneFunc, isDeep) { + var Ctor = object.constructor; + switch (tag) { + case arrayBufferTag$2: + return _cloneArrayBuffer(object); + + case boolTag$3: + case dateTag$2: + return new Ctor(+object); + + case dataViewTag$3: + return _cloneDataView(object, isDeep); + + case float32Tag$2: case float64Tag$2: + case int8Tag$2: case int16Tag$2: case int32Tag$2: + case uint8Tag$2: case uint8ClampedTag$2: case uint16Tag$2: case uint32Tag$2: + return _cloneTypedArray(object, isDeep); + + case mapTag$4: + return _cloneMap(object, isDeep, cloneFunc); + + case numberTag$2: + case stringTag$3: + return new Ctor(object); + + case regexpTag$2: + return _cloneRegExp(object); + + case setTag$4: + return _cloneSet(object, isDeep, cloneFunc); + + case symbolTag$2: + return _cloneSymbol(object); + } +} + +var _initCloneByTag = initCloneByTag; + +/** Built-in value references. */ +var objectCreate = Object.create; + +/** + * The base implementation of `_.create` without support for assigning + * properties to the created object. + * + * @private + * @param {Object} proto The object to inherit from. + * @returns {Object} Returns the new object. + */ +var baseCreate = (function() { + function object() {} + return function(proto) { + if (!isObject_1(proto)) { + return {}; + } + if (objectCreate) { + return objectCreate(proto); + } + object.prototype = proto; + var result = new object; + object.prototype = undefined; + return result; + }; +}()); + +var _baseCreate = baseCreate; + +/** + * Initializes an object clone. + * + * @private + * @param {Object} object The object to clone. + * @returns {Object} Returns the initialized clone. + */ +function initCloneObject(object) { + return (typeof object.constructor == 'function' && !_isPrototype(object)) + ? _baseCreate(_getPrototype(object)) + : {}; +} + +var _initCloneObject = initCloneObject; + +/** Used to compose bitmasks for cloning. */ +var CLONE_DEEP_FLAG = 1; +var CLONE_FLAT_FLAG = 2; +var CLONE_SYMBOLS_FLAG$1 = 4; + +/** `Object#toString` result references. */ +var argsTag$2 = '[object Arguments]'; +var arrayTag$1 = '[object Array]'; +var boolTag$2 = '[object Boolean]'; +var dateTag$1 = '[object Date]'; +var errorTag$1 = '[object Error]'; +var funcTag$2 = '[object Function]'; +var genTag$1 = '[object GeneratorFunction]'; +var mapTag$3 = '[object Map]'; +var numberTag$1 = '[object Number]'; +var objectTag$2 = '[object Object]'; +var regexpTag$1 = '[object RegExp]'; +var setTag$3 = '[object Set]'; +var stringTag$2 = '[object String]'; +var symbolTag$1 = '[object Symbol]'; +var weakMapTag$2 = '[object WeakMap]'; + +var arrayBufferTag$1 = '[object ArrayBuffer]'; +var dataViewTag$2 = '[object DataView]'; +var float32Tag$1 = '[object Float32Array]'; +var float64Tag$1 = '[object Float64Array]'; +var int8Tag$1 = '[object Int8Array]'; +var int16Tag$1 = '[object Int16Array]'; +var int32Tag$1 = '[object Int32Array]'; +var uint8Tag$1 = '[object Uint8Array]'; +var uint8ClampedTag$1 = '[object Uint8ClampedArray]'; +var uint16Tag$1 = '[object Uint16Array]'; +var uint32Tag$1 = '[object Uint32Array]'; + +/** Used to identify `toStringTag` values supported by `_.clone`. */ +var cloneableTags = {}; +cloneableTags[argsTag$2] = cloneableTags[arrayTag$1] = +cloneableTags[arrayBufferTag$1] = cloneableTags[dataViewTag$2] = +cloneableTags[boolTag$2] = cloneableTags[dateTag$1] = +cloneableTags[float32Tag$1] = cloneableTags[float64Tag$1] = +cloneableTags[int8Tag$1] = cloneableTags[int16Tag$1] = +cloneableTags[int32Tag$1] = cloneableTags[mapTag$3] = +cloneableTags[numberTag$1] = cloneableTags[objectTag$2] = +cloneableTags[regexpTag$1] = cloneableTags[setTag$3] = +cloneableTags[stringTag$2] = cloneableTags[symbolTag$1] = +cloneableTags[uint8Tag$1] = cloneableTags[uint8ClampedTag$1] = +cloneableTags[uint16Tag$1] = cloneableTags[uint32Tag$1] = true; +cloneableTags[errorTag$1] = cloneableTags[funcTag$2] = +cloneableTags[weakMapTag$2] = false; + +/** + * The base implementation of `_.clone` and `_.cloneDeep` which tracks + * traversed objects. + * + * @private + * @param {*} value The value to clone. + * @param {boolean} bitmask The bitmask flags. + * 1 - Deep clone + * 2 - Flatten inherited properties + * 4 - Clone symbols + * @param {Function} [customizer] The function to customize cloning. + * @param {string} [key] The key of `value`. + * @param {Object} [object] The parent object of `value`. + * @param {Object} [stack] Tracks traversed objects and their clone counterparts. + * @returns {*} Returns the cloned value. + */ +function baseClone(value, bitmask, customizer, key, object, stack) { + var result, + isDeep = bitmask & CLONE_DEEP_FLAG, + isFlat = bitmask & CLONE_FLAT_FLAG, + isFull = bitmask & CLONE_SYMBOLS_FLAG$1; + + if (customizer) { + result = object ? customizer(value, key, object, stack) : customizer(value); + } + if (result !== undefined) { + return result; + } + if (!isObject_1(value)) { + return value; + } + var isArr = isArray_1(value); + if (isArr) { + result = _initCloneArray(value); + if (!isDeep) { + return _copyArray(value, result); + } + } else { + var tag = _getTag(value), + isFunc = tag == funcTag$2 || tag == genTag$1; + + if (isBuffer_1(value)) { + return _cloneBuffer(value, isDeep); + } + if (tag == objectTag$2 || tag == argsTag$2 || (isFunc && !object)) { + result = (isFlat || isFunc) ? {} : _initCloneObject(value); + if (!isDeep) { + return isFlat + ? _copySymbolsIn(value, _baseAssignIn(result, value)) + : _copySymbols(value, _baseAssign(result, value)); + } + } else { + if (!cloneableTags[tag]) { + return object ? value : {}; + } + result = _initCloneByTag(value, tag, baseClone, isDeep); + } + } + // Check for circular references and return its corresponding clone. + stack || (stack = new _Stack); + var stacked = stack.get(value); + if (stacked) { + return stacked; + } + stack.set(value, result); + + var keysFunc = isFull + ? (isFlat ? _getAllKeysIn : _getAllKeys) + : (isFlat ? keysIn : keys_1); + + var props = isArr ? undefined : keysFunc(value); + _arrayEach(props || value, function(subValue, key) { + if (props) { + key = subValue; + subValue = value[key]; + } + // Recursively populate clone (susceptible to call stack limits). + _assignValue(result, key, baseClone(subValue, bitmask, customizer, key, value, stack)); + }); + return result; +} + +var _baseClone = baseClone; + +/** Used to compose bitmasks for cloning. */ +var CLONE_SYMBOLS_FLAG = 4; + +/** + * Creates a shallow clone of `value`. + * + * **Note:** This method is loosely based on the + * [structured clone algorithm](https://mdn.io/Structured_clone_algorithm) + * and supports cloning arrays, array buffers, booleans, date objects, maps, + * numbers, `Object` objects, regexes, sets, strings, symbols, and typed + * arrays. The own enumerable properties of `arguments` objects are cloned + * as plain objects. An empty object is returned for uncloneable values such + * as error objects, functions, DOM nodes, and WeakMaps. + * + * @static + * @memberOf _ + * @since 0.1.0 + * @category Lang + * @param {*} value The value to clone. + * @returns {*} Returns the cloned value. + * @see _.cloneDeep + * @example + * + * var objects = [{ 'a': 1 }, { 'b': 2 }]; + * + * var shallow = _.clone(objects); + * console.log(shallow[0] === objects[0]); + * // => true + */ +function clone(value) { + return _baseClone(value, CLONE_SYMBOLS_FLAG); +} + +var clone_1 = clone; + +/** + * This method returns the first argument it receives. + * + * @static + * @since 0.1.0 + * @memberOf _ + * @category Util + * @param {*} value Any value. + * @returns {*} Returns `value`. + * @example + * + * var object = { 'a': 1 }; + * + * console.log(_.identity(object) === object); + * // => true + */ +function identity(value) { + return value; +} + +var identity_1 = identity; + +/** + * A faster alternative to `Function#apply`, this function invokes `func` + * with the `this` binding of `thisArg` and the arguments of `args`. + * + * @private + * @param {Function} func The function to invoke. + * @param {*} thisArg The `this` binding of `func`. + * @param {Array} args The arguments to invoke `func` with. + * @returns {*} Returns the result of `func`. + */ +function apply(func, thisArg, args) { + switch (args.length) { + case 0: return func.call(thisArg); + case 1: return func.call(thisArg, args[0]); + case 2: return func.call(thisArg, args[0], args[1]); + case 3: return func.call(thisArg, args[0], args[1], args[2]); + } + return func.apply(thisArg, args); +} + +var _apply = apply; + +/* Built-in method references for those with the same name as other `lodash` methods. */ +var nativeMax = Math.max; + +/** + * A specialized version of `baseRest` which transforms the rest array. + * + * @private + * @param {Function} func The function to apply a rest parameter to. + * @param {number} [start=func.length-1] The start position of the rest parameter. + * @param {Function} transform The rest array transform. + * @returns {Function} Returns the new function. + */ +function overRest(func, start, transform) { + start = nativeMax(start === undefined ? (func.length - 1) : start, 0); + return function() { + var args = arguments, + index = -1, + length = nativeMax(args.length - start, 0), + array = Array(length); + + while (++index < length) { + array[index] = args[start + index]; + } + index = -1; + var otherArgs = Array(start + 1); + while (++index < start) { + otherArgs[index] = args[index]; + } + otherArgs[start] = transform(array); + return _apply(func, this, otherArgs); + }; +} + +var _overRest = overRest; + +/** + * Creates a function that returns `value`. + * + * @static + * @memberOf _ + * @since 2.4.0 + * @category Util + * @param {*} value The value to return from the new function. + * @returns {Function} Returns the new constant function. + * @example + * + * var objects = _.times(2, _.constant({ 'a': 1 })); + * + * console.log(objects); + * // => [{ 'a': 1 }, { 'a': 1 }] + * + * console.log(objects[0] === objects[1]); + * // => true + */ +function constant(value) { + return function() { + return value; + }; +} + +var constant_1 = constant; + +/** + * The base implementation of `setToString` without support for hot loop shorting. + * + * @private + * @param {Function} func The function to modify. + * @param {Function} string The `toString` result. + * @returns {Function} Returns `func`. + */ +var baseSetToString = !_defineProperty ? identity_1 : function(func, string) { + return _defineProperty(func, 'toString', { + 'configurable': true, + 'enumerable': false, + 'value': constant_1(string), + 'writable': true + }); +}; + +var _baseSetToString = baseSetToString; + +/** Used to detect hot functions by number of calls within a span of milliseconds. */ +var HOT_COUNT = 800; +var HOT_SPAN = 16; + +/* Built-in method references for those with the same name as other `lodash` methods. */ +var nativeNow = Date.now; + +/** + * Creates a function that'll short out and invoke `identity` instead + * of `func` when it's called `HOT_COUNT` or more times in `HOT_SPAN` + * milliseconds. + * + * @private + * @param {Function} func The function to restrict. + * @returns {Function} Returns the new shortable function. + */ +function shortOut(func) { + var count = 0, + lastCalled = 0; + + return function() { + var stamp = nativeNow(), + remaining = HOT_SPAN - (stamp - lastCalled); + + lastCalled = stamp; + if (remaining > 0) { + if (++count >= HOT_COUNT) { + return arguments[0]; + } + } else { + count = 0; + } + return func.apply(undefined, arguments); + }; +} + +var _shortOut = shortOut; + +/** + * Sets the `toString` method of `func` to return `string`. + * + * @private + * @param {Function} func The function to modify. + * @param {Function} string The `toString` result. + * @returns {Function} Returns `func`. + */ +var setToString = _shortOut(_baseSetToString); + +var _setToString = setToString; + +/** + * The base implementation of `_.rest` which doesn't validate or coerce arguments. + * + * @private + * @param {Function} func The function to apply a rest parameter to. + * @param {number} [start=func.length-1] The start position of the rest parameter. + * @returns {Function} Returns the new function. + */ +function baseRest(func, start) { + return _setToString(_overRest(func, start, identity_1), func + ''); +} + +var _baseRest = baseRest; + +/** + * Checks if the given arguments are from an iteratee call. + * + * @private + * @param {*} value The potential iteratee value argument. + * @param {*} index The potential iteratee index or key argument. + * @param {*} object The potential iteratee object argument. + * @returns {boolean} Returns `true` if the arguments are from an iteratee call, + * else `false`. + */ +function isIterateeCall(value, index, object) { + if (!isObject_1(object)) { + return false; + } + var type = typeof index; + if (type == 'number' + ? (isArrayLike_1(object) && _isIndex(index, object.length)) + : (type == 'string' && index in object) + ) { + return eq_1(object[index], value); + } + return false; +} + +var _isIterateeCall = isIterateeCall; + +/** + * Creates a function like `_.assign`. + * + * @private + * @param {Function} assigner The function to assign values. + * @returns {Function} Returns the new assigner function. + */ +function createAssigner(assigner) { + return _baseRest(function(object, sources) { + var index = -1, + length = sources.length, + customizer = length > 1 ? sources[length - 1] : undefined, + guard = length > 2 ? sources[2] : undefined; + + customizer = (assigner.length > 3 && typeof customizer == 'function') + ? (length--, customizer) + : undefined; + + if (guard && _isIterateeCall(sources[0], sources[1], guard)) { + customizer = length < 3 ? undefined : customizer; + length = 1; + } + object = Object(object); + while (++index < length) { + var source = sources[index]; + if (source) { + assigner(object, source, index, customizer); + } + } + return object; + }); +} + +var _createAssigner = createAssigner; + +/** Used for built-in method references. */ +var objectProto$14 = Object.prototype; + +/** Used to check objects for own properties. */ +var hasOwnProperty$11 = objectProto$14.hasOwnProperty; + +/** + * Assigns own enumerable string keyed properties of source objects to the + * destination object. Source objects are applied from left to right. + * Subsequent sources overwrite property assignments of previous sources. + * + * **Note:** This method mutates `object` and is loosely based on + * [`Object.assign`](https://mdn.io/Object/assign). + * + * @static + * @memberOf _ + * @since 0.10.0 + * @category Object + * @param {Object} object The destination object. + * @param {...Object} [sources] The source objects. + * @returns {Object} Returns `object`. + * @see _.assignIn + * @example + * + * function Foo() { + * this.a = 1; + * } + * + * function Bar() { + * this.c = 3; + * } + * + * Foo.prototype.b = 2; + * Bar.prototype.d = 4; + * + * _.assign({ 'a': 0 }, new Foo, new Bar); + * // => { 'a': 1, 'c': 3 } + */ +var assign = _createAssigner(function(object, source) { + if (_isPrototype(source) || isArrayLike_1(source)) { + _copyObject(source, keys_1(source), object); + return; + } + for (var key in source) { + if (hasOwnProperty$11.call(source, key)) { + _assignValue(object, key, source[key]); + } + } +}); + +var assign_1 = assign; + +/** + * This function is like `assignValue` except that it doesn't assign + * `undefined` values. + * + * @private + * @param {Object} object The object to modify. + * @param {string} key The key of the property to assign. + * @param {*} value The value to assign. + */ +function assignMergeValue(object, key, value) { + if ((value !== undefined && !eq_1(object[key], value)) || + (value === undefined && !(key in object))) { + _baseAssignValue(object, key, value); + } +} + +var _assignMergeValue = assignMergeValue; + +/** + * Creates a base function for methods like `_.forIn` and `_.forOwn`. + * + * @private + * @param {boolean} [fromRight] Specify iterating from right to left. + * @returns {Function} Returns the new base function. + */ +function createBaseFor(fromRight) { + return function(object, iteratee, keysFunc) { + var index = -1, + iterable = Object(object), + props = keysFunc(object), + length = props.length; + + while (length--) { + var key = props[fromRight ? length : ++index]; + if (iteratee(iterable[key], key, iterable) === false) { + break; + } + } + return object; + }; +} + +var _createBaseFor = createBaseFor; + +/** + * The base implementation of `baseForOwn` which iterates over `object` + * properties returned by `keysFunc` and invokes `iteratee` for each property. + * Iteratee functions may exit iteration early by explicitly returning `false`. + * + * @private + * @param {Object} object The object to iterate over. + * @param {Function} iteratee The function invoked per iteration. + * @param {Function} keysFunc The function to get the keys of `object`. + * @returns {Object} Returns `object`. + */ +var baseFor = _createBaseFor(); + +var _baseFor = baseFor; + +/** + * This method is like `_.isArrayLike` except that it also checks if `value` + * is an object. + * + * @static + * @memberOf _ + * @since 4.0.0 + * @category Lang + * @param {*} value The value to check. + * @returns {boolean} Returns `true` if `value` is an array-like object, + * else `false`. + * @example + * + * _.isArrayLikeObject([1, 2, 3]); + * // => true + * + * _.isArrayLikeObject(document.body.children); + * // => true + * + * _.isArrayLikeObject('abc'); + * // => false + * + * _.isArrayLikeObject(_.noop); + * // => false + */ +function isArrayLikeObject(value) { + return isObjectLike_1(value) && isArrayLike_1(value); +} + +var isArrayLikeObject_1 = isArrayLikeObject; + +/** `Object#toString` result references. */ +var objectTag$3 = '[object Object]'; + +/** Used for built-in method references. */ +var funcProto$2 = Function.prototype; +var objectProto$15 = Object.prototype; + +/** Used to resolve the decompiled source of functions. */ +var funcToString$2 = funcProto$2.toString; + +/** Used to check objects for own properties. */ +var hasOwnProperty$12 = objectProto$15.hasOwnProperty; + +/** Used to infer the `Object` constructor. */ +var objectCtorString = funcToString$2.call(Object); + +/** + * Checks if `value` is a plain object, that is, an object created by the + * `Object` constructor or one with a `[[Prototype]]` of `null`. + * + * @static + * @memberOf _ + * @since 0.8.0 + * @category Lang + * @param {*} value The value to check. + * @returns {boolean} Returns `true` if `value` is a plain object, else `false`. + * @example + * + * function Foo() { + * this.a = 1; + * } + * + * _.isPlainObject(new Foo); + * // => false + * + * _.isPlainObject([1, 2, 3]); + * // => false + * + * _.isPlainObject({ 'x': 0, 'y': 0 }); + * // => true + * + * _.isPlainObject(Object.create(null)); + * // => true + */ +function isPlainObject(value) { + if (!isObjectLike_1(value) || _baseGetTag(value) != objectTag$3) { + return false; + } + var proto = _getPrototype(value); + if (proto === null) { + return true; + } + var Ctor = hasOwnProperty$12.call(proto, 'constructor') && proto.constructor; + return typeof Ctor == 'function' && Ctor instanceof Ctor && + funcToString$2.call(Ctor) == objectCtorString; +} + +var isPlainObject_1 = isPlainObject; + +/** + * Converts `value` to a plain object flattening inherited enumerable string + * keyed properties of `value` to own properties of the plain object. + * + * @static + * @memberOf _ + * @since 3.0.0 + * @category Lang + * @param {*} value The value to convert. + * @returns {Object} Returns the converted plain object. + * @example + * + * function Foo() { + * this.b = 2; + * } + * + * Foo.prototype.c = 3; + * + * _.assign({ 'a': 1 }, new Foo); + * // => { 'a': 1, 'b': 2 } + * + * _.assign({ 'a': 1 }, _.toPlainObject(new Foo)); + * // => { 'a': 1, 'b': 2, 'c': 3 } + */ +function toPlainObject(value) { + return _copyObject(value, keysIn_1(value)); +} + +var toPlainObject_1 = toPlainObject; + +/** + * A specialized version of `baseMerge` for arrays and objects which performs + * deep merges and tracks traversed objects enabling objects with circular + * references to be merged. + * + * @private + * @param {Object} object The destination object. + * @param {Object} source The source object. + * @param {string} key The key of the value to merge. + * @param {number} srcIndex The index of `source`. + * @param {Function} mergeFunc The function to merge values. + * @param {Function} [customizer] The function to customize assigned values. + * @param {Object} [stack] Tracks traversed source values and their merged + * counterparts. + */ +function baseMergeDeep(object, source, key, srcIndex, mergeFunc, customizer, stack) { + var objValue = object[key], + srcValue = source[key], + stacked = stack.get(srcValue); + + if (stacked) { + _assignMergeValue(object, key, stacked); + return; + } + var newValue = customizer + ? customizer(objValue, srcValue, (key + ''), object, source, stack) + : undefined; + + var isCommon = newValue === undefined; + + if (isCommon) { + var isArr = isArray_1(srcValue), + isBuff = !isArr && isBuffer_1(srcValue), + isTyped = !isArr && !isBuff && isTypedArray_1(srcValue); + + newValue = srcValue; + if (isArr || isBuff || isTyped) { + if (isArray_1(objValue)) { + newValue = objValue; + } + else if (isArrayLikeObject_1(objValue)) { + newValue = _copyArray(objValue); + } + else if (isBuff) { + isCommon = false; + newValue = _cloneBuffer(srcValue, true); + } + else if (isTyped) { + isCommon = false; + newValue = _cloneTypedArray(srcValue, true); + } + else { + newValue = []; + } + } + else if (isPlainObject_1(srcValue) || isArguments_1(srcValue)) { + newValue = objValue; + if (isArguments_1(objValue)) { + newValue = toPlainObject_1(objValue); + } + else if (!isObject_1(objValue) || (srcIndex && isFunction_1(objValue))) { + newValue = _initCloneObject(srcValue); + } + } + else { + isCommon = false; + } + } + if (isCommon) { + // Recursively merge objects and arrays (susceptible to call stack limits). + stack.set(srcValue, newValue); + mergeFunc(newValue, srcValue, srcIndex, customizer, stack); + stack['delete'](srcValue); + } + _assignMergeValue(object, key, newValue); +} + +var _baseMergeDeep = baseMergeDeep; + +/** + * The base implementation of `_.merge` without support for multiple sources. + * + * @private + * @param {Object} object The destination object. + * @param {Object} source The source object. + * @param {number} srcIndex The index of `source`. + * @param {Function} [customizer] The function to customize merged values. + * @param {Object} [stack] Tracks traversed source values and their merged + * counterparts. + */ +function baseMerge(object, source, srcIndex, customizer, stack) { + if (object === source) { + return; + } + _baseFor(source, function(srcValue, key) { + if (isObject_1(srcValue)) { + stack || (stack = new _Stack); + _baseMergeDeep(object, source, key, srcIndex, baseMerge, customizer, stack); + } + else { + var newValue = customizer + ? customizer(object[key], srcValue, (key + ''), object, source, stack) + : undefined; + + if (newValue === undefined) { + newValue = srcValue; + } + _assignMergeValue(object, key, newValue); + } + }, keysIn_1); +} + +var _baseMerge = baseMerge; + +/** + * This method is like `_.assign` except that it recursively merges own and + * inherited enumerable string keyed properties of source objects into the + * destination object. Source properties that resolve to `undefined` are + * skipped if a destination value exists. Array and plain object properties + * are merged recursively. Other objects and value types are overridden by + * assignment. Source objects are applied from left to right. Subsequent + * sources overwrite property assignments of previous sources. + * + * **Note:** This method mutates `object`. + * + * @static + * @memberOf _ + * @since 0.5.0 + * @category Object + * @param {Object} object The destination object. + * @param {...Object} [sources] The source objects. + * @returns {Object} Returns `object`. + * @example + * + * var object = { + * 'a': [{ 'b': 2 }, { 'd': 4 }] + * }; + * + * var other = { + * 'a': [{ 'c': 3 }, { 'e': 5 }] + * }; + * + * _.merge(object, other); + * // => { 'a': [{ 'b': 2, 'c': 3 }, { 'd': 4, 'e': 5 }] } + */ +var merge = _createAssigner(function(object, source, srcIndex) { + _baseMerge(object, source, srcIndex); +}); + +var merge_1 = merge; + +/** + * The base implementation of `_.slice` without an iteratee call guard. + * + * @private + * @param {Array} array The array to slice. + * @param {number} [start=0] The start position. + * @param {number} [end=array.length] The end position. + * @returns {Array} Returns the slice of `array`. + */ +function baseSlice(array, start, end) { + var index = -1, + length = array.length; + + if (start < 0) { + start = -start > length ? 0 : (length + start); + } + end = end > length ? length : end; + if (end < 0) { + end += length; + } + length = start > end ? 0 : ((end - start) >>> 0); + start >>>= 0; + + var result = Array(length); + while (++index < length) { + result[index] = array[index + start]; + } + return result; +} + +var _baseSlice = baseSlice; + +/** + * Casts `array` to a slice if it's needed. + * + * @private + * @param {Array} array The array to inspect. + * @param {number} start The start position. + * @param {number} [end=array.length] The end position. + * @returns {Array} Returns the cast slice. + */ +function castSlice(array, start, end) { + var length = array.length; + end = end === undefined ? length : end; + return (!start && end >= length) ? array : _baseSlice(array, start, end); +} + +var _castSlice = castSlice; + +/** Used to compose unicode character classes. */ +var rsAstralRange = '\\ud800-\\udfff'; +var rsComboMarksRange = '\\u0300-\\u036f'; +var reComboHalfMarksRange = '\\ufe20-\\ufe2f'; +var rsComboSymbolsRange = '\\u20d0-\\u20ff'; +var rsComboRange = rsComboMarksRange + reComboHalfMarksRange + rsComboSymbolsRange; +var rsVarRange = '\\ufe0e\\ufe0f'; + +/** Used to compose unicode capture groups. */ +var rsZWJ = '\\u200d'; + +/** Used to detect strings with [zero-width joiners or code points from the astral planes](http://eev.ee/blog/2015/09/12/dark-corners-of-unicode/). */ +var reHasUnicode = RegExp('[' + rsZWJ + rsAstralRange + rsComboRange + rsVarRange + ']'); + +/** + * Checks if `string` contains Unicode symbols. + * + * @private + * @param {string} string The string to inspect. + * @returns {boolean} Returns `true` if a symbol is found, else `false`. + */ +function hasUnicode(string) { + return reHasUnicode.test(string); +} + +var _hasUnicode = hasUnicode; + +/** + * Converts an ASCII `string` to an array. + * + * @private + * @param {string} string The string to convert. + * @returns {Array} Returns the converted array. + */ +function asciiToArray(string) { + return string.split(''); +} + +var _asciiToArray = asciiToArray; + +/** Used to compose unicode character classes. */ +var rsAstralRange$1 = '\\ud800-\\udfff'; +var rsComboMarksRange$1 = '\\u0300-\\u036f'; +var reComboHalfMarksRange$1 = '\\ufe20-\\ufe2f'; +var rsComboSymbolsRange$1 = '\\u20d0-\\u20ff'; +var rsComboRange$1 = rsComboMarksRange$1 + reComboHalfMarksRange$1 + rsComboSymbolsRange$1; +var rsVarRange$1 = '\\ufe0e\\ufe0f'; + +/** Used to compose unicode capture groups. */ +var rsAstral = '[' + rsAstralRange$1 + ']'; +var rsCombo = '[' + rsComboRange$1 + ']'; +var rsFitz = '\\ud83c[\\udffb-\\udfff]'; +var rsModifier = '(?:' + rsCombo + '|' + rsFitz + ')'; +var rsNonAstral = '[^' + rsAstralRange$1 + ']'; +var rsRegional = '(?:\\ud83c[\\udde6-\\uddff]){2}'; +var rsSurrPair = '[\\ud800-\\udbff][\\udc00-\\udfff]'; +var rsZWJ$1 = '\\u200d'; + +/** Used to compose unicode regexes. */ +var reOptMod = rsModifier + '?'; +var rsOptVar = '[' + rsVarRange$1 + ']?'; +var rsOptJoin = '(?:' + rsZWJ$1 + '(?:' + [rsNonAstral, rsRegional, rsSurrPair].join('|') + ')' + rsOptVar + reOptMod + ')*'; +var rsSeq = rsOptVar + reOptMod + rsOptJoin; +var rsSymbol = '(?:' + [rsNonAstral + rsCombo + '?', rsCombo, rsRegional, rsSurrPair, rsAstral].join('|') + ')'; + +/** Used to match [string symbols](https://mathiasbynens.be/notes/javascript-unicode). */ +var reUnicode = RegExp(rsFitz + '(?=' + rsFitz + ')|' + rsSymbol + rsSeq, 'g'); + +/** + * Converts a Unicode `string` to an array. + * + * @private + * @param {string} string The string to convert. + * @returns {Array} Returns the converted array. + */ +function unicodeToArray(string) { + return string.match(reUnicode) || []; +} + +var _unicodeToArray = unicodeToArray; + +/** + * Converts `string` to an array. + * + * @private + * @param {string} string The string to convert. + * @returns {Array} Returns the converted array. + */ +function stringToArray(string) { + return _hasUnicode(string) + ? _unicodeToArray(string) + : _asciiToArray(string); +} + +var _stringToArray = stringToArray; + +/** + * Creates a function like `_.lowerFirst`. + * + * @private + * @param {string} methodName The name of the `String` case method to use. + * @returns {Function} Returns the new case function. + */ +function createCaseFirst(methodName) { + return function(string) { + string = toString_1(string); + + var strSymbols = _hasUnicode(string) + ? _stringToArray(string) + : undefined; + + var chr = strSymbols + ? strSymbols[0] + : string.charAt(0); + + var trailing = strSymbols + ? _castSlice(strSymbols, 1).join('') + : string.slice(1); + + return chr[methodName]() + trailing; + }; +} + +var _createCaseFirst = createCaseFirst; + +/** + * Converts the first character of `string` to upper case. + * + * @static + * @memberOf _ + * @since 4.0.0 + * @category String + * @param {string} [string=''] The string to convert. + * @returns {string} Returns the converted string. + * @example + * + * _.upperFirst('fred'); + * // => 'Fred' + * + * _.upperFirst('FRED'); + * // => 'FRED' + */ +var upperFirst = _createCaseFirst('toUpperCase'); + +var upperFirst_1 = upperFirst; + +/** + * The base implementation of `_.findIndex` and `_.findLastIndex` without + * support for iteratee shorthands. + * + * @private + * @param {Array} array The array to inspect. + * @param {Function} predicate The function invoked per iteration. + * @param {number} fromIndex The index to search from. + * @param {boolean} [fromRight] Specify iterating from right to left. + * @returns {number} Returns the index of the matched value, else `-1`. + */ +function baseFindIndex(array, predicate, fromIndex, fromRight) { + var length = array.length, + index = fromIndex + (fromRight ? 1 : -1); + + while ((fromRight ? index-- : ++index < length)) { + if (predicate(array[index], index, array)) { + return index; + } + } + return -1; +} + +var _baseFindIndex = baseFindIndex; + +/** + * The base implementation of `_.isNaN` without support for number objects. + * + * @private + * @param {*} value The value to check. + * @returns {boolean} Returns `true` if `value` is `NaN`, else `false`. + */ +function baseIsNaN(value) { + return value !== value; +} + +var _baseIsNaN = baseIsNaN; + +/** + * A specialized version of `_.indexOf` which performs strict equality + * comparisons of values, i.e. `===`. + * + * @private + * @param {Array} array The array to inspect. + * @param {*} value The value to search for. + * @param {number} fromIndex The index to search from. + * @returns {number} Returns the index of the matched value, else `-1`. + */ +function strictIndexOf(array, value, fromIndex) { + var index = fromIndex - 1, + length = array.length; + + while (++index < length) { + if (array[index] === value) { + return index; + } + } + return -1; +} + +var _strictIndexOf = strictIndexOf; + +/** + * The base implementation of `_.indexOf` without `fromIndex` bounds checks. + * + * @private + * @param {Array} array The array to inspect. + * @param {*} value The value to search for. + * @param {number} fromIndex The index to search from. + * @returns {number} Returns the index of the matched value, else `-1`. + */ +function baseIndexOf(array, value, fromIndex) { + return value === value + ? _strictIndexOf(array, value, fromIndex) + : _baseFindIndex(array, _baseIsNaN, fromIndex); +} + +var _baseIndexOf = baseIndexOf; + +/** + * This function is like `baseIndexOf` except that it accepts a comparator. + * + * @private + * @param {Array} array The array to inspect. + * @param {*} value The value to search for. + * @param {number} fromIndex The index to search from. + * @param {Function} comparator The comparator invoked per element. + * @returns {number} Returns the index of the matched value, else `-1`. + */ +function baseIndexOfWith(array, value, fromIndex, comparator) { + var index = fromIndex - 1, + length = array.length; + + while (++index < length) { + if (comparator(array[index], value)) { + return index; + } + } + return -1; +} + +var _baseIndexOfWith = baseIndexOfWith; + +/** Used for built-in method references. */ +var arrayProto$1 = Array.prototype; + +/** Built-in value references. */ +var splice$1 = arrayProto$1.splice; + +/** + * The base implementation of `_.pullAllBy` without support for iteratee + * shorthands. + * + * @private + * @param {Array} array The array to modify. + * @param {Array} values The values to remove. + * @param {Function} [iteratee] The iteratee invoked per element. + * @param {Function} [comparator] The comparator invoked per element. + * @returns {Array} Returns `array`. + */ +function basePullAll(array, values, iteratee, comparator) { + var indexOf = comparator ? _baseIndexOfWith : _baseIndexOf, + index = -1, + length = values.length, + seen = array; + + if (array === values) { + values = _copyArray(values); + } + if (iteratee) { + seen = _arrayMap(array, _baseUnary(iteratee)); + } + while (++index < length) { + var fromIndex = 0, + value = values[index], + computed = iteratee ? iteratee(value) : value; + + while ((fromIndex = indexOf(seen, computed, fromIndex, comparator)) > -1) { + if (seen !== array) { + splice$1.call(seen, fromIndex, 1); + } + splice$1.call(array, fromIndex, 1); + } + } + return array; +} + +var _basePullAll = basePullAll; + +/** + * This method is like `_.pull` except that it accepts an array of values to remove. + * + * **Note:** Unlike `_.difference`, this method mutates `array`. + * + * @static + * @memberOf _ + * @since 4.0.0 + * @category Array + * @param {Array} array The array to modify. + * @param {Array} values The values to remove. + * @returns {Array} Returns `array`. + * @example + * + * var array = ['a', 'b', 'c', 'a', 'b', 'c']; + * + * _.pullAll(array, ['a', 'c']); + * console.log(array); + * // => ['b', 'b'] + */ +function pullAll(array, values) { + return (array && array.length && values && values.length) + ? _basePullAll(array, values) + : array; +} + +var pullAll_1 = pullAll; + +/** + * Removes all given values from `array` using + * [`SameValueZero`](http://ecma-international.org/ecma-262/7.0/#sec-samevaluezero) + * for equality comparisons. + * + * **Note:** Unlike `_.without`, this method mutates `array`. Use `_.remove` + * to remove elements from an array by predicate. + * + * @static + * @memberOf _ + * @since 2.0.0 + * @category Array + * @param {Array} array The array to modify. + * @param {...*} [values] The values to remove. + * @returns {Array} Returns `array`. + * @example + * + * var array = ['a', 'b', 'c', 'a', 'b', 'c']; + * + * _.pull(array, 'a', 'c'); + * console.log(array); + * // => ['b', 'b'] + */ +var pull = _baseRest(pullAll_1); + +var pull_1 = pull; + +/** + * The base implementation of `_.forOwn` without support for iteratee shorthands. + * + * @private + * @param {Object} object The object to iterate over. + * @param {Function} iteratee The function invoked per iteration. + * @returns {Object} Returns `object`. + */ +function baseForOwn(object, iteratee) { + return object && _baseFor(object, iteratee, keys_1); +} + +var _baseForOwn = baseForOwn; + +/** + * Creates a `baseEach` or `baseEachRight` function. + * + * @private + * @param {Function} eachFunc The function to iterate over a collection. + * @param {boolean} [fromRight] Specify iterating from right to left. + * @returns {Function} Returns the new base function. + */ +function createBaseEach(eachFunc, fromRight) { + return function(collection, iteratee) { + if (collection == null) { + return collection; + } + if (!isArrayLike_1(collection)) { + return eachFunc(collection, iteratee); + } + var length = collection.length, + index = fromRight ? length : -1, + iterable = Object(collection); + + while ((fromRight ? index-- : ++index < length)) { + if (iteratee(iterable[index], index, iterable) === false) { + break; + } + } + return collection; + }; +} + +var _createBaseEach = createBaseEach; + +/** + * The base implementation of `_.forEach` without support for iteratee shorthands. + * + * @private + * @param {Array|Object} collection The collection to iterate over. + * @param {Function} iteratee The function invoked per iteration. + * @returns {Array|Object} Returns `collection`. + */ +var baseEach = _createBaseEach(_baseForOwn); + +var _baseEach = baseEach; + +/** + * Casts `value` to `identity` if it's not a function. + * + * @private + * @param {*} value The value to inspect. + * @returns {Function} Returns cast function. + */ +function castFunction(value) { + return typeof value == 'function' ? value : identity_1; +} + +var _castFunction = castFunction; + +/** + * Iterates over elements of `collection` and invokes `iteratee` for each element. + * The iteratee is invoked with three arguments: (value, index|key, collection). + * Iteratee functions may exit iteration early by explicitly returning `false`. + * + * **Note:** As with other "Collections" methods, objects with a "length" + * property are iterated like arrays. To avoid this behavior use `_.forIn` + * or `_.forOwn` for object iteration. + * + * @static + * @memberOf _ + * @since 0.1.0 + * @alias each + * @category Collection + * @param {Array|Object} collection The collection to iterate over. + * @param {Function} [iteratee=_.identity] The function invoked per iteration. + * @returns {Array|Object} Returns `collection`. + * @see _.forEachRight + * @example + * + * _.forEach([1, 2], function(value) { + * console.log(value); + * }); + * // => Logs `1` then `2`. + * + * _.forEach({ 'a': 1, 'b': 2 }, function(value, key) { + * console.log(key); + * }); + * // => Logs 'a' then 'b' (iteration order is not guaranteed). + */ +function forEach(collection, iteratee) { + var func = isArray_1(collection) ? _arrayEach : _baseEach; + return func(collection, _castFunction(iteratee)); +} + +var forEach_1 = forEach; + +/** + * Converts `iterator` to an array. + * + * @private + * @param {Object} iterator The iterator to convert. + * @returns {Array} Returns the converted array. + */ +function iteratorToArray(iterator) { + var data, + result = []; + + while (!(data = iterator.next()).done) { + result.push(data.value); + } + return result; +} + +var _iteratorToArray = iteratorToArray; + +/** + * The base implementation of `_.values` and `_.valuesIn` which creates an + * array of `object` property values corresponding to the property names + * of `props`. + * + * @private + * @param {Object} object The object to query. + * @param {Array} props The property names to get values for. + * @returns {Object} Returns the array of property values. + */ +function baseValues(object, props) { + return _arrayMap(props, function(key) { + return object[key]; + }); +} + +var _baseValues = baseValues; + +/** + * Creates an array of the own enumerable string keyed property values of `object`. + * + * **Note:** Non-object values are coerced to objects. + * + * @static + * @since 0.1.0 + * @memberOf _ + * @category Object + * @param {Object} object The object to query. + * @returns {Array} Returns the array of property values. + * @example + * + * function Foo() { + * this.a = 1; + * this.b = 2; + * } + * + * Foo.prototype.c = 3; + * + * _.values(new Foo); + * // => [1, 2] (iteration order is not guaranteed) + * + * _.values('hi'); + * // => ['h', 'i'] + */ +function values(object) { + return object == null ? [] : _baseValues(object, keys_1(object)); +} + +var values_1 = values; + +/** `Object#toString` result references. */ +var mapTag$5 = '[object Map]'; +var setTag$5 = '[object Set]'; + +/** Built-in value references. */ +var symIterator = _Symbol ? _Symbol.iterator : undefined; + +/** + * Converts `value` to an array. + * + * @static + * @since 0.1.0 + * @memberOf _ + * @category Lang + * @param {*} value The value to convert. + * @returns {Array} Returns the converted array. + * @example + * + * _.toArray({ 'a': 1, 'b': 2 }); + * // => [1, 2] + * + * _.toArray('abc'); + * // => ['a', 'b', 'c'] + * + * _.toArray(1); + * // => [] + * + * _.toArray(null); + * // => [] + */ +function toArray(value) { + if (!value) { + return []; + } + if (isArrayLike_1(value)) { + return isString_1(value) ? _stringToArray(value) : _copyArray(value); + } + if (symIterator && value[symIterator]) { + return _iteratorToArray(value[symIterator]()); + } + var tag = _getTag(value), + func = tag == mapTag$5 ? _mapToArray : (tag == setTag$5 ? _setToArray : values_1); + + return func(value); +} + +var toArray_1 = toArray; + +var PRECISION = 0.00001; // 常量,据的精度,小于这个精度认为是0 +var RADIAN = Math.PI / 180; +var DEGREE = 180 / Math.PI; + +var common = { + isFunction: isFunction_1, + isObject: isObject_1, + isBoolean: isBoolean_1, + isNil: isNil_1, + isString: isString_1, + isArray: isArray_1, + isEmpty: isEmpty_1, // isBlank + uniqueId: uniqueId_1, + clone: clone_1, + assign: assign_1, // simpleMix + merge: merge_1, // mix + upperFirst: upperFirst_1, // ucfirst + remove: pull_1, + each: forEach_1, + toArray: toArray_1, + extend: function (subclass, superclass, overrides, staticOverrides) { + // 如果只提供父类构造函数,则自动生成子类构造函数 + if (!this.isFunction(superclass)) { + overrides = superclass; + superclass = subclass; + subclass = function () {}; + } + + var create = Object.create ? function (proto, c) { + return Object.create(proto, { + constructor: { + value: c + } + }); + } : function (proto, c) { + function F() {} + + F.prototype = proto; + var o = new F(); + o.constructor = c; + return o; + }; + + var superObj = create(superclass.prototype, subclass); // new superclass(),//实例化父类作为子类的prototype + subclass.prototype = this.merge(superObj, subclass.prototype); // 指定子类的prototype + subclass.superclass = create(superclass.prototype, superclass); + this.merge(superObj, overrides); + this.merge(subclass, staticOverrides); + return subclass; + }, + augment: function (c) { + var args = this.toArray(arguments); + for (var i = 1; i < args.length; i++) { + var obj = args[i]; + if (this.isFunction(obj)) { + obj = obj.prototype; + } + this.merge(c.prototype, obj); + } + }, + + /** + * 判断两个数是否相等 + * @param {Number} a 数 + * @param {Number} b 数 + * @return {Boolean} 是否相等 + **/ + isNumberEqual: function (a, b) { + return Math.abs(a - b) < PRECISION; + }, + + /** + * 获取角度对应的弧度 + * @param {Number} degree 角度 + * @return {Number} 弧度 + **/ + toRadian: function (degree) { + return RADIAN * degree; + }, + + /** + * 获取弧度对应的角度 + * @param {Number} radian 弧度 + * @return {Number} 角度 + **/ + toDegree: function (radian) { + return DEGREE * radian; + }, + + /** + * 广义取模运算 + * @param {Number} n 被取模的值 + * @param {Number} m 模 + * @return {Number} 返回n 被 m 取模的结果 + */ + mod: function (n, m) { + return (n % m + m) % m; + } +}; + +var TABLE = document.createElement('table'); +var TABLE_TR = document.createElement('tr'); +var FRAGMENT_REG = /^\s*<(\w+|!)[^>]*>/; +var CONTAINERS = { + tr: document.createElement('tbody'), + tbody: TABLE, + thead: TABLE, + tfoot: TABLE, + td: TABLE_TR, + th: TABLE_TR, + '*': document.createElement('div') +}; + +var dom = { + getBoundingClientRect: function (node) { + var rect = node.getBoundingClientRect(); + var top = document.documentElement.clientTop; + var left = document.documentElement.clientLeft; + return { + top: rect.top - top, + bottom: rect.bottom - top, + left: rect.left - left, + right: rect.right - left + }; + }, + + /** + * 获取样式 + * @param {Object} dom DOM节点 + * @param {String} name 样式名 + * @return {String} 属性值 + */ + getStyle: function (dom, name) { + if (window.getComputedStyle) { + return window.getComputedStyle(dom, null)[name]; + } + return dom.currentStyle[name]; + }, + modiCSS: function (dom, css) { + for (var key in css) { + if (css.hasOwnProperty(key)) { + dom.style[key] = css[key]; + } + } + return dom; + }, + + /** + * 创建DOM 节点 + * @param {String} str Dom 字符串 + * @return {HTMLElement} DOM 节点 + */ + createDom: function (str) { + var name = FRAGMENT_REG.test(str) && RegExp.$1; + if (!(name in CONTAINERS)) { + name = '*'; + } + var container = CONTAINERS[name]; + str = str.replace(/(^\s*)|(\s*$)/g, ''); + container.innerHTML = '' + str; + return container.childNodes[0]; + }, + getRatio: function () { + return window.devicePixelRatio ? window.devicePixelRatio : 2; + }, + + /** + * 获取宽度 + * @param {HTMLElement} el dom节点 + * @return {Number} 宽度 + */ + getWidth: function (el) { + var width = this.getStyle(el, 'width'); + if (width === 'auto') { + width = el.offsetWidth; + } + return parseFloat(width); + }, + + /** + * 获取高度 + * @param {HTMLElement} el dom节点 + * @return {Number} 高度 + */ + getHeight: function (el) { + var height = this.getStyle(el, 'height'); + if (height === 'auto') { + height = el.offsetHeight; + } + return parseFloat(height); + }, + + /** + * 获取外层高度 + * @param {HTMLElement} el dom节点 + * @return {Number} 高度 + */ + getOuterHeight: function (el) { + var height = this.getHeight(el); + var bTop = parseFloat(this.getStyle(el, 'borderTopWidth')) || 0; + var pTop = parseFloat(this.getStyle(el, 'paddingTop')); + var pBottom = parseFloat(this.getStyle(el, 'paddingBottom')); + var bBottom = parseFloat(this.getStyle(el, 'borderBottomWidth')) || 0; + return height + bTop + bBottom + pTop + pBottom; + }, + + /** + * TODO: 应该移除的 + * 添加时间监听器 + * @param {Object} target DOM对象 + * @param {Object} eventType 事件名 + * @param {Funtion} callback 回调函数 + * @return {Object} 返回对象 + */ + addEventListener: function (target, eventType, callback) { + if (target.addEventListener) { + target.addEventListener(eventType, callback, false); + return { + remove: function () { + target.removeEventListener(eventType, callback, false); + } + }; + } else if (target.attachEvent) { + target.attachEvent('on' + eventType, callback); + return { + remove: function () { + target.detachEvent('on' + eventType, callback); + } + }; + } + }, + requestAnimationFrame: function (fn) { + var method = window.requestAnimationFrame || window.webkitRequestAnimationFrame || function (fn) { + return setTimeout(fn, 16); + }; + + return method(fn); + }, + cancelAnimationFrame: function (id) { + var method = window.cancelAnimationFrame || window.webkitCancelAnimationFrame || function (id) { + return clearTimeout(id); + }; + return method(id); + } +}; + +var Util$3 = {}; + +common.merge(Util$3, common, dom, { + mixin: function (c, mixins) { + var Param = c.CFG ? 'CFG' : 'ATTRS'; + if (c && mixins) { + c._mixins = mixins; + c[Param] = c[Param] || {}; + var temp = {}; + Util$3.each(mixins, function (mixin) { + Util$3.augment(c, mixin); + var attrs = mixin[Param]; + if (attrs) { + Util$3.merge(temp, attrs); + } + }); + c[Param] = Util$3.merge(temp, c[Param]); + } + } +}); + +var index$8 = Util$3; + +var Event = function(type, event, bubbles, cancelable) { + this.type = type; // 事件类型 + this.target = null; // 目标 + this.currentTarget = null; // 当前目标 + this.bubbles = bubbles; // 冒泡 + this.cancelable = cancelable; // 是否能够阻止 + this.timeStamp = (new Date()).getTime(); // 时间戳 + this.defaultPrevented = false; // 阻止默认 + this.propagationStopped = false; // 阻止冒泡 + this.removed= false; //是否被移除 + this.event = event; // 触发的原生事件 +}; + + +index$4.augment(Event, { + preventDefault: function() { + this.defaultPrevented = this.cancelable && true; + }, + stopPropagation: function() { + this.propagationStopped = true; + }, + remove: function() { + this.remove = true; + }, + clone: function() { + return index$4.clone(this); + }, + toString: function() { + return '[Event (type=' + this.type + ')]'; + } +}); + +var event = Event; + +var index$10 = event; + +var MouseEvent = function (canvas) { + this.canvas = canvas; + this.el = canvas.get('el'); + this.current = null; + this.pre = null; +}; + +index$8.augment(MouseEvent, { + tryTrigger: function (element, event) { + if (element.__listeners) { + element.trigger(event); + } else { + return; + } + }, + getCurrent: function (e) { + var canvas = this.canvas; + var point = canvas.getPointByClient(e.clientX, e.clientY); + this.point = point; + this.pre = this.current; + this.current = canvas.getShape(point.x, point.y); + }, + mousemove: function (e) { + this.getCurrent(e); + var point = this.point; + var canvas = this.canvas; + if (canvas.has('canvas-mousemove')) { + var canvasmousemove = new index$10('canvas-mousemove', e, true, true); + canvasmousemove.x = point.x; + canvasmousemove.y = point.y; + canvasmousemove.clientX = e.clientX; + canvasmousemove.clientY = e.clientY; + canvasmousemove.currentTarget = canvas; + this.tryTrigger(canvas, canvasmousemove); + } + + if (this.pre && this.pre !== this.current) { + var mouseleave = new index$10('mouseleave', e, true, true); + mouseleave.x = point.x; + mouseleave.y = point.y; + mouseleave.clientX = e.clientX; + mouseleave.clientY = e.clientY; + mouseleave.currentTarget = this.pre; + mouseleave.target = this.pre; + this.tryTrigger(this.pre, mouseleave); + } + + if (this.current) { + var mousemove = new index$10('mousemove', e, true, true); + mousemove.x = point.x; + mousemove.y = point.y; + mousemove.clientX = e.clientX; + mousemove.clientY = e.clientY; + mousemove.currentTarget = this.current; + mousemove.target = this.current; + this.tryTrigger(this.current, mousemove); + + if (this.pre !== this.current) { + var mouseenter = new index$10('mouseenter', e, true, true); + mouseenter.x = point.x; + mouseenter.y = point.y; + mouseenter.clientX = e.clientX; + mouseenter.clientY = e.clientY; + mouseenter.currentTarget = this.current; + mouseenter.target = this.current; + this.tryTrigger(this.current, mouseenter); + } + } + }, + mousedown: function (e) { + var point = this.point; + var canvas = this.canvas; + + if (canvas.has('canvas-mousedown')) { + var canvasmousedown = new index$10('canvas-mousedown', e, true, true); + canvasmousedown.x = point.x; + canvasmousedown.y = point.y; + canvasmousedown.clientX = e.clientX; + canvasmousedown.clientY = e.clientY; + canvasmousedown.currentTarget = canvas; + this.tryTrigger(canvas, canvasmousedown); + } + + if (this.current) { + var mousedown = new index$10('mousedown', e, true, true); + mousedown.x = point.x; + mousedown.y = point.y; + mousedown.clientX = e.clientX; + mousedown.clientY = e.clientY; + mousedown.currentTarget = this.current; + mousedown.target = this.current; + this.tryTrigger(this.current, mousedown); + } + }, + mouseup: function (e) { + var point = this.point; + var canvas = this.canvas; + if (canvas.has('canvas-mouseup')) { + var canvasmouseup = new index$10('canvas-mouseup', e, true, true); + canvasmouseup.x = point.x; + canvasmouseup.y = point.y; + canvasmouseup.clientX = e.clientX; + canvasmouseup.clientY = e.clientY; + canvasmouseup.currentTarget = canvas; + this.tryTrigger(canvas, canvasmouseup); + } + if (this.current) { + var mouseup = new index$10('mouseup', e, true, true); + mouseup.x = point.x; + mouseup.y = point.y; + mouseup.clientX = e.clientX; + mouseup.clientY = e.clientY; + mouseup.currentTarget = this.current; + mouseup.target = this.current; + this.tryTrigger(this.current, mouseup); + } + }, + click: function (e) { + this.getCurrent(e); + var point = this.point; + var canvas = this.canvas; + if (canvas.has('canvas-click')) { + var canvasclick = new index$10('canvas-click', e, true, true); + canvasclick.x = point.x; + canvasclick.y = point.y; + canvasclick.clientX = e.clientX; + canvasclick.clientY = e.clientY; + canvasclick.currentTarget = canvas; + this.tryTrigger(canvas, canvasclick); + } + + if (this.current) { + var click = new index$10('click', e, true, true); + click.x = point.x; + click.y = point.y; + click.clientX = e.clientX; + click.clientY = e.clientY; + click.currentTarget = this.current; + click.target = this.current; + this.tryTrigger(this.current, click); + } + }, + dblclick: function (e) { + var point = this.point; + var canvas = this.canvas; + + if (canvas.has('canvas-dblclick')) { + var canvasdblclick = new index$10('canvas-dblclick', e, true, true); + canvasdblclick.x = point.x; + canvasdblclick.y = point.y; + canvasdblclick.clientX = e.clientX; + canvasdblclick.clientY = e.clientY; + canvasdblclick.currentTarget = canvas; + this.tryTrigger(canvas, canvasdblclick); + } + + if (this.current) { + var dblclick = new index$10('dblclick', e, true, true); + dblclick.x = point.x; + dblclick.y = point.y; + dblclick.clientX = e.clientX; + dblclick.clientY = e.clientY; + dblclick.currentTarget = this.current; + dblclick.target = this.current; + this.tryTrigger(this.current, dblclick); + } + }, + mouseout: function (e) { + var point = this.point; + var canvas = this.canvas; + + var canvasmouseleave = new index$10('canvas-mouseleave', e, true, true); + canvasmouseleave.x = point.x; + canvasmouseleave.y = point.y; + canvasmouseleave.currentTarget = canvas; + this.tryTrigger(canvas, canvasmouseleave); + }, + mouseover: function (e) { + var canvas = this.canvas; + + var canvasmouseenter = new index$10('canvas-mouseenter', e, true, true); + canvasmouseenter.currentTarget = canvas; + this.tryTrigger(canvas, canvasmouseenter); + } +}); + +var mouseEvent = MouseEvent; + +/** + * @fileOverview 公共类 + * @author hankaiai@126.com + */ +var common$2 = { + prefix: 'g', + backupContext: document.createElement('canvas').getContext('2d'), + debug: false, + warn: function () {} +}; + +/** + * @fileOverview gMath 基础数学工具类 + * @author hankaiai@126.com + * @author dxq613@gmail.com + * @ignore + */ + +//取小于当前值的 +function arrayFloor(values,value){ + var length = values.length; + if (length === 0) { + return NaN; + } + + + var pre = values[0]; + + if(value < values[0]){ + return NaN; + } + + if(value >= values[length - 1]){ + return values[length - 1]; + } + for (var i = 1; i < values.length; i++) { + if(value < values[i]){ + break; + } + pre = values[i]; + } + + return pre; +} +//大于当前值的第一个 +function arrayCeiling(values,value){ + var length = values.length; + if (length === 0) { + return NaN; + } + var pre = values[0], + rst; + if(value > values[length - 1]){ + return NaN; + } + if(value < values[0]){ + return values[0]; + } + + for (var i = 1; i < values.length; i++) { + if(value <= values[i]){ + rst = values[i]; + break; + } + pre = values[i]; + } + + return rst; +} + + +var gMath = { + /** + * 常亮:数据的精度,小于这个精度认为是0 + **/ + PRECISION: 0.00001, + /** + * 判断两个数是否相等 + * @param {Number} a 数 + * @param {Number} b 数 + * @return {Boolean} 是否相等 + **/ + equal: function(a, b) { + return (Math.abs((a - b)) < gMath.PRECISION); + }, + /** + * 把a夹在min,max中间, 低于min的返回min,高于max的返回max,否则返回自身 + * @param {Number} a 数 + * @param {Number} min 下限 + * @param {Number} max 上限 + **/ + clamp: function(a, min, max) { + if (a < min) { + return min; + } else if (a > max){ + return max; + } else { + return a; + } + }, + /** + * 获取逼近的值,用于对齐数据 + * @param {Array} values 数据集合 + * @param {Number} value 数值 + * @return {Number} 逼近的值 + */ + snapTo : function(values, value){ + // 这里假定values是升序排列 + var floorVal = arrayFloor(values,value), + ceilingVal = arrayCeiling(values,value); + if(isNaN(floorVal) || isNaN(ceilingVal)){ + if(values[0] >= value){ + return values[0]; + } + var last = values[values.length -1]; + if(last <= value){ + return last; + } + } + + + if(Math.abs(value - floorVal) < Math.abs(ceilingVal - value)){ + return floorVal; + } + return ceilingVal; + }, + /** + * 获取逼近的最小值,用于对齐数据 + * @param {Array} values 数据集合 + * @param {Number} value 数值 + * @return {Number} 逼近的最小值 + */ + snapFloor : function(values,value){ + // 这里假定values是升序排列 + return arrayFloor(values,value); + }, + /** + * 获取逼近的最大值,用于对齐数据 + * @param {Array} values 数据集合 + * @param {Number} value 数值 + * @return {Number} 逼近的最大值 + */ + snapCeiling : function(values,value){ + // 这里假定values是升序排列 + return arrayCeiling(values,value); + }, + /** + * 获取角度对应的弧度 + * @param {Number} degree 角度 + * @return {Number} 弧度 + **/ + degreeToRad: function(degree) { + return Math.PI / 180 * degree; + }, + /** + * 获取弧度对应的角度 + * @param {Number} rad 弧度 + * @return {Number} 角度 + **/ + radToDegree: function(rad) { + return 180 / Math.PI * rad; + }, + /** + * 广义取模运算 + * @param {Number} v 被取模的值 + * @param {Number} m 模 + */ + mod: function(n, m) { + return ( ( n % m ) + m ) % m; + } +}; + + + +var math = gMath; + +var index$16 = math; + +function Matrix3() { + this.elements = [ + 1, 0, 0, + 0, 1, 0, + 0, 0, 1 + ]; +} + +Matrix3.multiply = function(m1, m2) { + var te = m1.elements; + var me = m2.elements; + var m = new Matrix3(); + return m.set( + te[0] * me[0] + te[3] * me[1] + te[6] * me[2], te[0] * me[3] + te[3] * me[4] + te[6] * me[5], te[0] * me[6] + te[3] * me[7] + te[6] * me[8], + te[1] * me[0] + te[4] * me[1] + te[7] * me[2], te[1] * me[3] + te[4] * me[4] + te[7] * me[5], te[1] * me[6] + te[4] * me[7] + te[7] * me[8], + te[2] * me[0] + te[5] * me[1] + te[8] * me[2], te[2] * me[3] + te[5] * me[4] + te[8] * me[5], te[2] * me[6] + te[5] * me[7] + te[8] * me[8] + ); +}; + +Matrix3.equal = function(m1, m2) { + var m1e = m1.elements; + var m2e = m2.elements; + var res = true; + for (var i = 0, l = m1e.length; i < l; i ++) { + if (!index$16.equal(m1e[i], m2e[i])) { + res = false; + break; + } + } + return res; +}; + +index$4.augment(Matrix3, { + type: 'matrix3', + set: function( + n11, n12, n13, + n21, n22, n23, + n31, n32, n33 + ) { + var te = this.elements; + + te[0] = n11; te[3] = n12; te[6] = n13; + te[1] = n21; te[4] = n22; te[7] = n23; + te[2] = n31; te[5] = n32; te[8] = n33; + + return this; + }, + get: function(i, j) { + i --; + j --; + return this.elements[j * 3 + i]; + }, + identity: function() { + return this.set( + 1, 0, 0, + 0, 1, 0, + 0, 0, 1 + ); + }, + multiplyScalar: function(s) { + var te = this.elements; + + te[0] *= s; te[3] *= s; te[6] *= s; + te[1] *= s; te[4] *= s; te[7] *= s; + te[2] *= s; te[5] *= s; te[8] *= s; + + return this; + }, + det: function() { + var te = this.elements; + var a = te[ 0 ], b = te[ 1 ], c = te[ 2 ], + d = te[ 3 ], e = te[ 4 ], f = te[ 5 ], + g = te[ 6 ], h = te[ 7 ], i = te[ 8 ]; + + return a * e * i - a * f * h - b * d * i + b * f * g + c * d * h - c * e * g; + }, + inverse: function(throwOnInvertible) { + return this.copy(this.getInverse(throwOnInvertible)); + }, + getInverse: function(throwOnInvertible) { + var det = this.det(); + if (det === 0) { + if (throwOnInvertible) { + throw 'matrix exception: get inverse matrix with 0 det'; + } else { + console.warn('matrix cannot inverse'); + return new Matrix3(); + } + } + var te = this.elements; + var a = te[ 0 ], b = te[ 3 ], c = te[ 6 ], + d = te[ 1 ], e = te[ 4 ], f = te[ 7 ], + g = te[ 2 ], h = te[ 5 ], i = te[ 8 ]; + var inverse = new Matrix3(); + inverse.set( + te[4] * te[8] - te[7] * te[5] , -(te[3] * te[8] - te[6] * te[5]), te[3] * te[7] - te[6] * te[4] , + -(te[1] * te[8] - te[7] * te[2]), te[0] * te[8] - te[6] * te[2] , -(te[0] * te[7] - te[6] * te[1]), + te[1] * te[5] - te[4] * te[2] , -(te[0] * te[5] - te[3] * te[2]), te[0] * te[4] - te[3] * te[1] + ); + inverse.multiplyScalar(1 / det); + return inverse; + }, + transpose: function() { + var tmp, te = this.elements; + tmp = te[1]; te[1] = te[3]; te[3] = tmp; + tmp = te[2]; te[2] = te[6]; te[6] = tmp; + tmp = te[5]; te[5] = te[7]; te[7] = tmp; + return this; + }, + multiply: function(m) { + return this.copy(Matrix3.multiply(this, m)); + }, + translate: function(x, y) { + var t = new Matrix3(); + t.set( + 1, 0, x, + 0, 1, y, + 0, 0, 1 + ); + return this.copy(Matrix3.multiply(t, this)); + }, + rotate: function(rad) { + var r = new Matrix3(); + r.set( + Math.cos(rad), -Math.sin(rad), 0, + Math.sin(rad), Math.cos(rad), 0, + 0, 0, 1 + ); + return this.copy(Matrix3.multiply(r, this)); + }, + scale: function(s1, s2) { + var s = new Matrix3(); + s.set( + s1, 0, 0, + 0, s2, 0, + 0, 0, 1 + ); + return this.copy(Matrix3.multiply(s, this)); + }, + equal: function(m) { + return Matrix3.equal(this, m); + }, + copy: function(m) { + var me = m.elements; + var te = this.elements; + for (var i = 0, l = me.length; i < l; i ++) { + te[i] = me[i]; + } + return this; + }, + clone: function() { + var m = new Matrix3(); + var me = m.elements; + var te = this.elements; + for (var i = 0, l = te.length; i < l; i ++) { + me[i] = te[i]; + } + return m; + }, + to2DObject: function() { + var te = this.elements; + return { + a: te[0], + b: te[1], + c: te[3], + d: te[4], + e: te[6], + f: te[7] + }; + }, + from2DObject: function(obj) { + var te = this.elements; + te[0] = obj.a; + te[1] = obj.b; + te[3] = obj.c; + te[4] = obj.d; + te[6] = obj.e; + te[7] = obj.f; + return this; + } +}); + + +var matrix3 = Matrix3; + +function Vector2(x, y) { + if (arguments.length === 1) { + var arr = x; + x = arr[0]; + y = arr[1]; + } + this.x = x || 0; + this.y = y || 0; +} + +// v1 v2 和 +Vector2.add = function(v1, v2) { + return new Vector2(v1.x + v2.x, v1.y + v2.y); +}; + +// v1 v2 差 +Vector2.sub = function(v1, v2) { + return new Vector2(v1.x - v2.x, v1.y - v2.y); +}; + +// v1 v2 插值 +Vector2.lerp = function(v1, v2, alpha) { + return new Vector2(v1.x + (v2.x - v1.x) * alpha, v1.y + (v2.y - v1.y) * alpha); +}; + +// v1 v2 夹角 +Vector2.angle = function(v1, v2) { + var theta = v1.dot(v2) / (v1.length() * v2.length()); + + return Math.acos(index$16.clamp(theta, -1, 1)); +}; + +// v1 到 v2 夹角的方向 +Vector2.direction = function(v1, v2) { // >= 0 顺时针 < 0 逆时针 + return v1.x * v2.y - v2.x * v1.y; +}; + + + +index$4.augment(Vector2, { + type: 'vector2', + set: function(x, y) { + this.x = x; + this.y = y; + return this; + }, + setComponent: function(index, value) { + switch(index) { + case 0: this.x = value; return this; + case 1: this.y = value; return this; + default: throw new Error('the index out of range:' + index); + } + }, + getComponent: function(index) { + switch(index) { + case 0: return this.x; + case 1: return this.y; + default: throw new Error('the index out of range:' + index); + } + }, + copy: function(v) { + this.x = v.x; + this.y = v.y; + return this; + }, + add: function(v) { + return this.copy(Vector2.add(this, v)); + }, + sub: function(v) { + return this.copy(Vector2.sub(this, v)); + }, + subBy: function(v) { + return this.copy(Vector2.sub(v, this)); + }, + multiplyScaler: function(s) { + this.x *= s; + this.y *= s; + return this; + }, + divideScaler: function(s) { + if (s !== 0) { + var invScaler = 1 / s; + this.x *= invScaler; + this.y *= invScaler; + } else { + this.x = 0; + this.y = 0; + } + return this; + }, + min: function(v) { + if (this.x > v.x) { + this.x = v.x; + } + + if (this.y > v.y) { + this.y = v.y; + } + return this; + }, + max: function(v) { + if (this.x < v.x) { + this.x = v.x; + } + + if (this.y < v.y) { + this.y = v.y; + } + + return this; + }, + clamp: function(min, max) { + if (this.x < min.x) { + this.x = min.x; + } else if (this.x > max.x){ + this.x = max.x; + } + + if (this.y < min.y) { + this.y = min.y; + } else if (this.y > max.y) { + this.y = max.y; + } + + return this; + }, + clampScale: (function() { + var min, max; + return function (minVal, maxVal) { + if (min === undefined) { + min = new Vector2(); + max = new Vector2(); + } + min.set(minVal, minVal); + max.set(maxVal, maxVal); + + return this.clamp(min, max); + }; + })(), + floor: function() { + this.x = Math.floor(this.x); + this.y = Math.floor(this.y); + return this; + }, + ceil: function() { + this.x = Math.ceil(this.x); + this.y = Math.ceil(this.y); + return this; + }, + round: function() { + this.x = Math.round(this.x); + this.y = Math.round(this.y); + return this; + }, + roundToZero: function() { + this.x = (this.x < 0) ? Math.ceil(this.x) : Math.floor(this.x); + this.y = (this.y < 0) ? Math.ceil(this.y) : Math.floor(this.y); + return this; + }, + negate: function() { + this.x = - this.x; + this.y = - this.y; + return this; + }, + dot: function(v) { + return this.x * v.x + this.y * v.y; + }, + lengthSq: function() { + return this.x * this.x + this.y * this.y; + }, + length: function() { + return Math.sqrt(this.lengthSq()); + }, + normalize: function() { + return this.divideScaler(this.length()); + }, + distanceToSquared: function(v) { + var dx = this.x - v.x, dy = this.y - v.y; + return dx * dx + dy * dy; + }, + distanceTo: function(v) { + return Math.sqrt(this.distanceToSquared(v)); + }, + angleTo: function(v, direct) { + var angle = this.angle(v); + var angleLargeThanPi = Vector2.direction(this, v) >= 0; + if (direct) { + if (angleLargeThanPi) { + return Math.PI * 2 - angle; + } else { + return angle; + } + } else { + if (angleLargeThanPi) { + return angle; + } else { + return Math.PI * 2 - angle; + } + } + }, + vertical: function(left) { + if (left) { + return new Vector2(this.y, -this.x); + } else { + return new Vector2(-this.y, this.x); + } + }, + angle: function(v) { + return Vector2.angle(this, v); + }, + setLength: function(l) { + var oldLength = this.length(); + if (oldLength !== 0 && l !== oldLength) { + this.multiplyScaler(l / oldLength); + } + return this; + }, + isZero: function() { + return this.x === 0 && this.y === 0; + }, + lerp: function(v, alpha) { + return this.copy(Vector2.lerp(this, v, alpha)); + }, + equal: function(v) { + return index$16.equal(this.x, v.x) && index$16.equal(this.y, v.y); + }, + clone: function() { + return new Vector2(this.x, this.y); + }, + rotate: function(angle) { + var nx = (this.x * Math.cos(angle)) - (this.y * Math.sin(angle)); + var ny = (this.x * Math.sin(angle)) + (this.y * Math.cos(angle)); + + this.x = nx; + this.y = ny; + + return this; + } +}); + +var vector2 = Vector2; + +function Vector3$1(x, y, z) { + if (arguments.length === 1) { + if (index$4.isArray(x)) { + var arr = x; + x = arr[0]; + y = arr[1]; + z = arr[2]; + } else if (x.type === 'vector2') { + var v = x; + x = v.x; + y = v.y; + z = 1; + } + } + this.x = x || 0; + this.y = y || 0; + this.z = z || 0; +} + +Vector3$1.add = function(v1, v2) { + return new Vector3$1(v1.x + v2.x, v1.y + v2.y, v1.z + v2.z); +}; + +Vector3$1.sub = function(v1, v2) { + return new Vector3$1(v1.x - v2.x, v1.y - v2.y, v1.z - v2.z); +}; + +Vector3$1.lerp = function(v1, v2, alpha) { + return new Vector3$1( + v1.x + (v2.x - v1.x) * alpha, + v1.y + (v2.y - v1.y) * alpha, + v1.z + (v2.z - v1.z) * alpha + ); +}; + +Vector3$1.cross = function(v, w) { + var vx = v.x, vy = v.y, vz = v.z; + var wx = w.x, wy = w.y, wz = w.z; + return new Vector3$1( + vy * wz - vz * wy, + vz * wx - vx * wz, + vx * wy - vy * wx + ); +}; + +Vector3$1.angle = function(v1, v2) { + var theta = v1.dot(v2) / (v1.length() * v2.length()); + + return Math.acos(index$16.clamp(theta, -1, 1)); +}; + +index$4.augment(Vector3$1, { + type: 'vector3', + set: function(x, y, z) { + this.x = x; + this.y = y; + this.z = z; + return this; + }, + setComponent: function(index, value) { + switch(index) { + case 0: this.x = value; return this; + case 1: this.y = value; return this; + case 2: this.z = value; return this; + default: throw new Error('index is out of range:' + index); + } + }, + getComponent: function(index) { + switch(index) { + case 0: return this.x; + case 1: return this.y; + case 2: return this.z; + default: throw new Error('index is out of range:' + index); + } + }, + add: function(v) { + return this.copy(Vector3$1.add(this, v)); + }, + sub: function(v) { + return this.copy(Vector3$1.sub(this, v)); + }, + subBy: function(v) { + return this.copy(Vector3$1.sub(v, this)); + }, + multiplyScaler: function(s) { + this.x *= s; + this.y *= s; + this.z *= s; + return this; + }, + divideScaler: function(s) { + if (s !== 0) { + var invs = 1 / s; + this.x *= invs; + this.y *= invs; + this.z *= invs; + } else { + this.x = 0; + this.y = 0; + this.z = 0; + } + return this; + }, + min: function(v) { + if (this.x > v.x) { + this.x = v.x; + } + if (this.y > v.y) { + this.y = v.y; + } + if (this.z > v.z) { + this.z = v.z; + } + return this; + }, + max: function(v) { + if (this.x < v.x) { + this.x = v.x; + } + if (this.y < v.y) { + this.y = v.y; + } + if (this.z < v.z) { + this.z = v.z; + } + return this; + }, + clamp: function(min, max) { + if (this.x < min.x) { + this.x = min.x; + } else if (this.x > max.x){ + this.x = max.x; + } + + if (this.y < min.y) { + this.y = min.y; + } else if (this.y > max.y){ + this.y = max.y; + } + + if (this.z < min.z) { + this.z = min.z; + } else if (this.z > max.z) { + this.z = max.z; + } + return this; + }, + clampScale: function() { + var min, max; + return function(minVal, maxVal) { + if (min === undefined) { + min = new Vector3$1(); + max = new Vector3$1(); + } + min.set(minVal, minVal, minVal); + max.set(maxVal, maxVal, maxVal); + + return this.clamp(min, max); + }; + }(), + floor: function() { + this.x = Math.floor(this.x); + this.y = Math.floor(this.y); + this.z = Math.floor(this.z); + return this; + }, + ceil: function() { + this.x = Math.ceil(this.x); + this.y = Math.ceil(this.y); + this.z = Math.ceil(this.z); + return this; + }, + round: function() { + this.x = Math.round(this.x); + this.y = Math.round(this.y); + this.z = Math.round(this.z); + return this; + }, + roundToZero: function() { + this.x = (this.x < 0) ? Math.ceil(this.x) : Math.floor(this.x); + this.y = (this.y < 0) ? Math.ceil(this.y) : Math.floor(this.y); + this.z = (this.z < 0) ? Math.ceil(this.z) : Math.floor(this.z); + return this; + }, + negate: function() { + this.x = - this.x; + this.y = - this.y; + this.z = - this.z; + + return this; + }, + dot: function(v) { + return this.x * v.x + this.y * v.y + this.z * v.z; + }, + lengthSq: function() { + return this.x * this.x + this.y * this.y + this.z * this.z; + }, + length: function() { + return Math.sqrt(this.lengthSq()); + }, + lengthManhattan: function() { + return Math.abs(this.x) + Math.abs(this.y) + Math.abs(this.z); + }, + normalize: function() { + return this.divideScaler(this.length()); + }, + setLength: function(l) { + var oldLength = this.length(); + + if (oldLength !== 0 && l !== oldLength) { + this.multiplyScaler(l / oldLength); + } + return this; + }, + lerp: function(v, alpha) { + return this.copy(Vector3$1.lerp(this, v, alpha)); + }, + cross: function(v) { + return this.copy(Vector3$1.cross(this, v)); + }, + // angleTo: function(v) { + // var theta = this.dot(v) / (this.length() * v.length()); + + // return Math.acos(gMath.clamp(theta, -1, 1)); + // }, + angle: function(v) { + return Vector3$1.angle(this, v); + }, + distanceToSquared: function(v) { + var dx = this.x - v.x; + var dy = this.y - v.y; + var dz = this.z - v.z; + + return dx * dx + dy * dy + dz * dz; + }, + distanceTo: function(v) { + return Math.sqrt(this.distanceToSquared(v)); + }, + applyMatrix: function(m) { + var me = m.elements; + var x = me[0] * this.x + me[3] * this.y + me[6] * this.z; + var y = me[1] * this.x + me[4] * this.y + me[7] * this.z; + var z = me[2] * this.x + me[5] * this.y + me[8] * this.z; + + this.x = x; + this.y = y; + this.z = z; + return this; + }, + copy: function(v) { + this.x = v.x; + this.y = v.y; + this.z = v.z !== undefined ? v.z : 1; + return this; + }, + equal: function(v) { + return index$16.equal(this.x, v.x) + && index$16.equal(this.y, v.y) + && index$16.equal(this.z, v.z); + }, + clone: function() { + return new Vector3$1(this.x, this.y, this.z); + } +}); + +var vector3 = Vector3$1; + +var gMatrix = { + Matrix3: matrix3, + Vector2: vector2, + Vector3: vector3 +}; + +var index$14 = gMatrix; + +var Vector3$2 = index$14.Vector3; + +var ALIAS_ATTRS = ['strokeStyle', 'fillStyle', 'globalAlpha']; +var CLIP_SHAPES = ['circle', 'ellipse', 'fan', 'polygon', 'rect', 'path']; +var CAPITALIZED_ATTRS_MAP = { + r: 'R', + opacity: 'Opacity', + lineWidth: 'LineWidth', + clip: 'Clip', + stroke: 'Stroke', + fill: 'Fill', + strokeOpacity: 'Stroke', + fillOpacity: 'Fill', + x: 'X', + y: 'Y', + rx: 'Rx', + ry: 'Ry', + re: 'Re', + rs: 'Rs', + width: 'Width', + height: 'Height', + img: 'Img', + x1: 'X1', + x2: 'X2', + y1: 'Y1', + y2: 'Y2', + points: 'Points', + p1: 'P1', + p2: 'P2', + p3: 'P3', + p4: 'P4', + text: 'Text', + radius: 'Radius', + textAlign: 'TextAlign', + textBaseline: 'TextBaseline', + font: 'Font', + fontSize: 'FontSize', + fontStyle: 'FontStyle', + fontVariant: 'FontVariant', + fontWeight: 'FontWeight', + fontFamily: 'FontFamily', + clockwise: 'Clockwise', + startAngle: 'StartAngle', + endAngle: 'EndAngle', + path: 'Path' +}; +var ALIAS_ATTRS_MAP = { + stroke: 'strokeStyle', + fill: 'fillStyle', + opacity: 'globalAlpha' +}; + +var attributes = { + canFill: false, + canStroke: false, + initAttrs: function (attrs) { + this.__attrs = { + opacity: 1, + fillOpacity: 1, + strokeOpacity: 1 + }; + this.attr(index$8.assign(this.getDefaultAttrs(), attrs)); + return this; + }, + getDefaultAttrs: function () { + return {}; + }, + + /** + * 设置或者设置属性,有以下 4 种情形: + * - name 不存在, 则返回属性集合 + * - name 为字符串,value 为空,获取属性值 + * - name 为字符串,value 不为空,设置属性值,返回 this + * - name 为键值对,value 为空,设置属性值 + * + * @param {String | Object} name 属性名 + * @param {*} value 属性值 + * @return {*} 属性值 + */ + attr: function (name, value) { + var self = this; + if (arguments.length === 0) { + return self.__attrs; + } + + if (index$8.isObject(name)) { + for (var k in name) { + if (ALIAS_ATTRS.indexOf(k) === -1) { + var v = name[k]; + self._setAttr(k, v); + } + } + if (self.__afterSetAttrAll) { + self.__afterSetAttrAll(name); + } + // self.setSilent('box', null); + self.clearBBox(); + return self; + } + if (arguments.length === 2) { + if (self._setAttr(name, value) !== false) { + var m = '__afterSetAttr' + CAPITALIZED_ATTRS_MAP[name]; + if (self[m]) { + self[m](value); + } + } + // self.setSilent('box', null); + self.clearBBox(); + return self; + } + return self._getAttr(name); + }, + clearBBox: function () { + this.setSilent('box', null); + }, + __afterSetAttrAll: function () {}, + + // 属性获取触发函数 + _getAttr: function (name) { + return this.__attrs[name]; + }, + + // 属性设置触发函数 + _setAttr: function (name, value) { + var self = this; + if (name === 'clip') { + self.__setAttrClip(value); + self.__attrs.clip = value; + } else { + self.__attrs[name] = value; + var alias = ALIAS_ATTRS_MAP[name]; + if (alias) { + self.__attrs[alias] = value; + } + } + return self; + }, + hasFill: function () { + return this.canFill && this.__attrs.fillStyle; + }, + hasStroke: function () { + return this.canStroke && this.__attrs.strokeStyle; + }, + + // 设置透明度 + __setAttrOpacity: function (v) { + this.__attrs.globalAlpha = v; + return v; + }, + __setAttrClip: function (clip) { + var self = this; + if (clip && CLIP_SHAPES.indexOf(clip.type) > -1) { + if (clip.get('canvas') === null) { + clip = index$8.clone(clip); + } + clip.set('parent', self.get('parent')); + clip.set('context', self.get('context')); + clip.inside = function (x, y) { + var v = new Vector3$2(x, y, 1); + clip.invert(v, self.get('canvas')); // 已经在外面转换 + return clip.__isPointInFill(v.x, v.y); + }; + return clip; + } + return null; + } +}; + +var Matrix3$1 = index$14.Matrix3; + +// 是否未改变 +function isUnchanged(m) { + var elements = m.elements; + return elements[0] === 1 && elements[1] === 0 && elements[3] === 0 && elements[4] === 1 && elements[6] === 0 && elements[7] === 0; +} + +// 是否仅仅是scale +function isScale(m) { + var elements = m.elements; + return elements[1] === 0 && elements[3] === 0 && elements[6] === 0 && elements[7] === 0; +} + +function multiple(m1, m2) { + if (!isUnchanged(m2)) { + if (isScale(m2)) { + m1.elements[0] *= m2.elements[0]; + m1.elements[4] *= m2.elements[4]; + } else { + m1.multiply(m2); + } + } +} + +var transform = { + initTransform: function () { + this.__m = new Matrix3$1(); + }, + translate: function (tx, ty) { + this.__m.translate(tx, ty); + this.clearTotalMatrix(); + return this; + }, + rotate: function (angle) { + this.__m.rotate(angle); // 仅支持弧度,不再支持角度 + this.clearTotalMatrix(); + return this; + }, + scale: function (s1, s2) { + this.__m.scale(s1, s2); + this.clearTotalMatrix(); + return this; + }, + + /** + * 绕起始点旋转 + * @param {Number} rotate 0~360 + */ + rotateAtStart: function (rotate) { + var x = this.attr('x'); + var y = this.attr('y'); + if (Math.abs(rotate) > Math.PI * 2) { + rotate = rotate / 180 * Math.PI; + } + this.transform([['t', -x, -y], ['r', rotate], ['t', x, y]]); + }, + + /** + * 移动的到位置 + * @param {Number} x 移动到x + * @param {Number} y 移动到y + */ + move: function (x, y) { + var cx = this.get('x') || 0; // 当前的x + var cy = this.get('y') || 0; // 当前的y + this.translate(x - cx, y - cy); + this.set('x', x); + this.set('y', y); + }, + transform: function (ts) { + var self = this; + index$8.each(ts, function (t) { + switch (t[0]) { + case 't': + self.translate(t[1], t[2]); + break; + case 's': + self.scale(t[1], t[2]); + break; + case 'r': + self.rotate(t[1]); + break; + case 'm': + self.__m = Matrix3$1.multiply(t[1], self.__m); + self.clearTotalMatrix(); + break; + default: + break; + } + }); + return self; + }, + setTransform: function (ts) { + this.__m.identity(); + return this.transform(ts); + }, + getMatrix: function () { + return this.__m; + }, + setMatrix: function (m) { + this.__m = m; + this.clearTotalMatrix(); + return this; + }, + apply: function (v, root) { + var m = void 0; + if (root) { + m = this._getMatrixByRoot(root); + } else { + m = this.__m; + } + v.applyMatrix(m); + return this; + }, + + // 获取到达指定根节点的矩阵 + _getMatrixByRoot: function (root) { + var self = this; + root = root || self; + var parent = self; + var parents = []; + + while (parent !== root) { + parents.unshift(parent); + parent = parent.get('parent'); + } + parents.unshift(parent); + + var m = new Matrix3$1(); + index$8.each(parents, function (child) { + m.multiply(child.__m); + }); + return m; + }, + + /** + * 应用到当前元素上的总的矩阵 + * @return {Matrix} 矩阵 + */ + getTotalMatrix: function () { + var m = this.__cfg.totalMatrix; + if (!m) { + m = new Matrix3$1(); + var parent = this.__cfg.parent; + if (parent) { + var pm = parent.getTotalMatrix(); + /* if (!isUnchanged(pm)) { + m.multiply(pm); + } */ + multiple(m, pm); + } + /* if (!isUnchanged(this.__m)) { + m.multiply(this.__m); + } */ + multiple(m, this.__m); + this.__cfg.totalMatrix = m; + } + return m; + }, + + // 清除当前的矩阵 + clearTotalMatrix: function () { + // this.__cfg.totalMatrix = null; + }, + invert: function (v) { + var m = this.getTotalMatrix(); + // 单精屏幕下大多数矩阵没变化 + if (isScale(m)) { + v.x /= m.elements[0]; + v.y /= m.elements[4]; + } else { + var inm = m.getInverse(); + v.applyMatrix(inm); + } + return this; + }, + resetTransform: function (context) { + var mo = this.__m.to2DObject(); + // 不改变时 + if (!isUnchanged(this.__m)) { + context.transform(mo.a, mo.b, mo.c, mo.d, mo.e, mo.f); + } + } +}; + +var Base; + +// copy attr +function initClassAttrs(c){ + if(c._attrs || c === Base){ + return; + } + + var superCon = c.superclass.constructor; + if(superCon && !superCon._attrs){ + initClassAttrs(superCon); + } + c._attrs = {}; + + index$4.mix(true,c._attrs,superCon._attrs); + index$4.mix(true,c._attrs,c.ATTRS); +} + +Base = function (cfg) { + initClassAttrs(this.constructor); // 初始化类的属性 + this._attrs = {}; // 存放变量 + this.events = {}; + var defaultCfg = this.getDefaultCfg(); + index$4.mix(this._attrs,defaultCfg,cfg); // 复制属性到对象 +}; + +index$4.augment(Base,{ + + /** + * @protected + * get the default cfg + * @return {Object} default cfg + */ + getDefaultCfg: function(){ + var _self = this, + con = _self.constructor, + attrs = con._attrs, + rst = index$4.mix(true,{},attrs); + return rst; + }, + /** + * 设置属性信息 + * @protected + */ + set : function(name,value){ + var m = '_onRender' + index$4.ucfirst(name); + if(this[m]){ + this[m](value,this._attrs[name]); + } + this._attrs[name] = value; + return this; + }, + /** + * get the property + * @protected + */ + get : function(name){ + return this._attrs[name]; + }, + /** + * bind event + * @param {String} eventType event type + * @param {Function} fn callback function + */ + on : function(eventType,fn){ + + var self = this, + events = self.events, + callbacks = events[eventType]; + + if(!callbacks){ + callbacks = events[eventType] = []; + } + callbacks.push(fn); + return self; + }, + /** + * fire the event + * @param {String} eventType event type + */ + fire : function(eventType,eventObj){ + var _self = this, + events = _self.events, + callbacks = events[eventType]; + if(callbacks){ + index$4.each(callbacks,function(m){ + m(eventObj); + }); + } + }, + /** + * remove the event + * @param {String} eventType event type + * @param {Function} fn the callback function + */ + off : function(eventType,fn){ + var self = this, + events = self.events, + callbacks = events[eventType]; + if(!eventType){ + self.events = {}; + return self; + } + if(callbacks){ + index$4.remove(callbacks,fn); + } + return self; + }, + /** + * 析构函数 + */ + destroy : function(){ + var self = this; + var destroyed = self.destroyed; + + if(destroyed){ + return self; + } + self._attrs = {}; + self.events = {}; + self.destroyed = true; + } + +}); + + + +var base = Base; + +var index$20 = base; + +function path(a, b) { + var curves = index$2.toCurve(a.path, b.path); + var curvea = curves[0]; + var curveb = curves[1]; + return function(t) { + var rst = []; + if(t >= 1){ + return b.path; + } + if(t <= 0){ + return a.path; + } + for (var i = 0; i < curvea.length; i++) { + rst[i] = [curvea[i][0]]; + for (var j = 1; j < curvea[i].length; j++) { + rst[i][j] = (curveb[i][j] - curvea[i][j])*t + curvea[i][j]; + } + } + return rst; + } +} + +var path_1 = { + path: path +}; + +function number(a, b) { + a = +a; + b = +b; + return function(t) { + return a * (1 - t) + b * t; + }; +} + +function unNumber(a, b) { + b -= a; + return function(x) { + return b === 0 ? 0 : (x - a) / b; + } +} + +var number_1 = { + number: number, + unNumber: unNumber +}; + +var HSL = function() { + this.h = 0; + this.s = 0; + this.l = 0; +}; + +index$4.augment(HSL, { + type: 'hsl', + setHSL: function(h, s, l, a) { + this.h = index$16.mod(h, 1); + this.s = index$16.clamp(s, 0, 1); + this.l = index$16.clamp(l, 0, 1); + if (a !== undefined) { + this.a = index$16.clamp(a, 0, 1); + } else { + this.a = undefined; + } + }, + toRGB: function () { + function hue2rgb( p, q, t ) { + if ( t < 0 ) t += 1; + if ( t > 1 ) t -= 1; + if ( t < 1 / 6 ) return p + ( q - p ) * 6 * t; + if ( t < 1 / 2 ) return q; + if ( t < 2 / 3 ) return p + ( q - p ) * 6 * ( 2 / 3 - t ); + return p; + } + return function () { + // h,s,l ranges are in 0.0 - 1.0 + + var self = this; + var h = self.h; + var s = self.s; + var l = self.l; + + if ( s === 0 ) { + return { + r: l, + g: l, + b: l, + a: self.a + }; + } else { + var p = l <= 0.5 ? l * ( 1 + s ) : l + s - ( l * s ); + var q = ( 2 * l ) - p; + } + return { + r: hue2rgb( q, p, h + 1 / 3 ), + g: hue2rgb( q, p, h ), + b: hue2rgb( q, p, h - 1 / 3 ), + a: self.a + }; + }; + }(), + clone: function() { + var hsl = new HSL(); + hsl.h = this.h; + hsl.s = this.s; + hsl.l = this.l; + hsl.a = this.a; + return hsl; + }, + copy: function(hsl) { + this.h = hsl.h; + this.s = hsl.s; + this.l = hsl.l; + this.a = hsl.a; + return this; + }, + getStyle: function() { + var self = this; + if (self.a === undefined) { + return 'hsl(' + Math.round(self.h * 360) + ', ' + Math.round(self.s * 100) + '%, ' + Math.round(self.l * 100) + '%)'; + } else { + return 'hsla(' + Math.round(self.h * 360) + ', ' + Math.round(self.s * 100) + '%, ' + Math.round(self.l * 100) + '%, ' + self.a +')'; + } + } +}); + +var hsl$1 = HSL; + +var RGB = function() { + this.r = 0; + this.g = 0; + this.b = 0; + this.type = 'rgb'; +}; + +index$4.augment(RGB, { + type: 'rgb', + setRGB: function(r, g, b, a) { + this.r = index$16.clamp(r, 0, 1); + this.g = index$16.clamp(g, 0, 1); + this.b = index$16.clamp(b, 0, 1); + if (a !== undefined) { + this.a = index$16.clamp(a, 0, 1); + } else { + this.a = undefined; + } + }, + toHSL: function() { + // h,s,l ranges are in 0.0 - 1.0 + var r = this.r, g = this.g, b = this.b; + var max = Math.max( r, g, b ); + var min = Math.min( r, g, b ); + var hue, saturation; + var lightness = ( min + max ) / 2.0; + if ( min === max ) { + hue = 0; + saturation = 0; + } else { + var delta = max - min; + saturation = lightness <= 0.5 ? delta / ( max + min ) : delta / ( 2 - max - min ); + switch ( max ) { + case r: hue = ( g - b ) / delta + ( g < b ? 6 : 0 ); break; + case g: hue = ( b - r ) / delta + 2; break; + case b: hue = ( r - g ) / delta + 4; break; + } + hue /= 6; + } + + return { + h: hue, + s: saturation, + l: lightness, + a: this.a + }; + }, + getHex: function() { + var hex = ( this.r * 255 ) << 16 ^ ( this.g * 255 ) << 8 ^ ( this.b * 255 ) << 0; + return '#' + ('000000' + hex.toString(16)).slice(-6); + }, + getStyle: function() { + if (this.a === undefined) { + return 'rgb(' + Math.round(this.r * 255).toString() + ', ' + Math.round(this.g * 255).toString() + ', ' + Math.round(this.b * 255).toString() + ')'; + } else { + return 'rgba(' + Math.round(this.r * 255).toString() + ', ' + Math.round(this.g * 255).toString() + ', ' + Math.round(this.b * 255).toString() + ', ' + this.a + ')'; + } + }, + getPreStyle: function() { + if (this.a === undefined) { + return 'rgb(' + Math.round(this.r * 100).toString() + '%, ' + Math.round(this.g * 100).toString() + '%, ' + Math.round(this.b * 100).toString() + '%)'; + } else { + return 'rgba(' + Math.round(this.r * 100).toString() + '%, ' + Math.round(this.g * 100).toString() + '%, ' + Math.round(this.b * 100).toString() + '%, ' + this.a + ')'; + } + }, + clone: function() { + var rgb = new RGB(); + rgb.r = this.r; + rgb.g = this.g; + rgb.b = this.b; + rgb.a = this.a; + return rgb; + }, + copy: function(rgb) { + this.r = rgb.r; + this.g = rgb.g; + this.b = rgb.b; + this.a = rgb.a; + return this; + } +}); + + +var rgb$1 = RGB; + +var colorKeywords = { 'aliceblue': 0xF0F8FF, 'antiquewhite': 0xFAEBD7, 'aqua': 0x00FFFF, 'aquamarine': 0x7FFFD4, 'azure': 0xF0FFFF, +'beige': 0xF5F5DC, 'bisque': 0xFFE4C4, 'black': 0x000000, 'blanchedalmond': 0xFFEBCD, 'blue': 0x0000FF, 'blueviolet': 0x8A2BE2, +'brown': 0xA52A2A, 'burlywood': 0xDEB887, 'cadetblue': 0x5F9EA0, 'chartreuse': 0x7FFF00, 'chocolate': 0xD2691E, 'coral': 0xFF7F50, +'cornflowerblue': 0x6495ED, 'cornsilk': 0xFFF8DC, 'crimson': 0xDC143C, 'cyan': 0x00FFFF, 'darkblue': 0x00008B, 'darkcyan': 0x008B8B, +'darkgoldenrod': 0xB8860B, 'darkgray': 0xA9A9A9, 'darkgreen': 0x006400, 'darkgrey': 0xA9A9A9, 'darkkhaki': 0xBDB76B, 'darkmagenta': 0x8B008B, +'darkolivegreen': 0x556B2F, 'darkorange': 0xFF8C00, 'darkorchid': 0x9932CC, 'darkred': 0x8B0000, 'darksalmon': 0xE9967A, 'darkseagreen': 0x8FBC8F, +'darkslateblue': 0x483D8B, 'darkslategray': 0x2F4F4F, 'darkslategrey': 0x2F4F4F, 'darkturquoise': 0x00CED1, 'darkviolet': 0x9400D3, +'deeppink': 0xFF1493, 'deepskyblue': 0x00BFFF, 'dimgray': 0x696969, 'dimgrey': 0x696969, 'dodgerblue': 0x1E90FF, 'firebrick': 0xB22222, +'floralwhite': 0xFFFAF0, 'forestgreen': 0x228B22, 'fuchsia': 0xFF00FF, 'gainsboro': 0xDCDCDC, 'ghostwhite': 0xF8F8FF, 'gold': 0xFFD700, +'goldenrod': 0xDAA520, 'gray': 0x808080, 'green': 0x008000, 'greenyellow': 0xADFF2F, 'grey': 0x808080, 'honeydew': 0xF0FFF0, 'hotpink': 0xFF69B4, +'indianred': 0xCD5C5C, 'indigo': 0x4B0082, 'ivory': 0xFFFFF0, 'khaki': 0xF0E68C, 'lavender': 0xE6E6FA, 'lavenderblush': 0xFFF0F5, 'lawngreen': 0x7CFC00, +'lemonchiffon': 0xFFFACD, 'lightblue': 0xADD8E6, 'lightcoral': 0xF08080, 'lightcyan': 0xE0FFFF, 'lightgoldenrodyellow': 0xFAFAD2, 'lightgray': 0xD3D3D3, +'lightgreen': 0x90EE90, 'lightgrey': 0xD3D3D3, 'lightpink': 0xFFB6C1, 'lightsalmon': 0xFFA07A, 'lightseagreen': 0x20B2AA, 'lightskyblue': 0x87CEFA, +'lightslategray': 0x778899, 'lightslategrey': 0x778899, 'lightsteelblue': 0xB0C4DE, 'lightyellow': 0xFFFFE0, 'lime': 0x00FF00, 'limegreen': 0x32CD32, +'linen': 0xFAF0E6, 'magenta': 0xFF00FF, 'maroon': 0x800000, 'mediumaquamarine': 0x66CDAA, 'mediumblue': 0x0000CD, 'mediumorchid': 0xBA55D3, +'mediumpurple': 0x9370DB, 'mediumseagreen': 0x3CB371, 'mediumslateblue': 0x7B68EE, 'mediumspringgreen': 0x00FA9A, 'mediumturquoise': 0x48D1CC, +'mediumvioletred': 0xC71585, 'midnightblue': 0x191970, 'mintcream': 0xF5FFFA, 'mistyrose': 0xFFE4E1, 'moccasin': 0xFFE4B5, 'navajowhite': 0xFFDEAD, +'navy': 0x000080, 'oldlace': 0xFDF5E6, 'olive': 0x808000, 'olivedrab': 0x6B8E23, 'orange': 0xFFA500, 'orangered': 0xFF4500, 'orchid': 0xDA70D6, +'palegoldenrod': 0xEEE8AA, 'palegreen': 0x98FB98, 'paleturquoise': 0xAFEEEE, 'palevioletred': 0xDB7093, 'papayawhip': 0xFFEFD5, 'peachpuff': 0xFFDAB9, +'peru': 0xCD853F, 'pink': 0xFFC0CB, 'plum': 0xDDA0DD, 'powderblue': 0xB0E0E6, 'purple': 0x800080, 'red': 0xFF0000, 'rosybrown': 0xBC8F8F, +'royalblue': 0x4169E1, 'saddlebrown': 0x8B4513, 'salmon': 0xFA8072, 'sandybrown': 0xF4A460, 'seagreen': 0x2E8B57, 'seashell': 0xFFF5EE, +'sienna': 0xA0522D, 'silver': 0xC0C0C0, 'skyblue': 0x87CEEB, 'slateblue': 0x6A5ACD, 'slategray': 0x708090, 'slategrey': 0x708090, 'snow': 0xFFFAFA, +'springgreen': 0x00FF7F, 'steelblue': 0x4682B4, 'tan': 0xD2B48C, 'teal': 0x008080, 'thistle': 0xD8BFD8, 'tomato': 0xFF6347, 'turquoise': 0x40E0D0, +'violet': 0xEE82EE, 'wheat': 0xF5DEB3, 'white': 0xFFFFFF, 'whitesmoke': 0xF5F5F5, 'yellow': 0xFFFF00, 'yellowgreen': 0x9ACD32 }; + +var regex = { + hex: /^#([A-Fa-f0-9]{3}|[A-Fa-f0-9]{6})$/, // #ffffff or #fff + space: /^((?:rgb|hsl)a?)\(\s*([^\)]*)\)$/, // rbg | rgba | hsl | hsla + rgbNum: /^(\d+)\s*,\s*(\d+)\s*,\s*(\d+)\s*$/, // rgb(255, 0, 120) + rgbaNum: /^(\d+)\s*,\s*(\d+)\s*,\s*(\d+)\s*,\s*([0-9]*\.?[0-9]+)\s*$/, // rgba(255, 0, 120, 0.2) + rgbPre: /^(\d+)\%\s*,\s*(\d+)\%\s*,\s*(\d+)\%\s*$/, // rgb(100%, 20%, 50%) + rgbaPre: /^(\d+)\%\s*,\s*(\d+)\%\s*,\s*(\d+)\%\s*,\s*([0-9]*\.?[0-9]+)\s*$/, // rgba(100%, 20%, 50%, 0.1) + hsl: /^([0-9]*\.?[0-9]+)\s*,\s*(\d+)\%\s*,\s*(\d+)\%\s*$/, // hsl(360, 100%, 100%) + hsla: /^([0-9]*\.?[0-9]+)\s*,\s*(\d+)\%\s*,\s*(\d+)\%\s*,\s*([0-9]*\.?[0-9]+)\s*$/ // hsla(360.0, 100%, 100%, 0.2) +}; + + +function Color(color) { + this.space = {}; + if(index$4.isString(color)) { + this.setStyle(color); + } else if(color instanceof Color){ + this.copy(color); + } +} + +index$4.augment(Color, { + getType: function() { + return this.space.type; + }, + toRGB: function() { + var space = this.space; + if (space.type !== 'rgb') { + var rgb = space.toRGB(); + this.setRGB(rgb.r, rgb.g, rgb.b, rgb.a); + } + }, + toHSL: function() { + var space = this.space; + if (space.type !== 'hsl') { + var hsl = space.toHSL(); + this.setHSL(hsl.h, hsl.s, hsl.l, hsl.a); + } + }, + getR: function() { + this.toRGB(); + return this.space.r; + }, + getG: function() { + this.toRGB(); + return this.space.g; + }, + getB: function() { + this.toRGB(); + return this.space.b; + }, + getH: function() { + this.toHSL(); + return this.space.h; + }, + getS: function() { + this.toHSL(); + return this.space.s; + }, + getL: function() { + this.toHSL(); + return this.space.l; + }, + getA: function() { + return this.space.a; + }, + multiplyA: function(a) { + if (a === undefined) { + return this; + } + if (this.space.a === undefined) { + this.space.a = 1; + } + this.space.a *= a; + return this; + }, + getRGBStyle: function() { + this.toRGB(); + return this.space.getStyle(); + }, + getRGBPreStyle: function() { + this.toRGB(); + return this.space.getPreStyle(); + }, + getHSLStyle: function() { + this.toHSL(); + return this.space.getStyle(); + }, + getHex: function() { + this.toRGB(); + return this.space.getHex(); + }, + setRGB: function(r, g, b, a) { + this.space = new rgb$1(); + this.space.setRGB(r, g, b, a); + return this; + }, + setHSL: function(h, s, l, a) { + this.space = new hsl$1(); + this.space.setHSL(h, s, l, a); + return this; + }, + setHex: function(hex) { + this.space = new rgb$1(); + hex = Math.floor( hex ); + + this.space.r = ( hex >> 16 & 255 ) / 255; + this.space.g = ( hex >> 8 & 255 ) / 255; + this.space.b = ( hex & 255 ) / 255; + + return this; + }, + setStyle: function(style) { + var m; + if (m = regex.hex.exec(style)) { + var hex = m[1]; + var size = hex.length; + + if (size === 3) { + this.setRGB( + parseInt( hex.charAt( 0 ) + hex.charAt( 0 ), 16 ) / 255, + parseInt( hex.charAt( 1 ) + hex.charAt( 1 ), 16 ) / 255, + parseInt( hex.charAt( 2 ) + hex.charAt( 2 ), 16 ) / 255 + ); + return this; + } else if(size === 6) { + + this.setRGB( + parseInt( hex.charAt( 0 ) + hex.charAt( 1 ), 16 ) / 255, + parseInt( hex.charAt( 2 ) + hex.charAt( 3 ), 16 ) / 255, + parseInt( hex.charAt( 4 ) + hex.charAt( 5 ), 16 ) / 255 + ); + return this; + } + } else if (m = regex.space.exec(style)){ + var name = m[1]; + var components = m[2]; + var color; + switch(name) { + case 'rgb': + if (color = regex.rgbNum.exec(components)) { + + this.setRGB( + parseInt(color[1], 10) / 255, + parseInt(color[2], 10) / 255, + parseInt(color[3], 10) / 255 + ); + return this; + } + + if (color = regex.rgbPre.exec(components)) { + this.setRGB( + parseInt(color[1], 10) / 100, + parseInt(color[2], 10) / 100, + parseInt(color[3], 10) / 100 + ); + return this; + } + break; + case 'rgba': + if (color = regex.rgbaNum.exec(components)) { + this.setRGB( + parseInt(color[1], 10) / 255, + parseInt(color[2], 10) / 255, + parseInt(color[3], 10) / 255, + parseFloat(color[4]) + ); + return this; + } + + if (color = regex.rgbaPre.exec(components)) { + this.setRGB( + parseInt(color[1], 10) / 100, + parseInt(color[2], 10) / 100, + parseInt(color[3], 10) / 100, + parseFloat(color[4]) + ); + return this; + } + break; + case 'hsl': + if (color = regex.hsl.exec(components)) { + this.setHSL( + parseInt(color[1], 10) / 360, + parseInt(color[2], 10) / 100, + parseInt(color[3], 10) / 100 + ); + return this; + } + break; + case 'hsla': + if (color = regex.hsla.exec(components)) { + this.setHSL( + parseInt(color[1], 10) / 360, + parseInt(color[2], 10) / 100, + parseInt(color[3], 10) / 100, + parseFloat(color[4]) + ); + return this; + } + break; + } + } else { + style = style.toLowerCase(); + if (colorKeywords[style] !== undefined) { + this.setHex(colorKeywords[style]); + } else { + this.setHex(colorKeywords['black']); + } + } + }, + copy: function(color) { + this.space = color.space.clone(); + }, + clone: function() { + return new Color(this); + } +}); + + +var color$1 = Color; + +var index$24 = color$1; + +function color(color1, color2) { + switch(color2.getType()) { + case 'rgb': + return rgb(color1, color2); + case 'hsl': + return hsl(color1, color2); + } +} + +function unColor(color1, color2) { + switch(color2.getType()) { + case 'rgb': + return unRgb(color1, color2); + case 'hsl': + return unHsl(color1, color2); + } +} + +function rgb(color1, color2) { + var r1 = color1.getR(); + var g1 = color1.getG(); + var b1 = color1.getB(); + var a1 = color1.getA(); + + + var r2 = color2.getR() - r1; + var g2 = color2.getG() - g1; + var b2 = color2.getB() - b1; + var a2 = color2.getA(); + + if (a1 !== undefined || a2 !== undefined) { + a1 = a1 || 1; + a2 = (a2 === undefined ? 1 : a2) - a1; + } + + return function(t) { + var rst = new index$24(); + rst.setRGB( + r1 + r2 * t, + g1 + g2 * t, + b1 + b2 * t, + (a1 !== undefined && a2 !== undefined) ? a1 + a2 * t : undefined + ); + return rst.getRGBStyle(); + }; +} + +function unRgb(color1, color2) { + var r1 = color1.getR(); + var g1 = color1.getG(); + var b1 = color1.getB(); + var a1 = color1.getA(); + + + var r2 = color2.getR() - r1; + var g2 = color2.getG() - g1; + var b2 = color2.getB() - b1; + var a2 = color2.getA(); + + if (a1 !== undefined || a2 !== undefined) { + a1 = a1 || 1; + a2 = (a2 === undefined ? 1 : a2) - a1; + } + + return function(color) { + color = new index$24(color); + if (!color.getType()) { + return 0; + } + var r = color.getR(); + var g = color.getG(); + var b = color.getB(); + var a = color.getA(); + + a = a || 1; + + var rst = 0; + var num = 0; + + if (r2 !== 0) { + rst += (r - r1) / r2; + num ++; + } + if (g2 !== 0) { + rst += (g - g1) / g2; + num ++; + } + if (b2 !== 0) { + rst += (b - b1) / b2; + num ++; + } + if (a2 !== 0 && a2) { + rst += (a - a1) / a2; + num ++; + } + return num === 0 ? 0 : rst / num; + } +} + +function hsl(color1, color2) { + var h1 = color1.getH(); + var s1 = color1.getS(); + var l1 = color1.getL(); + var a1 = color1.getA(); + + var h2 = color2.getH() - h1; + var s2 = color2.getS() - s1; + var l2 = color2.getL() - l1; + var a2 = color2.getA(); + + if (a1 !== undefined || a2 !== undefined) { + a1 = a1 || 1; + a2 = (a2 === undefined ? 1 : a2) - a1; + } + + return function(t) { + var rst = new index$24(); + rst.setHSL( + h1 + h2 * t, + s1 + s2 * t, + l1 + l2 * t, + (a1 !== undefined && a2 !== undefined) ? a1 + a2 * t : undefined + ); + return rst.getHSLStyle(); + }; + +} + +function unHsl(color1, color2) { + var h1 = color1.getH(); + var s1 = color1.getS(); + var l1 = color1.getL(); + var a1 = color1.getA(); + + var h2 = color2.getH() - h1; + var s2 = color2.getS() - s1; + var l2 = color2.getL() - l1; + var a2 = color2.getA(); + + if (a1 !== undefined || a2 !== undefined) { + a1 = a1 || 1; + a2 = (a2 === undefined ? 1 : a2) - a1; + } + + return function(color) { + color = new index$24(color); + if (!color.getType()) { + return 0; + } + var h = color.getH(); + var s = color.getS(); + var l = color.getL(); + var a = color.getA(); + + a = a || 1; + + var rst = 0; + var num = 0; + if (h2 !== 0) { + rst += (h - h1) / h2; + num ++; + } + + if (s2 !== 0) { + rst += (s - s1) / s2; + num ++; + } + + if (l2 !== 0) { + rst += (l - l1) / l2; + num ++; + } + + if (a2 !== 0 && a2) { + rst += (a - a1) / a2; + num ++; + } + + return num === 0 ? 0 : rst / num; + } +} + + +var color_1 = { + color: color, + unColor: unColor +}; + +function singular(a, b) { + if (index$4.isNumeric(a) && index$4.isNumeric(b)) { + return number_1.number(a, b); + } else if(index$4.isString(a) && index$4.isString(b)) { + var color1 = new index$24(a); + var color2 = new index$24(b); + if (color1.getType() && color2.getType()) { + return color_1.color(color1, color2); + } + } +} + +function unSingular(a, b) { + if (index$4.isNumeric(a) && index$4.isNumeric(b)) { + return number_1.unNumber(a, b); + } else if (index$4.isString(a) && index$4.isString(b)) { + var color1 = new index$24(a); + var color2 = new index$24(b); + if (color1.getType() && color2.getType()) { + return color_1.unColor(color1, color2); + } + } +} + +var singular_1 = { + singular: singular, + unSingular: unSingular +}; + +function array(a, b) { + var x = []; + var l = Math.min(a.length, b.length); + + for (var i = 0; i < l; i ++) { + if(index$4.isArray(a[i]) && index$4.isArray(b[i])) { + x[i] = array(a[i], b[i]); + } else { + x[i] = singular_1.singular(a[i], b[i]); + } + } + return function(t) { + var c = []; + for (var i = 0; i < l; i ++) { + c[i] = x[i](t); + } + return c; + } +} + +function unArray(a, b) { + var x = []; + var l = Math.min(a.length, b.length); + + for (var i = 0; i < l; i ++) { + if(index$4.isArray(a[i]) && index$4.isArray(b[i])) { + x[i] = unArray(a[i], b[i]); + } else { + x[i] = singular_1.unSingular(a[i], b[i]); + } + } + + return function(c) { + var l = Math.min(x.length, c.length); + var rst = 0; + var num = 0; + for (var i = 0; i < l; i ++) { + rst += x[i](c[i]); + num ++; + } + return num === 0 ? 0 : rst / num; + } +} + +var array_1 = { + array: array, + unArray: unArray +}; + +function object(a, b) { + var x = {}; + + for (var k in a) { + if (k in b) { + x[k] = singular_1.singular(a[k], b[k]); + } + } + + return function(t) { + var c = {}; + for (var k in x) { + c[k] = x[k](t); + } + return c; + } +} + +function unObject(a, b) { + var x = {}; + for (var k in a) { + if (k in b) { + x[k] = singular_1.unSingular(a[k], b[k]); + } + } + + return function(c) { + var rst = 0; + var num = 0; + for (var k in x) { + if (k in c) { + rst += x[k](c[k]); + num ++; + } + } + return num === 0 ? 0 : rst / num; + } +} + +var object_1 = { + object: object, + unObject: unObject +}; + +var Matrix3$4 = index$14.Matrix3; + +var l = 9; + +function matrix(m1, m2) { + var x = []; + var m1e = m1.elements; + var m2e = m2.elements; + + for (var i = 0; i < l; i ++) { + x[i] = singular_1.singular(m1e[i], m2e[i]); + } + + return function(t) { + var m = new Matrix3$4(); + var me = m.elements; + + for (var i = 0; i < l; i ++) { + me[i] = x[i](t); + } + + return m; + } +} + +function unMatrix(m1, m2) { + var x = []; + var m1e = m1.elements; + var m2e = m2.elements; + + for (var i = 0; i < l; i ++) { + x[i] = singular_1.unSingular(m1e[i], m2e[i]); + } + + return function(m) { + var me = m.elements; + var rst = 0; + var num = 0; + for (var i = 0; i < l; i ++) { + var r = x[i](me[i]); + if (r !== 0) { + rst += r; + num ++; + } + } + return rst / num; + } +} + +var matrix_1 = { + matrix: matrix, + unMatrix: unMatrix +}; + +function interpolation(a, b) { + if (index$4.isObject(a) && index$4.isObject(b)) { + if ((a.type === 'matrix3') && (b.type === 'matrix3')) { + return matrix_1.matrix(a, b); + } else if ((a.type === 'path') && (b.type === 'path')) { + return path_1.path(a, b); + } + return object_1.object(a, b); + } else if (index$4.isArray(a) && index$4.isArray(b)) { + return array_1.array(a, b); + } else { + return singular_1.singular(a, b); + } +} + +function unInterpolation(a, b) { + if ((a.type === 'matrix3') && (b.type === 'matrix3')) { + return matrix_1.unMatrix(a, b); + } else if (index$4.isArray(a) && index$4.isArray(b)) { + return array_1.unArray(a, b); + } else if (index$4.isObject(a) && index$4.isObject(b)) { + return object_1.unObject(a, b); + } else { + return singular_1.unSingular(a, b); + } +} + +var interpolation_1 = { + interpolation: interpolation, + unInterpolation: unInterpolation +}; + +var index$22 = { + interpolation: interpolation_1.interpolation, + unInterpolation: interpolation_1.unInterpolation +}; + +var ReservedProps = { + duration: 'duration', + destroy: 'destroy', + delay: 'delay', + repeat: 'repeat', + onUpdate: 'onUpdate' +}; +var Matrix3$2 = index$14.Matrix3; + +var TweenUtil = { + /** + * 差值函数 + * @return {Function} fun 差值函数 + */ + interpolation: index$22.interpolation, + /** + * 获得帧 + * @param {Nmuber} ratio 比率 + * @param {Object} skf 起始关键帧 + * @param {Object} ekf 结束关键帧 + * @param {Object} interpolations 插值器集 + * @param {Object} target 目标图形对象 + * @return {Object} frame 当前比率帧 + */ + getFrame: function(ratio, skf, ekf, interpolations, target) { + var frame = { + attrs: {}, + matrix: null + }; + var onUpdate = ekf.onUpdate; + + for (var k in interpolations.attrs) { + frame.attrs[k] = interpolations.attrs[k](ratio); + } + if(interpolations.matrix) { + frame.matrix = interpolations.matrix(ratio); + } + if (index$4.isFunction(onUpdate)) { + onUpdate(frame, ratio); + } + return frame; + }, + /** + * 获取插值函数 + * @param {Object} startKeyFrame 起始帧 + * @param {Object} endKeyFrame 结束帧 + * @return {Object} interpolation 插值器集 + */ + getInterpolations: function(startKeyFrame, endKeyFrame) { + var interpolations = { + attrs: {}, + matrix: null + }; + var interpolation; + index$4.each(startKeyFrame.attrs, function(v, k) { + interpolation = null; + if(typeof v === typeof endKeyFrame.attrs[k]){ + if(k === 'path'){ + interpolation = TweenUtil.interpolation({ + path: v, + type: 'path' + }, { + path: endKeyFrame.attrs[k], + type: 'path' + }); + } else { + interpolation = TweenUtil.interpolation(v, endKeyFrame.attrs[k]); + } + if(interpolation) { + interpolations.attrs[k] = interpolation; + } + } + }); + if(endKeyFrame.matrix && startKeyFrame.matrix && !Matrix3$2.equal(startKeyFrame.matrix, endKeyFrame.matrix)) { + interpolations.matrix = TweenUtil.interpolation(startKeyFrame.matrix, endKeyFrame.matrix); + } + return interpolations; + }, + /** + * 通过Props获取Frames + * @param {Object} target 目标图形对象 + * @param {Object} props 目标属性(包括矩阵和图形属性) + * @return {Object} frames 帧集 + */ + getKeyFrameByProps: function(target, props) { + var frames = []; + var endKeyFrame = TweenUtil.props2frame(target, props); + var startKeyFrame = { + attrs: TweenUtil.getTargetAttrs(target, endKeyFrame.attrs), + matrix: target.getMatrix() + }; + frames[0] = startKeyFrame; + frames[1] = endKeyFrame; + return frames; + }, + /** + * 格式化Props 为 Frame + * @param {Object} target 目标图形对象 + * @param {Object} props 目标属性(包括矩阵和图形属性) + * @return {Object} frame 帧 + */ + props2frame: function(target, props) { + var frame = { + matrix: null, + attrs: {} + }; + index$4.each(props, function(v, k) { + if (k === 'transform' && !props['k']) { + frame.matrix = TweenUtil.transform(target.getMatrix(), v); + } else if (k === 'matrix') { + frame.matrix = v; + } else if(k === 'onUpdate') { + frame.onUpdate = props.onUpdate; + } else if (!ReservedProps[k]) { + frame.attrs[k] = v; + } + }); + return frame; + }, + /** + * 变换快捷方式 + * @param {Object} m 矩阵 + * @param {Array} ts 变换数组同 + * @return {Object} this 回调函数 + */ + transform: function(m, ts) { + m = m.clone(); + index$4.each(ts, function(t) { + switch (t[0]) { + case 't': + m.translate(t[1], t[2]); + break; + case 's': + m.scale(t[1], t[2]); + break; + case 'r': + m.rotate(t[1]); + break; + case 'm': + m.multiply(t[1]); + break; + default: + return false; + } + }); + return m; + }, + /** 获取图形相应的图形属性 + * @param {Object} target 目标图形对象 + * @param {Object} attrs 参考图形属性 + * @return {Object} rst 图形属性 + */ + getTargetAttrs: function(target, attrs) { + var rst = {}; + var k; + for (k in attrs) { + rst[k] = target.attr(k); + } + return rst; + } +}; + +var tweenUtil = TweenUtil; + +var Ease = { + linear: function (t) { + return t; + }, + easeInQuad: function (t) { + return t * t; + }, + easeOutQuad: function (t) { + return -1 * t * (t - 2); + }, + easeInOutQuad: function (t) { + if ((t /= 1 / 2) < 1){ + return 1 / 2 * t * t; + } + return -1 / 2 * ((--t) * (t - 2) - 1); + }, + easeInCubic: function (t) { + return t * t * t; + }, + easeOutCubic: function (t) { + return 1 * ((t = t / 1 - 1) * t * t + 1); + }, + easeInOutCubic: function (t) { + if ((t /= 1 / 2) < 1){ + return 1 / 2 * t * t * t; + } + return 1 / 2 * ((t -= 2) * t * t + 2); + }, + easeInQuart: function (t) { + return t * t * t * t; + }, + easeOutQuart: function (t) { + return -1 * ((t = t / 1 - 1) * t * t * t - 1); + }, + easeInOutQuart: function (t) { + if ((t /= 1 / 2) < 1){ + return 1 / 2 * t * t * t * t; + } + return -1 / 2 * ((t -= 2) * t * t * t - 2); + }, + easeInQuint: function (t) { + return 1 * (t /= 1) * t * t * t * t; + }, + easeOutQuint: function (t) { + return 1 * ((t = t / 1 - 1) * t * t * t * t + 1); + }, + easeInOutQuint: function (t) { + if ((t /= 1 / 2) < 1){ + return 1 / 2 * t * t * t * t * t; + } + return 1 / 2 * ((t -= 2) * t * t * t * t + 2); + }, + easeInSine: function (t) { + return -1 * Math.cos(t / 1 * (Math.PI / 2)) + 1; + }, + easeOutSine: function (t) { + return 1 * Math.sin(t / 1 * (Math.PI / 2)); + }, + easeInOutSine: function (t) { + return -1 / 2 * (Math.cos(Math.PI * t / 1) - 1); + }, + easeInExpo: function (t) { + return (t === 0) ? 1 : 1 * Math.pow(2, 10 * (t / 1 - 1)); + }, + easeOutExpo: function (t) { + return (t === 1) ? 1 : 1 * (-Math.pow(2, -10 * t / 1) + 1); + }, + easeInOutExpo: function (t) { + if (t === 0){ + return 0; + } + if (t === 1){ + return 1; + } + if ((t /= 1 / 2) < 1){ + return 1 / 2 * Math.pow(2, 10 * (t - 1)); + } + return 1 / 2 * (-Math.pow(2, -10 * --t) + 2); + }, + easeInCirc: function (t) { + if (t >= 1){ + return t; + } + return -1 * (Math.sqrt(1 - (t /= 1) * t) - 1); + }, + easeOutCirc: function (t) { + return 1 * Math.sqrt(1 - (t = t / 1 - 1) * t); + }, + easeInOutCirc: function (t) { + if ((t /= 1 / 2) < 1){ + return -1 / 2 * (Math.sqrt(1 - t * t) - 1); + } + return 1 / 2 * (Math.sqrt(1 - (t -= 2) * t) + 1); + }, + easeInElastic: function (t) { + var s = 1.70158; + var p = 0; + var a = 1; + if (t === 0){ + return 0; + } + if ((t /= 1) == 1){ + return 1; + } + if (!p){ + p = 1 * 0.3; + } + if (a < Math.abs(1)) { + a = 1; + s = p / 4; + } else{ + s = p / (2 * Math.PI) * Math.asin(1 / a); + } + return -(a * Math.pow(2, 10 * (t -= 1)) * Math.sin((t * 1 - s) * (2 * Math.PI) / p)); + }, + easeOutElastic: function (t) { + var s = 1.70158; + var p = 0; + var a = 1; + if (t === 0){ + return 0; + } + if ((t /= 1) == 1){ + return 1; + } + if (!p){ + p = 1 * 0.3; + } + if (a < Math.abs(1)) { + a = 1; + s = p / 4; + } else{ + s = p / (2 * Math.PI) * Math.asin(1 / a); + } + return a * Math.pow(2, -10 * t) * Math.sin((t * 1 - s) * (2 * Math.PI) / p) + 1; + }, + easeInOutElastic: function (t) { + var s = 1.70158; + var p = 0; + var a = 1; + if (t === 0){ + return 0; + } + if ((t /= 1 / 2) == 2){ + return 1; + } + if (!p){ + p = 1 * (0.3 * 1.5); + } + if (a < Math.abs(1)) { + a = 1; + s = p / 4; + } else { + s = p / (2 * Math.PI) * Math.asin(1 / a); + } + if (t < 1){ + return -0.5 * (a * Math.pow(2, 10 * (t -= 1)) * Math.sin((t * 1 - s) * (2 * Math.PI) / p));} + return a * Math.pow(2, -10 * (t -= 1)) * Math.sin((t * 1 - s) * (2 * Math.PI) / p) * 0.5 + 1; + }, + easeInBack: function (t) { + var s = 1.70158; + return 1 * (t /= 1) * t * ((s + 1) * t - s); + }, + easeOutBack: function (t) { + var s = 1.70158; + return 1 * ((t = t / 1 - 1) * t * ((s + 1) * t + s) + 1); + }, + easeInOutBack: function (t) { + var s = 1.70158; + if ((t /= 1 / 2) < 1){ + return 1 / 2 * (t * t * (((s *= (1.525)) + 1) * t - s)); + } + return 1 / 2 * ((t -= 2) * t * (((s *= (1.525)) + 1) * t + s) + 2); + }, + easeInBounce: function (t) { + return 1 - Ease.easeOutBounce(1 - t); + }, + easeOutBounce: function (t) { + if ((t /= 1) < (1 / 2.75)) { + return 1 * (7.5625 * t * t); + } else if (t < (2 / 2.75)) { + return 1 * (7.5625 * (t -= (1.5 / 2.75)) * t + 0.75); + } else if (t < (2.5 / 2.75)) { + return 1 * (7.5625 * (t -= (2.25 / 2.75)) * t + 0.9375); + } else { + return 1 * (7.5625 * (t -= (2.625 / 2.75)) * t + 0.984375); + } + }, + easeInOutBounce: function (t) { + if (t < 1 / 2){ + return Ease.easeInBounce(t * 2) * 0.5; + } + return Ease.easeOutBounce(t * 2 - 1) * 0.5 + 1 * 0.5; + } +}; +var ease = Ease; + +var Tween = function(cfg) { + index$4.mix(this, cfg); + this._init(); +}; + +index$4.augment(Tween, { + /** + * 类型 + * @type {String} + */ + type: 'tween', + /** + * 画布对象 + * @type {Object} + */ + canvas: null, + /** + * 目标图形对象 + * @type {Object} + */ + target: null, + /** + * 起始时间 + * @type {Number} + */ + startTime: null, + /** + * 结束时间 + * @type {Number} + */ + endTime: null, + /** + * 持续时间 + * @type {Number} + */ + duration: null, + /** + * 绘制比率 + * @type {Number} + */ + ratio: 0, + /** + * 动画结束后是否要被清除目标对象 + * @type {Boolean} + */ + destroyTarget: false, + /** + * 是否要被清除 + * @type {Boolean} + */ + needsDestroy: false, + /** + * 是否可被执行 + * @type {Boolean} + */ + available: true, + /** + * 是否重复 + * @type {Boolean} + */ + repeat: false, + /** + * 回调函数 + * @type {Function} + */ + callBack: null, + /** + * 当前帧 + * @type {Object} + */ + currentFrame: null, + /** + * 起始关键帧 + * @type {Object} + */ + startKeyFrame: { + attrs: null, + matrix: null + }, + /** + * 结束关键帧 + * @type {Object} + */ + endKeyFrame: { + attrs: null, + matrix: null + }, + /** + * 插值器集 + * @type {Object} + */ + interpolations: null, + _init: function() { + var startTime = this.startTime; + var duration = this.duration; + this.endTime = startTime + duration; + }, + /** + * 尝试执行 + * @param {Number} time 时间戳 + */ + tryStep: function(time) { + var startTime = this.startTime; + var duration = this.duration; + var startKeyFrame = this.startKeyFrame; + var target = this.target; + var realStartTime = startTime; + if(!target || target.get('destroyed')) { + this.needsDestroy = true; + return false; + } + try { + this.step(time); + } catch (ev) { // 异常,中断重绘 + this.needsDestroy = true; + return false; + } + }, + /** + * 执行 + * @param {Number} time 时间戳 + */ + step: function(time) { + var target = this.target; // 目标对象 + var startTime = this.startTime; // 开始时间 + var elapsed = time - startTime; // 逝去时间 + var duration = this.duration; // 持续时间 + var skf = this.startKeyFrame; // 开始帧 + var ekf = this.endKeyFrame; // 结束帧 + var easing = this.easing; // 缓动函数名 + var interpolations = this.interpolations; + var ckf; // 当前帧 + var ratio; // 真实比率 + var easeRatio; // 绘制比率 + + if (!index$4.isFunction(easing)) easing = ease[easing] ? ease[easing] : ease['linear']; + ratio = elapsed / duration; + ratio = ratio <= 0 ? 0 : ratio >= 1 ? 1 : ratio; + easeRatio = easing(ratio); + ckf = tweenUtil.getFrame(easeRatio, skf, ekf, interpolations, target); + ckf.attrs && target.attr(ckf.attrs); + ckf.matrix && target.setMatrix(ckf.matrix); + this.ratio = ratio; + this.currentFrame = ckf; + this.updateStatus(); + return target; + }, + /** + * 更新状态 + */ + updateStatus: function() { + var ratio = this.ratio; + var callBack = this.callBack; + var destroyTarget = this.destroyTarget; + var target = this.target; + var repeat = this.repeat; + if (ratio >= 1) { + if (repeat) { + var startTime = this.startTime; + var endTime = this.endTime; + var duration = this.duration; + this.startTime = startTime + duration; + this.endTime = endTime + duration; + this.reset(); + } else { + this.needsDestroy = true; + callBack && callBack.call(target); + destroyTarget && !target.get('destroyed') && target.remove(true); + } + } else { + return; + } + }, + /** + * 重置当前补间 + */ + reset: function() { + var target = this.target; + var skf = this.startKeyFrame; + skf.attrs && target.attr(skf.attrs); + skf.matrix && target.setMatrix(skf.matrix); + this.ratio = 0; + this.needsDestroy = false; + }, + destroy: function(){ + var target = this.target; + var ekf = this.endKeyFrame; + if(target && !target.get('destroyed')){ + ekf.attrs && target.attr(ekf.attrs); + ekf.matrix && target.setMatrix(ekf.matrix); + } + this.destroyed = true; + } +}); + +var tween$1 = Tween; + +var Creator = function(cfg) { + index$4.mix(this, cfg); +}; + +index$4.augment(Creator, { + /** + * 目标图形对象 + * @type {Object} + */ + target: null, + /** + * 时间轴 + * @type {Object} + */ + timeline: null, + /** + * 开始时间 + * @type {Number} + */ + startTime: null, + /** + * 添加方法 + * @param {Number} time 开始时间 + * @param {Object} props 属性 + * @param {String} easing 补间动画类型 + * @param {Function} callBack 回调函数 + */ + append: function(time, props, easing, callBack){ + var id = index$4.guid('tween_'); + var target = this.target; + var tweens = this.tweens; + var timeline = this.timeline; + var startTime = this.startTime; + var frames = tweenUtil.getKeyFrameByProps(target, props); + var startKeyFrame = frames[0]; // startKeyFrame 起始帧 + var endKeyFrame = frames[1]; // endKeyFrame 结束帧 + var interpolations = tweenUtil.getInterpolations(startKeyFrame, endKeyFrame); + var tween; + time = time ? time : startTime; + if(props && props.delay) time += props.delay; + tween = new tween$1({ + id: id, + canvas: target.get('canvas'), + startTime: time, + target: target, + easing: easing, + callBack: callBack, + startKeyFrame: startKeyFrame, + endKeyFrame: endKeyFrame, + interpolations: interpolations, + duration: props.duration ? props.duration : 1000, + repeat: props.repeat ? props.repeat : false, + destroyTarget: props.destroy ? props.destroy : false + }); + timeline && timeline.add(tween); // 如果时间轴存在,则添加到时间轴 + return this; + } +}); + +var tweenCreator = Creator; + +var Timeline = function(cfg) { + Timeline.superclass.constructor.call(this, cfg); + this._init(); +}; + +Timeline.ATTRS = { + /** + * 运行到的时间 + * @type {Boolean} + */ + time: 0, + + /** + * 创建时间 + * @type {Number} + */ + createTime: null, + + /** + * 播放时间 + * @type {Number} + */ + playTime: null, + + /** + * 距离上次播放的暂停间隔时间 + * @type {Number} + */ + pauseTimeSpace: 0, + + /** + * 是否可被执行 + * @type {Boolean} + */ + available: false, + /** + * 画布集 + * @type {Array} + */ + canvases: [], + + /** + * 补间集 + * @type {Array} + */ + tweens: [], + + /** + * 结束时间 + * @type {Number} + */ + endTime: 0, + + /** + * 是否自动播放 + * @type {Boolean} + */ + autoPlay: false, + + /** + * 状态 + * @type {String} + * silent 静默 + * playing 播放 + */ + status: 'silent', + + /** + * 自动绘制 + * @type {Boolean} + */ + autoDraw: true +}; + +index$4.extend(Timeline, index$20); + +index$4.augment(Timeline, { + // 初始化 + _init: function() { + var autoPlay = this.get('autoPlay'); + this.set('createTime', +new Date()); + if (autoPlay) { + this.play(); + } + }, + // 尝试设置结束时间 + _trySetEndTime: function(tween){ + var self = this; + if (index$4.isObject(tween)) { + self._setEndTime(tween); + }else if (index$4.isArray(tween)) { + index$4.each(tween, function(v, k){ + self._setEndTime(v); + }); + } + }, + // 尝试设置Canvas + _trySetCanvases: function(tween){ + var self = this; + if (index$4.isObject(tween)) { + self._setCanvases(tween); + }else if (index$4.isArray(tween)) { + index$4.each(tween, function(v, k){ + self._setCanvases(v); + }); + } + }, + // 设置结束时间 + _setEndTime: function(tween){ + var endTime = this.get('endTime'); + var tweenEndTime = tween.endTime; + if(tweenEndTime > endTime){ + this.set('endTime', tweenEndTime); + } + }, + // 设置画布 + _setCanvases: function(tween){ + var canvas = tween.canvas; + var canvases = this.get('canvases'); + if (canvases.indexOf(canvas) === -1) { + canvases.push(canvas); + } + }, + // 重置补间 + _resetTweens: function(){ + var tweens = this.get('tweens'); + tweens.sort(function(a, b){ // 需要让起始时间最小的最后重设 + return b.get('startTime')-a.get('startTime'); + }); + index$4.each(tweens, function(v) { + v.reset(); + }); + }, + // 获取自身时间轴 + _getTime: function(){ + var playTime = this.get('playTime'); + var pauseTimeSpace = this.get('pauseTimeSpace'); + return +new Date() - playTime + pauseTimeSpace; + }, + // 刷新 (画布刷新) + _refresh: function(time){ + var tweens = this.get('tweens'); + var canvases = this.get('canvases'); + var autoDraw = this.get('autoDraw'); + var tweensStash = []; // 缓存未销毁的补间 + var canvasesStash = []; // 缓存当前动画涉及画布 + var canvas; + var tween; + for (var i = 0; i < tweens.length; i++) { + tween = tweens[i]; + canvas = tween.canvas; + if (tween.needsDestroy) { + tween.destroy(); + } else if (!tween.destroyed && !tween.needsDestroy) { + tween.tryStep(time); // 尝试运行 + } + if (!tween.destroyed) { + tweensStash.push(tween); + } + if (!index$4.inArray(canvasesStash, canvas) && !tween.destroyed){ + canvasesStash.push(canvas); + } + } + if(autoDraw) { + this.draw(); + } + this.set('canvases', canvasesStash); + this.set('tweens', tweensStash); + }, + // 更新(时间和状态) + _update: function() { + if(!this.get('available')) { + return; // 不可用则强制停止所有更新 + } + var self = this; + var tweens = self.get('tweens'); + var time; + if(tweens.length > 0){ + time = self._getTime(); + self._refresh(time); + } + self.fire('update'); + index$4.requestAnimationFrame(function() { + self._update(); + }); + }, + /** + * 生成补间生成器 + * @param {Object} target 图形对象 + * @param {Number} startTime 开始时间 + * @return {Object} tweenCreator 补间生成器 + */ + animate: function(target, startTime) { + var tweenCreator$$1 = new tweenCreator({ + target: target, + timeline: this, + startTime: startTime ? startTime : 0 + }); + return tweenCreator$$1; + }, + /** + * 添加补间 + * @param {Object || Array} tweens 补间 + * @return {Object} this + */ + add: function(tween) { + var tweens = this.get('tweens'); + var rst; + if (index$4.isArray(tween)) { + rst = tweens.concat(tween); + } else if (index$4.isObject(tween) && tween.type === 'tween') { + tweens.push(tween); + rst = tweens; + } else { + console.error('Timeline not Support this type'); + } + this.set('tweens', rst); + this._trySetCanvases(tween); + this._trySetEndTime(tween); + return this; + }, + /** + * 获取当前时间 + * @param {Nmuber} time 自身时间轴时间点 + */ + getNow: function() { + var playTime = this.get('playTime'); + return playTime ? (+new Date() - playTime) : 0 ; + }, + /** + * 通过实际时间,获取时间轴时间 (同getNow, 0.3.x废弃) + * @param {Nmuber} time 自身时间轴时间点 + */ + getTime: function() { + var playTime = this.get('playTime'); + return playTime ? (+new Date() - playTime) : 0 ; + }, + /** + * 播放 + */ + play: function() { + var status = this.get('status'); + if (status === 'silent') { + this.set('playTime', +new Date()); + this.set('available', true); + this.set('status', 'playing'); + this._update(); + } + return this; + }, + /** + * 停止 + */ + stop: function(){ + this.set('status', 'silent'); + this.set('available', false); + this.set('pauseTimeSpace', 0); + this._resetTweens(); + this._refresh(0); // 画面刷新至初始态 + this.draw(); + }, + /** + * 暂停 + */ + pause: function() { + var available = this.get('available'); + if(available) this.set('pauseTimeSpace', +new Date() - this.get('playTime')); + this.set('available', false); + this.set('status', 'silent'); + return this; + }, + /** + * 重置 + */ + reset: function() { + this.set('status', 'silent'); + this.set('available', false); + this.set('pauseTimeSpace', 0); + this.set('playTime', 0); + this.set('endTime', 0); + this.set('tweens', []); + this.set('canvases', []); + }, + /** + * 绘制 + */ + draw: function() { + var canvases = this.get('canvases'); + var canvas; + for (var i = 0; i < canvases.length; i++) { + canvas = canvases[i]; + !canvas.get('destroyed') && canvas.draw(); + } + return; + } +}); + +var timeline = Timeline; + +timeline.Tween = tween$1; +timeline.Ease = ease; +var index$18 = timeline; + +var tween = new index$18(); + +var animate = { + tween: tween, + animate: function (toProps, duration, easing, callBack) { + var now = tween.getNow(); + var cfg = index$8.merge({}, toProps, { + duration: duration + }); + tween.animate(this).append(now, cfg, easing, callBack); + if (tween.get('status') === 'silent') tween.play(); + } +}; + +var eventDispatcher = { + /** + * 事件分发器的处理函数 + */ + initEventDispatcher: function () { + this.__listeners = {}; + }, + + /** + * 为对象注册事件 + * @param {String} type 事件类型 + * @param {Function} listener 回调函数 + * @return {Object} this + */ + on: function (type, listener) { + var listeners = this.__listeners; + + if (index$8.isNil(listeners[type])) { + listeners[type] = []; + } + + if (listeners[type].indexOf(listener) === -1) { + listeners[type].push(listener); + } + return this; + }, + + /** + * 为对象取消事件回调 + * 三个模式 + * 模式1: 没有参数的时候,取消所有回调处理函数 + * 模式2: 只有type的时候,取消所有type的回调类别 + * 模式3: 同时具有type, listener参数时,只取消type中listener对应的回调 + * @param {String} type 事件类型 + * @param {Function} listener 回调函数 + * @return {Object} this + */ + off: function (type, listener) { + var listeners = this.__listeners; + if (arguments.length === 0) { + this.__listeners = {}; + return this; + } + + if (arguments.length === 1 && index$8.isString(type)) { + listeners[type] = []; + return this; + } + + if (arguments.length === 2 && index$8.isString(type) && index$8.isFunction(listener)) { + index$8.remove(listeners[type], listener); + return this; + } + }, + + /** + * 判断某个listener是否是当前对象的回调函数 + * @param {String} type 事件类型 + * @param {Function} listener 回调函数 + * @return {Object} this + */ + has: function (type, listener) { + var listeners = this.__listeners; + + if (arguments.length === 0) { + if (!index$8.isEmpty(listeners)) { + return true; + } + } + + if (arguments.length === 1) { + if (listeners[type] && !index$8.isEmpty(listeners[type])) { + return true; + } + } + + if (arguments.length === 2) { + if (listeners[type] && listeners[type].indexOf(listener) !== -1) { + return true; + } + } + + return false; + }, + trigger: function (event) { + var self = this; + var listeners = self.__listeners; + var listenersArray = listeners[event.type]; + event.target = self; + if (!index$8.isNil(listenersArray)) { + listenersArray.forEach(function (listener) { + listener.call(self, event); + }); + } + if (event.bubbles) { + var parent = self.get('parent'); + if (parent && !event.propagationStopped) { + parent.trigger(event); + } + } + return self; + }, + + /** + * fire the event + * @param {String} eventType event type + * @param {Object} [eventObj] event + */ + fire: function (eventType, eventObj) { + var event = new index$10(eventType); + index$8.each(eventObj, function (v, k) { + event[k] = v; + }); + this.trigger(event); + } +}; + +var regexTags = /[MLHVQTCSAZ]([^MLHVQTCSAZ]*)/ig; +var regexDot = /[^\s\,]+/ig; +var regexLG = /^l\s*\(\s*([\d.]+)\s*\)\s*(.*)/i; +var regexRG = /^r\s*\(\s*([\d.]+)\s*,\s*([\d.]+)\s*,\s*([\d.]+)\s*\)\s*(.*)/i; +var regexPR = /^p\s*([axyn])\s+(.*)/i; +var regexColorStop = /[\d.]+:(#[^\s]+|[^\)]+\))/ig; +var numColorCache = {}; + +function multiplyOpacity(color, opacity) { + if (opacity === undefined) { + return color; + } + color = new index$24(color); + color.multiplyA(opacity); + var type = color.getType(); + if (type === 'hsl') { + return color.getHSLStyle(); + } else if (type === 'rgb') { + return color.getRGBStyle(); + } +} + +function addStop(steps, gradient, opacity) { + var arr = steps.match(regexColorStop); + index$8.each(arr, function (item) { + item = item.split(':'); + var color = multiplyOpacity(item[1], opacity); + gradient.addColorStop(item[0], color); + }); +} + +function parseLineGradient(color, self, opacity) { + var arr = regexLG.exec(color); + var angle = index$8.mod(index$8.toRadian(parseFloat(arr[1])), Math.PI * 2); + var steps = arr[2]; + var box = self.getBBox(); + var start = void 0; + var end = void 0; + + if (angle >= 0 && angle < 0.5 * Math.PI) { + start = { + x: box.minX, + y: box.minY + }; + end = { + x: box.maxX, + y: box.maxY + }; + } else if (0.5 * Math.PI <= angle && angle < Math.PI) { + start = { + x: box.maxX, + y: box.minY + }; + end = { + x: box.minX, + y: box.maxY + }; + } else if (Math.PI <= angle && angle < 1.5 * Math.PI) { + start = { + x: box.maxX, + y: box.maxY + }; + end = { + x: box.minX, + y: box.minY + }; + } else { + start = { + x: box.minX, + y: box.maxY + }; + end = { + x: box.maxX, + y: box.minY + }; + } + + var tanTheta = Math.tan(angle); + var tanTheta2 = tanTheta * tanTheta; + + var x = (end.x - start.x + tanTheta * (end.y - start.y)) / (tanTheta2 + 1) + start.x; + var y = tanTheta * (end.x - start.x + tanTheta * (end.y - start.y)) / (tanTheta2 + 1) + start.y; + var context = self.get('context'); + var gradient = context.createLinearGradient(start.x, start.y, x, y); + addStop(steps, gradient, opacity); + return gradient; +} + +function parseRadialGradient(color, self, opacity) { + var arr = regexRG.exec(color); + var fx = parseFloat(arr[1]); + var fy = parseFloat(arr[2]); + var fr = parseFloat(arr[3]); + var steps = arr[4]; + var box = self.getBBox(); + var context = self.get('context'); + var width = box.maxX - box.minX; + var height = box.maxY - box.minY; + var r = Math.sqrt(width * width + height * height) / 2; + var gradient = context.createRadialGradient(box.minX + width * fx, box.minY + height * fy, fr, box.minX + width / 2, box.minY + height / 2, r); + addStop(steps, gradient, opacity); + return gradient; +} + +function parsePattern(color, self) { + var arr = regexPR.exec(color); + var repeat = arr[1]; + var id = arr[2]; + switch (repeat) { + case 'a': + repeat = 'repeat'; + break; + case 'x': + repeat = 'repeat-x'; + break; + case 'y': + repeat = 'repeat-y'; + break; + case 'n': + repeat = 'no-repeat'; + break; + default: + repeat = 'no-repeat'; + } + var img = document.getElementById(id); + var context = self.get('context'); + var pattern = context.createPattern(img, repeat); + return pattern; +} + +var format = { + parsePath: function (path) { + path = path || []; + if (index$8.isArray(path)) { + return path; + } + + if (index$8.isString(path)) { + path = path.match(regexTags); + index$8.each(path, function (item, index) { + item = item.match(regexDot); + if (item[0].length > 1) { + var tag = item[0].charAt(0); + item.splice(1, 0, item[0].substr(1)); + item[0] = tag; + } + index$8.each(item, function (sub, i) { + if (!isNaN(sub)) { + item[i] = +sub; + } + }); + path[index] = item; + }); + return path; + } + }, + parseStyle: function (color, self, opacity) { + if (index$8.isString(color)) { + if (color[1] === '(' || color[2] === '(') { + if (color[0] === 'l') { + // regexLG.test(color) + return parseLineGradient(color, self, opacity); + } else if (color[0] === 'r') { + // regexRG.test(color) + return parseRadialGradient(color, self, opacity); + } else if (color[0] === 'p') { + // regexPR.test(color) + return parsePattern(color, self); + } + } + if (index$8.isNil(opacity)) { + return color; + } + return multiplyOpacity(color, opacity); + } + }, + numberToColor: function (num) { + // 增加缓存 + var color = numColorCache[num]; + if (!color) { + var str = num.toString(16); + for (var i = str.length; i < 6; i++) { + str = '0' + str; + } + color = '#' + str; + numColorCache[num] = color; + } + return color; + } +}; + +var SHAPE_ATTRS = ['fillStyle', 'font', 'globalAlpha', 'lineCap', 'lineWidth', 'lineJoin', 'miterLimit', 'shadowBlur', 'shadowColor', 'shadowOffsetX', 'shadowOffsetY', 'strokeStyle', 'textAlign', 'textBaseline', 'lineDash']; + +var Element = function (cfg) { + this.__cfg = { + zIndex: 0, + capture: true, + visible: true, + destroyed: false + }; // 配置存放地 + + index$8.assign(this.__cfg, this.getDefaultCfg(), cfg); // Element.CFG不合并,提升性能 合并默认配置,用户配置->继承默认配置->Element默认配置 + this.initAttrs(this.__cfg.attrs); // 初始化绘图属性 + this.initTransform(); // 初始化变换 + this.initEventDispatcher(); + this.init(); // 类型初始化 +}; + +Element.CFG = { + /** + * 唯一标示 + * @type {Number} + */ + id: null, + /** + * Z轴的层叠关系,Z值越大离用户越近 + * @type {Number} + */ + zIndex: 0, + /** + * Canvas对象 + * @type: {Object} + */ + canvas: null, + /** + * 父元素指针 + * @type {Object} + */ + parent: null, + /** + * 用来设置当前对象是否能被捕捉 + * true 能 + * false 不能 + * 对象默认是都可以被捕捉的, 当capture为false时,group.getShape(x, y)方法无法获得该元素 + * 通过将不必要捕捉的元素的该属性设置成false, 来提高捕捉性能 + * @type {Boolean} + **/ + capture: true, + /** + * 画布的上下文 + * @type {Object} + */ + context: null, + /** + * 是否显示 + * @type {Boolean} + */ + visible: true, + /** + * 是否被销毁 + * @type: {Boolean} + */ + destroyed: false +}; + +index$8.augment(Element, attributes, eventDispatcher, transform, animate, { + init: function () { + this.setSilent('animable', true); + var attrs = this.__attrs; + if (attrs && attrs.rotate) { + this.rotateAtStart(attrs.rotate); + } + }, + getParent: function () { + return this.get('parent'); + }, + + /** + * 获取默认的配置信息 + * @protected + * @return {Object} 默认的属性 + */ + getDefaultCfg: function () { + return {}; + }, + set: function (name, value) { + var m = '__set' + index$8.upperFirst(name); + + if (this[m]) { + value = this[m](value); + } + this.__cfg[name] = value; + return this; + }, + setSilent: function (name, value) { + this.__cfg[name] = value; + }, + get: function (name) { + return this.__cfg[name]; + }, + draw: function (context) { + if (this.get('destroyed')) { + return; + } + if (this.get('visible')) { + this.setContext(context); + this.drawInner(context); + this.restoreContext(context); + } + }, + setContext: function (context) { + var clip = this.__attrs.clip; + context.save(); + if (clip) { + // context.save(); + clip.resetTransform(context); + clip.createPath(context); + context.clip(); + // context.restore(); + } + this.resetContext(context); + this.resetTransform(context); + }, + restoreContext: function (context) { + context.restore(); + }, + resetContext: function (context) { + var elAttrs = this.__attrs; + // var canvas = this.get('canvas'); + if (!this.isGroup) { + // canvas.registShape(this); // 快速拾取方案暂时不执行 + for (var k in elAttrs) { + if (SHAPE_ATTRS.indexOf(k) > -1) { + // 非canvas属性不附加 + var v = elAttrs[k]; + if (k === 'fillStyle') { + v = format.parseStyle(v, this); + } + if (k === 'strokeStyle') { + v = format.parseStyle(v, this); + } + if (k === 'lineDash' && context.setLineDash) { + if (index$8.isArray(v)) { + context.setLineDash(v); + } else if (index$8.isString(v)) { + context.setLineDash(v.split(' ')); + } + } else { + context[k] = v; + } + } + } + } + }, + drawInner: function () /* context */{}, + show: function () { + this.set('visible', true); + return this; + }, + hide: function () { + this.set('visible', false); + return this; + }, + remove: function (destroy) { + if (destroy === undefined) { + destroy = true; + } + + if (this.get('parent')) { + var parent = this.get('parent'); + var children = parent.get('children'); + index$8.remove(children, this); + // this.set('parent', null); + } + + if (destroy) { + this.destroy(); + } + + return this; + }, + destroy: function () { + var destroyed = this.get('destroyed'); + + if (destroyed) { + return; + } + this.__cfg = {}; + this.__attrs = null; + this.__listeners = null; + this.__m = null; + this.set('destroyed', true); + }, + __setZIndex: function (zIndex) { + this.__cfg.zIndex = zIndex; + if (!index$8.isNil(this.get('parent'))) { + this.get('parent').sort(); + } + return zIndex; + }, + __setAttrs: function (attrs) { + this.attr(attrs); + return attrs; + }, + clone: function () { + return index$8.clone(this); + }, + getBBox: function () { + return { + minX: 0, + maxX: 0, + minY: 0, + maxY: 0 + }; + } +}); + +var element = Element; + +/** + * @fileOverview 直线算法 + * @author hankaiai@126.com + * @ignore + */ +var Vector2$1 = index$14.Vector2; + +var line = { + at: function (p1, p2, t) { + return (p2 - p1) * t + p1; + }, + pointDistance: function (x1, y1, x2, y2, x, y) { + var d = new Vector2$1(x2 - x1, y2 - y1); + if (d.isZero()) { + return NaN; + } + + var u = d.vertical(); + u.normalize(); + var a = new Vector2$1(x - x1, y - y1); + return Math.abs(a.dot(u)); + }, + box: function (x1, y1, x2, y2, lineWidth) { + var halfWidth = lineWidth / 2; + var minX = Math.min(x1, x2); + var maxX = Math.max(x1, x2); + var minY = Math.min(y1, y2); + var maxY = Math.max(y1, y2); + + return { + minX: minX - halfWidth, + minY: minY - halfWidth, + maxX: maxX + halfWidth, + maxY: maxY + halfWidth + }; + }, + len: function (x1, y1, x2, y2) { + return Math.sqrt((x2 - x1) * (x2 - x1) + (y2 - y1) * (y2 - y1)); + } +}; + +/** + * @fileOverview 二次贝赛尔曲线算法 + * @author hankaiai@126.com + * @ignore + */ +var Vector2$2 = index$14.Vector2; + + +function quadraticAt(p0, p1, p2, t) { + var onet = 1 - t; + return onet * (onet * p0 + 2 * t * p1) + t * t * p2; +} + +function quadraticProjectPoint(x1, y1, x2, y2, x3, y3, x, y, out) { + var t = void 0; + var interval = 0.005; + var d = Infinity; + var d1 = void 0; + var v1 = void 0; + var v2 = void 0; + var _t = void 0; + var d2 = void 0; + var i = void 0; + var EPSILON = 0.0001; + var v0 = new Vector2$2(x, y); + + for (_t = 0; _t < 1; _t += 0.05) { + v1 = new Vector2$2(quadraticAt(x1, x2, x3, _t), quadraticAt(y1, y2, y3, _t)); + + d1 = v1.distanceToSquared(v0); + if (d1 < d) { + t = _t; + d = d1; + } + } + d = Infinity; + + for (i = 0; i < 32; i++) { + if (interval < EPSILON) { + break; + } + + var prev = t - interval; + var next = t + interval; + + v1 = new Vector2$2(quadraticAt(x1, x2, x3, prev), quadraticAt(y1, y2, y3, prev)); + + d1 = v1.distanceToSquared(v0); + + if (prev >= 0 && d1 < d) { + t = prev; + d = d1; + } else { + v2 = new Vector2$2(quadraticAt(x1, x2, x3, next), quadraticAt(y1, y2, y3, next)); + + d2 = v2.distanceToSquared(v0); + + if (next <= 1 && d2 < d) { + t = next; + d = d2; + } else { + interval *= 0.5; + } + } + } + + if (out) { + out.x = quadraticAt(x1, x2, x3, t); + out.y = quadraticAt(y1, y2, y3, t); + } + + return Math.sqrt(d); +} + +function quadraticExtrema(p0, p1, p2) { + var a = p0 + p2 - 2 * p1; + if (index$8.isNumberEqual(a, 0)) { + return [0.5]; + } + var rst = (p0 - p1) / a; + if (rst <= 1 && rst >= 0) { + return [rst]; + } + return []; +} + +var quadratic = { + at: quadraticAt, + projectPoint: function (x1, y1, x2, y2, x3, y3, x, y) { + var rst = {}; + quadraticProjectPoint(x1, y1, x2, y2, x3, y3, x, y, rst); + return rst; + }, + + pointDistance: quadraticProjectPoint, + extrema: quadraticExtrema +}; + +/** + * @fileOverview 三次贝赛尔曲线算法 + * @author hankaiai@126.com + * @ignore + */ +var Vector2$3 = index$14.Vector2; + + +function cubicAt(p0, p1, p2, p3, t) { + var onet = 1 - t; + return onet * onet * (onet * p3 + 3 * t * p2) + t * t * (t * p0 + 3 * onet * p1); +} + +function cubicDerivativeAt(p0, p1, p2, p3, t) { + var onet = 1 - t; + return 3 * (((p1 - p0) * onet + 2 * (p2 - p1) * t) * onet + (p3 - p2) * t * t); +} + +function cubicProjectPoint(x1, y1, x2, y2, x3, y3, x4, y4, x, y, out) { + var t = void 0; + var interval = 0.005; + var d = Infinity; + var _t = void 0; + var v1 = void 0; + var d1 = void 0; + var d2 = void 0; + var v2 = void 0; + var prev = void 0; + var next = void 0; + var EPSILON = 0.0001; + var v0 = new Vector2$3(x, y); + + for (_t = 0; _t < 1; _t += 0.05) { + v1 = new Vector2$3(cubicAt(x1, x2, x3, x4, _t), cubicAt(y1, y2, y3, y4, _t)); + + d1 = v1.distanceToSquared(v0); + if (d1 < d) { + t = _t; + d = d1; + } + } + d = Infinity; + + for (var i = 0; i < 32; i++) { + if (interval < EPSILON) { + break; + } + + prev = t - interval; + next = t + interval; + + v1 = new Vector2$3(cubicAt(x1, x2, x3, x4, prev), cubicAt(y1, y2, y3, y4, prev)); + + d1 = v1.distanceToSquared(v0); + + if (prev >= 0 && d1 < d) { + t = prev; + d = d1; + } else { + v2 = new Vector2$3(cubicAt(x1, x2, x3, x4, next), cubicAt(y1, y2, y3, y4, next)); + + d2 = v2.distanceToSquared(v0); + + if (next <= 1 && d2 < d) { + t = next; + d = d2; + } else { + interval *= 0.5; + } + } + } + + if (out) { + out.x = cubicAt(x1, x2, x3, x4, t); + out.y = cubicAt(y1, y2, y3, y4, t); + } + + return Math.sqrt(d); +} + +function cubicExtrema(p0, p1, p2, p3) { + var a = 3 * p0 - 9 * p1 + 9 * p2 - 3 * p3; + var b = 6 * p1 - 12 * p2 + 6 * p3; + var c = 3 * p2 - 3 * p3; + var extrema = []; + var t1 = void 0; + var t2 = void 0; + var discSqrt = void 0; + + if (index$8.isNumberEqual(a, 0)) { + if (!index$8.isNumberEqual(b, 0)) { + t1 = -c / b; + if (t1 >= 0 && t1 <= 1) { + extrema.push(t1); + } + } + } else { + var disc = b * b - 4 * a * c; + if (index$8.isNumberEqual(disc, 0)) { + extrema.push(-b / (2 * a)); + } else if (disc > 0) { + discSqrt = Math.sqrt(disc); + t1 = (-b + discSqrt) / (2 * a); + t2 = (-b - discSqrt) / (2 * a); + if (t1 >= 0 && t1 <= 1) { + extrema.push(t1); + } + if (t2 >= 0 && t2 <= 1) { + extrema.push(t2); + } + } + } + return extrema; +} + +function base3(t, p1, p2, p3, p4) { + var t1 = -3 * p1 + 9 * p2 - 9 * p3 + 3 * p4; + var t2 = t * t1 + 6 * p1 - 12 * p2 + 6 * p3; + return t * t2 - 3 * p1 + 3 * p2; +} + +function cubiclLen(x1, y1, x2, y2, x3, y3, x4, y4, z) { + if (index$8.isNil(z)) { + z = 1; + } + z = z > 1 ? 1 : z < 0 ? 0 : z; + var z2 = z / 2; + var n = 12; + var Tvalues = [-0.1252, 0.1252, -0.3678, 0.3678, -0.5873, 0.5873, -0.7699, 0.7699, -0.9041, 0.9041, -0.9816, 0.9816]; + var Cvalues = [0.2491, 0.2491, 0.2335, 0.2335, 0.2032, 0.2032, 0.1601, 0.1601, 0.1069, 0.1069, 0.0472, 0.0472]; + var sum = 0; + for (var i = 0; i < n; i++) { + var ct = z2 * Tvalues[i] + z2; + var xbase = base3(ct, x1, x2, x3, x4); + var ybase = base3(ct, y1, y2, y3, y4); + var comb = xbase * xbase + ybase * ybase; + sum += Cvalues[i] * Math.sqrt(comb); + } + return z2 * sum; +} + +var cubic = { + at: cubicAt, + derivativeAt: cubicDerivativeAt, + projectPoint: function (x1, y1, x2, y2, x3, y3, x4, y4, x, y) { + var rst = {}; + cubicProjectPoint(x1, y1, x2, y2, x3, y3, x4, y4, x, y, rst); + return rst; + }, + + pointDistance: cubicProjectPoint, + extrema: cubicExtrema, + len: cubiclLen +}; + +/** + * @fileOverview 圆弧线算法 + * @author hankaiai@126.com + * @ignore + */ +var Vector2$4 = index$14.Vector2; + + +function circlePoint(cx, cy, r, angle) { + return { + x: Math.cos(angle) * r + cx, + y: Math.sin(angle) * r + cy + }; +} + +function angleNearTo(angle, min, max, out) { + var v1 = void 0; + var v2 = void 0; + if (out) { + if (angle < min) { + v1 = min - angle; + v2 = Math.PI * 2 - max + angle; + } else if (angle > max) { + v1 = Math.PI * 2 - angle + min; + v2 = angle - max; + } + } else { + v1 = angle - min; + v2 = max - angle; + } + + return v1 > v2 ? max : min; +} + +function nearAngle(angle, startAngle, endAngle, clockwise) { + var plus = 0; + if (endAngle - startAngle >= Math.PI * 2) { + plus = Math.PI * 2; + } + startAngle = index$8.mod(startAngle, Math.PI * 2); + endAngle = index$8.mod(endAngle, Math.PI * 2) + plus; + angle = index$8.mod(angle, Math.PI * 2); + if (clockwise) { + if (startAngle >= endAngle) { + if (angle > endAngle && angle < startAngle) { + return angle; + } + return angleNearTo(angle, endAngle, startAngle, true); + } + if (angle < startAngle || angle > endAngle) { + return angle; + } + return angleNearTo(angle, startAngle, endAngle); + } + if (startAngle <= endAngle) { + if (startAngle < angle && angle < endAngle) { + return angle; + } + return angleNearTo(angle, startAngle, endAngle, true); + } + if (angle > startAngle || angle < endAngle) { + return angle; + } + return angleNearTo(angle, endAngle, startAngle); +} + +function arcProjectPoint(cx, cy, r, startAngle, endAngle, clockwise, x, y, out) { + var v = new Vector2$4(x, y); + var v0 = new Vector2$4(cx, cy); + var v1 = new Vector2$4(1, 0); + var subv = Vector2$4.sub(v, v0); + var angle = v1.angleTo(subv); + + angle = nearAngle(angle, startAngle, endAngle, clockwise); + var vpoint = new Vector2$4(r * Math.cos(angle) + cx, r * Math.sin(angle) + cy); + if (out) { + out.x = vpoint.x; + out.y = vpoint.y; + } + var d = v.distanceTo(vpoint); + return d; +} + +function arcBox(cx, cy, r, startAngle, endAngle, clockwise) { + var angleRight = 0; + var angleBottom = Math.PI / 2; + var angleLeft = Math.PI; + var angleTop = Math.PI * 3 / 2; + var points = []; + var angle = nearAngle(angleRight, startAngle, endAngle, clockwise); + if (angle === angleRight) { + points.push(circlePoint(cx, cy, r, angleRight)); + } + + angle = nearAngle(angleBottom, startAngle, endAngle, clockwise); + if (angle === angleBottom) { + points.push(circlePoint(cx, cy, r, angleBottom)); + } + + angle = nearAngle(angleLeft, startAngle, endAngle, clockwise); + if (angle === angleLeft) { + points.push(circlePoint(cx, cy, r, angleLeft)); + } + + angle = nearAngle(angleTop, startAngle, endAngle, clockwise); + if (angle === angleTop) { + points.push(circlePoint(cx, cy, r, angleTop)); + } + + points.push(circlePoint(cx, cy, r, startAngle)); + points.push(circlePoint(cx, cy, r, endAngle)); + var minX = Infinity; + var maxX = -Infinity; + var minY = Infinity; + var maxY = -Infinity; + index$8.each(points, function (point) { + if (minX > point.x) { + minX = point.x; + } + if (maxX < point.x) { + maxX = point.x; + } + if (minY > point.y) { + minY = point.y; + } + if (maxY < point.y) { + maxY = point.y; + } + }); + + return { + minX: minX, + minY: minY, + maxX: maxX, + maxY: maxY + }; +} + +var arc = { + nearAngle: nearAngle, + projectPoint: function (cx, cy, r, startAngle, endAngle, clockwise, x, y) { + var rst = {}; + arcProjectPoint(cx, cy, r, startAngle, endAngle, clockwise, x, y, rst); + return rst; + }, + + pointDistance: arcProjectPoint, + box: arcBox +}; + +/** + * @fileOverview isInside + * @author dxq613@gmail.com + * @author hankaiai@126.com + * @ignore + */ + + + + + +var inside = { + line: function (x1, y1, x2, y2, lineWidth, x, y) { + var box = line.box(x1, y1, x2, y2, lineWidth); + + if (!this.box(box.minX, box.maxX, box.minY, box.maxY, x, y)) { + return false; + } + + var d = line.pointDistance(x1, y1, x2, y2, x, y); + if (isNaN(d)) { + return false; + } + return d <= lineWidth / 2; + }, + polyline: function (points, lineWidth, x, y) { + var l = points.length - 1; + if (l < 1) { + return false; + } + for (var i = 0; i < l; i++) { + var x1 = points[i][0]; + var y1 = points[i][1]; + var x2 = points[i + 1][0]; + var y2 = points[i + 1][1]; + + if (this.line(x1, y1, x2, y2, lineWidth, x, y)) { + return true; + } + } + + return false; + }, + cubicline: function (x1, y1, x2, y2, x3, y3, x4, y4, lineWidth, x, y) { + return cubic.pointDistance(x1, y1, x2, y2, x3, y3, x4, y4, x, y) <= lineWidth / 2; + }, + quadraticline: function (x1, y1, x2, y2, x3, y3, lineWidth, x, y) { + return quadratic.pointDistance(x1, y1, x2, y2, x3, y3, x, y) <= lineWidth / 2; + }, + arcline: function (cx, cy, r, startAngle, endAngle, clockwise, lineWidth, x, y) { + return arc.pointDistance(cx, cy, r, startAngle, endAngle, clockwise, x, y) <= lineWidth / 2; + }, + rect: function (rx, ry, width, height, x, y) { + return rx <= x && x <= rx + width && ry <= y && y <= ry + height; + }, + circle: function (cx, cy, r, x, y) { + return Math.pow(x - cx, 2) + Math.pow(y - cy, 2) <= Math.pow(r, 2); + }, + box: function (minX, maxX, minY, maxY, x, y) { + return minX <= x && x <= maxX && minY <= y && y <= maxY; + } +}; + +var Vector3$3 = index$14.Vector3; + +var Shape$1 = function (cfg) { + Shape$1.superclass.constructor.call(this, cfg); +}; + +Shape$1.ATTRS = {}; + +index$8.extend(Shape$1, element); + +index$8.augment(Shape$1, { + isShape: true, + createPath: function () {}, + drawInner: function (context) { + var self = this; + var attrs = self.__attrs; + self.createPath(context); + var originOpacity = context.globalAlpha; + if (self.hasFill()) { + var fillOpacity = attrs.fillOpacity; + if (!index$8.isNil(fillOpacity) && fillOpacity !== 1) { + context.globalAlpha = fillOpacity; + context.fill(); + context.globalAlpha = originOpacity; + } else { + context.fill(); + } + } + if (self.hasStroke()) { + var lineWidth = self.__attrs.lineWidth; + if (lineWidth > 0) { + var strokeOpacity = attrs.strokeOpacity; + if (!index$8.isNil(strokeOpacity) && strokeOpacity !== 1) { + context.globalAlpha = strokeOpacity; + } + context.stroke(); + } + } + }, + + /** + * 节点是否在图形中 + * @param {Number} x x 坐标 + * @param {Number} y y 坐标 + * @return {Boolean} 是否在图形中 + */ + isPointInPath: function () { + return false; + }, + + /** + * 击中图形时是否进行包围盒判断 + * @return {Boolean} [description] + */ + isHitBox: function () { + return true; + }, + + /** + * 节点是否能够被击中 + * @param {Number} x x坐标 + * @param {Number} y y坐标 + * @return {Boolean} 是否在图形中 + */ + isHit: function (x, y) { + var self = this; + var v = new Vector3$3(x, y, 1); + self.invert(v); // canvas + + if (self.isHitBox()) { + var box = self.getBBox(); + if (box && !inside.box(box.minX, box.maxX, box.minY, box.maxY, v.x, v.y)) { + return false; + } + } + var clip = self.__attrs.clip; + if (clip) { + if (clip.inside(x, y)) { + return self.isPointInPath(v.x, v.y); + } + } else { + return self.isPointInPath(v.x, v.y); + } + return false; + }, + + /** + * @protected + * 计算包围盒 + * @return {Object} 包围盒 + */ + calculateBox: function () { + return null; + }, + + // 清除当前的矩阵 + clearTotalMatrix: function () { + this.__cfg.totalMatrix = null; + this.__cfg.region = null; + }, + clearBBox: function () { + this.__cfg.box = null; + this.__cfg.region = null; + }, + getBBox: function () { + var box = this.__cfg.box; + // 延迟计算 + if (!box) { + box = this.calculateBox(); + if (box) { + box.x = box.minX; + box.y = box.minY; + box.width = box.maxX - box.minX; + box.height = box.maxY - box.minY; + } + this.__cfg.box = box; + } + return box; + } +}); + +var shape = Shape$1; + +/** + * @fileOverview 矩形 + * @author dxq613@gmail.com + * @author hankaiai@126.com + * @ignore + */ + + + + +var Rect = function (cfg) { + Rect.superclass.constructor.call(this, cfg); +}; + +Rect.ATTRS = { + x: 0, + y: 0, + width: 0, + height: 0, + radius: 0, + lineWidth: 1 +}; + +index$8.extend(Rect, shape); + +index$8.augment(Rect, { + canFill: true, + canStroke: true, + type: 'rect', + getDefaultAttrs: function () { + return { + lineWidth: 1, + radius: 0 + }; + }, + calculateBox: function () { + var self = this; + var attrs = self.__attrs; + var x = attrs.x; + var y = attrs.y; + var width = attrs.width; + var height = attrs.height; + var lineWidth = attrs.lineWidth; + + var halfWidth = lineWidth / 2; + return { + minX: x - halfWidth, + minY: y - halfWidth, + maxX: x + width + halfWidth, + maxY: y + height + halfWidth + }; + }, + isPointInPath: function (x, y) { + var self = this; + var fill = self.hasFill(); + var stroke = self.hasStroke(); + + if (fill && stroke) { + return self.__isPointInFill(x, y) || self.__isPointInStroke(x, y); + } + + if (fill) { + return self.__isPointInFill(x, y); + } + + if (stroke) { + return self.__isPointInStroke(x, y); + } + + return false; + }, + __isPointInFill: function (x, y) { + var context = this.get('context'); + + if (!context) return false; + this.createPath(); + return context.isPointInPath(x, y); + }, + __isPointInStroke: function (x, y) { + var self = this; + var attrs = self.__attrs; + var rx = attrs.x; + var ry = attrs.y; + var width = attrs.width; + var height = attrs.height; + var radius = attrs.radius; + var lineWidth = attrs.lineWidth; + + if (radius === 0) { + var halfWidth = lineWidth / 2; + return inside.line(rx - halfWidth, ry, rx + width + halfWidth, ry, lineWidth, x, y) || inside.line(rx + width, ry - halfWidth, rx + width, ry + height + halfWidth, lineWidth, x, y) || inside.line(rx + width + halfWidth, ry + height, rx - halfWidth, ry + height, lineWidth, x, y) || inside.line(rx, ry + height + halfWidth, rx, ry - halfWidth, lineWidth, x, y); + } + + return inside.line(rx + radius, ry, rx + width - radius, ry, lineWidth, x, y) || inside.line(rx + width, ry + radius, rx + width, ry + height - radius, lineWidth, x, y) || inside.line(rx + width - radius, ry + height, rx + radius, ry + height, lineWidth, x, y) || inside.line(rx, ry + height - radius, rx, ry + radius, lineWidth, x, y) || inside.arcline(rx + width - radius, ry + radius, radius, 1.5 * Math.PI, 2 * Math.PI, false, lineWidth, x, y) || inside.arcline(rx + width - radius, ry + height - radius, radius, 0, 0.5 * Math.PI, false, lineWidth, x, y) || inside.arcline(rx + radius, ry + height - radius, radius, 0.5 * Math.PI, Math.PI, false, lineWidth, x, y) || inside.arcline(rx + radius, ry + radius, radius, Math.PI, 1.5 * Math.PI, false, lineWidth, x, y); + }, + createPath: function (context) { + var self = this; + var attrs = self.__attrs; + var x = attrs.x; + var y = attrs.y; + var width = attrs.width; + var height = attrs.height; + var radius = attrs.radius; + context = context || self.get('context'); + + context.beginPath(); + if (radius === 0) { + // 改成原生的rect方法 + context.rect(x, y, width, height); + } else { + context.moveTo(x + radius, y); + context.lineTo(x + width - radius, y); + context.arc(x + width - radius, y + radius, radius, -Math.PI / 2, 0, false); + context.lineTo(x + width, y + height - radius); + context.arc(x + width - radius, y + height - radius, radius, 0, Math.PI / 2, false); + context.lineTo(x + radius, y + height); + context.arc(x + radius, y + height - radius, radius, Math.PI / 2, Math.PI, false); + context.lineTo(x, y + radius); + context.arc(x + radius, y + radius, radius, Math.PI, Math.PI * 3 / 2, false); + context.closePath(); + } + } +}); + +var rect = Rect; + +/** + * @fileOverview circle + * @author dxq613@gmail.com + * @author hankaiai@126.com + * @ignore + */ + + + + +var Circle = function (cfg) { + Circle.superclass.constructor.call(this, cfg); +}; + +Circle.ATTRS = { + x: 0, + y: 0, + r: 0, + lineWidth: 1 +}; + +index$8.extend(Circle, shape); + +index$8.augment(Circle, { + canFill: true, + canStroke: true, + type: 'circle', + getDefaultAttrs: function () { + return { + lineWidth: 1 + }; + }, + calculateBox: function () { + var attrs = this.__attrs; + var cx = attrs.x; + var cy = attrs.y; + var r = attrs.r; + var lineWidth = attrs.lineWidth; + var halfWidth = lineWidth / 2 + r; + return { + minX: cx - halfWidth, + minY: cy - halfWidth, + maxX: cx + halfWidth, + maxY: cy + halfWidth + }; + }, + isPointInPath: function (x, y) { + var fill = this.hasFill(); + var stroke = this.hasStroke(); + if (fill && stroke) { + return this.__isPointInFill(x, y) || this.__isPointInStroke(x, y); + } + + if (fill) { + return this.__isPointInFill(x, y); + } + + if (stroke) { + return this.__isPointInStroke(x, y); + } + + return false; + }, + __isPointInFill: function (x, y) { + var attrs = this.__attrs; + var cx = attrs.x; + var cy = attrs.y; + var r = attrs.r; + + return inside.circle(cx, cy, r, x, y); + }, + __isPointInStroke: function (x, y) { + var attrs = this.__attrs; + var cx = attrs.x; + var cy = attrs.y; + var r = attrs.r; + var lineWidth = attrs.lineWidth; + + return inside.arcline(cx, cy, r, 0, Math.PI * 2, false, lineWidth, x, y); + }, + createPath: function (context) { + var attrs = this.__attrs; + var cx = attrs.x; + var cy = attrs.y; + var r = attrs.r; + context = context || self.get('context'); + + context.beginPath(); + context.arc(cx, cy, r, 0, Math.PI * 2, false); + } +}); + +var circle = Circle; + +/** + * @fileOverview Ellipse + * @author dxq613@gmail.com + * @author hankaiai@126.com + * @ignore + */ + + + + +var Matrix3$5 = index$14.Matrix3; +var Vector3$4 = index$14.Vector3; + +var Ellipse = function (cfg) { + Ellipse.superclass.constructor.call(this, cfg); +}; + +Ellipse.ATTRS = { + x: 0, + y: 0, + rx: 1, + ry: 1, + lineWidth: 1 +}; + +index$8.extend(Ellipse, shape); + +index$8.augment(Ellipse, { + canFill: true, + canStroke: true, + type: 'ellipse', + getDefaultAttrs: function () { + return { + lineWidth: 1 + }; + }, + calculateBox: function () { + var attrs = this.__attrs; + var cx = attrs.x; + var cy = attrs.y; + var rx = attrs.rx; + var ry = attrs.ry; + var lineWidth = attrs.lineWidth; + var halfXWidth = rx + lineWidth / 2; + var halfYWidth = ry + lineWidth / 2; + + return { + minX: cx - halfXWidth, + minY: cy - halfYWidth, + maxX: cx + halfXWidth, + maxY: cy + halfYWidth + }; + }, + isPointInPath: function (x, y) { + var fill = this.hasFill(); + var stroke = this.hasStroke(); + + if (fill && stroke) { + return this.__isPointInFill(x, y) || this.__isPointInStroke(x, y); + } + + if (fill) { + return this.__isPointInFill(x, y); + } + + if (stroke) { + return this.__isPointInStroke(x, y); + } + + return false; + }, + __isPointInFill: function (x, y) { + var attrs = this.__attrs; + var cx = attrs.x; + var cy = attrs.y; + var rx = attrs.rx; + var ry = attrs.ry; + + var r = rx > ry ? rx : ry; + var scaleX = rx > ry ? 1 : rx / ry; + var scaleY = rx > ry ? ry / rx : 1; + + var p = new Vector3$4(x, y, 1); + var m = new Matrix3$5(); + m.scale(scaleX, scaleY); + m.translate(cx, cy); + var inm = m.getInverse(); + p.applyMatrix(inm); + + return inside.circle(0, 0, r, p.x, p.y); + }, + __isPointInStroke: function (x, y) { + var attrs = this.__attrs; + var cx = attrs.x; + var cy = attrs.y; + var rx = attrs.rx; + var ry = attrs.ry; + var lineWidth = attrs.lineWidth; + + var r = rx > ry ? rx : ry; + var scaleX = rx > ry ? 1 : rx / ry; + var scaleY = rx > ry ? ry / rx : 1; + + var p = new Vector3$4(x, y, 1); + var m = new Matrix3$5(); + m.scale(scaleX, scaleY); + m.translate(cx, cy); + var inm = m.getInverse(); + p.applyMatrix(inm); + + return inside.arcline(0, 0, r, 0, Math.PI * 2, false, lineWidth, p.x, p.y); + }, + createPath: function (context) { + var attrs = this.__attrs; + var cx = attrs.x; + var cy = attrs.y; + var rx = attrs.rx; + var ry = attrs.ry; + + context = context || self.get('context'); + var r = rx > ry ? rx : ry; + var scaleX = rx > ry ? 1 : rx / ry; + var scaleY = rx > ry ? ry / rx : 1; + + var m = new Matrix3$5(); + m.scale(scaleX, scaleY); + m.translate(cx, cy); + var mo = m.to2DObject(); + context.beginPath(); + context.save(); + context.transform(mo.a, mo.b, mo.c, mo.d, mo.e, mo.f); + context.arc(0, 0, r, 0, Math.PI * 2); + context.restore(); + context.closePath(); + } +}); + +var ellipse = Ellipse; + +/** + * @fileOverview ellipse math + * @author dxq613@gmail.com + * @author hankaiai@126.com + * @ignore + */ +var ellipse$2 = { + xAt: function (psi, rx, ry, cx, t) { + return rx * Math.cos(psi) * Math.cos(t) - ry * Math.sin(psi) * Math.sin(t) + cx; + }, + yAt: function (psi, rx, ry, cy, t) { + return rx * Math.sin(psi) * Math.cos(t) + ry * Math.cos(psi) * Math.sin(t) + cy; + }, + xExtrema: function (psi, rx, ry) { + return Math.atan(-ry / rx * Math.tan(psi)); + }, + yExtrema: function (psi, rx, ry) { + return Math.atan(ry / (rx * Math.tan(psi))); + } +}; + +/** + * @fileOverview Path + * @author dxq613@gmail.com + * @author hankaiai@126.com + * @ignore + */ + + + + + + +var Vector2$6 = index$14.Vector2; +var Vector3$5 = index$14.Vector3; +var Matrix3$6 = index$14.Matrix3; + +var ARR_CMD = ['m', 'l', 'c', 'a', 'q', 'h', 'v', 't', 's', 'z']; + +function toAbsolute(x, y, curPoint) { + // 获取绝对坐标 + return { + x: curPoint.x + x, + y: curPoint.y + y + }; +} + +function toSymmetry(point, center) { + // 点对称 + return { + x: center.x + (center.x - point.x), + y: center.y + (center.y - point.y) + }; +} + +function vMag(v) { + return Math.sqrt(v[0] * v[0] + v[1] * v[1]); +} + +function vRatio(u, v) { + return (u[0] * v[0] + u[1] * v[1]) / (vMag(u) * vMag(v)); +} + +function vAngle(u, v) { + return (u[0] * v[1] < u[1] * v[0] ? -1 : 1) * Math.acos(vRatio(u, v)); +} + +function getArcParams(point1, point2, fa, fs, rx, ry, psiDeg) { + var psi = index$8.mod(index$8.toRadian(psiDeg), Math.PI * 2); + var x1 = point1.x; + var y1 = point1.y; + var x2 = point2.x; + var y2 = point2.y; + var xp = Math.cos(psi) * (x1 - x2) / 2.0 + Math.sin(psi) * (y1 - y2) / 2.0; + var yp = -1 * Math.sin(psi) * (x1 - x2) / 2.0 + Math.cos(psi) * (y1 - y2) / 2.0; + var lambda = xp * xp / (rx * rx) + yp * yp / (ry * ry); + + if (lambda > 1) { + rx *= Math.sqrt(lambda); + ry *= Math.sqrt(lambda); + } + + var f = Math.sqrt((rx * rx * (ry * ry) - rx * rx * (yp * yp) - ry * ry * (xp * xp)) / (rx * rx * (yp * yp) + ry * ry * (xp * xp))); + + if (fa === fs) { + f *= -1; + } + if (isNaN(f)) { + f = 0; + } + + var cxp = f * rx * yp / ry; + var cyp = f * -ry * xp / rx; + + var cx = (x1 + x2) / 2.0 + Math.cos(psi) * cxp - Math.sin(psi) * cyp; + var cy = (y1 + y2) / 2.0 + Math.sin(psi) * cxp + Math.cos(psi) * cyp; + + var theta = vAngle([1, 0], [(xp - cxp) / rx, (yp - cyp) / ry]); + var u = [(xp - cxp) / rx, (yp - cyp) / ry]; + var v = [(-1 * xp - cxp) / rx, (-1 * yp - cyp) / ry]; + var dTheta = vAngle(u, v); + + if (vRatio(u, v) <= -1) { + dTheta = Math.PI; + } + if (vRatio(u, v) >= 1) { + dTheta = 0; + } + if (fs === 0 && dTheta > 0) { + dTheta = dTheta - 2 * Math.PI; + } + if (fs === 1 && dTheta < 0) { + dTheta = dTheta + 2 * Math.PI; + } + return [point1, cx, cy, rx, ry, theta, dTheta, psi, fs]; +} + +var PathSegment = function (item, preSegment, isLast) { + this.preSegment = preSegment; + this.isLast = isLast; + this.init(item, preSegment); +}; + +index$8.augment(PathSegment, { + init: function (item, preSegment) { + var command = item[0]; + preSegment = preSegment || { + endPoint: { + x: 0, + y: 0 + } + }; + var relative = ARR_CMD.indexOf(command) >= 0; // /[a-z]/.test(command); + var cmd = relative ? command.toUpperCase() : command; + var p = item; + var point1 = void 0; + var point2 = void 0; + var point3 = void 0; + var point = void 0; + var preEndPoint = preSegment.endPoint; + + var p1 = p[1]; + var p2 = p[2]; + switch (cmd) { + default: + break; + case 'M': + if (relative) { + point = toAbsolute(p1, p2, preEndPoint); + } else { + point = { + x: p1, + y: p2 + }; + } + this.command = 'M'; + this.params = [preEndPoint, point]; + this.subStart = point; + this.endPoint = point; + break; + case 'L': + if (relative) { + point = toAbsolute(p1, p2, preEndPoint); + } else { + point = { + x: p1, + y: p2 + }; + } + this.command = 'L'; + this.params = [preEndPoint, point]; + this.subStart = preSegment.subStart; + this.endPoint = point; + if (this.isLast) { + this.endTangent = function () { + return new Vector2$6(point.x - preEndPoint.x, point.y - preEndPoint.y); + }; + } + break; + case 'H': + if (relative) { + point = toAbsolute(p1, 0, preEndPoint); + } else { + point = { + x: p1, + y: preEndPoint.y + }; + } + this.command = 'L'; + this.params = [preEndPoint, point]; + this.subStart = preSegment.subStart; + this.endPoint = point; + this.endTangent = function () { + return new Vector2$6(point.x - preEndPoint.x, point.y - preEndPoint.y); + }; + break; + case 'V': + if (relative) { + point = toAbsolute(0, p1, preEndPoint); + } else { + point = { + x: preEndPoint.x, + y: p1 + }; + } + this.command = 'L'; + this.params = [preEndPoint, point]; + this.subStart = preSegment.subStart; + this.endPoint = point; + this.endTangent = function () { + return new Vector2$6(point.x - preEndPoint.x, point.y - preEndPoint.y); + }; + break; + case 'Q': + if (relative) { + point1 = toAbsolute(p1, p2, preEndPoint); + point2 = toAbsolute(p[3], p[4], preEndPoint); + } else { + point1 = { + x: p1, + y: p2 + }; + point2 = { + x: p[3], + y: p[4] + }; + } + this.command = 'Q'; + this.params = [preEndPoint, point1, point2]; + this.subStart = preSegment.subStart; + this.endPoint = point2; + this.endTangent = function () { + return new Vector2$6(point2.x - point1.x, point2.y - point1.y); + }; + break; + case 'T': + if (relative) { + point2 = toAbsolute(p1, p2, preEndPoint); + } else { + point2 = { + x: p1, + y: p2 + }; + } + if (preSegment.command === 'Q') { + point1 = toSymmetry(preSegment.params[1], preEndPoint); + this.command = 'Q'; + this.params = [preEndPoint, point1, point2]; + this.subStart = preSegment.subStart; + this.endPoint = point2; + this.endTangent = function () { + return new Vector2$6(point2.x - point1.x, point2.y - point1.y); + }; + } else { + this.command = 'TL'; + this.params = [preEndPoint, point2]; + this.subStart = preSegment.subStart; + this.endPoint = point2; + this.endTangent = function () { + return new Vector2$6(point2.x - preEndPoint.x, point2.y - preEndPoint.y); + }; + } + + break; + case 'C': + if (relative) { + point1 = toAbsolute(p1, p2, preEndPoint); + point2 = toAbsolute(p[3], p[4], preEndPoint); + point3 = toAbsolute(p[5], p[6], preEndPoint); + } else { + point1 = { + x: p1, + y: p2 + }; + point2 = { + x: p[3], + y: p[4] + }; + point3 = { + x: p[5], + y: p[6] + }; + } + this.command = 'C'; + this.params = [preEndPoint, point1, point2, point3]; + this.subStart = preSegment.subStart; + this.endPoint = point3; + this.endTangent = function () { + return new Vector2$6(point3.x - point2.x, point3.y - point2.y); + }; + break; + case 'S': + if (relative) { + point2 = toAbsolute(p1, p2, preEndPoint); + point3 = toAbsolute(p[3], p[4], preEndPoint); + } else { + point2 = { + x: p1, + y: p2 + }; + point3 = { + x: p[3], + y: p[4] + }; + } + if (preSegment.command === 'C') { + point1 = toSymmetry(preSegment.params[2], preEndPoint); + this.command = 'C'; + this.params = [preEndPoint, point1, point2, point3]; + this.subStart = preSegment.subStart; + this.endPoint = point3; + this.endTangent = function () { + return new Vector2$6(point3.x - point2.x, point3.y - point2.y); + }; + } else { + this.command = 'SQ'; + this.params = [preEndPoint, point2, point3]; + this.subStart = preSegment.subStart; + this.endPoint = point3; + this.endTangent = function () { + return new Vector2$6(point3.x - point2.x, point3.y - point2.y); + }; + } + break; + case 'A': + { + var rx = p1; + var ry = p2; + var psi = p[3]; + var fa = p[4]; + var fs = p[5]; + if (relative) { + point = toAbsolute(p[6], p[7], preEndPoint); + } else { + point = { + x: p[6], + y: p[7] + }; + } + + this.command = 'A'; + this.params = getArcParams(preEndPoint, point, fa, fs, rx, ry, psi); + this.subStart = preSegment.subStart; + this.endPoint = point; + break; + } + case 'Z': + { + this.command = 'Z'; + this.params = [preEndPoint, preSegment.subStart]; + this.subStart = preSegment.subStart; + this.endPoint = preSegment.subStart; + } + } + }, + isInside: function (x, y, lineWidth) { + var self = this; + var command = self.command; + var params = self.params; + var box = self.box; + if (box) { + if (!inside.box(box.minX, box.maxX, box.minY, box.maxY, x, y)) { + return false; + } + } + switch (command) { + default: + break; + case 'M': + return false; + case 'TL': + case 'L': + case 'Z': + return inside.line(params[0].x, params[0].y, params[1].x, params[1].y, lineWidth, x, y); + case 'SQ': + case 'Q': + return inside.quadraticline(params[0].x, params[0].y, params[1].x, params[1].y, params[2].x, params[2].y, lineWidth, x, y); + case 'C': + { + return inside.cubicline(params[0].x, params[0].y, params[1].x, params[1].y, params[2].x, params[2].y, params[3].x, params[3].y, lineWidth, x, y); + } + case 'A': + { + var p = params; + var cx = p[1]; + var cy = p[2]; + var rx = p[3]; + var ry = p[4]; + var theta = p[5]; + var dTheta = p[6]; + var psi = p[7]; + var fs = p[8]; + + var r = rx > ry ? rx : ry; + var scaleX = rx > ry ? 1 : rx / ry; + var scaleY = rx > ry ? ry / rx : 1; + + p = new Vector3$5(x, y, 1); + var m = new Matrix3$6(); + m.translate(-cx, -cy); + m.rotate(-psi); + m.scale(1 / scaleX, 1 / scaleY); + p.applyMatrix(m); + return inside.arcline(0, 0, r, theta, theta + dTheta, 1 - fs, lineWidth, p.x, p.y); + } + } + return false; + }, + draw: function (context) { + var command = this.command; + var params = this.params; + var point1 = void 0; + var point2 = void 0; + var point3 = void 0; + + switch (command) { + default: + break; + case 'M': + context.moveTo(params[1].x, params[1].y); + break; + case 'TL': + case 'L': + context.lineTo(params[1].x, params[1].y); + break; + case 'SQ': + case 'Q': + point1 = params[1]; + point2 = params[2]; + context.quadraticCurveTo(point1.x, point1.y, point2.x, point2.y); + break; + case 'C': + point1 = params[1]; + point2 = params[2]; + point3 = params[3]; + context.bezierCurveTo(point1.x, point1.y, point2.x, point2.y, point3.x, point3.y); + break; + case 'A': + { + var p = params; + var p1 = p[1]; + var p2 = p[2]; + var cx = p1; + var cy = p2; + var rx = p[3]; + var ry = p[4]; + var theta = p[5]; + var dTheta = p[6]; + var psi = p[7]; + var fs = p[8]; + + var r = rx > ry ? rx : ry; + var scaleX = rx > ry ? 1 : rx / ry; + var scaleY = rx > ry ? ry / rx : 1; + + context.translate(cx, cy); + context.rotate(psi); + context.scale(scaleX, scaleY); + context.arc(0, 0, r, theta, theta + dTheta, 1 - fs); + context.scale(1 / scaleX, 1 / scaleY); + context.rotate(-psi); + context.translate(-cx, -cy); + break; + } + case 'Z': + context.closePath(); + break; + } + }, + getBBox: function (lineWidth) { + var halfWidth = lineWidth / 2; + var params = this.params; + var yDims = void 0; + var xDims = void 0; + var i = void 0; + var l = void 0; + + switch (this.command) { + default: + case 'M': + case 'Z': + break; + case 'TL': + case 'L': + this.box = { + minX: Math.min(params[0].x, params[1].x) - halfWidth, + maxX: Math.max(params[0].x, params[1].x) + halfWidth, + minY: Math.min(params[0].y, params[1].y) - halfWidth, + maxY: Math.max(params[0].y, params[1].y) + halfWidth + }; + break; + case 'SQ': + case 'Q': + xDims = quadratic.extrema(params[0].x, params[1].x, params[2].x); + for (i = 0, l = xDims.length; i < l; i++) { + xDims[i] = quadratic.at(params[0].x, params[1].x, params[2].x, xDims[i]); + } + xDims.push(params[0].x, params[2].x); + yDims = quadratic.extrema(params[0].y, params[1].y, params[2].y); + for (i = 0, l = yDims.length; i < l; i++) { + yDims[i] = quadratic.at(params[0].y, params[1].y, params[2].y, yDims); + } + yDims.push(params[0].y, params[2].y); + this.box = { + minX: Math.min.apply(Math, xDims) - halfWidth, + maxX: Math.max.apply(Math, xDims) + halfWidth, + minY: Math.min.apply(Math, yDims) - halfWidth, + maxY: Math.max.apply(Math, yDims) + halfWidth + }; + break; + case 'C': + xDims = cubic.extrema(params[0].x, params[1].x, params[2].x, params[3].x); + for (i = 0, l = xDims.length; i < l; i++) { + xDims[i] = cubic.at(params[0].x, params[1].x, params[2].x, params[3].x, xDims[i]); + } + yDims = cubic.extrema(params[0].y, params[1].y, params[2].y, params[3].y); + for (i = 0, l = yDims.length; i < l; i++) { + yDims[i] = cubic.at(params[0].y, params[1].y, params[2].y, params[3].y, yDims[i]); + } + xDims.push(params[0].x, params[3].x); + yDims.push(params[0].y, params[3].y); + this.box = { + minX: Math.min.apply(Math, xDims) - halfWidth, + maxX: Math.max.apply(Math, xDims) + halfWidth, + minY: Math.min.apply(Math, yDims) - halfWidth, + maxY: Math.max.apply(Math, yDims) + halfWidth + }; + break; + case 'A': + { + // todo 待优化 + var p = params; + var cx = p[1]; + var cy = p[2]; + var rx = p[3]; + var ry = p[4]; + var theta = p[5]; + var dTheta = p[6]; + var psi = p[7]; + var fs = p[8]; + var start = theta; + var end = theta + dTheta; + + var xDim = ellipse$2.xExtrema(psi, rx, ry); + var minX = Infinity; + var maxX = -Infinity; + var xs = [start, end]; + for (i = -Math.PI * 2; i <= Math.PI * 2; i += Math.PI) { + var xAngle = xDim + i; + if (fs === 1) { + if (start < xAngle && xAngle < end) { + xs.push(xAngle); + } + } else { + if (end < xAngle && xAngle < start) { + xs.push(xAngle); + } + } + } + + for (i = 0, l = xs.length; i < l; i++) { + var x = ellipse$2.xAt(psi, rx, ry, cx, xs[i]); + if (x < minX) { + minX = x; + } + if (x > maxX) { + maxX = x; + } + } + + var yDim = ellipse$2.yExtrema(psi, rx, ry); + var minY = Infinity; + var maxY = -Infinity; + var ys = [start, end]; + for (i = -Math.PI * 2; i <= Math.PI * 2; i += Math.PI) { + var yAngle = yDim + i; + if (fs === 1) { + if (start < yAngle && yAngle < end) { + ys.push(yAngle); + } + } else { + if (end < yAngle && yAngle < start) { + ys.push(yAngle); + } + } + } + + for (i = 0, l = ys.length; i < l; i++) { + var y = ellipse$2.yAt(psi, rx, ry, cy, ys[i]); + if (y < minY) { + minY = y; + } + if (y > maxY) { + maxY = y; + } + } + this.box = { + minX: minX - halfWidth, + maxX: maxX + halfWidth, + minY: minY - halfWidth, + maxY: maxY + halfWidth + }; + break; + } + } + } +}); + +var pathSegment = PathSegment; + +var Vector2$7 = index$14.Vector2; + +var THETA = Math.PI / 6; + +function calculatePoints(vector, end, lineWidth) { + var angle = new Vector2$7(1, 0).angleTo(vector); + var downAngle = angle - THETA; + var upAngle = angle + THETA; + var length = 6 + lineWidth * 3; + return [{ + x: end.x - length * Math.cos(downAngle), + y: end.y - length * Math.sin(downAngle) + }, end, { + x: end.x - length * Math.cos(upAngle), + y: end.y - length * Math.sin(upAngle) + }]; +} + +function arrow(context, points) { + context.moveTo(points[0].x, points[0].y); + context.lineTo(points[1].x, points[1].y); + context.lineTo(points[2].x, points[2].y); +} + +function makeArrow(context, vector, end, lineWidth) { + arrow(context, calculatePoints(vector, end, lineWidth)); +} + +function getEndPoint(vector, end, lineWidth) { + var miterLimit = lineWidth / Math.sin(THETA); + vector.setLength(miterLimit / 2); + end.sub(vector); + return end; +} + +var arrow_1 = { + makeArrow: makeArrow, + getEndPoint: getEndPoint +}; + +/** + * @fileOverview Path + * @author dxq613@gmail.com + * @author hankaiai@126.com + * @see http://www.w3.org/TR/2011/REC-SVG11-20110816/paths.html#PathData + * @ignore + */ + + + + + + + + +var Vector2$5 = index$14.Vector2; + +var Path = function (cfg) { + Path.superclass.constructor.call(this, cfg); +}; + +Path.ATTRS = { + path: null, + lineWidth: 1, + curve: null, // 曲线path + tCache: null +}; + +index$8.extend(Path, shape); + +index$8.augment(Path, { + canFill: true, + canStroke: true, + type: 'path', + getDefaultAttrs: function () { + return { + lineWidth: 1 + }; + }, + __afterSetAttrPath: function (path) { + var self = this; + if (index$8.isNil(path)) { + self.setSilent('segments', null); + self.setSilent('box', undefined); + return; + } + var pathArray = format.parsePath(path); + var preSegment = void 0; + var segments = []; + + if (!index$8.isArray(pathArray) || pathArray.length === 0 || pathArray[0][0] !== 'M' && pathArray[0][0] !== 'm') { + return; + } + var count = pathArray.length; + for (var i = 0; i < pathArray.length; i++) { + var item = pathArray[i]; + preSegment = new pathSegment(item, preSegment, i === count - 1); + segments.push(preSegment); + } + self.setSilent('segments', segments); + self.set('tCache', null); + this.setSilent('box', null); + }, + __afterSetAttrAll: function (objs) { + if (objs.path) { + this.__afterSetAttrPath(objs.path); + } + }, + calculateBox: function () { + var self = this; + var attrs = self.__attrs; + var lineWidth = attrs.lineWidth; + var lineAppendWidth = attrs.lineAppendWidth || 0; + var segments = self.get('segments'); + + if (!segments) { + return null; + } + lineWidth += lineAppendWidth; + var minX = Infinity; + var maxX = -Infinity; + var minY = Infinity; + var maxY = -Infinity; + index$8.each(segments, function (segment) { + segment.getBBox(lineWidth); + var box = segment.box; + if (box) { + if (box.minX < minX) { + minX = box.minX; + } + + if (box.maxX > maxX) { + maxX = box.maxX; + } + + if (box.minY < minY) { + minY = box.minY; + } + + if (box.maxY > maxY) { + maxY = box.maxY; + } + } + }); + return { + minX: minX, + minY: minY, + maxX: maxX, + maxY: maxY + }; + }, + isPointInPath: function (x, y) { + var self = this; + var fill = self.hasFill(); + var stroke = self.hasStroke(); + + if (fill && stroke) { + return self.__isPointInFill(x, y) || self.__isPointInStroke(x, y); + } + + if (fill) { + return self.__isPointInFill(x, y); + } + + if (stroke) { + return self.__isPointInStroke(x, y); + } + + return false; + }, + __isPointInFill: function (x, y) { + var self = this; + var context = self.get('context'); + if (!context) return undefined; + self.createPath(); + return context.isPointInPath(x, y); + }, + __isPointInStroke: function (x, y) { + var self = this; + var segments = self.get('segments'); + var attrs = self.__attrs; + var lineWidth = attrs.lineWidth; + var appendWidth = attrs.lineAppendWidth || 0; + lineWidth += appendWidth; + for (var i = 0, l = segments.length; i < l; i++) { + if (segments[i].isInside(x, y, lineWidth)) { + return true; + } + } + + return false; + }, + __setTcache: function () { + var totalLength = 0; + var tempLength = 0; + var tCache = []; + var segmentT = void 0; + var segmentL = void 0; + var segmentN = void 0; + var l = void 0; + var curve = this.curve; + + if (!curve) { + return; + } + + index$8.each(curve, function (segment, i) { + segmentN = curve[i + 1]; + l = segment.length; + if (segmentN) { + totalLength += cubic.len(segment[l - 2], segment[l - 1], segmentN[1], segmentN[2], segmentN[3], segmentN[4], segmentN[5], segmentN[6]); + } + }); + + index$8.each(curve, function (segment, i) { + segmentN = curve[i + 1]; + l = segment.length; + if (segmentN) { + segmentT = []; + segmentT[0] = tempLength / totalLength; + segmentL = cubic.len(segment[l - 2], segment[l - 1], segmentN[1], segmentN[2], segmentN[3], segmentN[4], segmentN[5], segmentN[6]); + tempLength += segmentL; + segmentT[1] = tempLength / totalLength; + tCache.push(segmentT); + } + }); + + this.tCache = tCache; + }, + __calculateCurve: function () { + var self = this; + var attrs = self.__attrs; + var path = attrs.path; + this.curve = index$2.toCurve(path); + }, + getPoint: function (t) { + var tCache = this.tCache; + var subt = void 0; + var index = void 0; + + if (!tCache) { + this.__calculateCurve(); + this.__setTcache(); + tCache = this.tCache; + } + + var curve = this.curve; + + if (!tCache) { + if (curve) { + return { + x: curve[0][1], + y: curve[0][2] + }; + } + return null; + } + index$8.each(tCache, function (v, i) { + if (t >= v[0] && t <= v[1]) { + subt = (t - v[0]) / (v[1] - v[0]); + index = i; + } + }); + var seg = curve[index]; + if (index$8.isNil(seg) || index$8.isNil(index)) { + return null; + } + var l = seg.length; + var nextSeg = curve[index + 1]; + return { + x: cubic.at(seg[l - 2], nextSeg[1], nextSeg[3], nextSeg[5], 1 - subt), + y: cubic.at(seg[l - 1], nextSeg[2], nextSeg[4], nextSeg[6], 1 - subt) + }; + }, + createPath: function (context) { + var self = this; + var attrs = self.__attrs; + var segments = self.get('segments'); + var lineWidth = attrs.lineWidth; + var arrow = attrs.arrow; + + if (!index$8.isArray(segments)) return; + context = context || self.get('context'); + context.beginPath(); + for (var i = 0, l = segments.length; i < l; i++) { + if (i === l - 1 && arrow) { + var lastSeg = segments[i]; + var endTangent = segments[i].endTangent; + var endPoint = { + x: lastSeg.params[lastSeg.params.length - 1].x, + y: lastSeg.params[lastSeg.params.length - 1].y + }; + if (lastSeg && index$8.isFunction(endTangent)) { + var v = endTangent(); + var end = arrow_1.getEndPoint(v, new Vector2$5(endPoint.x, endPoint.y), lineWidth); + lastSeg.params[lastSeg.params.length - 1] = end; + segments[i].draw(context); + arrow_1.makeArrow(context, v, end, lineWidth); + lastSeg.params[lastSeg.params.length - 1] = endPoint; + } + } else { + segments[i].draw(context); + } + } + } +}); + +var path$2 = Path; + +/** + * @fileOverview text 文本 + * @author dxq613@gmail.com + * @author hankaiai@126.com + * @ignore + */ + + + + + +var CText = function (cfg) { + CText.superclass.constructor.call(this, cfg); +}; + +CText.ATTRS = { + x: 0, + y: 0, + text: null, + fontSize: 12, + fontFamily: 'sans-serif', + fontStyle: 'normal', + fontWeight: 'normal', + fontVariant: 'normal', + textAlign: 'start', + textBaseline: 'bottom', + lineHeight: null, + textArr: null +}; + +index$8.extend(CText, shape); + +index$8.augment(CText, { + canFill: true, + canStroke: true, + type: 'text', + getDefaultAttrs: function () { + return { + lineWidth: 1, + lineCount: 1, + fontSize: 12, + fontFamily: 'sans-serif', + fontStyle: 'normal', + fontWeight: 'normal', + fontVariant: 'normal', + textAlign: 'start', + textBaseline: 'bottom' + }; + }, + __assembleFont: function () { + // var self = this; + var attrs = this.__attrs; + var fontSize = attrs.fontSize; + var fontFamily = attrs.fontFamily; + var fontWeight = attrs.fontWeight; + var fontStyle = attrs.fontStyle; // self.attr('fontStyle'); + var fontVariant = attrs.fontVariant; // self.attr('fontVariant'); + // self.attr('font', [fontStyle, fontVariant, fontWeight, fontSize + 'px', fontFamily].join(' ')); + attrs.font = [fontStyle, fontVariant, fontWeight, fontSize + 'px', fontFamily].join(' '); + }, + __afterSetAttrFontSize: function () { + /* this.attr({ + height: this.__getTextHeight() + }); */ + this.__assembleFont(); + }, + __afterSetAttrFontFamily: function () { + this.__assembleFont(); + }, + __afterSetAttrFontWeight: function () { + this.__assembleFont(); + }, + __afterSetAttrFontStyle: function () { + this.__assembleFont(); + }, + __afterSetAttrFontVariant: function () { + this.__assembleFont(); + }, + __afterSetAttrFont: function () { + // this.attr('width', this.measureText()); + }, + __afterSetAttrText: function () { + var attrs = this.__attrs; + var text = attrs.text; + var textArr = void 0; + if (index$8.isString(text) && text.indexOf('\n') !== -1) { + textArr = text.split('\n'); + var lineCount = textArr.length; + attrs.lineCount = lineCount; + attrs.textArr = textArr; + } + // attrs.height = this.__getTextHeight(); + // attrs.width = this.measureText(); + }, + __getTextHeight: function () { + var attrs = this.__attrs; + var lineCount = attrs.lineCount; + var fontSize = attrs.fontSize * 1; + if (lineCount > 1) { + var spaceingY = this.__getSpaceingY(); + return fontSize * lineCount + spaceingY * (lineCount - 1); + } + return fontSize; + }, + + // 计算浪费,效率低,待优化 + __afterSetAttrAll: function (objs) { + var self = this; + if ('fontSize' in objs || 'fontWeight' in objs || 'fontStyle' in objs || 'fontVariant' in objs || 'fontFamily' in objs) { + self.__assembleFont(); + } + + if ('text' in objs) { + self.__afterSetAttrText(objs.text); + } + }, + isHitBox: function () { + return false; + }, + calculateBox: function () { + var self = this; + var attrs = self.__attrs; + var x = attrs.x; + var y = attrs.y; + var width = self.measureText(); // attrs.width + if (!width) { + // 如果width不存在,四点共其实点 + return { + minX: x, + minY: y, + maxX: x, + maxY: y + }; + } + var height = self.__getTextHeight(); // attrs.height + var textAlign = attrs.textAlign; + var textBaseline = attrs.textBaseline; + var lineWidth = attrs.lineWidth; + var point = { + x: x, + y: y - height + }; + + if (textAlign) { + if (textAlign === 'end' || textAlign === 'right') { + point.x -= width; + } else if (textAlign === 'center') { + point.x -= width / 2; + } + } + + if (textBaseline) { + if (textBaseline === 'top') { + point.y += height; + } else if (textBaseline === 'middle') { + point.y += height / 2; + } + } + + this.set('startPoint', point); + var halfWidth = lineWidth / 2; + return { + minX: point.x - halfWidth, + minY: point.y - halfWidth, + maxX: point.x + width + halfWidth, + maxY: point.y + height + halfWidth + }; + }, + __getSpaceingY: function () { + var attrs = this.__attrs; + var lineHeight = attrs.lineHeight; + var fontSize = attrs.fontSize * 1; + return lineHeight ? lineHeight - fontSize : fontSize * 0.14; + }, + isPointInPath: function (x, y) { + var self = this; + var box = self.getBBox(); + if (self.hasFill() || self.hasStroke()) { + return inside.box(box.minX, box.maxX, box.minY, box.maxY, x, y); + } + }, + drawInner: function (context) { + var self = this; + var attrs = self.__attrs; + var text = attrs.text; + if (!text) { + return; + } + var textArr = attrs.textArr; + var fontSize = attrs.fontSize * 1; + var spaceingY = self.__getSpaceingY(); + var x = attrs.x; + var y = attrs.y; + var textBaseline = attrs.textBaseline; + var height = void 0; + if (textArr) { + var box = self.getBBox(); + height = box.maxY - box.minY; + } + var subY = void 0; + + context.beginPath(); + if (self.hasFill()) { + var fillOpacity = attrs.fillOpacity; + if (!index$8.isNil(fillOpacity) && fillOpacity !== 1) { + context.globalAlpha = fillOpacity; + } + if (textArr) { + index$8.each(textArr, function (subText, index) { + subY = y + index * (spaceingY + fontSize) - height + fontSize; // bottom; + if (textBaseline === 'middle') subY += height - fontSize - (height - fontSize) / 2; + if (textBaseline === 'top') subY += height - fontSize; + context.fillText(subText, x, subY); + }); + } else { + context.fillText(text, x, y); + } + } + + if (self.hasStroke()) { + if (textArr) { + index$8.each(textArr, function (subText, index) { + subY = y + index * (spaceingY + fontSize) - height + fontSize; // bottom; + if (textBaseline === 'middle') subY += height - fontSize - (height - fontSize) / 2; + if (textBaseline === 'top') subY += height - fontSize; + context.strokeText(subText, x, subY); + }); + } else { + context.strokeText(text, x, y); + } + } + }, + measureText: function () { + var self = this; + var attrs = self.__attrs; + var text = attrs.text; + var font = attrs.font; + var textArr = attrs.textArr; + var measureWidth = void 0; + var width = 0; + + if (index$8.isNil(text)) return undefined; + var context = common$2.backupContext; + context.save(); + context.font = font; + if (textArr) { + index$8.each(textArr, function (subText) { + measureWidth = context.measureText(subText).width; + if (width < measureWidth) { + width = measureWidth; + } + context.restore(); + }); + } else { + width = context.measureText(text).width; + context.restore(); + } + return width; + } +}); + +var text = CText; + +/** + * @fileOverview 直线 + * @author dxq613@gmail.com + * @author hankaiai@126.com + * @ignore + */ + + + + + + +var Vector2$8 = index$14.Vector2; + +var Line = function (cfg) { + Line.superclass.constructor.call(this, cfg); +}; + +Line.ATTRS = { + x1: 0, + y1: 0, + x2: 0, + y2: 0, + lineWidth: 1, + arrow: false +}; + +index$8.extend(Line, shape); + +index$8.augment(Line, { + canStroke: true, + type: 'line', + getDefaultAttrs: function () { + return { + lineWidth: 1, + arrow: false + }; + }, + calculateBox: function () { + var attrs = this.__attrs; + var x1 = attrs.x1; + var y1 = attrs.y1; + var x2 = attrs.x2; + var y2 = attrs.y2; + var lineWidth = attrs.lineWidth; + + return line.box(x1, y1, x2, y2, lineWidth); + }, + isPointInPath: function (x, y) { + var attrs = this.__attrs; + var x1 = attrs.x1; + var y1 = attrs.y1; + var x2 = attrs.x2; + var y2 = attrs.y2; + var lineWidth = attrs.lineWidth; + if (this.hasStroke()) { + return inside.line(x1, y1, x2, y2, lineWidth, x, y); + } + + return false; + }, + createPath: function (context) { + var attrs = this.__attrs; + var x1 = attrs.x1; + var y1 = attrs.y1; + var x2 = attrs.x2; + var y2 = attrs.y2; + var arrow = attrs.arrow; + var lineWidth = attrs.lineWidth; + context = context || self.get('context'); + context.beginPath(); + context.moveTo(x1, y1); + if (arrow) { + var v = new Vector2$8(x2 - x1, y2 - y1); + var end = arrow_1.getEndPoint(v, new Vector2$8(x2, y2), lineWidth); + context.lineTo(end.x, end.y); + arrow_1.makeArrow(context, v, end, lineWidth); + } else { + context.lineTo(x2, y2); + } + }, + getPoint: function (t) { + var attrs = this.__attrs; + return { + x: line.at(attrs.x1, attrs.x2, t), + y: line.at(attrs.y1, attrs.y2, t) + }; + } +}); + +var line$2 = Line; + +/** + * @fileOverview 图像 + * @author dxq613@gmail.com + * @author hankaiai@126.com + * @ignore + */ + + + + +var CImage = function (cfg) { + CImage.superclass.constructor.call(this, cfg); +}; + +CImage.ATTRS = { + x: 0, + y: 0, + img: undefined, + width: 0, + height: 0, + sx: null, + sy: null, + swidth: null, + sheight: null +}; + +index$8.extend(CImage, shape); + +index$8.augment(CImage, { + type: 'image', + __afterSetAttrImg: function (img) { + this.__setAttrImg(img); + }, + __afterSetAttrAll: function (params) { + if (params.img) { + this.__setAttrImg(params.img); + } + }, + isHitBox: function () { + return false; + }, + calculateBox: function () { + var attrs = this.__attrs; + var x = attrs.x; + var y = attrs.y; + var width = attrs.width; + var height = attrs.height; + + return { + minX: x, + minY: y, + maxX: x + width, + maxY: y + height + }; + }, + isPointInPath: function (x, y) { + var attrs = this.__attrs; + if (this.get('toDraw') || !attrs.img) { + return false; + } + var rx = attrs.x; + var ry = attrs.y; + var width = attrs.width; + var height = attrs.height; + return inside.rect(rx, ry, width, height, x, y); + }, + __setLoading: function (loading) { + var canvas = this.get('canvas'); + if (loading === false && this.get('toDraw') === true) { + this.__cfg.loading = false; + canvas.draw(); + } + return loading; + }, + __setAttrImg: function (img) { + var self = this; + var attrs = self.__attrs; + if (index$8.isString(img)) { + var image = new Image(); + image.onload = function () { + if (self.get('destroyed')) return false; + self.attr('imgSrc', img); + self.attr('img', image); + var callback = self.get('callback'); + if (callback) { + callback.call(self); + } + self.set('loading', false); + }; + image.src = img; + self.set('loading', true); + } else if (img instanceof Image) { + if (!attrs.width) { + self.attr('width', img.width); + } + + if (!attrs.height) { + self.attr('height', img.height); + } + return img; + } else if (img instanceof HTMLElement && index$8.isString(img.nodeName) && img.nodeName.toUpperCase() === 'CANVAS') { + if (!attrs.width) { + self.attr('width', Number(img.getAttribute('width'))); + } + + if (!attrs.height) { + self.attr('height', Number(img.getAttribute('height'))); + } + return img; + } else if (img instanceof ImageData) { + if (!attrs.width) { + self.attr('width', img.width); + } + + if (!attrs.height) { + self.attr('height', img.height); + } + return img; + } else { + return null; + } + }, + drawInner: function (context) { + if (this.get('loading')) { + this.set('toDraw', true); + return; + } + this.__drawImage(context); + }, + __drawImage: function (context) { + var attrs = this.__attrs; + var x = attrs.x; + var y = attrs.y; + var img = attrs.img; + var width = attrs.width; + var height = attrs.height; + var sx = attrs.sx; + var sy = attrs.sy; + var swidth = attrs.swidth; + var sheight = attrs.sheight; + this.set('toDraw', false); + + if (img instanceof Image || img instanceof HTMLElement && index$8.isString(img.nodeName) && img.nodeName.toUpperCase() === 'CANVAS') { + if (index$8.isNil(sx) || index$8.isNil(sy) || index$8.isNil(swidth) || index$8.isNil(sheight)) { + context.drawImage(img, x, y, width, height); + return; + } + if (!index$8.isNil(sx) && !index$8.isNil(sy) && !index$8.isNil(swidth) && !index$8.isNil(sheight)) { + context.drawImage(img, sx, sy, swidth, sheight, x, y, width, height); + return; + } + } else if (img instanceof ImageData) { + context.putImageData(img, x, y, sx || 0, sy || 0, swidth || width, sheight || height); + return; + } + return; + } +}); + +var image = CImage; + +/** + * @fileOverview polygon + * @author dxq613@gmail.com + * @author hankaiai@126.com + * @ignore + */ + + + + +var Polygon = function (cfg) { + Polygon.superclass.constructor.call(this, cfg); +}; + +Polygon.ATTRS = { + points: null, + lineWidth: 1 +}; + +index$8.extend(Polygon, shape); + +index$8.augment(Polygon, { + canFill: true, + canStroke: true, + type: 'polygon', + getDefaultAttrs: function () { + return { + lineWidth: 1 + }; + }, + calculateBox: function () { + var self = this; + var attrs = self.__attrs; + var points = attrs.points; + var lineWidth = attrs.lineWidth; + if (!points || points.length === 0) { + return null; + } + var minX = Infinity; + var minY = Infinity; + var maxX = -Infinity; + var maxY = -Infinity; + + index$8.each(points, function (point) { + var x = point[0]; + var y = point[1]; + if (x < minX) { + minX = x; + } + if (x > maxX) { + maxX = x; + } + + if (y < minY) { + minY = y; + } + + if (y > maxY) { + maxY = y; + } + }); + + var halfWidth = lineWidth / 2; + return { + minX: minX - halfWidth, + minY: minY - halfWidth, + maxX: maxX + halfWidth, + maxY: maxY + halfWidth + }; + }, + isPointInPath: function (x, y) { + var self = this; + var fill = self.hasFill(); + var stroke = self.hasStroke(); + + if (fill && stroke) { + return self.__isPointInFill(x, y) || self.__isPointInStroke(x, y); + } + + if (fill) { + return self.__isPointInFill(x, y); + } + + if (stroke) { + return self.__isPointInStroke(x, y); + } + + return false; + }, + __isPointInFill: function (x, y) { + var self = this; + var context = self.get('context'); + self.createPath(); + return context.isPointInPath(x, y); + }, + __isPointInStroke: function (x, y) { + var self = this; + var attrs = self.__attrs; + var points = attrs.points; + if (points.length < 2) { + return false; + } + var lineWidth = attrs.lineWidth; + var outPoints = points.slice(0); + if (points.length >= 3) { + outPoints.push(points[0]); + } + + return inside.polyline(outPoints, lineWidth, x, y); + }, + createPath: function (context) { + var self = this; + var attrs = self.__attrs; + var points = attrs.points; + if (points.length < 2) { + return; + } + context = context || self.get('context'); + context.beginPath(); + index$8.each(points, function (point, index) { + if (index === 0) { + context.moveTo(point[0], point[1]); + } else { + context.lineTo(point[0], point[1]); + } + }); + context.closePath(); + } +}); + +var polygon = Polygon; + +/** + * @fileOverview polyline + * @author dxq613@gmail.com + * @author hankaiai@126.com + * @ignore + */ + + + + + + +var Vector2$9 = index$14.Vector2; + +var Polyline = function (cfg) { + Polyline.superclass.constructor.call(this, cfg); +}; + +Polyline.ATTRS = { + points: null, + lineWidth: 1, + arrow: false, + tCache: null +}; + +index$8.extend(Polyline, shape); + +index$8.augment(Polyline, { + canStroke: true, + type: 'polyline', + tCache: null, // 缓存各点的t + getDefaultAttrs: function () { + return { + lineWidth: 1, + arrow: false + }; + }, + calculateBox: function () { + var self = this; + var attrs = self.__attrs; + var lineWidth = attrs.lineWidth; + var points = attrs.points; + if (!points || points.length === 0) { + return null; + } + var minX = Infinity; + var minY = Infinity; + var maxX = -Infinity; + var maxY = -Infinity; + + index$8.each(points, function (point) { + var x = point[0]; + var y = point[1]; + if (x < minX) { + minX = x; + } + if (x > maxX) { + maxX = x; + } + + if (y < minY) { + minY = y; + } + + if (y > maxY) { + maxY = y; + } + }); + + var halfWidth = lineWidth / 2; + return { + minX: minX - halfWidth, + minY: minY - halfWidth, + maxX: maxX + halfWidth, + maxY: maxY + halfWidth + }; + }, + __setTcache: function () { + var self = this; + var attrs = self.__attrs; + var points = attrs.points; + var totalLength = 0; + var tempLength = 0; + var tCache = []; + var segmentT = void 0; + var segmentL = void 0; + if (!points || points.length === 0) { + return; + } + + index$8.each(points, function (p, i) { + if (points[i + 1]) { + totalLength += line.len(p[0], p[1], points[i + 1][0], points[i + 1][1]); + } + }); + if (totalLength <= 0) { + return; + } + index$8.each(points, function (p, i) { + if (points[i + 1]) { + segmentT = []; + segmentT[0] = tempLength / totalLength; + segmentL = line.len(p[0], p[1], points[i + 1][0], points[i + 1][1]); + tempLength += segmentL; + segmentT[1] = tempLength / totalLength; + tCache.push(segmentT); + } + }); + this.tCache = tCache; + }, + isPointInPath: function (x, y) { + var self = this; + var attrs = self.__attrs; + if (self.hasStroke()) { + var points = attrs.points; + if (points.length < 2) { + return false; + } + var lineWidth = attrs.lineWidth; + return inside.polyline(points, lineWidth, x, y); + } + return false; + }, + createPath: function (context) { + var self = this; + var attrs = self.__attrs; + var points = attrs.points; + var arrow = attrs.arrow; + var lineWidth = attrs.lineWidth; + var l = void 0; + var i = void 0; + + if (points.length < 2) { + return; + } + context = context || self.get('context'); + context.beginPath(); + context.moveTo(points[0][0], points[0][1]); + for (i = 1, l = points.length - 1; i < l; i++) { + context.lineTo(points[i][0], points[i][1]); + } + if (arrow) { + var v = new Vector2$9(points[l][0] - points[l - 1][0], points[l][1] - points[l - 1][1]); + var end = arrow_1.getEndPoint(v, new Vector2$9(points[l][0], points[l][1]), lineWidth); + context.lineTo(end.x, end.y); + arrow_1.makeArrow(context, v, end, lineWidth); + } else { + context.lineTo(points[l][0], points[l][1]); + } + }, + getPoint: function (t) { + var attrs = this.__attrs; + var points = attrs.points; + var tCache = this.tCache; + var subt = void 0; + var index = void 0; + if (!tCache) { + this.__setTcache(); + tCache = this.tCache; + } + index$8.each(tCache, function (v, i) { + if (t >= v[0] && t <= v[1]) { + subt = (t - v[0]) / (v[1] - v[0]); + index = i; + } + }); + return { + x: line.at(points[index][0], points[index + 1][0], subt), + y: line.at(points[index][1], points[index + 1][1], subt) + }; + } +}); + +var polyline = Polyline; + +/** + * @fileOverview arc + * @author dxq613@gmail.com + * @author hankaiai@126.com + * @ignore + */ + + +var Vector2$10 = index$14.Vector2; + + + + + +var Arc = function (cfg) { + Arc.superclass.constructor.call(this, cfg); +}; + +Arc.ATTRS = { + x: 0, + y: 0, + r: 0, + startAngle: 0, + endAngle: 0, + clockwise: false, + lineWidth: 1, + arrow: false +}; + +index$8.extend(Arc, shape); + +index$8.augment(Arc, { + canStroke: true, + type: 'arc', + getDefaultAttrs: function () { + return { + x: 0, + y: 0, + r: 0, + startAngle: 0, + endAngle: 0, + clockwise: false, + lineWidth: 1, + arrow: false + }; + }, + calculateBox: function () { + var attrs = this.__attrs; + var cx = attrs.x; + var cy = attrs.y; + var r = attrs.r; + var startAngle = attrs.startAngle; + var endAngle = attrs.endAngle; + var clockwise = attrs.clockwise; + var lineWidth = attrs.lineWidth; + var halfWidth = lineWidth / 2; + var box = arc.box(cx, cy, r, startAngle, endAngle, clockwise); + box.minX -= halfWidth; + box.minY -= halfWidth; + box.maxX += halfWidth; + box.maxY += halfWidth; + return box; + }, + isPointInPath: function (x, y) { + var attrs = this.__attrs; + var cx = attrs.x; + var cy = attrs.y; + var r = attrs.r; + var startAngle = attrs.startAngle; + var endAngle = attrs.endAngle; + var clockwise = attrs.clockwise; + var lineWidth = attrs.lineWidth; + + if (this.hasStroke()) { + return inside.arcline(cx, cy, r, startAngle, endAngle, clockwise, lineWidth, x, y); + } + return false; + }, + createPath: function (context) { + var attrs = this.__attrs; + var cx = attrs.x; + var cy = attrs.y; + var r = attrs.r; + var startAngle = attrs.startAngle; + var endAngle = attrs.endAngle; + var clockwise = attrs.clockwise; + var lineWidth = attrs.lineWidth; + var arrow = attrs.arrow; + context = context || self.get('context'); + + context.beginPath(); + context.arc(cx, cy, r, startAngle, endAngle, clockwise); + + if (arrow) { + var end = { + x: cx + r * Math.cos(endAngle), + y: cy + r * Math.sin(endAngle) + }; + + var v = new Vector2$10(-r * Math.sin(endAngle), r * Math.cos(endAngle)); + if (clockwise) { + v.multiplyScaler(-1); + } + arrow_1.makeArrow(context, v, end, lineWidth); + } + } +}); + +var arc$2 = Arc; + +/** + * @fileOverview 扇形 + * @author dxq613@gmail.com + * @author hankaiai@126.com + * @ignore + */ + + + + + +var Vector2$11 = index$14.Vector2; + +var Fan = function (cfg) { + Fan.superclass.constructor.call(this, cfg); +}; + +Fan.ATTRS = { + x: 0, + y: 0, + rs: 0, + re: 0, + startAngle: 0, + endAngle: 0, + clockwise: false, + lineWidth: 1 +}; + +index$8.extend(Fan, shape); + +index$8.augment(Fan, { + canFill: true, + canStroke: true, + type: 'fan', + getDefaultAttrs: function () { + return { + clockwise: false, + lineWidth: 1, + rs: 0, + re: 0 + }; + }, + calculateBox: function () { + var self = this; + var attrs = self.__attrs; + var cx = attrs.x; + var cy = attrs.y; + var rs = attrs.rs; + var re = attrs.re; + var startAngle = attrs.startAngle; + var endAngle = attrs.endAngle; + var clockwise = attrs.clockwise; + var lineWidth = attrs.lineWidth; + + var boxs = arc.box(cx, cy, rs, startAngle, endAngle, clockwise); + var boxe = arc.box(cx, cy, re, startAngle, endAngle, clockwise); + var minX = Math.min(boxs.minX, boxe.minX); + var minY = Math.min(boxs.minY, boxe.minY); + var maxX = Math.max(boxs.maxX, boxe.maxX); + var maxY = Math.max(boxs.maxY, boxe.maxY); + + var halfWidth = lineWidth / 2; + return { + minX: minX - halfWidth, + minY: minY - halfWidth, + maxX: maxX + halfWidth, + maxY: maxY + halfWidth + }; + }, + isPointInPath: function (x, y) { + var fill = this.hasFill(); + var stroke = this.hasStroke(); + + if (fill && stroke) { + return this.__isPointInFill(x, y) || this.__isPointInStroke(x, y); + } + + if (fill) { + return this.__isPointInFill(x, y); + } + + if (stroke) { + return this.__isPointInStroke(x, y); + } + return false; + }, + __isPointInFill: function (x, y) { + var attrs = this.__attrs; + var cx = attrs.x; + var cy = attrs.y; + var rs = attrs.rs; + var re = attrs.re; + var startAngle = attrs.startAngle; + var endAngle = attrs.endAngle; + var clockwise = attrs.clockwise; + + var v1 = new Vector2$11(1, 0); + var subv = new Vector2$11(x - cx, y - cy); + var angle = v1.angleTo(subv); + + var angle1 = arc.nearAngle(angle, startAngle, endAngle, clockwise); + + if (index$8.isNumberEqual(angle, angle1)) { + var ls = subv.lengthSq(); + if (rs * rs <= ls && ls <= re * re) { + return true; + } + } + return false; + }, + __isPointInStroke: function (x, y) { + var attrs = this.__attrs; + var cx = attrs.x; + var cy = attrs.y; + var rs = attrs.rs; + var re = attrs.re; + var startAngle = attrs.startAngle; + var endAngle = attrs.endAngle; + var clockwise = attrs.clockwise; + var lineWidth = attrs.lineWidth; + + var ssp = { + x: Math.cos(startAngle) * rs + cx, + y: Math.sin(startAngle) * rs + cy + }; + var sep = { + x: Math.cos(startAngle) * re + cx, + y: Math.sin(startAngle) * re + cy + }; + var esp = { + x: Math.cos(endAngle) * rs + cx, + y: Math.sin(endAngle) * rs + cy + }; + var eep = { + x: Math.cos(endAngle) * re + cx, + y: Math.sin(endAngle) * re + cy + }; + + if (inside.line(ssp.x, ssp.y, sep.x, sep.y, lineWidth, x, y)) { + return true; + } + + if (inside.line(esp.x, esp.y, eep.x, eep.y, lineWidth, x, y)) { + return true; + } + + if (inside.arcline(cx, cy, rs, startAngle, endAngle, clockwise, lineWidth, x, y)) { + return true; + } + + if (inside.arcline(cx, cy, re, startAngle, endAngle, clockwise, lineWidth, x, y)) { + return true; + } + + return false; + }, + createPath: function (context) { + var attrs = this.__attrs; + var cx = attrs.x; + var cy = attrs.y; + var rs = attrs.rs; + var re = attrs.re; + var startAngle = attrs.startAngle; + var endAngle = attrs.endAngle; + var clockwise = attrs.clockwise; + + var ssp = { + x: Math.cos(startAngle) * rs + cx, + y: Math.sin(startAngle) * rs + cy + }; + var sep = { + x: Math.cos(startAngle) * re + cx, + y: Math.sin(startAngle) * re + cy + }; + var esp = { + x: Math.cos(endAngle) * rs + cx, + y: Math.sin(endAngle) * rs + cy + }; + + context = context || self.get('context'); + context.beginPath(); + context.moveTo(ssp.x, ssp.y); + context.lineTo(sep.x, sep.y); + context.arc(cx, cy, re, startAngle, endAngle, clockwise); + context.lineTo(esp.x, esp.y); + context.arc(cx, cy, rs, endAngle, startAngle, !clockwise); + context.closePath(); + } +}); + +var fan = Fan; + +/** + * @fileOverview Cubic + * @author hankaiai@126.com + * @ignore + */ + + + + + +var Vector2$12 = index$14.Vector2; + +var Cubic = function (cfg) { + Cubic.superclass.constructor.call(this, cfg); +}; + +Cubic.ATTRS = { + p1: null, + p2: null, + p3: null, + p4: null, + lineWidth: 1, + arrow: false +}; + +index$8.extend(Cubic, shape); + +index$8.augment(Cubic, { + canStroke: true, + type: 'cubic', + getDefaultAttrs: function () { + return { + lineWidth: 1 + }; + }, + calculateBox: function () { + var attrs = this.__attrs; + var p1 = attrs.p1; + var p2 = attrs.p2; + var p3 = attrs.p3; + var p4 = attrs.p4; + var i = void 0; + var l = void 0; + + if (index$8.isNil(p1) || index$8.isNil(p2) || index$8.isNil(p3) || index$8.isNil(p4)) { + return null; + } + var halfWidth = attrs.lineWidth / 2; + + var xDim = cubic.extrema(p1[0], p2[0], p3[0], p4[0]); + for (i = 0, l = xDim.length; i < l; i++) { + xDim[i] = cubic.at(p1[0], p2[0], p3[0], p4[0], xDim[i]); + } + var yDim = cubic.extrema(p1[1], p2[1], p3[1], p4[1]); + for (i = 0, l = yDim.length; i < l; i++) { + yDim[i] = cubic.at(p1[1], p2[1], p3[1], p4[1], yDim[i]); + } + xDim.push(p1[0], p4[0]); + yDim.push(p1[1], p4[1]); + + return { + minX: Math.min.apply(Math, xDim) - halfWidth, + maxX: Math.max.apply(Math, xDim) + halfWidth, + minY: Math.min.apply(Math, yDim) - halfWidth, + maxY: Math.max.apply(Math, yDim) + halfWidth + }; + }, + isPointInPath: function (x, y) { + var attrs = this.__attrs; + var p1 = attrs.p1; + var p2 = attrs.p2; + var p3 = attrs.p3; + var p4 = attrs.p4; + var lineWidth = attrs.lineWidth; + + return inside.cubicline(p1[0], p1[1], p2[0], p2[1], p3[0], p3[1], p4[0], p4[1], lineWidth, x, y); + }, + createPath: function (context) { + var attrs = this.__attrs; + var p1 = attrs.p1; + var p2 = attrs.p2; + var p3 = attrs.p3; + var p4 = attrs.p4; + var lineWidth = attrs.lineWidth; + var arrow = attrs.arrow; + context = context || self.get('context'); + if (index$8.isNil(p1) || index$8.isNil(p2) || index$8.isNil(p3) || index$8.isNil(p4)) { + return; + } + + context.beginPath(); + context.moveTo(p1[0], p1[1]); + + if (arrow) { + var v = new Vector2$12(p4[0] - p3[0], p4[1] - p3[1]); + var end = arrow_1.getEndPoint(v, new Vector2$12(p4[0], p4[1]), lineWidth); + context.bezierCurveTo(p2[0], p2[1], p3[0], p3[1], end.x, end.y); + arrow_1.makeArrow(context, v, end, lineWidth); + } else { + context.bezierCurveTo(p2[0], p2[1], p3[0], p3[1], p4[0], p4[1]); + } + }, + getPoint: function (t) { + var attrs = this.__attrs; + return { + x: cubic.at(attrs.p4[0], attrs.p3[0], attrs.p2[0], attrs.p1[0], t), + y: cubic.at(attrs.p4[1], attrs.p3[1], attrs.p2[1], attrs.p1[1], t) + }; + } +}); + +var cubic$2 = Cubic; + +/** + * @fileOverview Quadratic + * @author hankaiai@126.com + * @ignore + */ + + + + + +var Vector2$13 = index$14.Vector2; + +var Quadratic = function (cfg) { + Quadratic.superclass.constructor.call(this, cfg); +}; + +Quadratic.ATTRS = { + p1: null, + p2: null, + p3: null, + lineWidth: 1, + arrow: false +}; + +index$8.extend(Quadratic, shape); + +index$8.augment(Quadratic, { + canStroke: true, + type: 'quadratic', + getDefaultAttrs: function () { + return { + lineWidth: 1, + arrow: false + }; + }, + calculateBox: function () { + var self = this; + var attrs = self.__attrs; + var p1 = attrs.p1; + var p2 = attrs.p2; + var p3 = attrs.p3; + var i = void 0; + var l = void 0; + + if (index$8.isNil(p1) || index$8.isNil(p2) || index$8.isNil(p3)) { + return null; + } + var halfWidth = attrs.lineWidth / 2; + + var xDims = quadratic.extrema(p1[0], p2[0], p3[0]); + for (i = 0, l = xDims.length; i < l; i++) { + xDims[i] = quadratic.at(p1[0], p2[0], p3[0], xDims[i]); + } + xDims.push(p1[0], p3[0]); + var yDims = quadratic.extrema(p1[1], p2[1], p3[1]); + for (i = 0, l = yDims.length; i < l; i++) { + yDims[i] = quadratic.at(p1[1], p2[1], p3[1], yDims[i]); + } + yDims.push(p1[1], p3[1]); + + return { + minX: Math.min.apply(Math, xDims) - halfWidth, + maxX: Math.max.apply(Math, xDims) + halfWidth, + minY: Math.min.apply(Math, yDims) - halfWidth, + maxY: Math.max.apply(Math, yDims) + halfWidth + }; + }, + isPointInPath: function (x, y) { + var self = this; + var attrs = self.__attrs; + var p1 = attrs.p1; + var p2 = attrs.p2; + var p3 = attrs.p3; + var lineWidth = attrs.lineWidth; + + return inside.quadraticline(p1[0], p1[1], p2[0], p2[1], p3[0], p3[1], lineWidth, x, y); + }, + createPath: function (context) { + var self = this; + var attrs = self.__attrs; + var p1 = attrs.p1; + var p2 = attrs.p2; + var p3 = attrs.p3; + var lineWidth = attrs.lineWidth; + var arrow = attrs.arrow; + + if (index$8.isNil(p1) || index$8.isNil(p2) || index$8.isNil(p3)) { + return; + } + context = context || self.get('context'); + context.beginPath(); + context.moveTo(p1[0], p1[1]); + + if (arrow) { + var v = new Vector2$13(p3[0] - p2[0], p3[1] - p2[1]); + var end = arrow_1.getEndPoint(v, new Vector2$13(p3[0], p3[1]), lineWidth); + context.quadraticCurveTo(p2[0], p2[1], end.x, end.y); + arrow_1.makeArrow(context, v, end, lineWidth); + } else { + context.quadraticCurveTo(p2[0], p2[1], p3[0], p3[1]); + } + }, + getPoint: function (t) { + var attrs = this.__attrs; + return { + x: quadratic.at(attrs.p1[0], attrs.p2[0], attrs.p3[0], t), + y: quadratic.at(attrs.p1[1], attrs.p2[1], attrs.p3[1], t) + }; + } +}); + +var quadratic$2 = Quadratic; + +var Marker = function (cfg) { + Marker.superclass.constructor.call(this, cfg); +}; + +Marker.Symbols = { + // 圆 + circle: function (x, y, r, ctx) { + ctx.arc(x, y, r, 0, Math.PI * 2, false); + }, + + // 正方形 + square: function (x, y, r, ctx) { + ctx.moveTo(x - r, y - r); + ctx.lineTo(x + r, y - r); + ctx.lineTo(x + r, y + r); + ctx.lineTo(x - r, y + r); + ctx.closePath(); + }, + + // 菱形 + diamond: function (x, y, r, ctx) { + ctx.moveTo(x - r, y); + ctx.lineTo(x, y - r); + ctx.lineTo(x + r, y); + ctx.lineTo(x, y + r); + ctx.closePath(); + }, + + // 三角形 + triangle: function (x, y, r, ctx) { + var diffX = r / 0.966; + var diffY = r; + ctx.moveTo(x, y - r); + ctx.lineTo(x + diffX, y + diffY); + ctx.lineTo(x - diffX, y + diffY); + ctx.closePath(); + }, + + // 倒三角形 + 'triangle-down': function (x, y, r, ctx) { + var diffX = r / 0.966; + var diffY = r; + ctx.moveTo(x, y + r); + ctx.lineTo(x + diffX, y - diffY); + ctx.lineTo(x - diffX, y - diffY); + ctx.closePath(); + } +}; + +Marker.ATTRS = { + path: null, + lineWidth: 1 +}; + +index$8.extend(Marker, shape); + +index$8.augment(Marker, { + type: 'marker', + canFill: true, + canStroke: true, + getDefaultAttrs: function () { + return { + x: 0, + y: 0, + lineWidth: 1 + }; + }, + calculateBox: function () { + var attrs = this.__attrs; + var cx = attrs.x; + var cy = attrs.y; + var r = attrs.radius; + var lineWidth = attrs.lineWidth; + var halfWidth = lineWidth / 2 + r; + return { + minX: cx - halfWidth, + minY: cy - halfWidth, + maxX: cx + halfWidth, + maxY: cy + halfWidth + }; + }, + isPointInPath: function (x, y) { + var attrs = this.__attrs; + var cx = attrs.x; + var cy = attrs.y; + var r = attrs.radius; + return inside.circle(cx, cy, r, x, y); + }, + createPath: function (context) { + var attrs = this.__attrs; + var x = attrs.x; + var y = attrs.y; + var r = attrs.radius; + var symbol = attrs.symbol || 'circle'; + var method = void 0; + if (index$8.isFunction(symbol)) { + method = symbol; + } else { + method = Marker.Symbols[symbol]; + } + context.beginPath(); + method(x, y, r, context); + } /**/ + +}); + +var marker = Marker; + +var Shape = { + Rect: rect, + Circle: circle, + Ellipse: ellipse, + Path: path$2, + Text: text, + Line: line$2, + Image: image, + Polygon: polygon, + Polyline: polyline, + Arc: arc$2, + Fan: fan, + Cubic: cubic$2, + Quadratic: quadratic$2, + Marker: marker +}; + +var index$26 = Shape; + +var Vector3 = index$14.Vector3; + + +var SHAPE_MAP = {}; // 缓存图形类型 + +function find(children, x, y) { + var rst = void 0; + for (var i = children.length - 1; i >= 0; i--) { + var child = children[i]; + if (child.__cfg.visible && child.__cfg.capture) { + if (child.isGroup) { + rst = child.getShape(x, y); + } else if (child.isHit(x, y)) { + rst = child; + } + } + if (rst) { + break; + } + } + return rst; +} + +var Group = function (cfg) { + Group.superclass.constructor.call(this, cfg); + this.set('children', []); + + this._beforeRenderUI(); + this._renderUI(); + this._bindUI(); +}; + +function initClassCfgs(c) { + if (c.__cfg || c === Group) { + return; + } + var superCon = c.superclass.constructor; + if (superCon && !superCon.__cfg) { + initClassCfgs(superCon); + } + c.__cfg = {}; + + index$8.merge(c.__cfg, superCon.__cfg); + index$8.merge(c.__cfg, c.CFG); +} + +index$8.extend(Group, element); + +index$8.augment(Group, { + isGroup: true, + canFill: true, + canStroke: true, + getDefaultCfg: function () { + initClassCfgs(this.constructor); + return index$8.merge({}, this.constructor.__cfg); + }, + _beforeRenderUI: function () {}, + _renderUI: function () {}, + _bindUI: function () {}, + addShape: function (type, cfg) { + var canvas = this.get('canvas'); + cfg = cfg || {}; + var shapeType = SHAPE_MAP[type]; + if (!shapeType) { + shapeType = index$8.upperFirst(type); + SHAPE_MAP[type] = shapeType; + } + if (cfg.attrs) { + var attrs = cfg.attrs; + if (type === 'text') { + // 临时解决 + var topFontFamily = canvas.get('fontFamily'); + if (topFontFamily) { + attrs.fontFamily = attrs.fontFamily ? attrs.fontFamily : topFontFamily; + } + } + } + cfg.canvas = canvas; + cfg.type = type; + var rst = new index$26[shapeType](cfg); + this.add(rst); + return rst; + }, + + /** 添加图组 + * @param {Function|Object|undefined} param 图组类 + * @param {Object} cfg 配置项 + * @return {Object} rst 图组 + */ + addGroup: function (param, cfg) { + var canvas = this.get('canvas'); + var rst = void 0; + cfg = index$8.merge({}, cfg); + if (index$8.isFunction(param)) { + if (cfg) { + cfg.canvas = canvas; + cfg.parent = this; + rst = new param(cfg); + } else { + rst = new param({ + canvas: canvas, + parent: this + }); + } + this.add(rst); + } else if (index$8.isObject(param)) { + param.canvas = canvas; + rst = new Group(param); + this.add(rst); + } else if (param === undefined) { + rst = new Group(); + this.add(rst); + } else { + return false; + } + return rst; + }, + + /** 绘制背景 + * @param {Array} padding 内边距 + * @param {Attrs} attrs 图形属性 + * @param {Shape} backShape 背景图形 + * @return {Object} 背景层对象 + */ + renderBack: function (padding, attrs) { + var backShape = this.get('backShape'); + var innerBox = this.getBBox(); + var parent = this.get('parent'); // getParent + index$8.merge(attrs, { + x: innerBox.minX - padding[3], + y: innerBox.minY - padding[0], + width: innerBox.width + padding[1] + padding[3], + height: innerBox.height + padding[0] + padding[2] + }); + if (backShape) { + backShape.attr(attrs); + } else { + backShape = parent.addShape('rect', { + zIndex: -1, + attrs: attrs + }); + } + this.set('backShape', backShape); + parent.sort(); + return backShape; + }, + removeChild: function (item, destroy) { + if (arguments.length >= 2) { + if (this.contain(item)) { + item.remove(destroy); + } + } else { + if (arguments.length === 1) { + if (index$8.isBoolean(item)) { + destroy = item; + } else { + if (this.contain(item)) { + item.remove(true); + } + return this; + } + } + if (arguments.length === 0) { + destroy = true; + } + + Group.superclass.remove.call(this, destroy); + } + return this; + }, + + /** + * 向组中添加shape或者group + * @param {Object} items 图形或者分组 + * @return {Object} group 本尊 + */ + add: function (items) { + var self = this; + var children = self.get('children'); + if (index$8.isArray(items)) { + index$8.each(items, function (item) { + var parent = item.get('parent'); + if (parent) { + parent.removeChild(item, false); + } + self.__setEvn(item); + }); + children.push.apply(children, items); + } else { + var item = items; + var parent = item.get('parent'); + if (parent) { + parent.removeChild(item, false); + } + self.__setEvn(item); + children.push(item); + } + return self; + }, + contain: function (item) { + var children = this.get('children'); + return children.indexOf(item) > -1; + }, + getChildByIndex: function (index) { + var children = this.get('children'); + return children[index]; + }, + getFirst: function () { + return this.getChildByIndex(0); + }, + getLast: function () { + var lastIndex = this.get('children').length - 1; + return this.getChildByIndex(lastIndex); + }, + __setEvn: function (item) { + var self = this; + item.__cfg.parent = self; + item.__cfg.context = self.__cfg.context; + item.__cfg.canvas = self.__cfg.canvas; + var clip = item.__attrs.clip; + if (clip) { + clip.setSilent('parent', self); + clip.setSilent('context', self.get('context')); + } + var children = item.__cfg.children; + if (children) { + index$8.each(children, function (child) { + item.__setEvn(child); + }); + } + }, + getBBox: function () { + var self = this; + var minX = Infinity; + var maxX = -Infinity; + var minY = Infinity; + var maxY = -Infinity; + var children = self.get('children'); + index$8.each(children, function (child) { + if (child.get('visible')) { + var _box = child.getBBox(); + if (!_box) { + return true; + } + var leftTop = new Vector3(_box.minX, _box.minY, 1); + var leftBottom = new Vector3(_box.minX, _box.maxY, 1); + var rightTop = new Vector3(_box.maxX, _box.minY, 1); + var rightBottom = new Vector3(_box.maxX, _box.maxY, 1); + + child.apply(leftTop); + child.apply(leftBottom); + child.apply(rightTop); + child.apply(rightBottom); + + var boxMinX = Math.min(leftTop.x, leftBottom.x, rightTop.x, rightBottom.x); + var boxMaxX = Math.max(leftTop.x, leftBottom.x, rightTop.x, rightBottom.x); + var boxMinY = Math.min(leftTop.y, leftBottom.y, rightTop.y, rightBottom.y); + var boxMaxY = Math.max(leftTop.y, leftBottom.y, rightTop.y, rightBottom.y); + + if (boxMinX < minX) { + minX = boxMinX; + } + + if (boxMaxX > maxX) { + maxX = boxMaxX; + } + + if (boxMinY < minY) { + minY = boxMinY; + } + + if (boxMaxY > maxY) { + maxY = boxMaxY; + } + } + }); + var box = { + minX: minX, + minY: minY, + maxX: maxX, + maxY: maxY + }; + box.x = box.minX; + box.y = box.minY; + box.width = box.maxX - box.minX; + box.height = box.maxY - box.minY; + return box; + }, + drawInner: function (context) { + var children = this.get('children'); + for (var i = 0; i < children.length; i++) { + var child = children[i]; + child.draw(context); + } + return this; + }, + getCount: function () { + return this.get('children').length; + }, + sort: function () { + var children = this.get('children'); + children.sort(function (obj1, obj2) { + return obj1.get('zIndex') - obj2.get('zIndex'); + }); + return this; + }, + find: function (id) { + return this.findBy(function (item) { + return item.get('id') === id; + }); + }, + + /** + * 根据查找函数查找分组或者图形 + * @param {Function} fn 匹配函数 + * @return {Canvas.Base} 分组或者图形 + */ + findBy: function (fn) { + var children = this.get('children'); + var rst = null; + + index$8.each(children, function (item) { + if (fn(item)) { + rst = item; + } else if (item.findBy) { + rst = item.findBy(fn); + } + if (rst) { + return false; + } + }); + return rst; + }, + findAllBy: function (fn) { + var children = this.get('children'); + var rst = []; + var childRst = []; + index$8.each(children, function (item) { + if (fn(item)) { + rst.push(item); + } + if (item.findAllBy) { + childRst = item.findAllBy(fn); + rst = rst.concat(childRst); + } + }); + return rst; + }, + + /** + * 根据x,y轴坐标获取对应的图形 + * @param {Number} x x坐标 + * @param {Number} y y坐标 + * @return {Object} 最上面的图形 + */ + getShape: function (x, y) { + var self = this; + var clip = self.__attrs.clip; + var children = self.__cfg.children; + var rst = void 0; + if (clip) { + if (clip.inside(x, y)) { + rst = find(children, x, y); + } + } else { + rst = find(children, x, y); + } + return rst; + }, + clearTotalMatrix: function () { + var m = this.get('totalMatrix'); + if (m) { + this.setSilent('totalMatrix', null); + var children = this.__cfg.children; + for (var i = 0; i < children.length; i++) { + var child = children[i]; + child.clearTotalMatrix(); + } + } + }, + clear: function () { + var children = this.get('children'); + + while (children.length !== 0) { + children[children.length - 1].remove(); + } + return this; + }, + destroy: function () { + if (this.get('destroyed')) { + return; + } + this.clear(); + Group.superclass.destroy.call(this); + } +}); + +var group = Group; + +var G = { + Group: group, + Shape: shape, + Rect: rect, + Circle: circle, + Ellipse: ellipse, + Path: path$2, + Text: text, + Line: line$2, + Image: image, + Polygon: polygon, + Polyline: polyline, + Arc: arc$2, + Fan: fan, + Cubic: cubic$2, + Quadratic: quadratic$2, + Marker: marker, + debug: function (debug) { + common$2.debug = debug; + } +}; + +var index$12 = G; + +var Canvas = function (cfg) { + Canvas.superclass.constructor.call(this, cfg); +}; + +Canvas.CFG = { + eventEnable: true, + /** + * 像素宽度 + * @type {Number} + */ + width: null, + /** + * 像素高度 + * @type {Number} + */ + height: null, + /** + * 画布宽度 + * @type {Number} + */ + widthCanvas: null, + /** + * 画布高度 + * @type {Number} + */ + heightCanvas: null, + /** + * CSS宽 + * @type {String} + */ + widthStyle: null, + /** + * CSS高 + * @type {String} + */ + heightStyle: null, + /** + * 容器DOM + * @type {Object} + */ + containerDOM: null, + /** + * 当前Canvas的DOM + * @type {Object} + */ + canvasDOM: null, + /** + * 屏幕像素比 + * @type {Number} + */ + pixelRatio: null +}; + +index$8.extend(Canvas, index$12.Group); + +index$8.augment(Canvas, { + init: function () { + Canvas.superclass.init.call(this); + this._setGlobalParam(); + this._setDOM(); + this._setInitSize(); + this._setCanvas(); + this._scale(); + if (this.get('eventEnable')) { + this._registEvents(); + } + }, + _registEvents: function () { + var self = this; + var el = self.get('el'); + var mouseEvent$$1 = new mouseEvent(self); + + el.addEventListener('mouseout', function (e) { + mouseEvent$$1.mouseout(e); + }, false); + + el.addEventListener('mouseover', function (e) { + mouseEvent$$1.mouseover(e); + }, false); + + el.addEventListener('mousemove', function (e) { + mouseEvent$$1.mousemove(e); + }, false); + + el.addEventListener('mousedown', function (e) { + mouseEvent$$1.mousedown(e); + }, false); + + el.addEventListener('mouseup', function (e) { + mouseEvent$$1.mouseup(e); + }, false); + + el.addEventListener('click', function (e) { + mouseEvent$$1.click(e); + }, false); + + el.addEventListener('dblclick', function (e) { + mouseEvent$$1.dblclick(e); + }, false); + }, + _scale: function () { + var pixelRatio = this.get('pixelRatio'); + this.scale(pixelRatio, pixelRatio); + }, + _setCanvas: function () { + var canvasDOM = this.get('canvasDOM'); + this.set('el', canvasDOM); + this.set('context', canvasDOM.getContext('2d')); + this.set('canvas', this); + }, + _setGlobalParam: function () { + var pixelRatio = this.get('pixelRatio'); + if (!pixelRatio) { + this.set('pixelRatio', index$8.getRatio()); + } + return; + }, + _setDOM: function () { + this._setContainer(); + this._setLayer(); + }, + _setContainer: function () { + var containerId = this.get('containerId'); + var containerDOM = this.get('containerDOM'); + if (!containerDOM) { + containerDOM = document.getElementById(containerId); + this.set('containerDOM', containerDOM); + } + index$8.modiCSS(containerDOM, { + position: 'relative' + }); + }, + _setLayer: function () { + var containerDOM = this.get('containerDOM'); + var canvasId = index$8.uniqueId('canvas_'); + if (containerDOM) { + var canvasDOM = index$8.createDom(''); + containerDOM.appendChild(canvasDOM); + this.set('canvasDOM', canvasDOM); + } + }, + _setInitSize: function () { + this.changeSize(this.get('width'), this.get('height')); + }, + _reSize: function () { + var canvasDOM = this.get('canvasDOM'); + var widthCanvas = this.get('widthCanvas'); + var heightCanvas = this.get('heightCanvas'); + var widthStyle = this.get('widthStyle'); + var heightStyle = this.get('heightStyle'); + + canvasDOM.style.width = widthStyle; + canvasDOM.style.height = heightStyle; + canvasDOM.setAttribute('width', widthCanvas); + canvasDOM.setAttribute('height', heightCanvas); + }, + getWidth: function () { + var pixelRatio = this.get('pixelRatio'); + var width = this.get('width'); + return width * pixelRatio; + }, + getHeight: function () { + var pixelRatio = this.get('pixelRatio'); + var height = this.get('height'); + return height * pixelRatio; + }, + changeSize: function (width, height) { + var pixelRatio = this.get('pixelRatio'); + var widthCanvas = width * pixelRatio; + var heightCanvas = height * pixelRatio; + + this.set('widthCanvas', widthCanvas); + this.set('heightCanvas', heightCanvas); + this.set('widthStyle', width + 'px'); + this.set('heightStyle', height + 'px'); + this.set('width', width); + this.set('height', height); + this._reSize(); + }, + + /** + * 将窗口坐标转变成 canvas 坐标 + * @param {Number} clientX 窗口x坐标 + * @param {Number} clientY 窗口y坐标 + * @return {Object} canvas坐标 + */ + getPointByClient: function (clientX, clientY) { + var el = this.get('el'); + var bbox = el.getBoundingClientRect(); + var width = bbox.right - bbox.left; + var height = bbox.bottom - bbox.top; + return { + x: (clientX - bbox.left) * (el.width / width), + y: (clientY - bbox.top) * (el.height / height) + }; + }, + getClientByPoint: function (x, y) { + var el = this.get('el'); + var bbox = el.getBoundingClientRect(); + var width = bbox.right - bbox.left; + var height = bbox.bottom - bbox.top; + return { + clientX: x / (el.width / width) + bbox.left, + clientY: y / (el.height / height) + bbox.top + }; + }, + beforeDraw: function () { + var context = this.get('context'); + var el = this.get('el'); + context && context.clearRect(0, 0, el.width, el.height); + }, + _beginDraw: function () { + this.setSilent('toDraw', true); + }, + _endDraw: function () { + this.setSilent('toDraw', false); + }, + draw: function () { + var self = this; + function drawInner() { + self.set('animateHandler', index$8.requestAnimationFrame(function () { + self.set('animateHandler', undefined); + if (self.get('toDraw')) { + drawInner(); + } + })); + self.beforeDraw(); + try { + var context = self.get('context'); + Canvas.superclass.draw.call(self, context); + // self._drawCanvas(); + } catch (ev) { + // 绘制时异常,中断重绘 + console.warn('error in draw canvas, detail as:'); + console.warn(ev); + self._endDraw(); + } + self._endDraw(); + } + + if (self.get('destroyed')) { + return; + } + if (self.get('animateHandler')) { + this._beginDraw(); + } else { + drawInner(); + } + }, + destroy: function () { + var containerDOM = this.get('containerDOM'); + var canvasDOM = this.get('canvasDOM'); + if (canvasDOM && containerDOM) { + containerDOM.removeChild(canvasDOM); + } + Canvas.superclass.destroy.call(this); + } +}); + +var canvas = Canvas; + +var matrix$2 = { + /** + * 同 G transform + * @param {Object} m 矩阵 + * @param {Array} ts 变换数组同 + * @return {Object} this 回调函数 + */ + transform: function (m, ts) { + m = m.clone(); + for (var i = 0, len = ts.length; i < len; i++) { + var t = ts[i]; + switch (t[0]) { + case 't': + m.translate(t[1], t[2]); + break; + case 's': + m.scale(t[1], t[2]); + break; + case 'r': + m.rotate(t[1]); + break; + case 'm': + m.multiply(t[1]); + break; + default: + continue; + } + } + return m; + }, + + /** + * 基于某点缩放 + * @param {Object} m 矩阵 + * @param {Number} sx x缩放 + * @param {Number} sy y缩放 + * @param {Number} x 坐标点 + * @param {Number} y 坐标点 + * @return {Matrix} 返回变换后的矩阵 + */ + scale: function (m, sx, sy, x, y) { + m = m.clone(); + m.translate(-1 * x, -1 * y); + m.scale(sx, sy); + m.translate(x, y); + return m; + }, + + /** + * 基于某点旋转 + * @param {Object} m 矩阵 + * @param {Number} r 旋转角度,用弧度表示 + * @param {Number} x 坐标点 + * @param {Number} y 坐标点 + * @return {Matrix} 返回变换后的矩阵 + */ + rotate: function (m, r, x, y) { + m = m.clone(); + m.translate(-1 * x, -1 * y); + m.rotate(r); + m.translate(x, y); + return m; + }, + + /** + * 判断是否是3阶矩阵 + * @param {Object} m 矩阵 + * @return {Boolean} 返回是否是三阶矩阵 + */ + isMatrix3: function (m) { + return m.type === 'matrix3'; + } +}; + +canvas.G = index$12; +canvas.Group = index$12.Group; +canvas.Shape = {}; +canvas.Shape.Marker = index$12.Marker; +canvas.PathUtil = { + parsePathString: index$2.toArray, + parsePathArray: index$2.toString, // Util.path2string + path2curve: index$2.toCurve, + pathToAbsolute: index$2.toAbsolute, // Util.path2Absolute + catmullRom2bezier: index$2.catmullRomToBezier +}; +canvas.MatrixUtil = matrix$2; +canvas.DomUtil = dom; +canvas.Matrix = index$14; + +var index = canvas; + +return index; + +}))); diff --git a/examples/method.md b/demos/method.md similarity index 100% rename from examples/method.md rename to demos/method.md diff --git a/examples/profile-canvas.md b/demos/profile-canvas.md similarity index 100% rename from examples/profile-canvas.md rename to demos/profile-canvas.md diff --git a/examples/profile-capture.md b/demos/profile-capture.md similarity index 100% rename from examples/profile-capture.md rename to demos/profile-capture.md diff --git a/examples/profile-fps.md b/demos/profile-fps.md similarity index 100% rename from examples/profile-fps.md rename to demos/profile-fps.md diff --git a/examples/profile-marker.md b/demos/profile-marker.md similarity index 100% rename from examples/profile-marker.md rename to demos/profile-marker.md diff --git a/examples/profile-path.md b/demos/profile-path.md similarity index 100% rename from examples/profile-path.md rename to demos/profile-path.md diff --git a/examples/profile-text.md b/demos/profile-text.md similarity index 100% rename from examples/profile-text.md rename to demos/profile-text.md diff --git a/examples/profile.md b/demos/profile.md similarity index 100% rename from examples/profile.md rename to demos/profile.md diff --git a/examples/test.html b/demos/test.html similarity index 100% rename from examples/test.html rename to demos/test.html diff --git a/examples/test1.jpg b/demos/test1.jpg similarity index 100% rename from examples/test1.jpg rename to demos/test1.jpg diff --git a/examples/test2.jpg b/demos/test2.jpg similarity index 100% rename from examples/test2.jpg rename to demos/test2.jpg diff --git a/index.js b/index.js index 12b004beb..0d6407549 100644 --- a/index.js +++ b/index.js @@ -1,17 +1,16 @@ -import {toArray, toString, toCurve, toAbsolute, catmullRomToBezier} from '@ali/g-path-util'; - -var Canvas = require('./src/canvas'); -var G = require('./src/g/index'); +const PathUtil = require('@ali/g-path-util'); +const Canvas = require('./src/canvas'); +const G = require('./src/g/index'); Canvas.G = G; Canvas.Group = G.Group; Canvas.Shape = {}; Canvas.Shape.Marker = G.Marker; Canvas.PathUtil = { - parsePathString: toArray, - parsePathArray: toString, // Util.path2string - path2curve: toCurve, - pathToAbsolute: toAbsolute, // Util.path2Absolute - catmullRom2bezier: catmullRomToBezier, + parsePathString: PathUtil.toArray, + parsePathArray: PathUtil.toString, // Util.path2string + path2curve: PathUtil.toCurve, + pathToAbsolute: PathUtil.toAbsolute, // Util.path2Absolute + catmullRom2bezier: PathUtil.catmullRomToBezier }; Canvas.MatrixUtil = require('./src/util/matrix'); Canvas.DomUtil = require('./src/util/dom'); diff --git a/package.json b/package.json index d63c4e600..7b92c9492 100644 --- a/package.json +++ b/package.json @@ -18,37 +18,42 @@ "url": "http://gitlab.alibaba-inc.com/datavis/g/issues" }, "devDependencies": { - "atool-build": "0.6.x", - "atool-doc": "0.3.0-beta0", - "atool-test": "~0.4.10", - "babel-cli": "~6.6.4", - "babel-core": "~6.7.4", - "babel-plugin-add-module-exports": "~0.1.2", - "babel-preset-es2015": "~6.6.0", - "babel-preset-stage-0": "~6.5.0", - "dora": "0.3.x", - "@ali/expect.js": "~0.3.1", - "jquery": "~2.1.4", - "less": "~2.6.0", - "pre-commit": "^1.1.2", - "eslint": "~1.10.3", - "eslint-config-airbnb": "~4.0.0", - "@ali/g-coord": "^1.2.3-beta", + "babel-eslint": "^7.2.3", + "babel-plugin-external-helpers": "^6.22.0", + "babel-preset-es2015-loose-rollup": "^7.0.0", + "babel-preset-stage-0": "^6.24.1", + "chai": "^4.0.1", + "electron": "^1.7.2", + "electron-mocha": "^3.4.0", + "eslint": "^3.19.0", + "eslint-config-airbnb": "^15.0.1", + "eslint-config-egg": "^4.2.0", + "pre-commit": "^1.2.2", + "rollup": "^0.42.0", + "rollup-plugin-babel": "^2.7.1", + "rollup-plugin-commonjs": "^8.0.2", + "rollup-plugin-node-resolve": "^3.0.0", + "uglify-js": "^3.0.15", "spm-sinon": "^1.6.0", - "event-simulate": "^1.0.0" + "event-simulate": "^1.0.0", + "jquery": "~2.1.4" }, "scripts": { - "transpiler": "rm -rf lib && babel src --out-dir lib", - "build": "atool-build", - "lint": "eslint --ext .js src", - "test": "atool-test --no-chai", - "test-keep": "atool-test --no-chai --keep --no-coverage", - "doc": "atool-doc", - "doc-build": "atool-doc --build", - "ci": "tnpm run lint && tnpm run test" + "lint": "eslint ./", + "lint-fix": "eslint --fix ./", + "build": "rollup -c -- index.js", + "pretest": "rm -rf build && mkdir build && npm run build", + "test": "electron-mocha --renderer --recursive ./test/unit", + "test-live": "npm run pretest && electron-mocha --opts ./test/support/mocha.opts --renderer --interactive --recursive ./test/unit", + "dist": "rm -rf dist && mkdir dist && uglifyjs --compress --mangle --output dist/g2.min.js -- build/g2.js", + "ci": "tnpm run test" }, - "entry": { - "index": "./index" + "pre-commit": { + "run": [ + "lint", + "test" + ], + "silent": false }, "dependencies": { "@ali/g-color": "~0.0.7", @@ -58,17 +63,5 @@ "@ali/g-path-util": "~1.0.0", "@ali/g-tween": "~0.3.1-beta.1", "gl-matrix": "^2.3.2" - }, - "pre-commit": { - "run": [ - "test" - ], - "silent": false - }, - "engines": { - "node": ">=4.0.0" - }, - "publishConfig": { - "registry": "http://registry.npm.alibaba-inc.com" } } diff --git a/rollup.config.js b/rollup.config.js new file mode 100644 index 000000000..47fd02938 --- /dev/null +++ b/rollup.config.js @@ -0,0 +1,18 @@ +// rollup.config.js +const resolve = require('rollup-plugin-node-resolve'); +const commonjs = require('rollup-plugin-commonjs'); +const babel = require('rollup-plugin-babel'); + +module.exports = { + entry: 'index.js', + dest: 'build/g.js', + moduleName: 'G', + format: 'umd', + plugins: [ + resolve(), + babel({ + exclude: 'node_modules/**' // only transpile our source code + }), + commonjs() + ] +}; diff --git a/src/canvas.js b/src/canvas.js index b041874c3..1e25a044d 100644 --- a/src/canvas.js +++ b/src/canvas.js @@ -1,6 +1,6 @@ -import Util from './util/index'; -import MouseEvent from './mouse-event'; -import G from './g/index'; +const Util = require('./util/index'); +const MouseEvent = require('./mouse-event'); +const G = require('./g/index'); const Canvas = function(cfg) { Canvas.superclass.constructor.call(this, cfg); @@ -58,27 +58,10 @@ Canvas.CFG = { Util.extend(Canvas, G.Group); Util.augment(Canvas, { - init: function() { - /** - * 执行父类的父类的init方法 - */ + init() { Canvas.superclass.init.call(this); - - /** - * @SET {Number} pixelRatio 屏幕像素比 - */ this._setGlobalParam(); - /** - * @SET {Object} containerDOM 容器 - * @SET {Object} layer 图层 - */ this._setDOM(); - /** - * @SET {Number} width Canvas 宽度 - * @SET {Number} height Canvas 高度 - * @SET {Number} widthCanvas px 宽度 - * @SET {Number} heightCanvas px 高度 - */ this._setInitSize(); this._setCanvas(); this._scale(); @@ -86,10 +69,10 @@ Util.augment(Canvas, { this._registEvents(); } }, - _registEvents: function() { - var self = this; - var el = self.get('el'); - var mouseEvent = new MouseEvent(self); + _registEvents() { + const self = this; + const el = self.get('el'); + const mouseEvent = new MouseEvent(self); el.addEventListener('mouseout', function(e) { mouseEvent.mouseout(e); @@ -119,41 +102,30 @@ Util.augment(Canvas, { mouseEvent.dblclick(e); }, false); }, - // 初始化缩放 - _scale: function() { - var pixelRatio = this.get('pixelRatio'); + _scale() { + const pixelRatio = this.get('pixelRatio'); this.scale(pixelRatio, pixelRatio); }, - // 设置画布 - _setCanvas: function() { - var canvasDOM = this.get('canvasDOM'); + _setCanvas() { + const canvasDOM = this.get('canvasDOM'); this.set('el', canvasDOM); this.set('context', canvasDOM.getContext('2d')); this.set('canvas', this); }, - /** - * 设置全局参数 - */ - _setGlobalParam: function() { - var pixelRatio = this.get('pixelRatio'); + _setGlobalParam() { + const pixelRatio = this.get('pixelRatio'); if (!pixelRatio) { this.set('pixelRatio', Util.getRatio()); } return; }, - /** - * 设置所有DOM - */ - _setDOM: function() { + _setDOM() { this._setContainer(); this._setLayer(); }, - /** - * 设置容器DOM - */ - _setContainer: function() { - var containerId = this.get('containerId'); - var containerDOM = this.get('containerDOM'); + _setContainer() { + const containerId = this.get('containerId'); + let containerDOM = this.get('containerDOM'); if (!containerDOM) { containerDOM = document.getElementById(containerId); this.set('containerDOM', containerDOM); @@ -162,65 +134,44 @@ Util.augment(Canvas, { position: 'relative' }); }, - /** - * 设置图层DOM - */ - _setLayer: function() { - var containerDOM = this.get('containerDOM'); - var canvasId = Util.uniqueId('canvas_'); + _setLayer() { + const containerDOM = this.get('containerDOM'); + const canvasId = Util.uniqueId('canvas_'); if (containerDOM) { - var canvasDOM = Util.createDom(''); + const canvasDOM = Util.createDom(''); containerDOM.appendChild(canvasDOM); this.set('canvasDOM', canvasDOM); } }, - /** - * 设置初始画布参数 - */ - _setInitSize: function() { + _setInitSize() { this.changeSize(this.get('width'), this.get('height')); }, - /** - * 重设画布尺寸 - */ - _reSize: function() { - var canvasDOM = this.get('canvasDOM'); - var widthCanvas = this.get('widthCanvas'); - var heightCanvas = this.get('heightCanvas'); - var widthStyle = this.get('widthStyle'); - var heightStyle = this.get('heightStyle'); + _reSize() { + const canvasDOM = this.get('canvasDOM'); + const widthCanvas = this.get('widthCanvas'); + const heightCanvas = this.get('heightCanvas'); + const widthStyle = this.get('widthStyle'); + const heightStyle = this.get('heightStyle'); canvasDOM.style.width = widthStyle; canvasDOM.style.height = heightStyle; canvasDOM.setAttribute('width', widthCanvas); canvasDOM.setAttribute('height', heightCanvas); }, - /** - * 获取宽度 - */ - getWidth: function() { - var pixelRatio = this.get('pixelRatio'); - var width = this.get('width'); + getWidth() { + const pixelRatio = this.get('pixelRatio'); + const width = this.get('width'); return width * pixelRatio; }, - /** - * 获取高度 - */ - getHeight: function() { - var pixelRatio = this.get('pixelRatio'); - var height = this.get('height'); + getHeight() { + const pixelRatio = this.get('pixelRatio'); + const height = this.get('height'); return height * pixelRatio; }, - /** - * 设置画布尺寸 - * @param {Number} Canvas width - * @param {Number} Canvas height - * @param {Number} pixelRatio height - */ - changeSize: function(width, height) { - var pixelRatio = this.get('pixelRatio'); - var widthCanvas = width * pixelRatio; - var heightCanvas = height * pixelRatio; + changeSize(width, height) { + const pixelRatio = this.get('pixelRatio'); + const widthCanvas = width * pixelRatio; + const heightCanvas = height * pixelRatio; this.set('widthCanvas', widthCanvas); this.set('heightCanvas', heightCanvas); @@ -236,45 +187,39 @@ Util.augment(Canvas, { * @param {Number} clientY 窗口y坐标 * @return {Object} canvas坐标 */ - getPointByClient: function(clientX, clientY) { - var el = this.get('el'); - var bbox = el.getBoundingClientRect(); - var width = bbox.right - bbox.left; - var height = bbox.bottom - bbox.top; + getPointByClient(clientX, clientY) { + const el = this.get('el'); + const bbox = el.getBoundingClientRect(); + const width = bbox.right - bbox.left; + const height = bbox.bottom - bbox.top; return { x: (clientX - bbox.left) * (el.width / width), y: (clientY - bbox.top) * (el.height / height) }; }, - /** - * 将 canvas 坐标转变成窗口坐标 - * @param {Number} x canvas x坐标 - * @param {Number} x canvas y坐标 - * @return {Object} 窗口坐标 - */ - getClientByPoint: function(x, y) { - var el = this.get('el'); - var bbox = el.getBoundingClientRect(); - var width = bbox.right - bbox.left; - var height = bbox.bottom - bbox.top; + getClientByPoint(x, y) { + const el = this.get('el'); + const bbox = el.getBoundingClientRect(); + const width = bbox.right - bbox.left; + const height = bbox.bottom - bbox.top; return { clientX: x / (el.width / width) + bbox.left, clientY: y / (el.height / height) + bbox.top }; }, - beforeDraw: function() { - var context = this.get('context'); - var el = this.get('el'); + beforeDraw() { + const context = this.get('context'); + const el = this.get('el'); context && context.clearRect(0, 0, el.width, el.height); }, - _beginDraw: function() { + _beginDraw() { this.setSilent('toDraw', true); }, - _endDraw: function() { + _endDraw() { this.setSilent('toDraw', false); }, - draw: function() { - var self = this; + draw() { + const self = this; function drawInner() { self.set('animateHandler', Util.requestAnimationFrame(function() { self.set('animateHandler', undefined); @@ -284,7 +229,7 @@ Util.augment(Canvas, { })); self.beforeDraw(); try { - var context = self.get('context'); + const context = self.get('context'); Canvas.superclass.draw.call(self, context); // self._drawCanvas(); } catch (ev) { // 绘制时异常,中断重绘 @@ -304,12 +249,9 @@ Util.augment(Canvas, { drawInner(); } }, - /** - * 销毁 - */ - destroy: function() { - var containerDOM = this.get('containerDOM'); - var canvasDOM = this.get('canvasDOM'); + destroy() { + const containerDOM = this.get('containerDOM'); + const canvasDOM = this.get('canvasDOM'); if (canvasDOM && containerDOM) { containerDOM.removeChild(canvasDOM); } diff --git a/src/g/common.js b/src/g/common.js index 67e154fa5..3339fca25 100644 --- a/src/g/common.js +++ b/src/g/common.js @@ -6,5 +6,5 @@ module.exports = { prefix: 'g', backupContext: document.createElement('canvas').getContext('2d'), debug: false, - warn: function() {} + warn() {} }; diff --git a/src/g/core/element.js b/src/g/core/element.js index 4bbf0b7b7..0042bf7fa 100644 --- a/src/g/core/element.js +++ b/src/g/core/element.js @@ -1,17 +1,11 @@ -/** - * @fileOverview 图形控件或者分组的基类 - * @author dxq613@gmail.com - * @author hankaiai@126.com - * @ignore - */ -var Util = require('../../util/index'); -var Attributes = require('./mixin/attributes'); -var Transform = require('./mixin/transform'); -var Animate = require('./mixin/animate'); -var EventDispatcher = require('./mixin/event-dispatcher'); -var Format = require('../format'); +const Util = require('../../util/index'); +const Attributes = require('./mixin/attributes'); +const Transform = require('./mixin/transform'); +const Animate = require('./mixin/animate'); +const EventDispatcher = require('./mixin/event-dispatcher'); +const Format = require('../format'); -var SHAPE_ATTRS = [ +const SHAPE_ATTRS = [ 'fillStyle', 'font', 'globalAlpha', @@ -29,7 +23,7 @@ var SHAPE_ATTRS = [ 'lineDash' ]; -var Element = function(cfg) { +const Element = function(cfg) { this.__cfg = { zIndex: 0, capture: true, @@ -71,6 +65,7 @@ Element.CFG = { * false 不能 * 对象默认是都可以被捕捉的, 当capture为false时,group.getShape(x, y)方法无法获得该元素 * 通过将不必要捕捉的元素的该属性设置成false, 来提高捕捉性能 + * @type {Boolean} **/ capture: true, /** @@ -91,18 +86,14 @@ Element.CFG = { }; Util.augment(Element, Attributes, EventDispatcher, Transform, Animate, { - /** - * @protected - * 初始化 - */ - init: function() { + init() { this.setSilent('animable', true); - var attrs = this.__attrs; + const attrs = this.__attrs; if (attrs && attrs.rotate) { this.rotateAtStart(attrs.rotate); } }, - getParent: function() { + getParent() { return this.get('parent'); }, /** @@ -110,15 +101,11 @@ Util.augment(Element, Attributes, EventDispatcher, Transform, Animate, { * @protected * @return {Object} 默认的属性 */ - getDefaultCfg: function() { + getDefaultCfg() { return {}; }, - /** - * 设置属性信息 - * @protected - */ - set: function(name, value) { - var m = '__set' + Util.upperFirst(name); + set(name, value) { + const m = '__set' + Util.upperFirst(name); if (this[m]) { value = this[m](value); @@ -126,24 +113,13 @@ Util.augment(Element, Attributes, EventDispatcher, Transform, Animate, { this.__cfg[name] = value; return this; }, - /** - * 设置属性信息,不进行特殊处理 - * @protected - */ - setSilent: function(name, value) { + setSilent(name, value) { this.__cfg[name] = value; }, - /** - * 获取属性信息 - * @protected - */ - get: function(name) { + get(name) { return this.__cfg[name]; }, - /** - * 绘制自身 - */ - draw: function(context) { + draw(context) { if (this.get('destroyed')) { return; } @@ -153,8 +129,8 @@ Util.augment(Element, Attributes, EventDispatcher, Transform, Animate, { this.restoreContext(context); } }, - setContext: function(context) { - var clip = this.__attrs.clip; + setContext(context) { + const clip = this.__attrs.clip; context.save(); if (clip) { // context.save(); @@ -166,21 +142,17 @@ Util.augment(Element, Attributes, EventDispatcher, Transform, Animate, { this.resetContext(context); this.resetTransform(context); }, - restoreContext: function(context) { + restoreContext(context) { context.restore(); }, - /** - * @protected - * 设置绘图属性 - */ - resetContext: function(context) { - var elAttrs = this.__attrs; + resetContext(context) { + const elAttrs = this.__attrs; // var canvas = this.get('canvas'); if (!this.isGroup) { // canvas.registShape(this); // 快速拾取方案暂时不执行 - for (var k in elAttrs) { + for (const k in elAttrs) { if (SHAPE_ATTRS.indexOf(k) > -1) { // 非canvas属性不附加 - var v = elAttrs[k]; + let v = elAttrs[k]; if (k === 'fillStyle') { v = Format.parseStyle(v, this); } @@ -200,33 +172,25 @@ Util.augment(Element, Attributes, EventDispatcher, Transform, Animate, { } } }, - /** - * @protected - * 绘制内部图形 - */ - drawInner: function(/* context */) { + drawInner(/* context */) { }, - show: function() { + show() { this.set('visible', true); return this; }, - hide: function() { + hide() { this.set('visible', false); return this; }, - /** - * 删除自己, 从父元素中删除自己 - * @param {Boolean} [destroy=true] - */ - remove: function(destroy) { + remove(destroy) { if (destroy === undefined) { destroy = true; } if (this.get('parent')) { - var parent = this.get('parent'); - var children = parent.get('children'); + const parent = this.get('parent'); + const children = parent.get('children'); Util.remove(children, this); // this.set('parent', null); } @@ -237,8 +201,8 @@ Util.augment(Element, Attributes, EventDispatcher, Transform, Animate, { return this; }, - destroy: function() { - var destroyed = this.get('destroyed'); + destroy() { + const destroyed = this.get('destroyed'); if (destroyed) { return; @@ -249,21 +213,21 @@ Util.augment(Element, Attributes, EventDispatcher, Transform, Animate, { this.__m = null; this.set('destroyed', true); }, - __setZIndex: function(zIndex) { + __setZIndex(zIndex) { this.__cfg.zIndex = zIndex; if (!Util.isNil(this.get('parent'))) { this.get('parent').sort(); } return zIndex; }, - __setAttrs: function(attrs) { + __setAttrs(attrs) { this.attr(attrs); return attrs; }, - clone: function() { + clone() { return Util.clone(this); }, - getBBox: function() { + getBBox() { return { minX: 0, maxX: 0, diff --git a/src/g/core/group.js b/src/g/core/group.js index f45ef7df2..af71aff37 100644 --- a/src/g/core/group.js +++ b/src/g/core/group.js @@ -1,14 +1,13 @@ -var Util = require('../../util/index'); -var Vector3 = require('@ali/g-matrix').Vector3; -// import {vec3} from 'gl-matrix'; -var Element = require('./element'); -var Shape = require('../shape/index'); -var SHAPE_MAP = {}; // 缓存图形类型 +const Util = require('../../util/index'); +const Vector3 = require('@ali/g-matrix').Vector3; +const Element = require('./element'); +const Shape = require('../shape/index'); +const SHAPE_MAP = {}; // 缓存图形类型 function find(children, x, y) { - var rst; - for (var i = children.length - 1; i >= 0; i--) { - var child = children[i]; + let rst; + for (let i = children.length - 1; i >= 0; i--) { + const child = children[i]; if (child.__cfg.visible && child.__cfg.capture) { if (child.isGroup) { rst = child.getShape(x, y); @@ -23,7 +22,7 @@ function find(children, x, y) { return rst; } -var Group = function(cfg) { +const Group = function(cfg) { Group.superclass.constructor.call(this, cfg); this.set('children', []); @@ -32,15 +31,11 @@ var Group = function(cfg) { this._bindUI(); }; -/** - * 混合原型链CFG - * @param {Object} c 函数对象 - */ function initClassCfgs(c) { if (c.__cfg || c === Group) { return; } - var superCon = c.superclass.constructor; + const superCon = c.superclass.constructor; if (superCon && !superCon.__cfg) { initClassCfgs(superCon); } @@ -56,34 +51,25 @@ Util.augment(Group, { isGroup: true, canFill: true, canStroke: true, - getDefaultCfg: function() { + getDefaultCfg() { initClassCfgs(this.constructor); return Util.merge({}, this.constructor.__cfg); }, - // 渲染组件前 - _beforeRenderUI: function() {}, - // 渲染组件 - _renderUI: function() {}, - // 绑定事件 - _bindUI: function() {}, - /** 添加图形 - * @param {String} type - * @param {Object} cfg - * @return {Object} rst 图形 - */ - addShape: function(type, cfg) { - var canvas = this.get('canvas'); - var rst; + _beforeRenderUI() {}, + _renderUI() {}, + _bindUI() {}, + addShape(type, cfg) { + const canvas = this.get('canvas'); cfg = cfg || {}; - var shapeType = SHAPE_MAP[type]; + let shapeType = SHAPE_MAP[type]; if (!shapeType) { shapeType = Util.upperFirst(type); SHAPE_MAP[type] = shapeType; } if (cfg.attrs) { - var attrs = cfg.attrs; + const attrs = cfg.attrs; if (type === 'text') { // 临时解决 - var topFontFamily = canvas.get('fontFamily'); + const topFontFamily = canvas.get('fontFamily'); if (topFontFamily) { attrs.fontFamily = attrs.fontFamily ? attrs.fontFamily : topFontFamily; } @@ -91,7 +77,7 @@ Util.augment(Group, { } cfg.canvas = canvas; cfg.type = type; - rst = new Shape[shapeType](cfg); + const rst = new Shape[shapeType](cfg); this.add(rst); return rst; }, @@ -100,9 +86,9 @@ Util.augment(Group, { * @param {Object} cfg 配置项 * @return {Object} rst 图组 */ - addGroup: function(param, cfg) { - var canvas = this.get('canvas'); - var rst; + addGroup(param, cfg) { + const canvas = this.get('canvas'); + let rst; cfg = Util.merge({}, cfg); if (Util.isFunction(param)) { if (cfg) { @@ -111,7 +97,7 @@ Util.augment(Group, { rst = new param(cfg); } else { rst = new param({ - canvas: canvas, + canvas, parent: this }); } @@ -132,11 +118,12 @@ Util.augment(Group, { * @param {Array} padding 内边距 * @param {Attrs} attrs 图形属性 * @param {Shape} backShape 背景图形 + * @return {Object} 背景层对象 */ - renderBack: function(padding, attrs) { - var backShape = this.get('backShape'); - var innerBox = this.getBBox(); - var parent = this.get('parent'); // getParent + renderBack(padding, attrs) { + let backShape = this.get('backShape'); + const innerBox = this.getBBox(); + const parent = this.get('parent'); // getParent Util.merge(attrs, { x: innerBox.minX - padding[3], y: innerBox.minY - padding[0], @@ -148,18 +135,14 @@ Util.augment(Group, { } else { backShape = parent.addShape('rect', { zIndex: -1, - attrs: attrs + attrs }); } this.set('backShape', backShape); parent.sort(); return backShape; }, - /** - * 从组中移除 shape 或者 group - * @param {Object} item 图形或者分组, 如果item存在则移除item - */ - removeChild: function(item, destroy) { + removeChild(item, destroy) { if (arguments.length >= 2) { if (this.contain(item)) { item.remove(destroy); @@ -185,14 +168,15 @@ Util.augment(Group, { }, /** * 向组中添加shape或者group - * @param {Object} item 图形或者分组 + * @param {Object} items 图形或者分组 + * @return {Object} group 本尊 */ - add: function(items) { - var self = this; - var children = self.get('children'); + add(items) { + const self = this; + const children = self.get('children'); if (Util.isArray(items)) { Util.each(items, function(item) { - var parent = item.get('parent'); + const parent = item.get('parent'); if (parent) { parent.removeChild(item, false); } @@ -200,8 +184,8 @@ Util.augment(Group, { }); children.push.apply(children, items); } else { - var item = items; - var parent = item.get('parent'); + const item = items; + const parent = item.get('parent'); if (parent) { parent.removeChild(item, false); } @@ -210,74 +194,65 @@ Util.augment(Group, { } return self; }, - /** - * 当前 group 是否拥有某个 item - **/ - contain: function(item) { - var children = this.get('children'); + contain(item) { + const children = this.get('children'); return children.indexOf(item) > -1; }, - /** 获取第N个子元素 - */ - getChildByIndex: function(index) { - var children = this.get('children'); + getChildByIndex(index) { + const children = this.get('children'); return children[index]; }, - getFirst: function() { + getFirst() { return this.getChildByIndex(0); }, - getLast: function() { - var lastIndex = this.get('children').length - 1; + getLast() { + const lastIndex = this.get('children').length - 1; return this.getChildByIndex(lastIndex); }, - /** - * 设置子元素及子孙元素的环境属性 - * @private - */ - __setEvn: function(item) { - var self = this; + __setEvn(item) { + const self = this; item.__cfg.parent = self; item.__cfg.context = self.__cfg.context; item.__cfg.canvas = self.__cfg.canvas; - var clip = item.__attrs.clip; + const clip = item.__attrs.clip; if (clip) { clip.setSilent('parent', self); clip.setSilent('context', self.get('context')); } - var children = item.__cfg.children; + const children = item.__cfg.children; if (children) { Util.each(children, function(child) { item.__setEvn(child); }); } }, - getBBox: function() { - var self = this; - var minX = Infinity; - var maxX = -Infinity; - var minY = Infinity; - var maxY = -Infinity; - var children = self.get('children'); + getBBox() { + const self = this; + let minX = Infinity; + let maxX = -Infinity; + let minY = Infinity; + let maxY = -Infinity; + const children = self.get('children'); Util.each(children, function(child) { if (child.get('visible')) { - var box = child.getBBox(); + const box = child.getBBox(); if (!box) { return true; } - var leftTop = new Vector3(box.minX, box.minY, 1); - var leftBottom = new Vector3(box.minX, box.maxY, 1); - var rightTop = new Vector3(box.maxX, box.minY, 1); - var rightBottom = new Vector3(box.maxX, box.maxY, 1); + const leftTop = new Vector3(box.minX, box.minY, 1); + const leftBottom = new Vector3(box.minX, box.maxY, 1); + const rightTop = new Vector3(box.maxX, box.minY, 1); + const rightBottom = new Vector3(box.maxX, box.maxY, 1); child.apply(leftTop); child.apply(leftBottom); child.apply(rightTop); child.apply(rightBottom); - var boxMinX = Math.min(leftTop.x, leftBottom.x, rightTop.x, rightBottom.x); - var boxMaxX = Math.max(leftTop.x, leftBottom.x, rightTop.x, rightBottom.x); - var boxMinY = Math.min(leftTop.y, leftBottom.y, rightTop.y, rightBottom.y); - var boxMaxY = Math.max(leftTop.y, leftBottom.y, rightTop.y, rightBottom.y); + const boxMinX = Math.min(leftTop.x, leftBottom.x, rightTop.x, rightBottom.x); + const boxMaxX = Math.max(leftTop.x, leftBottom.x, rightTop.x, rightBottom.x); + const boxMinY = Math.min(leftTop.y, leftBottom.y, rightTop.y, rightBottom.y); + const boxMaxY = Math.max(leftTop.y, leftBottom.y, rightTop.y, rightBottom.y); if (boxMinX < minX) { minX = boxMinX; @@ -296,11 +271,11 @@ Util.augment(Group, { } } }); - var box = { - minX: minX, - minY: minY, - maxX: maxX, - maxY: maxY + const box = { + minX, + minY, + maxX, + maxY }; box.x = box.minX; box.y = box.minY; @@ -308,35 +283,25 @@ Util.augment(Group, { box.height = box.maxY - box.minY; return box; }, - /** - * @protected - * 绘制内部图形 - */ - drawInner: function(context) { - var children = this.get('children'); - for (var i = 0; i < children.length; i++) { - var child = children[i]; + drawInner(context) { + const children = this.get('children'); + for (let i = 0; i < children.length; i++) { + const child = children[i]; child.draw(context); } return this; }, - /** - * 获得子元素的个数 - */ - getCount: function() { + getCount() { return this.get('children').length; }, - /** - * 将子元素按照zIndex排序 - */ - sort: function() { - var children = this.get('children'); + sort() { + const children = this.get('children'); children.sort(function(obj1, obj2) { return obj1.get('zIndex') - obj2.get('zIndex'); }); return this; }, - find: function(id) { + find(id) { return this.findBy(function(item) { return item.get('id') === id; }); @@ -346,9 +311,9 @@ Util.augment(Group, { * @param {Function} fn 匹配函数 * @return {Canvas.Base} 分组或者图形 */ - findBy: function(fn) { - var children = this.get('children'); - var rst = null; + findBy(fn) { + const children = this.get('children'); + let rst = null; Util.each(children, function(item) { if (fn(item)) { @@ -362,10 +327,10 @@ Util.augment(Group, { }); return rst; }, - findAllBy: function(fn) { - var children = this.get('children'); - var rst = []; - var childRst = []; + findAllBy(fn) { + const children = this.get('children'); + let rst = []; + let childRst = []; Util.each(children, function(item) { if (fn(item)) { rst.push(item); @@ -383,11 +348,11 @@ Util.augment(Group, { * @param {Number} y y坐标 * @return {Object} 最上面的图形 */ - getShape: function(x, y) { - var self = this; - var clip = self.__attrs.clip; - var children = self.__cfg.children; - var rst; + getShape(x, y) { + const self = this; + const clip = self.__attrs.clip; + const children = self.__cfg.children; + let rst; if (clip) { if (clip.inside(x, y)) { rst = find(children, x, y); @@ -397,33 +362,26 @@ Util.augment(Group, { } return rst; }, - // 连同一起清理子元素的矩阵 - clearTotalMatrix: function() { - var m = this.get('totalMatrix'); + clearTotalMatrix() { + const m = this.get('totalMatrix'); if (m) { this.setSilent('totalMatrix', null); - var children = this.__cfg.children; - for (var i = 0; i < children.length; i++) { - var child = children[i]; + const children = this.__cfg.children; + for (let i = 0; i < children.length; i++) { + const child = children[i]; child.clearTotalMatrix(); } } }, - /** - * 清除容器内的图形或者分组 - */ - clear: function() { - var children = this.get('children'); + clear() { + const children = this.get('children'); while (children.length !== 0) { children[children.length - 1].remove(); } return this; }, - /** - * 析构函数 - */ - destroy: function() { + destroy() { if (this.get('destroyed')) { return; } diff --git a/src/g/core/mixin/animate.js b/src/g/core/mixin/animate.js index 0c3e676ab..4a0628e39 100644 --- a/src/g/core/mixin/animate.js +++ b/src/g/core/mixin/animate.js @@ -1,13 +1,13 @@ -var Util = require('../../../util/index'); -var Tween = require('@ali/g-tween'); -var tween = new Tween(); +const Util = require('../../../util/index'); +const Tween = require('@ali/g-tween'); +const tween = new Tween(); module.exports = { - tween: tween, - animate: function(toProps, duration, easing, callBack) { - var now = tween.getNow(); - var cfg = Util.merge({}, toProps, { - duration: duration + tween, + animate(toProps, duration, easing, callBack) { + const now = tween.getNow(); + const cfg = Util.merge({}, toProps, { + duration }); tween.animate(this).append(now, cfg, easing, callBack); if (tween.get('status') === 'silent') tween.play(); diff --git a/src/g/core/mixin/attributes.js b/src/g/core/mixin/attributes.js index 6c61d6d6d..895ce2b3b 100644 --- a/src/g/core/mixin/attributes.js +++ b/src/g/core/mixin/attributes.js @@ -1,9 +1,9 @@ -var Util = require('../../../util/index'); -var Vector3 = require('@ali/g-matrix').Vector3; +const Util = require('../../../util/index'); +const Vector3 = require('@ali/g-matrix').Vector3; -var ALIAS_ATTRS = ['strokeStyle', 'fillStyle', 'globalAlpha']; -var CLIP_SHAPES = ['circle', 'ellipse', 'fan', 'polygon', 'rect', 'path']; -var CAPITALIZED_ATTRS_MAP = { +const ALIAS_ATTRS = [ 'strokeStyle', 'fillStyle', 'globalAlpha' ]; +const CLIP_SHAPES = [ 'circle', 'ellipse', 'fan', 'polygon', 'rect', 'path' ]; +const CAPITALIZED_ATTRS_MAP = { r: 'R', opacity: 'Opacity', lineWidth: 'LineWidth', @@ -45,7 +45,7 @@ var CAPITALIZED_ATTRS_MAP = { endAngle: 'EndAngle', path: 'Path' }; -var ALIAS_ATTRS_MAP = { +const ALIAS_ATTRS_MAP = { stroke: 'strokeStyle', fill: 'fillStyle', opacity: 'globalAlpha' @@ -54,7 +54,7 @@ var ALIAS_ATTRS_MAP = { module.exports = { canFill: false, canStroke: false, - initAttrs: function(attrs) { + initAttrs(attrs) { this.__attrs = { opacity: 1, fillOpacity: 1, @@ -63,7 +63,7 @@ module.exports = { this.attr(Util.assign(this.getDefaultAttrs(), attrs)); return this; }, - getDefaultAttrs: function() { + getDefaultAttrs() { return {}; }, /** @@ -77,16 +77,16 @@ module.exports = { * @param {*} value 属性值 * @return {*} 属性值 */ - attr: function(name, value) { - var self = this; + attr(name, value) { + const self = this; if (arguments.length === 0) { return self.__attrs; } if (Util.isObject(name)) { - for (var k in name) { + for (const k in name) { if (ALIAS_ATTRS.indexOf(k) === -1) { - var v = name[k]; + const v = name[k]; self._setAttr(k, v); } } @@ -99,7 +99,7 @@ module.exports = { } if (arguments.length === 2) { if (self._setAttr(name, value) !== false) { - var m = '__afterSetAttr' + CAPITALIZED_ATTRS_MAP[name]; + const m = '__afterSetAttr' + CAPITALIZED_ATTRS_MAP[name]; if (self[m]) { self[m](value); } @@ -110,52 +110,52 @@ module.exports = { } return self._getAttr(name); }, - clearBBox: function() { + clearBBox() { this.setSilent('box', null); }, - __afterSetAttrAll: function() { + __afterSetAttrAll() { }, // 属性获取触发函数 - _getAttr: function(name) { + _getAttr(name) { return this.__attrs[name]; }, // 属性设置触发函数 - _setAttr: function(name, value) { - var self = this; + _setAttr(name, value) { + const self = this; if (name === 'clip') { self.__setAttrClip(value); self.__attrs.clip = value; } else { self.__attrs[name] = value; - var alias = ALIAS_ATTRS_MAP[name]; + const alias = ALIAS_ATTRS_MAP[name]; if (alias) { self.__attrs[alias] = value; } } return self; }, - hasFill: function() { + hasFill() { return this.canFill && this.__attrs.fillStyle; }, - hasStroke: function() { + hasStroke() { return this.canStroke && this.__attrs.strokeStyle; }, // 设置透明度 - __setAttrOpacity: function(v) { + __setAttrOpacity(v) { this.__attrs.globalAlpha = v; return v; }, - __setAttrClip: function(clip) { - var self = this; + __setAttrClip(clip) { + const self = this; if (clip && (CLIP_SHAPES.indexOf(clip.type) > -1)) { if (clip.get('canvas') === null) { clip = Util.clone(clip); } clip.set('parent', self.get('parent')); clip.set('context', self.get('context')); - clip.inside = function (x, y) { - var v = new Vector3(x, y, 1); + clip.inside = function(x, y) { + const v = new Vector3(x, y, 1); clip.invert(v, self.get('canvas')); // 已经在外面转换 return clip.__isPointInFill(v.x, v.y); }; diff --git a/src/g/core/mixin/event-dispatcher.js b/src/g/core/mixin/event-dispatcher.js index 436a30c46..650cc5772 100644 --- a/src/g/core/mixin/event-dispatcher.js +++ b/src/g/core/mixin/event-dispatcher.js @@ -5,7 +5,7 @@ module.exports = { /** * 事件分发器的处理函数 */ - initEventDispatcher: function() { + initEventDispatcher() { this.__listeners = {}; }, /** @@ -14,7 +14,7 @@ module.exports = { * @param {Function} listener 回调函数 * @return {Object} this */ - on: function(type, listener) { + on(type, listener) { const listeners = this.__listeners; if (Util.isNil(listeners[type])) { @@ -36,8 +36,8 @@ module.exports = { * @param {Function} listener 回调函数 * @return {Object} this */ - off: function(type, listener) { - var listeners = this.__listeners; + off(type, listener) { + const listeners = this.__listeners; if (arguments.length === 0) { this.__listeners = {}; return this; @@ -59,8 +59,8 @@ module.exports = { * @param {Function} listener 回调函数 * @return {Object} this */ - has: function(type, listener) { - var listeners = this.__listeners; + has(type, listener) { + const listeners = this.__listeners; if (arguments.length === 0) { if (!Util.isEmpty(listeners)) { @@ -82,10 +82,10 @@ module.exports = { return false; }, - trigger: function(event) { - var self = this; - var listeners = self.__listeners; - var listenersArray = listeners[event.type]; + trigger(event) { + const self = this; + const listeners = self.__listeners; + const listenersArray = listeners[event.type]; event.target = self; if (!Util.isNil(listenersArray)) { listenersArray.forEach(function(listener) { @@ -93,7 +93,7 @@ module.exports = { }); } if (event.bubbles) { - var parent = self.get('parent'); + const parent = self.get('parent'); if (parent && !event.propagationStopped) { parent.trigger(event); } @@ -103,9 +103,10 @@ module.exports = { /** * fire the event * @param {String} eventType event type + * @param {Object} [eventObj] event */ - fire: function(eventType, eventObj) { - var event = new Event(eventType); + fire(eventType, eventObj) { + const event = new Event(eventType); Util.each(eventObj, function(v, k) { event[k] = v; }); diff --git a/src/g/core/mixin/transform.js b/src/g/core/mixin/transform.js index efb7fa0f9..fafc307c8 100644 --- a/src/g/core/mixin/transform.js +++ b/src/g/core/mixin/transform.js @@ -1,15 +1,15 @@ -var Util = require('../../../util/index'); -var Matrix3 = require('@ali/g-matrix').Matrix3; +const Util = require('../../../util/index'); +const Matrix3 = require('@ali/g-matrix').Matrix3; // 是否未改变 function isUnchanged(m) { - var elements = m.elements; + const elements = m.elements; return elements[0] === 1 && elements[1] === 0 && elements[3] === 0 && elements[4] === 1 && elements[6] === 0 && elements[7] === 0; } // 是否仅仅是scale function isScale(m) { - var elements = m.elements; + const elements = m.elements; return elements[1] === 0 && elements[3] === 0 && elements[6] === 0 && elements[7] === 0; } @@ -25,20 +25,20 @@ function multiple(m1, m2) { } module.exports = { - initTransform: function() { + initTransform() { this.__m = new Matrix3(); }, - translate: function(tx, ty) { + translate(tx, ty) { this.__m.translate(tx, ty); this.clearTotalMatrix(); return this; }, - rotate: function(angle) { + rotate(angle) { this.__m.rotate(angle); // 仅支持弧度,不再支持角度 this.clearTotalMatrix(); return this; }, - scale: function(s1, s2) { + scale(s1, s2) { this.__m.scale(s1, s2); this.clearTotalMatrix(); return this; @@ -47,16 +47,16 @@ module.exports = { * 绕起始点旋转 * @param {Number} rotate 0~360 */ - rotateAtStart: function(rotate) { - var x = this.attr('x'); - var y = this.attr('y'); + rotateAtStart(rotate) { + const x = this.attr('x'); + const y = this.attr('y'); if (Math.abs(rotate) > Math.PI * 2) { rotate = rotate / 180 * Math.PI; } this.transform([ - ['t', -x, -y], - ['r', rotate], - ['t', x, y] + [ 't', -x, -y ], + [ 'r', rotate ], + [ 't', x, y ] ]); }, /** @@ -64,15 +64,15 @@ module.exports = { * @param {Number} x 移动到x * @param {Number} y 移动到y */ - move: function(x, y) { - var cx = this.get('x') || 0; // 当前的x - var cy = this.get('y') || 0; // 当前的y + move(x, y) { + const cx = this.get('x') || 0; // 当前的x + const cy = this.get('y') || 0; // 当前的y this.translate(x - cx, y - cy); this.set('x', x); this.set('y', y); }, - transform: function(ts) { - var self = this; + transform(ts) { + const self = this; Util.each(ts, function(t) { switch (t[0]) { case 't': @@ -94,20 +94,20 @@ module.exports = { }); return self; }, - setTransform: function(ts) { + setTransform(ts) { this.__m.identity(); return this.transform(ts); }, - getMatrix: function() { + getMatrix() { return this.__m; }, - setMatrix: function(m) { + setMatrix(m) { this.__m = m; this.clearTotalMatrix(); return this; }, - apply: function(v, root) { - var m; + apply(v, root) { + let m; if (root) { m = this._getMatrixByRoot(root); } else { @@ -117,11 +117,11 @@ module.exports = { return this; }, // 获取到达指定根节点的矩阵 - _getMatrixByRoot: function(root) { - var self = this; + _getMatrixByRoot(root) { + const self = this; root = root || self; - var parent = self; - var parents = []; + let parent = self; + const parents = []; while (parent !== root) { parents.unshift(parent); @@ -129,7 +129,7 @@ module.exports = { } parents.unshift(parent); - var m = new Matrix3(); + const m = new Matrix3(); Util.each(parents, function(child) { m.multiply(child.__m); }); @@ -139,13 +139,13 @@ module.exports = { * 应用到当前元素上的总的矩阵 * @return {Matrix} 矩阵 */ - getTotalMatrix: function() { - var m = this.__cfg.totalMatrix; + getTotalMatrix() { + let m = this.__cfg.totalMatrix; if (!m) { m = new Matrix3(); - var parent = this.__cfg.parent; + const parent = this.__cfg.parent; if (parent) { - var pm = parent.getTotalMatrix(); + const pm = parent.getTotalMatrix(); /* if (!isUnchanged(pm)) { m.multiply(pm); } */ @@ -160,23 +160,23 @@ module.exports = { return m; }, // 清除当前的矩阵 - clearTotalMatrix: function() { + clearTotalMatrix() { // this.__cfg.totalMatrix = null; }, - invert: function(v) { - var m = this.getTotalMatrix(); + invert(v) { + const m = this.getTotalMatrix(); // 单精屏幕下大多数矩阵没变化 if (isScale(m)) { v.x /= m.elements[0]; v.y /= m.elements[4]; } else { - var inm = m.getInverse(); + const inm = m.getInverse(); v.applyMatrix(inm); } return this; }, - resetTransform: function(context) { - var mo = this.__m.to2DObject(); + resetTransform(context) { + const mo = this.__m.to2DObject(); // 不改变时 if (!isUnchanged(this.__m)) { context.transform(mo.a, mo.b, mo.c, mo.d, mo.e, mo.f); diff --git a/src/g/core/shape.js b/src/g/core/shape.js index e7f84c5b1..cdbd2bd0d 100644 --- a/src/g/core/shape.js +++ b/src/g/core/shape.js @@ -1,9 +1,9 @@ -var Util = require('../../util/index'); -var Element = require('./element'); -var Inside = require('../shape/util/inside'); -var Vector3 = require('@ali/g-matrix').Vector3; +const Util = require('../../util/index'); +const Element = require('./element'); +const Inside = require('../shape/util/inside'); +const Vector3 = require('@ali/g-matrix').Vector3; -var Shape = function(cfg) { +const Shape = function(cfg) { Shape.superclass.constructor.call(this, cfg); }; @@ -13,14 +13,14 @@ Util.extend(Shape, Element); Util.augment(Shape, { isShape: true, - createPath: function() {}, - drawInner: function(context) { - var self = this; - var attrs = self.__attrs; + createPath() {}, + drawInner(context) { + const self = this; + const attrs = self.__attrs; self.createPath(context); - var originOpacity = context.globalAlpha; + const originOpacity = context.globalAlpha; if (self.hasFill()) { - var fillOpacity = attrs.fillOpacity; + const fillOpacity = attrs.fillOpacity; if (!Util.isNil(fillOpacity) && fillOpacity !== 1) { context.globalAlpha = fillOpacity; context.fill(); @@ -30,9 +30,9 @@ Util.augment(Shape, { } } if (self.hasStroke()) { - var lineWidth = self.__attrs.lineWidth; + const lineWidth = self.__attrs.lineWidth; if (lineWidth > 0) { - var strokeOpacity = attrs.strokeOpacity; + const strokeOpacity = attrs.strokeOpacity; if (!Util.isNil(strokeOpacity) && strokeOpacity !== 1) { context.globalAlpha = strokeOpacity; } @@ -46,14 +46,14 @@ Util.augment(Shape, { * @param {Number} y y 坐标 * @return {Boolean} 是否在图形中 */ - isPointInPath: function() { + isPointInPath() { return false; }, /** * 击中图形时是否进行包围盒判断 * @return {Boolean} [description] */ - isHitBox: function() { + isHitBox() { return true; }, /** @@ -62,18 +62,18 @@ Util.augment(Shape, { * @param {Number} y y坐标 * @return {Boolean} 是否在图形中 */ - isHit: function(x, y) { - var self = this; - var v = new Vector3(x, y, 1); + isHit(x, y) { + const self = this; + const v = new Vector3(x, y, 1); self.invert(v); // canvas if (self.isHitBox()) { - var box = self.getBBox(); + const box = self.getBBox(); if (box && !Inside.box(box.minX, box.maxX, box.minY, box.maxY, v.x, v.y)) { return false; } } - var clip = self.__attrs.clip; + const clip = self.__attrs.clip; if (clip) { if (clip.inside(x, y)) { return self.isPointInPath(v.x, v.y); @@ -88,20 +88,20 @@ Util.augment(Shape, { * 计算包围盒 * @return {Object} 包围盒 */ - calculateBox: function() { + calculateBox() { return null; }, // 清除当前的矩阵 - clearTotalMatrix: function() { + clearTotalMatrix() { this.__cfg.totalMatrix = null; this.__cfg.region = null; }, - clearBBox: function() { + clearBBox() { this.__cfg.box = null; this.__cfg.region = null; }, - getBBox: function() { - var box = this.__cfg.box; + getBBox() { + let box = this.__cfg.box; // 延迟计算 if (!box) { box = this.calculateBox(); diff --git a/src/g/format.js b/src/g/format.js index bceef241f..c1abe44d2 100644 --- a/src/g/format.js +++ b/src/g/format.js @@ -1,13 +1,13 @@ -var Util = require('../util/index'); -var GColor = require('@ali/g-color'); +const Util = require('../util/index'); +const GColor = require('@ali/g-color'); -var regexTags = /[MLHVQTCSAZ]([^MLHVQTCSAZ]*)/ig; -var regexDot = /[^\s\,]+/ig; -var regexLG = /^l\s*\(\s*([\d.]+)\s*\)\s*(.*)/i; -var regexRG = /^r\s*\(\s*([\d.]+)\s*,\s*([\d.]+)\s*,\s*([\d.]+)\s*\)\s*(.*)/i; -var regexPR = /^p\s*([axyn])\s+(.*)/i; -var regexColorStop = /[\d.]+:(#[^\s]+|[^\)]+\))/ig; -var numColorCache = {}; +const regexTags = /[MLHVQTCSAZ]([^MLHVQTCSAZ]*)/ig; +const regexDot = /[^\s\,]+/ig; +const regexLG = /^l\s*\(\s*([\d.]+)\s*\)\s*(.*)/i; +const regexRG = /^r\s*\(\s*([\d.]+)\s*,\s*([\d.]+)\s*,\s*([\d.]+)\s*\)\s*(.*)/i; +const regexPR = /^p\s*([axyn])\s+(.*)/i; +const regexColorStop = /[\d.]+:(#[^\s]+|[^\)]+\))/ig; +const numColorCache = {}; function multiplyOpacity(color, opacity) { if (opacity === undefined) { @@ -15,7 +15,7 @@ function multiplyOpacity(color, opacity) { } color = new GColor(color); color.multiplyA(opacity); - var type = color.getType(); + const type = color.getType(); if (type === 'hsl') { return color.getHSLStyle(); } else if (type === 'rgb') { @@ -24,21 +24,21 @@ function multiplyOpacity(color, opacity) { } function addStop(steps, gradient, opacity) { - var arr = steps.match(regexColorStop); + const arr = steps.match(regexColorStop); Util.each(arr, function(item) { item = item.split(':'); - var color = multiplyOpacity(item[1], opacity); + const color = multiplyOpacity(item[1], opacity); gradient.addColorStop(item[0], color); }); } function parseLineGradient(color, self, opacity) { - var arr = regexLG.exec(color); - var angle = Util.mod(Util.toRadian(parseFloat(arr[1])), Math.PI * 2); - var steps = arr[2]; - var box = self.getBBox(); - var start; - var end; + const arr = regexLG.exec(color); + const angle = Util.mod(Util.toRadian(parseFloat(arr[1])), Math.PI * 2); + const steps = arr[2]; + const box = self.getBBox(); + let start; + let end; if (angle >= 0 && angle < 0.5 * Math.PI) { start = { @@ -78,37 +78,37 @@ function parseLineGradient(color, self, opacity) { }; } - var tanTheta = Math.tan(angle); - var tanTheta2 = tanTheta * tanTheta; + const tanTheta = Math.tan(angle); + const tanTheta2 = tanTheta * tanTheta; - var x = ((end.x - start.x) + tanTheta * (end.y - start.y)) / (tanTheta2 + 1) + start.x; - var y = tanTheta * ((end.x - start.x) + tanTheta * (end.y - start.y)) / (tanTheta2 + 1) + start.y; - var context = self.get('context'); - var gradient = context.createLinearGradient(start.x, start.y, x, y); + const x = ((end.x - start.x) + tanTheta * (end.y - start.y)) / (tanTheta2 + 1) + start.x; + const y = tanTheta * ((end.x - start.x) + tanTheta * (end.y - start.y)) / (tanTheta2 + 1) + start.y; + const context = self.get('context'); + const gradient = context.createLinearGradient(start.x, start.y, x, y); addStop(steps, gradient, opacity); return gradient; } function parseRadialGradient(color, self, opacity) { - var arr = regexRG.exec(color); - var fx = parseFloat(arr[1]); - var fy = parseFloat(arr[2]); - var fr = parseFloat(arr[3]); - var steps = arr[4]; - var box = self.getBBox(); - var context = self.get('context'); - var width = box.maxX - box.minX; - var height = box.maxY - box.minY; - var r = Math.sqrt(width * width + height * height) / 2; - var gradient = context.createRadialGradient(box.minX + width * fx, box.minY + height * fy, fr, box.minX + width / 2, box.minY + height / 2, r); + const arr = regexRG.exec(color); + const fx = parseFloat(arr[1]); + const fy = parseFloat(arr[2]); + const fr = parseFloat(arr[3]); + const steps = arr[4]; + const box = self.getBBox(); + const context = self.get('context'); + const width = box.maxX - box.minX; + const height = box.maxY - box.minY; + const r = Math.sqrt(width * width + height * height) / 2; + const gradient = context.createRadialGradient(box.minX + width * fx, box.minY + height * fy, fr, box.minX + width / 2, box.minY + height / 2, r); addStop(steps, gradient, opacity); return gradient; } function parsePattern(color, self) { - var arr = regexPR.exec(color); - var repeat = arr[1]; - var id = arr[2]; + const arr = regexPR.exec(color); + let repeat = arr[1]; + const id = arr[2]; switch (repeat) { case 'a': repeat = 'repeat'; @@ -125,14 +125,14 @@ function parsePattern(color, self) { default: repeat = 'no-repeat'; } - var img = document.getElementById(id); - var context = self.get('context'); - var pattern = context.createPattern(img, repeat); + const img = document.getElementById(id); + const context = self.get('context'); + const pattern = context.createPattern(img, repeat); return pattern; } module.exports = { - parsePath: function(path) { + parsePath(path) { path = path || []; if (Util.isArray(path)) { return path; @@ -143,7 +143,7 @@ module.exports = { Util.each(path, function(item, index) { item = item.match(regexDot); if (item[0].length > 1) { - var tag = item[0].charAt(0); + const tag = item[0].charAt(0); item.splice(1, 0, item[0].substr(1)); item[0] = tag; } @@ -157,14 +157,14 @@ module.exports = { return path; } }, - parseStyle: function(color, self, opacity) { + parseStyle(color, self, opacity) { if (Util.isString(color)) { if (color[1] === '(' || color[2] === '(') { if (color[0] === 'l') { // regexLG.test(color) return parseLineGradient(color, self, opacity); } else if (color[0] === 'r') { // regexRG.test(color) return parseRadialGradient(color, self, opacity); - } else if (color[0] === 'p') {// regexPR.test(color) + } else if (color[0] === 'p') { // regexPR.test(color) return parsePattern(color, self); } } @@ -174,12 +174,12 @@ module.exports = { return multiplyOpacity(color, opacity); } }, - numberToColor: function(num) { + numberToColor(num) { // 增加缓存 - var color = numColorCache[num]; + let color = numColorCache[num]; if (!color) { - var str = num.toString(16); - for (var i = str.length; i < 6; i++) { + let str = num.toString(16); + for (let i = str.length; i < 6; i++) { str = '0' + str; } color = '#' + str; diff --git a/src/g/index.js b/src/g/index.js index 2c6b01ed8..56af0da6a 100644 --- a/src/g/index.js +++ b/src/g/index.js @@ -1,6 +1,6 @@ -var Common = require('./common'); +const Common = require('./common'); -var G = { +const G = { Group: require('./core/group'), Shape: require('./core/shape'), Rect: require('./shape/rect'), @@ -17,7 +17,7 @@ var G = { Cubic: require('./shape/cubic'), Quadratic: require('./shape/quadratic'), Marker: require('./shape/marker'), - debug: function(debug) { + debug(debug) { Common.debug = debug; } }; diff --git a/src/g/shape/arc.js b/src/g/shape/arc.js index c0b7f4db3..137344384 100644 --- a/src/g/shape/arc.js +++ b/src/g/shape/arc.js @@ -5,14 +5,14 @@ * @ignore */ -var Util = require('../../util/index'); -var Vector2 = require('@ali/g-matrix').Vector2; -var Shape = require('../core/shape'); -var Inside = require('./util/inside'); -var ArcMath = require('./math/arc'); -var Arrow = require('./util/arrow'); +const Util = require('../../util/index'); +const Vector2 = require('@ali/g-matrix').Vector2; +const Shape = require('../core/shape'); +const Inside = require('./util/inside'); +const ArcMath = require('./math/arc'); +const Arrow = require('./util/arrow'); -var Arc = function(cfg) { +const Arc = function(cfg) { Arc.superclass.constructor.call(this, cfg); }; @@ -32,7 +32,7 @@ Util.extend(Arc, Shape); Util.augment(Arc, { canStroke: true, type: 'arc', - getDefaultAttrs: function() { + getDefaultAttrs() { return { x: 0, y: 0, @@ -44,60 +44,60 @@ Util.augment(Arc, { arrow: false }; }, - calculateBox: function() { - var attrs = this.__attrs; - var cx = attrs.x; - var cy = attrs.y; - var r = attrs.r; - var startAngle = attrs.startAngle; - var endAngle = attrs.endAngle; - var clockwise = attrs.clockwise; - var lineWidth = attrs.lineWidth; - var halfWidth = lineWidth / 2; - var box = ArcMath.box(cx, cy, r, startAngle, endAngle, clockwise); + calculateBox() { + const attrs = this.__attrs; + const cx = attrs.x; + const cy = attrs.y; + const r = attrs.r; + const startAngle = attrs.startAngle; + const endAngle = attrs.endAngle; + const clockwise = attrs.clockwise; + const lineWidth = attrs.lineWidth; + const halfWidth = lineWidth / 2; + const box = ArcMath.box(cx, cy, r, startAngle, endAngle, clockwise); box.minX -= halfWidth; box.minY -= halfWidth; box.maxX += halfWidth; box.maxY += halfWidth; return box; }, - isPointInPath: function(x, y) { - var attrs = this.__attrs; - var cx = attrs.x; - var cy = attrs.y; - var r = attrs.r; - var startAngle = attrs.startAngle; - var endAngle = attrs.endAngle; - var clockwise = attrs.clockwise; - var lineWidth = attrs.lineWidth; + isPointInPath(x, y) { + const attrs = this.__attrs; + const cx = attrs.x; + const cy = attrs.y; + const r = attrs.r; + const startAngle = attrs.startAngle; + const endAngle = attrs.endAngle; + const clockwise = attrs.clockwise; + const lineWidth = attrs.lineWidth; if (this.hasStroke()) { return Inside.arcline(cx, cy, r, startAngle, endAngle, clockwise, lineWidth, x, y); } return false; }, - createPath: function(context) { - var attrs = this.__attrs; - var cx = attrs.x; - var cy = attrs.y; - var r = attrs.r; - var startAngle = attrs.startAngle; - var endAngle = attrs.endAngle; - var clockwise = attrs.clockwise; - var lineWidth = attrs.lineWidth; - var arrow = attrs.arrow; + createPath(context) { + const attrs = this.__attrs; + const cx = attrs.x; + const cy = attrs.y; + const r = attrs.r; + const startAngle = attrs.startAngle; + const endAngle = attrs.endAngle; + const clockwise = attrs.clockwise; + const lineWidth = attrs.lineWidth; + const arrow = attrs.arrow; context = context || self.get('context'); context.beginPath(); context.arc(cx, cy, r, startAngle, endAngle, clockwise); if (arrow) { - var end = { + const end = { x: cx + r * Math.cos(endAngle), y: cy + r * Math.sin(endAngle) }; - var v = new Vector2(-r * Math.sin(endAngle), r * Math.cos(endAngle)); + const v = new Vector2(-r * Math.sin(endAngle), r * Math.cos(endAngle)); if (clockwise) { v.multiplyScaler(-1); } diff --git a/src/g/shape/circle.js b/src/g/shape/circle.js index d30e86508..afeae1992 100644 --- a/src/g/shape/circle.js +++ b/src/g/shape/circle.js @@ -4,11 +4,11 @@ * @author hankaiai@126.com * @ignore */ -var Util = require('../../util/index'); -var Shape = require('../core/shape'); -var Inside = require('./util/inside'); +const Util = require('../../util/index'); +const Shape = require('../core/shape'); +const Inside = require('./util/inside'); -var Circle = function(cfg) { +const Circle = function(cfg) { Circle.superclass.constructor.call(this, cfg); }; @@ -25,18 +25,18 @@ Util.augment(Circle, { canFill: true, canStroke: true, type: 'circle', - getDefaultAttrs: function() { + getDefaultAttrs() { return { lineWidth: 1 }; }, - calculateBox: function() { - var attrs = this.__attrs; - var cx = attrs.x; - var cy = attrs.y; - var r = attrs.r; - var lineWidth = attrs.lineWidth; - var halfWidth = lineWidth / 2 + r; + calculateBox() { + const attrs = this.__attrs; + const cx = attrs.x; + const cy = attrs.y; + const r = attrs.r; + const lineWidth = attrs.lineWidth; + const halfWidth = lineWidth / 2 + r; return { minX: cx - halfWidth, minY: cy - halfWidth, @@ -44,9 +44,9 @@ Util.augment(Circle, { maxY: cy + halfWidth }; }, - isPointInPath: function(x, y) { - var fill = this.hasFill(); - var stroke = this.hasStroke(); + isPointInPath(x, y) { + const fill = this.hasFill(); + const stroke = this.hasStroke(); if (fill && stroke) { return this.__isPointInFill(x, y) || this.__isPointInStroke(x, y); } @@ -61,28 +61,28 @@ Util.augment(Circle, { return false; }, - __isPointInFill: function(x, y) { - var attrs = this.__attrs; - var cx = attrs.x; - var cy = attrs.y; - var r = attrs.r; + __isPointInFill(x, y) { + const attrs = this.__attrs; + const cx = attrs.x; + const cy = attrs.y; + const r = attrs.r; return Inside.circle(cx, cy, r, x, y); }, - __isPointInStroke: function(x, y) { - var attrs = this.__attrs; - var cx = attrs.x; - var cy = attrs.y; - var r = attrs.r; - var lineWidth = attrs.lineWidth; + __isPointInStroke(x, y) { + const attrs = this.__attrs; + const cx = attrs.x; + const cy = attrs.y; + const r = attrs.r; + const lineWidth = attrs.lineWidth; return Inside.arcline(cx, cy, r, 0, Math.PI * 2, false, lineWidth, x, y); }, - createPath: function(context) { - var attrs = this.__attrs; - var cx = attrs.x; - var cy = attrs.y; - var r = attrs.r; + createPath(context) { + const attrs = this.__attrs; + const cx = attrs.x; + const cy = attrs.y; + const r = attrs.r; context = context || self.get('context'); context.beginPath(); diff --git a/src/g/shape/cubic.js b/src/g/shape/cubic.js index b9e6dd50e..bad58b6cc 100644 --- a/src/g/shape/cubic.js +++ b/src/g/shape/cubic.js @@ -3,14 +3,14 @@ * @author hankaiai@126.com * @ignore */ -var Util = require('../../util/index'); -var Shape = require('../core/shape'); -var Inside = require('./util/inside'); -var Arrow = require('./util/arrow'); -var CubicMath = require('./math/cubic'); -var Vector2 = require('@ali/g-matrix').Vector2; +const Util = require('../../util/index'); +const Shape = require('../core/shape'); +const Inside = require('./util/inside'); +const Arrow = require('./util/arrow'); +const CubicMath = require('./math/cubic'); +const Vector2 = require('@ali/g-matrix').Vector2; -var Cubic = function(cfg) { +const Cubic = function(cfg) { Cubic.superclass.constructor.call(this, cfg); }; @@ -28,19 +28,19 @@ Util.extend(Cubic, Shape); Util.augment(Cubic, { canStroke: true, type: 'cubic', - getDefaultAttrs: function() { + getDefaultAttrs() { return { lineWidth: 1 }; }, - calculateBox: function() { - var attrs = this.__attrs; - var p1 = attrs.p1; - var p2 = attrs.p2; - var p3 = attrs.p3; - var p4 = attrs.p4; - var i; - var l; + calculateBox() { + const attrs = this.__attrs; + const p1 = attrs.p1; + const p2 = attrs.p2; + const p3 = attrs.p3; + const p4 = attrs.p4; + let i; + let l; if ( Util.isNil(p1) || @@ -50,13 +50,13 @@ Util.augment(Cubic, { ) { return null; } - var halfWidth = attrs.lineWidth / 2; + const halfWidth = attrs.lineWidth / 2; - var xDim = CubicMath.extrema(p1[0], p2[0], p3[0], p4[0]); + const xDim = CubicMath.extrema(p1[0], p2[0], p3[0], p4[0]); for (i = 0, l = xDim.length; i < l; i++) { xDim[i] = CubicMath.at(p1[0], p2[0], p3[0], p4[0], xDim[i]); } - var yDim = CubicMath.extrema(p1[1], p2[1], p3[1], p4[1]); + const yDim = CubicMath.extrema(p1[1], p2[1], p3[1], p4[1]); for (i = 0, l = yDim.length; i < l; i++) { yDim[i] = CubicMath.at(p1[1], p2[1], p3[1], p4[1], yDim[i]); } @@ -70,13 +70,13 @@ Util.augment(Cubic, { maxY: Math.max.apply(Math, yDim) + halfWidth }; }, - isPointInPath: function(x, y) { - var attrs = this.__attrs; - var p1 = attrs.p1; - var p2 = attrs.p2; - var p3 = attrs.p3; - var p4 = attrs.p4; - var lineWidth = attrs.lineWidth; + isPointInPath(x, y) { + const attrs = this.__attrs; + const p1 = attrs.p1; + const p2 = attrs.p2; + const p3 = attrs.p3; + const p4 = attrs.p4; + const lineWidth = attrs.lineWidth; return Inside.cubicline( p1[0], p1[1], @@ -86,14 +86,14 @@ Util.augment(Cubic, { lineWidth, x, y ); }, - createPath: function(context) { - var attrs = this.__attrs; - var p1 = attrs.p1; - var p2 = attrs.p2; - var p3 = attrs.p3; - var p4 = attrs.p4; - var lineWidth = attrs.lineWidth; - var arrow = attrs.arrow; + createPath(context) { + const attrs = this.__attrs; + const p1 = attrs.p1; + const p2 = attrs.p2; + const p3 = attrs.p3; + const p4 = attrs.p4; + const lineWidth = attrs.lineWidth; + const arrow = attrs.arrow; context = context || self.get('context'); if ( Util.isNil(p1) || @@ -108,16 +108,16 @@ Util.augment(Cubic, { context.moveTo(p1[0], p1[1]); if (arrow) { - var v = new Vector2(p4[0] - p3[0], p4[1] - p3[1]); - var end = Arrow.getEndPoint(v, new Vector2(p4[0], p4[1]), lineWidth); + const v = new Vector2(p4[0] - p3[0], p4[1] - p3[1]); + const end = Arrow.getEndPoint(v, new Vector2(p4[0], p4[1]), lineWidth); context.bezierCurveTo(p2[0], p2[1], p3[0], p3[1], end.x, end.y); Arrow.makeArrow(context, v, end, lineWidth); } else { context.bezierCurveTo(p2[0], p2[1], p3[0], p3[1], p4[0], p4[1]); } }, - getPoint: function(t) { - var attrs = this.__attrs; + getPoint(t) { + const attrs = this.__attrs; return { x: CubicMath.at(attrs.p4[0], attrs.p3[0], attrs.p2[0], attrs.p1[0], t), y: CubicMath.at(attrs.p4[1], attrs.p3[1], attrs.p2[1], attrs.p1[1], t) diff --git a/src/g/shape/ellipse.js b/src/g/shape/ellipse.js index 395156d08..f6bd170f3 100644 --- a/src/g/shape/ellipse.js +++ b/src/g/shape/ellipse.js @@ -4,14 +4,14 @@ * @author hankaiai@126.com * @ignore */ -var Util = require('../../util/index'); -var Shape = require('../core/shape'); -var Inside = require('./util/inside'); -var Matrix = require('@ali/g-matrix'); -var Matrix3 = Matrix.Matrix3; -var Vector3 = Matrix.Vector3; - -var Ellipse = function(cfg) { +const Util = require('../../util/index'); +const Shape = require('../core/shape'); +const Inside = require('./util/inside'); +const Matrix = require('@ali/g-matrix'); +const Matrix3 = Matrix.Matrix3; +const Vector3 = Matrix.Vector3; + +const Ellipse = function(cfg) { Ellipse.superclass.constructor.call(this, cfg); }; @@ -29,20 +29,20 @@ Util.augment(Ellipse, { canFill: true, canStroke: true, type: 'ellipse', - getDefaultAttrs: function() { + getDefaultAttrs() { return { lineWidth: 1 }; }, - calculateBox: function() { - var attrs = this.__attrs; - var cx = attrs.x; - var cy = attrs.y; - var rx = attrs.rx; - var ry = attrs.ry; - var lineWidth = attrs.lineWidth; - var halfXWidth = rx + lineWidth / 2; - var halfYWidth = ry + lineWidth / 2; + calculateBox() { + const attrs = this.__attrs; + const cx = attrs.x; + const cy = attrs.y; + const rx = attrs.rx; + const ry = attrs.ry; + const lineWidth = attrs.lineWidth; + const halfXWidth = rx + lineWidth / 2; + const halfYWidth = ry + lineWidth / 2; return { minX: cx - halfXWidth, @@ -51,9 +51,9 @@ Util.augment(Ellipse, { maxY: cy + halfYWidth }; }, - isPointInPath: function(x, y) { - var fill = this.hasFill(); - var stroke = this.hasStroke(); + isPointInPath(x, y) { + const fill = this.hasFill(); + const stroke = this.hasStroke(); if (fill && stroke) { return this.__isPointInFill(x, y) || this.__isPointInStroke(x, y); @@ -69,63 +69,63 @@ Util.augment(Ellipse, { return false; }, - __isPointInFill: function(x, y) { - var attrs = this.__attrs; - var cx = attrs.x; - var cy = attrs.y; - var rx = attrs.rx; - var ry = attrs.ry; - - var r = (rx > ry) ? rx : ry; - var scaleX = (rx > ry) ? 1 : rx / ry; - var scaleY = (rx > ry) ? ry / rx : 1; - - var p = new Vector3(x, y, 1); - var m = new Matrix3(); + __isPointInFill(x, y) { + const attrs = this.__attrs; + const cx = attrs.x; + const cy = attrs.y; + const rx = attrs.rx; + const ry = attrs.ry; + + const r = (rx > ry) ? rx : ry; + const scaleX = (rx > ry) ? 1 : rx / ry; + const scaleY = (rx > ry) ? ry / rx : 1; + + const p = new Vector3(x, y, 1); + const m = new Matrix3(); m.scale(scaleX, scaleY); m.translate(cx, cy); - var inm = m.getInverse(); + const inm = m.getInverse(); p.applyMatrix(inm); return Inside.circle(0, 0, r, p.x, p.y); }, - __isPointInStroke: function(x, y) { - var attrs = this.__attrs; - var cx = attrs.x; - var cy = attrs.y; - var rx = attrs.rx; - var ry = attrs.ry; - var lineWidth = attrs.lineWidth; - - var r = (rx > ry) ? rx : ry; - var scaleX = (rx > ry) ? 1 : rx / ry; - var scaleY = (rx > ry) ? ry / rx : 1; - - var p = new Vector3(x, y, 1); - var m = new Matrix3(); + __isPointInStroke(x, y) { + const attrs = this.__attrs; + const cx = attrs.x; + const cy = attrs.y; + const rx = attrs.rx; + const ry = attrs.ry; + const lineWidth = attrs.lineWidth; + + const r = (rx > ry) ? rx : ry; + const scaleX = (rx > ry) ? 1 : rx / ry; + const scaleY = (rx > ry) ? ry / rx : 1; + + const p = new Vector3(x, y, 1); + const m = new Matrix3(); m.scale(scaleX, scaleY); m.translate(cx, cy); - var inm = m.getInverse(); + const inm = m.getInverse(); p.applyMatrix(inm); return Inside.arcline(0, 0, r, 0, Math.PI * 2, false, lineWidth, p.x, p.y); }, - createPath: function(context) { - var attrs = this.__attrs; - var cx = attrs.x; - var cy = attrs.y; - var rx = attrs.rx; - var ry = attrs.ry; + createPath(context) { + const attrs = this.__attrs; + const cx = attrs.x; + const cy = attrs.y; + const rx = attrs.rx; + const ry = attrs.ry; context = context || self.get('context'); - var r = (rx > ry) ? rx : ry; - var scaleX = (rx > ry) ? 1 : rx / ry; - var scaleY = (rx > ry) ? ry / rx : 1; + const r = (rx > ry) ? rx : ry; + const scaleX = (rx > ry) ? 1 : rx / ry; + const scaleY = (rx > ry) ? ry / rx : 1; - var m = new Matrix3(); + const m = new Matrix3(); m.scale(scaleX, scaleY); m.translate(cx, cy); - var mo = m.to2DObject(); + const mo = m.to2DObject(); context.beginPath(); context.save(); context.transform(mo.a, mo.b, mo.c, mo.d, mo.e, mo.f); diff --git a/src/g/shape/fan.js b/src/g/shape/fan.js index bfc45ec89..6dff1a1f2 100644 --- a/src/g/shape/fan.js +++ b/src/g/shape/fan.js @@ -4,14 +4,14 @@ * @author hankaiai@126.com * @ignore */ -var Util = require('../../util/index'); -var Shape = require('../core/shape'); -var Inside = require('./util/inside'); -var ArcMath = require('./math/arc'); -var Matrix = require('@ali/g-matrix'); -var Vector2 = Matrix.Vector2; - -var Fan = function(cfg) { +const Util = require('../../util/index'); +const Shape = require('../core/shape'); +const Inside = require('./util/inside'); +const ArcMath = require('./math/arc'); +const Matrix = require('@ali/g-matrix'); +const Vector2 = Matrix.Vector2; + +const Fan = function(cfg) { Fan.superclass.constructor.call(this, cfg); }; @@ -32,7 +32,7 @@ Util.augment(Fan, { canFill: true, canStroke: true, type: 'fan', - getDefaultAttrs: function() { + getDefaultAttrs() { return { clockwise: false, lineWidth: 1, @@ -40,26 +40,26 @@ Util.augment(Fan, { re: 0 }; }, - calculateBox: function() { - var self = this; - var attrs = self.__attrs; - var cx = attrs.x; - var cy = attrs.y; - var rs = attrs.rs; - var re = attrs.re; - var startAngle = attrs.startAngle; - var endAngle = attrs.endAngle; - var clockwise = attrs.clockwise; - var lineWidth = attrs.lineWidth; - - var boxs = ArcMath.box(cx, cy, rs, startAngle, endAngle, clockwise); - var boxe = ArcMath.box(cx, cy, re, startAngle, endAngle, clockwise); - var minX = Math.min(boxs.minX, boxe.minX); - var minY = Math.min(boxs.minY, boxe.minY); - var maxX = Math.max(boxs.maxX, boxe.maxX); - var maxY = Math.max(boxs.maxY, boxe.maxY); - - var halfWidth = lineWidth / 2; + calculateBox() { + const self = this; + const attrs = self.__attrs; + const cx = attrs.x; + const cy = attrs.y; + const rs = attrs.rs; + const re = attrs.re; + const startAngle = attrs.startAngle; + const endAngle = attrs.endAngle; + const clockwise = attrs.clockwise; + const lineWidth = attrs.lineWidth; + + const boxs = ArcMath.box(cx, cy, rs, startAngle, endAngle, clockwise); + const boxe = ArcMath.box(cx, cy, re, startAngle, endAngle, clockwise); + const minX = Math.min(boxs.minX, boxe.minX); + const minY = Math.min(boxs.minY, boxe.minY); + const maxX = Math.max(boxs.maxX, boxe.maxX); + const maxY = Math.max(boxs.maxY, boxe.maxY); + + const halfWidth = lineWidth / 2; return { minX: minX - halfWidth, minY: minY - halfWidth, @@ -67,9 +67,9 @@ Util.augment(Fan, { maxY: maxY + halfWidth }; }, - isPointInPath: function(x, y) { - var fill = this.hasFill(); - var stroke = this.hasStroke(); + isPointInPath(x, y) { + const fill = this.hasFill(); + const stroke = this.hasStroke(); if (fill && stroke) { return this.__isPointInFill(x, y) || this.__isPointInStroke(x, y); @@ -84,55 +84,55 @@ Util.augment(Fan, { } return false; }, - __isPointInFill: function(x, y) { - var attrs = this.__attrs; - var cx = attrs.x; - var cy = attrs.y; - var rs = attrs.rs; - var re = attrs.re; - var startAngle = attrs.startAngle; - var endAngle = attrs.endAngle; - var clockwise = attrs.clockwise; + __isPointInFill(x, y) { + const attrs = this.__attrs; + const cx = attrs.x; + const cy = attrs.y; + const rs = attrs.rs; + const re = attrs.re; + const startAngle = attrs.startAngle; + const endAngle = attrs.endAngle; + const clockwise = attrs.clockwise; - var v1 = new Vector2(1, 0); - var subv = new Vector2(x - cx, y - cy); - var angle = v1.angleTo(subv); + const v1 = new Vector2(1, 0); + const subv = new Vector2(x - cx, y - cy); + const angle = v1.angleTo(subv); - var angle1 = ArcMath.nearAngle(angle, startAngle, endAngle, clockwise); + const angle1 = ArcMath.nearAngle(angle, startAngle, endAngle, clockwise); if (Util.isNumberEqual(angle, angle1)) { - var ls = subv.lengthSq(); + const ls = subv.lengthSq(); if (rs * rs <= ls && ls <= re * re) { return true; } } return false; }, - __isPointInStroke: function(x, y) { - var attrs = this.__attrs; - var cx = attrs.x; - var cy = attrs.y; - var rs = attrs.rs; - var re = attrs.re; - var startAngle = attrs.startAngle; - var endAngle = attrs.endAngle; - var clockwise = attrs.clockwise; - var lineWidth = attrs.lineWidth; - - var ssp = { + __isPointInStroke(x, y) { + const attrs = this.__attrs; + const cx = attrs.x; + const cy = attrs.y; + const rs = attrs.rs; + const re = attrs.re; + const startAngle = attrs.startAngle; + const endAngle = attrs.endAngle; + const clockwise = attrs.clockwise; + const lineWidth = attrs.lineWidth; + + const ssp = { x: Math.cos(startAngle) * rs + cx, y: Math.sin(startAngle) * rs + cy }; - var sep = { + const sep = { x: Math.cos(startAngle) * re + cx, y: Math.sin(startAngle) * re + cy }; - var esp = { + const esp = { x: Math.cos(endAngle) * rs + cx, y: Math.sin(endAngle) * rs + cy }; - var eep = { + const eep = { x: Math.cos(endAngle) * re + cx, y: Math.sin(endAngle) * re + cy }; @@ -155,25 +155,25 @@ Util.augment(Fan, { return false; }, - createPath: function(context) { - var attrs = this.__attrs; - var cx = attrs.x; - var cy = attrs.y; - var rs = attrs.rs; - var re = attrs.re; - var startAngle = attrs.startAngle; - var endAngle = attrs.endAngle; - var clockwise = attrs.clockwise; - - var ssp = { + createPath(context) { + const attrs = this.__attrs; + const cx = attrs.x; + const cy = attrs.y; + const rs = attrs.rs; + const re = attrs.re; + const startAngle = attrs.startAngle; + const endAngle = attrs.endAngle; + const clockwise = attrs.clockwise; + + const ssp = { x: Math.cos(startAngle) * rs + cx, y: Math.sin(startAngle) * rs + cy }; - var sep = { + const sep = { x: Math.cos(startAngle) * re + cx, y: Math.sin(startAngle) * re + cy }; - var esp = { + const esp = { x: Math.cos(endAngle) * rs + cx, y: Math.sin(endAngle) * rs + cy }; diff --git a/src/g/shape/image.js b/src/g/shape/image.js index 8f2b04737..c9186687f 100644 --- a/src/g/shape/image.js +++ b/src/g/shape/image.js @@ -4,11 +4,11 @@ * @author hankaiai@126.com * @ignore */ -var Util = require('../../util/index'); -var Shape = require('../core/shape'); -var Inside = require('./util/inside'); +const Util = require('../../util/index'); +const Shape = require('../core/shape'); +const Inside = require('./util/inside'); -var CImage = function(cfg) { +const CImage = function(cfg) { CImage.superclass.constructor.call(this, cfg); }; @@ -28,23 +28,23 @@ Util.extend(CImage, Shape); Util.augment(CImage, { type: 'image', - __afterSetAttrImg: function(img) { + __afterSetAttrImg(img) { this.__setAttrImg(img); }, - __afterSetAttrAll: function(params) { + __afterSetAttrAll(params) { if (params.img) { this.__setAttrImg(params.img); } }, - isHitBox: function() { + isHitBox() { return false; }, - calculateBox: function() { - var attrs = this.__attrs; - var x = attrs.x; - var y = attrs.y; - var width = attrs.width; - var height = attrs.height; + calculateBox() { + const attrs = this.__attrs; + const x = attrs.x; + const y = attrs.y; + const width = attrs.width; + const height = attrs.height; return { minX: x, @@ -53,35 +53,35 @@ Util.augment(CImage, { maxY: y + height }; }, - isPointInPath: function(x, y) { - var attrs = this.__attrs; + isPointInPath(x, y) { + const attrs = this.__attrs; if (this.get('toDraw') || !attrs.img) { return false; } - var rx = attrs.x; - var ry = attrs.y; - var width = attrs.width; - var height = attrs.height; + const rx = attrs.x; + const ry = attrs.y; + const width = attrs.width; + const height = attrs.height; return Inside.rect(rx, ry, width, height, x, y); }, - __setLoading: function(loading) { - var canvas = this.get('canvas'); + __setLoading(loading) { + const canvas = this.get('canvas'); if (loading === false && this.get('toDraw') === true) { this.__cfg.loading = false; canvas.draw(); } return loading; }, - __setAttrImg: function(img) { - var self = this; - var attrs = self.__attrs; + __setAttrImg(img) { + const self = this; + const attrs = self.__attrs; if (Util.isString(img)) { - var image = new Image(); + const image = new Image(); image.onload = function() { if (self.get('destroyed')) return false; self.attr('imgSrc', img); self.attr('img', image); - var callback = self.get('callback'); + const callback = self.get('callback'); if (callback) { callback.call(self); } @@ -120,24 +120,24 @@ Util.augment(CImage, { return null; } }, - drawInner: function(context) { + drawInner(context) { if (this.get('loading')) { this.set('toDraw', true); return; } this.__drawImage(context); }, - __drawImage: function(context) { - var attrs = this.__attrs; - var x = attrs.x; - var y = attrs.y; - var img = attrs.img; - var width = attrs.width; - var height = attrs.height; - var sx = attrs.sx; - var sy = attrs.sy; - var swidth = attrs.swidth; - var sheight = attrs.sheight; + __drawImage(context) { + const attrs = this.__attrs; + const x = attrs.x; + const y = attrs.y; + const img = attrs.img; + const width = attrs.width; + const height = attrs.height; + const sx = attrs.sx; + const sy = attrs.sy; + const swidth = attrs.swidth; + const sheight = attrs.sheight; this.set('toDraw', false); if (img instanceof Image || (img instanceof HTMLElement && Util.isString(img.nodeName) && img.nodeName.toUpperCase() === 'CANVAS')) { diff --git a/src/g/shape/index.js b/src/g/shape/index.js index 5d832c90f..8df316824 100644 --- a/src/g/shape/index.js +++ b/src/g/shape/index.js @@ -1,4 +1,4 @@ -var Shape = { +const Shape = { Rect: require('./rect'), Circle: require('./circle'), Ellipse: require('./ellipse'), diff --git a/src/g/shape/line.js b/src/g/shape/line.js index 607b7a7c3..486627425 100644 --- a/src/g/shape/line.js +++ b/src/g/shape/line.js @@ -4,15 +4,15 @@ * @author hankaiai@126.com * @ignore */ -var Util = require('../../util/index'); -var Shape = require('../core/shape'); -var Inside = require('./util/inside'); -var Arrow = require('./util/arrow'); -var LineMath = require('./math/line'); -var Matrix = require('@ali/g-matrix'); -var Vector2 = Matrix.Vector2; +const Util = require('../../util/index'); +const Shape = require('../core/shape'); +const Inside = require('./util/inside'); +const Arrow = require('./util/arrow'); +const LineMath = require('./math/line'); +const Matrix = require('@ali/g-matrix'); +const Vector2 = Matrix.Vector2; -var Line = function(cfg) { +const Line = function(cfg) { Line.superclass.constructor.call(this, cfg); }; @@ -30,57 +30,57 @@ Util.extend(Line, Shape); Util.augment(Line, { canStroke: true, type: 'line', - getDefaultAttrs: function() { + getDefaultAttrs() { return { lineWidth: 1, arrow: false }; }, - calculateBox: function() { - var attrs = this.__attrs; - var x1 = attrs.x1; - var y1 = attrs.y1; - var x2 = attrs.x2; - var y2 = attrs.y2; - var lineWidth = attrs.lineWidth; + calculateBox() { + const attrs = this.__attrs; + const x1 = attrs.x1; + const y1 = attrs.y1; + const x2 = attrs.x2; + const y2 = attrs.y2; + const lineWidth = attrs.lineWidth; return LineMath.box(x1, y1, x2, y2, lineWidth); }, - isPointInPath: function(x, y) { - var attrs = this.__attrs; - var x1 = attrs.x1; - var y1 = attrs.y1; - var x2 = attrs.x2; - var y2 = attrs.y2; - var lineWidth = attrs.lineWidth; + isPointInPath(x, y) { + const attrs = this.__attrs; + const x1 = attrs.x1; + const y1 = attrs.y1; + const x2 = attrs.x2; + const y2 = attrs.y2; + const lineWidth = attrs.lineWidth; if (this.hasStroke()) { return Inside.line(x1, y1, x2, y2, lineWidth, x, y); } return false; }, - createPath: function(context) { - var attrs = this.__attrs; - var x1 = attrs.x1; - var y1 = attrs.y1; - var x2 = attrs.x2; - var y2 = attrs.y2; - var arrow = attrs.arrow; - var lineWidth = attrs.lineWidth; + createPath(context) { + const attrs = this.__attrs; + const x1 = attrs.x1; + const y1 = attrs.y1; + const x2 = attrs.x2; + const y2 = attrs.y2; + const arrow = attrs.arrow; + const lineWidth = attrs.lineWidth; context = context || self.get('context'); context.beginPath(); context.moveTo(x1, y1); if (arrow) { - var v = new Vector2(x2 - x1, y2 - y1); - var end = Arrow.getEndPoint(v, new Vector2(x2, y2), lineWidth); + const v = new Vector2(x2 - x1, y2 - y1); + const end = Arrow.getEndPoint(v, new Vector2(x2, y2), lineWidth); context.lineTo(end.x, end.y); Arrow.makeArrow(context, v, end, lineWidth); } else { context.lineTo(x2, y2); } }, - getPoint: function(t) { - var attrs = this.__attrs; + getPoint(t) { + const attrs = this.__attrs; return { x: LineMath.at(attrs.x1, attrs.x2, t), y: LineMath.at(attrs.y1, attrs.y2, t) diff --git a/src/g/shape/marker.js b/src/g/shape/marker.js index efe368dc0..fb618c96e 100644 --- a/src/g/shape/marker.js +++ b/src/g/shape/marker.js @@ -1,18 +1,18 @@ -var Util = require('../../util/index'); -var Shape = require('../core/shape'); -var Inside = require('./util/inside'); +const Util = require('../../util/index'); +const Shape = require('../core/shape'); +const Inside = require('./util/inside'); -var Marker = function(cfg) { +const Marker = function(cfg) { Marker.superclass.constructor.call(this, cfg); }; Marker.Symbols = { // 圆 - circle: function(x, y, r, ctx) { + circle(x, y, r, ctx) { ctx.arc(x, y, r, 0, Math.PI * 2, false); }, // 正方形 - square: function(x, y, r, ctx) { + square(x, y, r, ctx) { ctx.moveTo(x - r, y - r); ctx.lineTo(x + r, y - r); ctx.lineTo(x + r, y + r); @@ -20,7 +20,7 @@ Marker.Symbols = { ctx.closePath(); }, // 菱形 - diamond: function(x, y, r, ctx) { + diamond(x, y, r, ctx) { ctx.moveTo(x - r, y); ctx.lineTo(x, y - r); ctx.lineTo(x + r, y); @@ -28,9 +28,9 @@ Marker.Symbols = { ctx.closePath(); }, // 三角形 - triangle: function(x, y, r, ctx) { - var diffX = r / 0.966; - var diffY = r; + triangle(x, y, r, ctx) { + const diffX = r / 0.966; + const diffY = r; ctx.moveTo(x, y - r); ctx.lineTo(x + diffX, y + diffY); ctx.lineTo(x - diffX, y + diffY); @@ -38,8 +38,8 @@ Marker.Symbols = { }, // 倒三角形 'triangle-down': function(x, y, r, ctx) { - var diffX = r / 0.966; - var diffY = r; + const diffX = r / 0.966; + const diffY = r; ctx.moveTo(x, y + r); ctx.lineTo(x + diffX, y - diffY); ctx.lineTo(x - diffX, y - diffY); @@ -58,20 +58,20 @@ Util.augment(Marker, { type: 'marker', canFill: true, canStroke: true, - getDefaultAttrs: function() { + getDefaultAttrs() { return { x: 0, y: 0, lineWidth: 1 }; }, - calculateBox: function() { - var attrs = this.__attrs; - var cx = attrs.x; - var cy = attrs.y; - var r = attrs.radius; - var lineWidth = attrs.lineWidth; - var halfWidth = lineWidth / 2 + r; + calculateBox() { + const attrs = this.__attrs; + const cx = attrs.x; + const cy = attrs.y; + const r = attrs.radius; + const lineWidth = attrs.lineWidth; + const halfWidth = lineWidth / 2 + r; return { minX: cx - halfWidth, minY: cy - halfWidth, @@ -79,20 +79,20 @@ Util.augment(Marker, { maxY: cy + halfWidth }; }, - isPointInPath: function(x, y) { - var attrs = this.__attrs; - var cx = attrs.x; - var cy = attrs.y; - var r = attrs.radius; + isPointInPath(x, y) { + const attrs = this.__attrs; + const cx = attrs.x; + const cy = attrs.y; + const r = attrs.radius; return Inside.circle(cx, cy, r, x, y); }, - createPath: function(context) { - var attrs = this.__attrs; - var x = attrs.x; - var y = attrs.y; - var r = attrs.radius; - var symbol = attrs.symbol || 'circle'; - var method; + createPath(context) { + const attrs = this.__attrs; + const x = attrs.x; + const y = attrs.y; + const r = attrs.radius; + const symbol = attrs.symbol || 'circle'; + let method; if (Util.isFunction(symbol)) { method = symbol; } else { diff --git a/src/g/shape/math/arc.js b/src/g/shape/math/arc.js index 03736e925..f7a587edb 100644 --- a/src/g/shape/math/arc.js +++ b/src/g/shape/math/arc.js @@ -3,8 +3,8 @@ * @author hankaiai@126.com * @ignore */ -var Vector2 = require('@ali/g-matrix').Vector2; -var Util = require('../../../util/index'); +const Vector2 = require('@ali/g-matrix').Vector2; +const Util = require('../../../util/index'); function circlePoint(cx, cy, r, angle) { return { @@ -14,8 +14,8 @@ function circlePoint(cx, cy, r, angle) { } function angleNearTo(angle, min, max, out) { - var v1; - var v2; + let v1; + let v2; if (out) { if (angle < min) { v1 = min - angle; @@ -33,7 +33,7 @@ function angleNearTo(angle, min, max, out) { } function nearAngle(angle, startAngle, endAngle, clockwise) { - var plus = 0; + let plus = 0; if (endAngle - startAngle >= Math.PI * 2) { plus = Math.PI * 2; } @@ -65,29 +65,29 @@ function nearAngle(angle, startAngle, endAngle, clockwise) { } function arcProjectPoint(cx, cy, r, startAngle, endAngle, clockwise, x, y, out) { - var v = new Vector2(x, y); - var v0 = new Vector2(cx, cy); - var v1 = new Vector2(1, 0); - var subv = Vector2.sub(v, v0); - var angle = v1.angleTo(subv); + const v = new Vector2(x, y); + const v0 = new Vector2(cx, cy); + const v1 = new Vector2(1, 0); + const subv = Vector2.sub(v, v0); + let angle = v1.angleTo(subv); angle = nearAngle(angle, startAngle, endAngle, clockwise); - var vpoint = new Vector2(r * Math.cos(angle) + cx, r * Math.sin(angle) + cy); + const vpoint = new Vector2(r * Math.cos(angle) + cx, r * Math.sin(angle) + cy); if (out) { out.x = vpoint.x; out.y = vpoint.y; } - var d = v.distanceTo(vpoint); + const d = v.distanceTo(vpoint); return d; } function arcBox(cx, cy, r, startAngle, endAngle, clockwise) { - var angleRight = 0; - var angleBottom = Math.PI / 2; - var angleLeft = Math.PI; - var angleTop = Math.PI * 3 / 2; - var points = []; - var angle = nearAngle(angleRight, startAngle, endAngle, clockwise); + const angleRight = 0; + const angleBottom = Math.PI / 2; + const angleLeft = Math.PI; + const angleTop = Math.PI * 3 / 2; + const points = []; + let angle = nearAngle(angleRight, startAngle, endAngle, clockwise); if (angle === angleRight) { points.push(circlePoint(cx, cy, r, angleRight)); } @@ -109,10 +109,10 @@ function arcBox(cx, cy, r, startAngle, endAngle, clockwise) { points.push(circlePoint(cx, cy, r, startAngle)); points.push(circlePoint(cx, cy, r, endAngle)); - var minX = Infinity; - var maxX = -Infinity; - var minY = Infinity; - var maxY = -Infinity; + let minX = Infinity; + let maxX = -Infinity; + let minY = Infinity; + let maxY = -Infinity; Util.each(points, function(point) { if (minX > point.x) { minX = point.x; @@ -129,17 +129,17 @@ function arcBox(cx, cy, r, startAngle, endAngle, clockwise) { }); return { - minX: minX, - minY: minY, - maxX: maxX, - maxY: maxY + minX, + minY, + maxX, + maxY }; } module.exports = { - nearAngle: nearAngle, - projectPoint: function(cx, cy, r, startAngle, endAngle, clockwise, x, y) { - var rst = {}; + nearAngle, + projectPoint(cx, cy, r, startAngle, endAngle, clockwise, x, y) { + const rst = {}; arcProjectPoint(cx, cy, r, startAngle, endAngle, clockwise, x, y, rst); return rst; }, diff --git a/src/g/shape/math/cubic.js b/src/g/shape/math/cubic.js index 319e2ed55..805ed1614 100644 --- a/src/g/shape/math/cubic.js +++ b/src/g/shape/math/cubic.js @@ -3,16 +3,16 @@ * @author hankaiai@126.com * @ignore */ -var Vector2 = require('@ali/g-matrix').Vector2; -var Util = require('../../../util/index'); +const Vector2 = require('@ali/g-matrix').Vector2; +const Util = require('../../../util/index'); function cubicAt(p0, p1, p2, p3, t) { - var onet = 1 - t; + const onet = 1 - t; return onet * onet * (onet * p3 + 3 * t * p2) + t * t * (t * p0 + 3 * onet * p1); } function cubicDerivativeAt(p0, p1, p2, p3, t) { - var onet = 1 - t; + const onet = 1 - t; return 3 * ( ((p1 - p0) * onet + 2 * (p2 - p1) * t) * onet + (p3 - p2) * t * t @@ -20,18 +20,18 @@ function cubicDerivativeAt(p0, p1, p2, p3, t) { } function cubicProjectPoint(x1, y1, x2, y2, x3, y3, x4, y4, x, y, out) { - var t; - var interval = 0.005; - var d = Infinity; - var _t; - var v1; - var d1; - var d2; - var v2; - var prev; - var next; - var EPSILON = 0.0001; - var v0 = new Vector2(x, y); + let t; + let interval = 0.005; + let d = Infinity; + let _t; + let v1; + let d1; + let d2; + let v2; + let prev; + let next; + const EPSILON = 0.0001; + const v0 = new Vector2(x, y); for (_t = 0; _t < 1; _t += 0.05) { v1 = new Vector2( @@ -48,7 +48,7 @@ function cubicProjectPoint(x1, y1, x2, y2, x3, y3, x4, y4, x, y, out) { } d = Infinity; - for (var i = 0; i < 32; i++) { + for (let i = 0; i < 32; i++) { if (interval < EPSILON) { break; } @@ -92,13 +92,13 @@ function cubicProjectPoint(x1, y1, x2, y2, x3, y3, x4, y4, x, y, out) { } function cubicExtrema(p0, p1, p2, p3) { - var a = 3 * p0 - 9 * p1 + 9 * p2 - 3 * p3; - var b = 6 * p1 - 12 * p2 + 6 * p3; - var c = 3 * p2 - 3 * p3; - var extrema = []; - var t1; - var t2; - var discSqrt; + const a = 3 * p0 - 9 * p1 + 9 * p2 - 3 * p3; + const b = 6 * p1 - 12 * p2 + 6 * p3; + const c = 3 * p2 - 3 * p3; + const extrema = []; + let t1; + let t2; + let discSqrt; if (Util.isNumberEqual(a, 0)) { if (!Util.isNumberEqual(b, 0)) { @@ -108,7 +108,7 @@ function cubicExtrema(p0, p1, p2, p3) { } } } else { - var disc = b * b - 4 * a * c; + const disc = b * b - 4 * a * c; if (Util.isNumberEqual(disc, 0)) { extrema.push(-b / (2 * a)); } else if (disc > 0) { @@ -127,8 +127,8 @@ function cubicExtrema(p0, p1, p2, p3) { } function base3(t, p1, p2, p3, p4) { - var t1 = -3 * p1 + 9 * p2 - 9 * p3 + 3 * p4; - var t2 = t * t1 + 6 * p1 - 12 * p2 + 6 * p3; + const t1 = -3 * p1 + 9 * p2 - 9 * p3 + 3 * p4; + const t2 = t * t1 + 6 * p1 - 12 * p2 + 6 * p3; return t * t2 - 3 * p1 + 3 * p2; } @@ -137,16 +137,16 @@ function cubiclLen(x1, y1, x2, y2, x3, y3, x4, y4, z) { z = 1; } z = z > 1 ? 1 : z < 0 ? 0 : z; - var z2 = z / 2; - var n = 12; - var Tvalues = [-0.1252, 0.1252, -0.3678, 0.3678, -0.5873, 0.5873, -0.7699, 0.7699, -0.9041, 0.9041, -0.9816, 0.9816]; - var Cvalues = [0.2491, 0.2491, 0.2335, 0.2335, 0.2032, 0.2032, 0.1601, 0.1601, 0.1069, 0.1069, 0.0472, 0.0472]; - var sum = 0; - for (var i = 0; i < n; i++) { - var ct = z2 * Tvalues[i] + z2; - var xbase = base3(ct, x1, x2, x3, x4); - var ybase = base3(ct, y1, y2, y3, y4); - var comb = xbase * xbase + ybase * ybase; + const z2 = z / 2; + const n = 12; + const Tvalues = [ -0.1252, 0.1252, -0.3678, 0.3678, -0.5873, 0.5873, -0.7699, 0.7699, -0.9041, 0.9041, -0.9816, 0.9816 ]; + const Cvalues = [ 0.2491, 0.2491, 0.2335, 0.2335, 0.2032, 0.2032, 0.1601, 0.1601, 0.1069, 0.1069, 0.0472, 0.0472 ]; + let sum = 0; + for (let i = 0; i < n; i++) { + const ct = z2 * Tvalues[i] + z2; + const xbase = base3(ct, x1, x2, x3, x4); + const ybase = base3(ct, y1, y2, y3, y4); + const comb = xbase * xbase + ybase * ybase; sum += Cvalues[i] * Math.sqrt(comb); } return z2 * sum; @@ -156,8 +156,8 @@ function cubiclLen(x1, y1, x2, y2, x3, y3, x4, y4, z) { module.exports = { at: cubicAt, derivativeAt: cubicDerivativeAt, - projectPoint: function(x1, y1, x2, y2, x3, y3, x4, y4, x, y) { - var rst = {}; + projectPoint(x1, y1, x2, y2, x3, y3, x4, y4, x, y) { + const rst = {}; cubicProjectPoint(x1, y1, x2, y2, x3, y3, x4, y4, x, y, rst); return rst; }, diff --git a/src/g/shape/math/ellipse.js b/src/g/shape/math/ellipse.js index c982816ad..7bfd2310d 100644 --- a/src/g/shape/math/ellipse.js +++ b/src/g/shape/math/ellipse.js @@ -5,16 +5,16 @@ * @ignore */ module.exports = { - xAt: function(psi, rx, ry, cx, t) { + xAt(psi, rx, ry, cx, t) { return rx * Math.cos(psi) * Math.cos(t) - ry * Math.sin(psi) * Math.sin(t) + cx; }, - yAt: function(psi, rx, ry, cy, t) { + yAt(psi, rx, ry, cy, t) { return rx * Math.sin(psi) * Math.cos(t) + ry * Math.cos(psi) * Math.sin(t) + cy; }, - xExtrema: function(psi, rx, ry) { + xExtrema(psi, rx, ry) { return Math.atan((-ry / rx) * Math.tan(psi)); }, - yExtrema: function(psi, rx, ry) { + yExtrema(psi, rx, ry) { return Math.atan((ry / (rx * Math.tan(psi)))); } }; diff --git a/src/g/shape/math/line.js b/src/g/shape/math/line.js index 120db4bf6..a4217b7d1 100644 --- a/src/g/shape/math/line.js +++ b/src/g/shape/math/line.js @@ -3,29 +3,29 @@ * @author hankaiai@126.com * @ignore */ -var Vector2 = require('@ali/g-matrix').Vector2; +const Vector2 = require('@ali/g-matrix').Vector2; module.exports = { - at: function(p1, p2, t) { + at(p1, p2, t) { return (p2 - p1) * t + p1; }, - pointDistance: function(x1, y1, x2, y2, x, y) { - var d = new Vector2(x2 - x1, y2 - y1); + pointDistance(x1, y1, x2, y2, x, y) { + const d = new Vector2(x2 - x1, y2 - y1); if (d.isZero()) { return NaN; } - var u = d.vertical(); + const u = d.vertical(); u.normalize(); - var a = new Vector2(x - x1, y - y1); + const a = new Vector2(x - x1, y - y1); return Math.abs(a.dot(u)); }, - box: function(x1, y1, x2, y2, lineWidth) { - var halfWidth = lineWidth / 2; - var minX = Math.min(x1, x2); - var maxX = Math.max(x1, x2); - var minY = Math.min(y1, y2); - var maxY = Math.max(y1, y2); + box(x1, y1, x2, y2, lineWidth) { + const halfWidth = lineWidth / 2; + const minX = Math.min(x1, x2); + const maxX = Math.max(x1, x2); + const minY = Math.min(y1, y2); + const maxY = Math.max(y1, y2); return { minX: minX - halfWidth, @@ -34,7 +34,7 @@ module.exports = { maxY: maxY + halfWidth }; }, - len: function(x1, y1, x2, y2) { + len(x1, y1, x2, y2) { return Math.sqrt((x2 - x1) * (x2 - x1) + (y2 - y1) * (y2 - y1)); } }; diff --git a/src/g/shape/math/quadratic.js b/src/g/shape/math/quadratic.js index dbc2a29ba..026fa9984 100644 --- a/src/g/shape/math/quadratic.js +++ b/src/g/shape/math/quadratic.js @@ -3,26 +3,26 @@ * @author hankaiai@126.com * @ignore */ -var Vector2 = require('@ali/g-matrix').Vector2; -var Util = require('../../../util/index'); +const Vector2 = require('@ali/g-matrix').Vector2; +const Util = require('../../../util/index'); function quadraticAt(p0, p1, p2, t) { - var onet = 1 - t; + const onet = 1 - t; return onet * (onet * p0 + 2 * t * p1) + t * t * p2; } function quadraticProjectPoint(x1, y1, x2, y2, x3, y3, x, y, out) { - var t; - var interval = 0.005; - var d = Infinity; - var d1; - var v1; - var v2; - var _t; - var d2; - var i; - var EPSILON = 0.0001; - var v0 = new Vector2(x, y); + let t; + let interval = 0.005; + let d = Infinity; + let d1; + let v1; + let v2; + let _t; + let d2; + let i; + const EPSILON = 0.0001; + const v0 = new Vector2(x, y); for (_t = 0; _t < 1; _t += 0.05) { v1 = new Vector2( @@ -43,8 +43,8 @@ function quadraticProjectPoint(x1, y1, x2, y2, x3, y3, x, y, out) { break; } - var prev = t - interval; - var next = t + interval; + const prev = t - interval; + const next = t + interval; v1 = new Vector2( quadraticAt(x1, x2, x3, prev), @@ -83,21 +83,21 @@ function quadraticProjectPoint(x1, y1, x2, y2, x3, y3, x, y, out) { function quadraticExtrema(p0, p1, p2) { - var a = p0 + p2 - 2 * p1; + const a = p0 + p2 - 2 * p1; if (Util.isNumberEqual(a, 0)) { - return [0.5]; + return [ 0.5 ]; } - var rst = (p0 - p1) / a; + const rst = (p0 - p1) / a; if (rst <= 1 && rst >= 0) { - return [rst]; + return [ rst ]; } return []; } module.exports = { at: quadraticAt, - projectPoint: function(x1, y1, x2, y2, x3, y3, x, y) { - var rst = {}; + projectPoint(x1, y1, x2, y2, x3, y3, x, y) { + const rst = {}; quadraticProjectPoint(x1, y1, x2, y2, x3, y3, x, y, rst); return rst; }, diff --git a/src/g/shape/path.js b/src/g/shape/path.js index 70f896f08..61951f524 100644 --- a/src/g/shape/path.js +++ b/src/g/shape/path.js @@ -5,17 +5,17 @@ * @see http://www.w3.org/TR/2011/REC-SVG11-20110816/paths.html#PathData * @ignore */ -var Util = require('../../util/index'); -var Shape = require('../core/shape'); -var PathSegment = require('./util/pathSegment'); -var Format = require('../format'); -var Arrow = require('./util/arrow'); -var pathUtil = require('@ali/g-path-util'); -var CubicMath = require('./math/cubic'); -var Matrix = require('@ali/g-matrix'); -var Vector2 = Matrix.Vector2; +const Util = require('../../util/index'); +const Shape = require('../core/shape'); +const PathSegment = require('./util/pathSegment'); +const Format = require('../format'); +const Arrow = require('./util/arrow'); +const pathUtil = require('@ali/g-path-util'); +const CubicMath = require('./math/cubic'); +const Matrix = require('@ali/g-matrix'); +const Vector2 = Matrix.Vector2; -var Path = function(cfg) { +const Path = function(cfg) { Path.superclass.constructor.call(this, cfg); }; @@ -32,21 +32,21 @@ Util.augment(Path, { canFill: true, canStroke: true, type: 'path', - getDefaultAttrs: function() { + getDefaultAttrs() { return { lineWidth: 1 }; }, - __afterSetAttrPath: function(path) { - var self = this; + __afterSetAttrPath(path) { + const self = this; if (Util.isNil(path)) { self.setSilent('segments', null); self.setSilent('box', undefined); return; } - var pathArray = Format.parsePath(path); - var preSegment; - var segments = []; + const pathArray = Format.parsePath(path); + let preSegment; + const segments = []; if (!Util.isArray(pathArray) || pathArray.length === 0 || @@ -55,9 +55,9 @@ Util.augment(Path, { ) { return; } - var count = pathArray.length; - for (var i = 0; i < pathArray.length; i++) { - var item = pathArray[i]; + const count = pathArray.length; + for (let i = 0; i < pathArray.length; i++) { + const item = pathArray[i]; preSegment = new PathSegment(item, preSegment, i === count - 1); segments.push(preSegment); } @@ -65,29 +65,29 @@ Util.augment(Path, { self.set('tCache', null); this.setSilent('box', null); }, - __afterSetAttrAll: function(objs) { + __afterSetAttrAll(objs) { if (objs.path) { this.__afterSetAttrPath(objs.path); } }, - calculateBox: function() { - var self = this; - var attrs = self.__attrs; - var lineWidth = attrs.lineWidth; - var lineAppendWidth = attrs.lineAppendWidth || 0; - var segments = self.get('segments'); + calculateBox() { + const self = this; + const attrs = self.__attrs; + let lineWidth = attrs.lineWidth; + const lineAppendWidth = attrs.lineAppendWidth || 0; + const segments = self.get('segments'); if (!segments) { return null; } lineWidth += lineAppendWidth; - var minX = Infinity; - var maxX = -Infinity; - var minY = Infinity; - var maxY = -Infinity; + let minX = Infinity; + let maxX = -Infinity; + let minY = Infinity; + let maxY = -Infinity; Util.each(segments, function(segment) { segment.getBBox(lineWidth); - var box = segment.box; + const box = segment.box; if (box) { if (box.minX < minX) { minX = box.minX; @@ -107,16 +107,16 @@ Util.augment(Path, { } }); return { - minX: minX, - minY: minY, - maxX: maxX, - maxY: maxY + minX, + minY, + maxX, + maxY }; }, - isPointInPath: function(x, y) { - var self = this; - var fill = self.hasFill(); - var stroke = self.hasStroke(); + isPointInPath(x, y) { + const self = this; + const fill = self.hasFill(); + const stroke = self.hasStroke(); if (fill && stroke) { return self.__isPointInFill(x, y) || self.__isPointInStroke(x, y); @@ -132,21 +132,21 @@ Util.augment(Path, { return false; }, - __isPointInFill: function(x, y) { - var self = this; - var context = self.get('context'); + __isPointInFill(x, y) { + const self = this; + const context = self.get('context'); if (!context) return undefined; self.createPath(); return context.isPointInPath(x, y); }, - __isPointInStroke: function(x, y) { - var self = this; - var segments = self.get('segments'); - var attrs = self.__attrs; - var lineWidth = attrs.lineWidth; - var appendWidth = attrs.lineAppendWidth || 0; + __isPointInStroke(x, y) { + const self = this; + const segments = self.get('segments'); + const attrs = self.__attrs; + let lineWidth = attrs.lineWidth; + const appendWidth = attrs.lineAppendWidth || 0; lineWidth += appendWidth; - for (var i = 0, l = segments.length; i < l; i++) { + for (let i = 0, l = segments.length; i < l; i++) { if (segments[i].isInside(x, y, lineWidth)) { return true; } @@ -154,15 +154,15 @@ Util.augment(Path, { return false; }, - __setTcache: function() { - var totalLength = 0; - var tempLength = 0; - var tCache = []; - var segmentT; - var segmentL; - var segmentN; - var l; - var curve = this.curve; + __setTcache() { + let totalLength = 0; + let tempLength = 0; + const tCache = []; + let segmentT; + let segmentL; + let segmentN; + let l; + const curve = this.curve; if (!curve) { return; @@ -191,20 +191,16 @@ Util.augment(Path, { this.tCache = tCache; }, - __calculateCurve: function() { - var self = this; - var attrs = self.__attrs; - var path = attrs.path; + __calculateCurve() { + const self = this; + const attrs = self.__attrs; + const path = attrs.path; this.curve = pathUtil.toCurve(path); }, - getPoint: function(t) { - var tCache = this.tCache; - var curve; - var subt; - var index; - var seg; - var l; - var nextSeg; + getPoint(t) { + let tCache = this.tCache; + let subt; + let index; if (!tCache) { this.__calculateCurve(); @@ -212,7 +208,7 @@ Util.augment(Path, { tCache = this.tCache; } - curve = this.curve; + const curve = this.curve; if (!tCache) { if (curve) { @@ -229,38 +225,38 @@ Util.augment(Path, { index = i; } }); - seg = curve[index]; + const seg = curve[index]; if (Util.isNil(seg) || Util.isNil(index)) { return null; } - l = seg.length; - nextSeg = curve[index + 1]; + const l = seg.length; + const nextSeg = curve[index + 1]; return { x: CubicMath.at(seg[l - 2], nextSeg[1], nextSeg[3], nextSeg[5], 1 - subt), y: CubicMath.at(seg[l - 1], nextSeg[2], nextSeg[4], nextSeg[6], 1 - subt) }; }, - createPath: function(context) { - var self = this; - var attrs = self.__attrs; - var segments = self.get('segments'); - var lineWidth = attrs.lineWidth; - var arrow = attrs.arrow; + createPath(context) { + const self = this; + const attrs = self.__attrs; + const segments = self.get('segments'); + const lineWidth = attrs.lineWidth; + const arrow = attrs.arrow; if (!Util.isArray(segments)) return; context = context || self.get('context'); context.beginPath(); - for (var i = 0, l = segments.length; i < l; i++) { + for (let i = 0, l = segments.length; i < l; i++) { if (i === l - 1 && arrow) { - var lastSeg = segments[i]; - var endTangent = segments[i].endTangent; - var endPoint = { + const lastSeg = segments[i]; + const endTangent = segments[i].endTangent; + const endPoint = { x: lastSeg.params[lastSeg.params.length - 1].x, y: lastSeg.params[lastSeg.params.length - 1].y }; if (lastSeg && Util.isFunction(endTangent)) { - var v = endTangent(); - var end = Arrow.getEndPoint(v, new Vector2(endPoint.x, endPoint.y), lineWidth); + const v = endTangent(); + const end = Arrow.getEndPoint(v, new Vector2(endPoint.x, endPoint.y), lineWidth); lastSeg.params[lastSeg.params.length - 1] = end; segments[i].draw(context); Arrow.makeArrow(context, v, end, lineWidth); diff --git a/src/g/shape/polygon.js b/src/g/shape/polygon.js index 47099f63a..aaa44912f 100644 --- a/src/g/shape/polygon.js +++ b/src/g/shape/polygon.js @@ -4,11 +4,11 @@ * @author hankaiai@126.com * @ignore */ -var Util = require('../../util/index'); -var Shape = require('../core/shape'); -var Inside = require('./util/inside'); +const Util = require('../../util/index'); +const Shape = require('../core/shape'); +const Inside = require('./util/inside'); -var Polygon = function(cfg) { +const Polygon = function(cfg) { Polygon.superclass.constructor.call(this, cfg); }; @@ -23,27 +23,27 @@ Util.augment(Polygon, { canFill: true, canStroke: true, type: 'polygon', - getDefaultAttrs: function() { + getDefaultAttrs() { return { lineWidth: 1 }; }, - calculateBox: function() { - var self = this; - var attrs = self.__attrs; - var points = attrs.points; - var lineWidth = attrs.lineWidth; + calculateBox() { + const self = this; + const attrs = self.__attrs; + const points = attrs.points; + const lineWidth = attrs.lineWidth; if (!points || points.length === 0) { return null; } - var minX = Infinity; - var minY = Infinity; - var maxX = -Infinity; - var maxY = -Infinity; + let minX = Infinity; + let minY = Infinity; + let maxX = -Infinity; + let maxY = -Infinity; Util.each(points, function(point) { - var x = point[0]; - var y = point[1]; + const x = point[0]; + const y = point[1]; if (x < minX) { minX = x; } @@ -60,7 +60,7 @@ Util.augment(Polygon, { } }); - var halfWidth = lineWidth / 2; + const halfWidth = lineWidth / 2; return { minX: minX - halfWidth, minY: minY - halfWidth, @@ -68,10 +68,10 @@ Util.augment(Polygon, { maxY: maxY + halfWidth }; }, - isPointInPath: function(x, y) { - var self = this; - var fill = self.hasFill(); - var stroke = self.hasStroke(); + isPointInPath(x, y) { + const self = this; + const fill = self.hasFill(); + const stroke = self.hasStroke(); if (fill && stroke) { return self.__isPointInFill(x, y) || self.__isPointInStroke(x, y); @@ -87,31 +87,31 @@ Util.augment(Polygon, { return false; }, - __isPointInFill: function(x, y) { - var self = this; - var context = self.get('context'); + __isPointInFill(x, y) { + const self = this; + const context = self.get('context'); self.createPath(); return context.isPointInPath(x, y); }, - __isPointInStroke: function(x, y) { - var self = this; - var attrs = self.__attrs; - var points = attrs.points; + __isPointInStroke(x, y) { + const self = this; + const attrs = self.__attrs; + const points = attrs.points; if (points.length < 2) { return false; } - var lineWidth = attrs.lineWidth; - var outPoints = points.slice(0); + const lineWidth = attrs.lineWidth; + const outPoints = points.slice(0); if (points.length >= 3) { outPoints.push(points[0]); } return Inside.polyline(outPoints, lineWidth, x, y); }, - createPath: function(context) { - var self = this; - var attrs = self.__attrs; - var points = attrs.points; + createPath(context) { + const self = this; + const attrs = self.__attrs; + const points = attrs.points; if (points.length < 2) { return; } diff --git a/src/g/shape/polyline.js b/src/g/shape/polyline.js index 211f656fc..bf9cf186e 100644 --- a/src/g/shape/polyline.js +++ b/src/g/shape/polyline.js @@ -4,15 +4,15 @@ * @author hankaiai@126.com * @ignore */ -var Util = require('../../util/index'); -var Shape = require('../core/shape'); -var Inside = require('./util/inside'); -var Arrow = require('./util/arrow'); -var LineMath = require('./math/line'); -var Matrix = require('@ali/g-matrix'); -var Vector2 = Matrix.Vector2; +const Util = require('../../util/index'); +const Shape = require('../core/shape'); +const Inside = require('./util/inside'); +const Arrow = require('./util/arrow'); +const LineMath = require('./math/line'); +const Matrix = require('@ali/g-matrix'); +const Vector2 = Matrix.Vector2; -var Polyline = function(cfg) { +const Polyline = function(cfg) { Polyline.superclass.constructor.call(this, cfg); }; @@ -29,28 +29,28 @@ Util.augment(Polyline, { canStroke: true, type: 'polyline', tCache: null, // 缓存各点的t - getDefaultAttrs: function() { + getDefaultAttrs() { return { lineWidth: 1, arrow: false }; }, - calculateBox: function() { - var self = this; - var attrs = self.__attrs; - var lineWidth = attrs.lineWidth; - var points = attrs.points; + calculateBox() { + const self = this; + const attrs = self.__attrs; + const lineWidth = attrs.lineWidth; + const points = attrs.points; if (!points || points.length === 0) { return null; } - var minX = Infinity; - var minY = Infinity; - var maxX = -Infinity; - var maxY = -Infinity; + let minX = Infinity; + let minY = Infinity; + let maxX = -Infinity; + let maxY = -Infinity; Util.each(points, function(point) { - var x = point[0]; - var y = point[1]; + const x = point[0]; + const y = point[1]; if (x < minX) { minX = x; } @@ -67,7 +67,7 @@ Util.augment(Polyline, { } }); - var halfWidth = lineWidth / 2; + const halfWidth = lineWidth / 2; return { minX: minX - halfWidth, minY: minY - halfWidth, @@ -75,15 +75,15 @@ Util.augment(Polyline, { maxY: maxY + halfWidth }; }, - __setTcache: function() { - var self = this; - var attrs = self.__attrs; - var points = attrs.points; - var totalLength = 0; - var tempLength = 0; - var tCache = []; - var segmentT; - var segmentL; + __setTcache() { + const self = this; + const attrs = self.__attrs; + const points = attrs.points; + let totalLength = 0; + let tempLength = 0; + const tCache = []; + let segmentT; + let segmentL; if (!points || points.length === 0) { return; } @@ -108,27 +108,27 @@ Util.augment(Polyline, { }); this.tCache = tCache; }, - isPointInPath: function(x, y) { - var self = this; - var attrs = self.__attrs; + isPointInPath(x, y) { + const self = this; + const attrs = self.__attrs; if (self.hasStroke()) { - var points = attrs.points; + const points = attrs.points; if (points.length < 2) { return false; } - var lineWidth = attrs.lineWidth; + const lineWidth = attrs.lineWidth; return Inside.polyline(points, lineWidth, x, y); } return false; }, - createPath: function(context) { - var self = this; - var attrs = self.__attrs; - var points = attrs.points; - var arrow = attrs.arrow; - var lineWidth = attrs.lineWidth; - var l; - var i; + createPath(context) { + const self = this; + const attrs = self.__attrs; + const points = attrs.points; + const arrow = attrs.arrow; + const lineWidth = attrs.lineWidth; + let l; + let i; if (points.length < 2) { return; @@ -140,20 +140,20 @@ Util.augment(Polyline, { context.lineTo(points[i][0], points[i][1]); } if (arrow) { - var v = new Vector2(points[l][0] - points[l - 1][0], points[l][1] - points[l - 1][1]); - var end = Arrow.getEndPoint(v, new Vector2(points[l][0], points[l][1]), lineWidth); + const v = new Vector2(points[l][0] - points[l - 1][0], points[l][1] - points[l - 1][1]); + const end = Arrow.getEndPoint(v, new Vector2(points[l][0], points[l][1]), lineWidth); context.lineTo(end.x, end.y); Arrow.makeArrow(context, v, end, lineWidth); } else { context.lineTo(points[l][0], points[l][1]); } }, - getPoint: function(t) { - var attrs = this.__attrs; - var points = attrs.points; - var tCache = this.tCache; - var subt; - var index; + getPoint(t) { + const attrs = this.__attrs; + const points = attrs.points; + let tCache = this.tCache; + let subt; + let index; if (!tCache) { this.__setTcache(); tCache = this.tCache; diff --git a/src/g/shape/quadratic.js b/src/g/shape/quadratic.js index 6f62f6a51..432c74a90 100644 --- a/src/g/shape/quadratic.js +++ b/src/g/shape/quadratic.js @@ -3,14 +3,14 @@ * @author hankaiai@126.com * @ignore */ -var Util = require('../../util/index'); -var Shape = require('../core/shape'); -var Inside = require('./util/inside'); -var Arrow = require('./util/arrow'); -var QuadraticMath = require('./math/quadratic'); -var Vector2 = require('@ali/g-matrix').Vector2; +const Util = require('../../util/index'); +const Shape = require('../core/shape'); +const Inside = require('./util/inside'); +const Arrow = require('./util/arrow'); +const QuadraticMath = require('./math/quadratic'); +const Vector2 = require('@ali/g-matrix').Vector2; -var Quadratic = function(cfg) { +const Quadratic = function(cfg) { Quadratic.superclass.constructor.call(this, cfg); }; @@ -27,20 +27,20 @@ Util.extend(Quadratic, Shape); Util.augment(Quadratic, { canStroke: true, type: 'quadratic', - getDefaultAttrs: function() { + getDefaultAttrs() { return { lineWidth: 1, arrow: false }; }, - calculateBox: function() { - var self = this; - var attrs = self.__attrs; - var p1 = attrs.p1; - var p2 = attrs.p2; - var p3 = attrs.p3; - var i; - var l; + calculateBox() { + const self = this; + const attrs = self.__attrs; + const p1 = attrs.p1; + const p2 = attrs.p2; + const p3 = attrs.p3; + let i; + let l; if ( Util.isNil(p1) || @@ -49,15 +49,15 @@ Util.augment(Quadratic, { ) { return null; } - var halfWidth = attrs.lineWidth / 2; + const halfWidth = attrs.lineWidth / 2; - var xDims = QuadraticMath.extrema(p1[0], p2[0], p3[0]); + const xDims = QuadraticMath.extrema(p1[0], p2[0], p3[0]); for (i = 0, l = xDims.length; i < l; i++) { xDims[i] = QuadraticMath.at(p1[0], p2[0], p3[0], xDims[i]); } xDims.push(p1[0], p3[0]); - var yDims = QuadraticMath.extrema(p1[1], p2[1], p3[1]); + const yDims = QuadraticMath.extrema(p1[1], p2[1], p3[1]); for (i = 0, l = yDims.length; i < l; i++) { yDims[i] = QuadraticMath.at(p1[1], p2[1], p3[1], yDims[i]); } @@ -70,13 +70,13 @@ Util.augment(Quadratic, { maxY: Math.max.apply(Math, yDims) + halfWidth }; }, - isPointInPath: function(x, y) { - var self = this; - var attrs = self.__attrs; - var p1 = attrs.p1; - var p2 = attrs.p2; - var p3 = attrs.p3; - var lineWidth = attrs.lineWidth; + isPointInPath(x, y) { + const self = this; + const attrs = self.__attrs; + const p1 = attrs.p1; + const p2 = attrs.p2; + const p3 = attrs.p3; + const lineWidth = attrs.lineWidth; return Inside.quadraticline( p1[0], p1[1], @@ -85,14 +85,14 @@ Util.augment(Quadratic, { lineWidth, x, y ); }, - createPath: function(context) { - var self = this; - var attrs = self.__attrs; - var p1 = attrs.p1; - var p2 = attrs.p2; - var p3 = attrs.p3; - var lineWidth = attrs.lineWidth; - var arrow = attrs.arrow; + createPath(context) { + const self = this; + const attrs = self.__attrs; + const p1 = attrs.p1; + const p2 = attrs.p2; + const p3 = attrs.p3; + const lineWidth = attrs.lineWidth; + const arrow = attrs.arrow; if ( Util.isNil(p1) || @@ -107,16 +107,16 @@ Util.augment(Quadratic, { if (arrow) { - var v = new Vector2(p3[0] - p2[0], p3[1] - p2[1]); - var end = Arrow.getEndPoint(v, new Vector2(p3[0], p3[1]), lineWidth); + const v = new Vector2(p3[0] - p2[0], p3[1] - p2[1]); + const end = Arrow.getEndPoint(v, new Vector2(p3[0], p3[1]), lineWidth); context.quadraticCurveTo(p2[0], p2[1], end.x, end.y); Arrow.makeArrow(context, v, end, lineWidth); } else { context.quadraticCurveTo(p2[0], p2[1], p3[0], p3[1]); } }, - getPoint: function(t) { - var attrs = this.__attrs; + getPoint(t) { + const attrs = this.__attrs; return { x: QuadraticMath.at(attrs.p1[0], attrs.p2[0], attrs.p3[0], t), y: QuadraticMath.at(attrs.p1[1], attrs.p2[1], attrs.p3[1], t) diff --git a/src/g/shape/rect.js b/src/g/shape/rect.js index 2ffd7d232..116837153 100644 --- a/src/g/shape/rect.js +++ b/src/g/shape/rect.js @@ -4,11 +4,11 @@ * @author hankaiai@126.com * @ignore */ -var Util = require('../../util/index'); -var Shape = require('../core/shape'); -var Inside = require('./util/inside'); +const Util = require('../../util/index'); +const Shape = require('../core/shape'); +const Inside = require('./util/inside'); -var Rect = function(cfg) { +const Rect = function(cfg) { Rect.superclass.constructor.call(this, cfg); }; @@ -27,22 +27,22 @@ Util.augment(Rect, { canFill: true, canStroke: true, type: 'rect', - getDefaultAttrs: function() { + getDefaultAttrs() { return { lineWidth: 1, radius: 0 }; }, - calculateBox: function() { - var self = this; - var attrs = self.__attrs; - var x = attrs.x; - var y = attrs.y; - var width = attrs.width; - var height = attrs.height; - var lineWidth = attrs.lineWidth; + calculateBox() { + const self = this; + const attrs = self.__attrs; + const x = attrs.x; + const y = attrs.y; + const width = attrs.width; + const height = attrs.height; + const lineWidth = attrs.lineWidth; - var halfWidth = lineWidth / 2; + const halfWidth = lineWidth / 2; return { minX: x - halfWidth, minY: y - halfWidth, @@ -50,10 +50,10 @@ Util.augment(Rect, { maxY: y + height + halfWidth }; }, - isPointInPath: function(x, y) { - var self = this; - var fill = self.hasFill(); - var stroke = self.hasStroke(); + isPointInPath(x, y) { + const self = this; + const fill = self.hasFill(); + const stroke = self.hasStroke(); if (fill && stroke) { return self.__isPointInFill(x, y) || self.__isPointInStroke(x, y); @@ -69,25 +69,25 @@ Util.augment(Rect, { return false; }, - __isPointInFill: function(x, y) { - var context = this.get('context'); + __isPointInFill(x, y) { + const context = this.get('context'); if (!context) return false; this.createPath(); return context.isPointInPath(x, y); }, - __isPointInStroke: function(x, y) { - var self = this; - var attrs = self.__attrs; - var rx = attrs.x; - var ry = attrs.y; - var width = attrs.width; - var height = attrs.height; - var radius = attrs.radius; - var lineWidth = attrs.lineWidth; + __isPointInStroke(x, y) { + const self = this; + const attrs = self.__attrs; + const rx = attrs.x; + const ry = attrs.y; + const width = attrs.width; + const height = attrs.height; + const radius = attrs.radius; + const lineWidth = attrs.lineWidth; if (radius === 0) { - var halfWidth = lineWidth / 2; + const halfWidth = lineWidth / 2; return Inside.line(rx - halfWidth, ry, rx + width + halfWidth, ry, lineWidth, x, y) || Inside.line(rx + width, ry - halfWidth, rx + width, ry + height + halfWidth, lineWidth, x, y) || Inside.line(rx + width + halfWidth, ry + height, rx - halfWidth, ry + height, lineWidth, x, y) || @@ -103,14 +103,14 @@ Util.augment(Rect, { Inside.arcline(rx + radius, ry + height - radius, radius, 0.5 * Math.PI, Math.PI, false, lineWidth, x, y) || Inside.arcline(rx + radius, ry + radius, radius, Math.PI, 1.5 * Math.PI, false, lineWidth, x, y); }, - createPath: function(context) { - var self = this; - var attrs = self.__attrs; - var x = attrs.x; - var y = attrs.y; - var width = attrs.width; - var height = attrs.height; - var radius = attrs.radius; + createPath(context) { + const self = this; + const attrs = self.__attrs; + const x = attrs.x; + const y = attrs.y; + const width = attrs.width; + const height = attrs.height; + const radius = attrs.radius; context = context || self.get('context'); context.beginPath(); diff --git a/src/g/shape/text.js b/src/g/shape/text.js index 5631b3edb..3fe5fb38d 100644 --- a/src/g/shape/text.js +++ b/src/g/shape/text.js @@ -4,12 +4,12 @@ * @author hankaiai@126.com * @ignore */ -var Util = require('../../util/index'); -var Shape = require('../core/shape'); -var Inside = require('./util/inside'); -var Common = require('../common'); +const Util = require('../../util/index'); +const Shape = require('../core/shape'); +const Inside = require('./util/inside'); +const Common = require('../common'); -var CText = function(cfg) { +const CText = function(cfg) { CText.superclass.constructor.call(this, cfg); }; @@ -34,7 +34,7 @@ Util.augment(CText, { canFill: true, canStroke: true, type: 'text', - getDefaultAttrs: function() { + getDefaultAttrs() { return { lineWidth: 1, lineCount: 1, @@ -47,64 +47,64 @@ Util.augment(CText, { textBaseline: 'bottom' }; }, - __assembleFont: function() { + __assembleFont() { // var self = this; - var attrs = this.__attrs; - var fontSize = attrs.fontSize; - var fontFamily = attrs.fontFamily; - var fontWeight = attrs.fontWeight; - var fontStyle = attrs.fontStyle; // self.attr('fontStyle'); - var fontVariant = attrs.fontVariant; // self.attr('fontVariant'); + const attrs = this.__attrs; + const fontSize = attrs.fontSize; + const fontFamily = attrs.fontFamily; + const fontWeight = attrs.fontWeight; + const fontStyle = attrs.fontStyle; // self.attr('fontStyle'); + const fontVariant = attrs.fontVariant; // self.attr('fontVariant'); // self.attr('font', [fontStyle, fontVariant, fontWeight, fontSize + 'px', fontFamily].join(' ')); - attrs.font = [fontStyle, fontVariant, fontWeight, fontSize + 'px', fontFamily].join(' '); + attrs.font = [ fontStyle, fontVariant, fontWeight, fontSize + 'px', fontFamily ].join(' '); }, - __afterSetAttrFontSize: function() { + __afterSetAttrFontSize() { /* this.attr({ height: this.__getTextHeight() }); */ this.__assembleFont(); }, - __afterSetAttrFontFamily: function() { + __afterSetAttrFontFamily() { this.__assembleFont(); }, - __afterSetAttrFontWeight: function() { + __afterSetAttrFontWeight() { this.__assembleFont(); }, - __afterSetAttrFontStyle: function() { + __afterSetAttrFontStyle() { this.__assembleFont(); }, - __afterSetAttrFontVariant: function() { + __afterSetAttrFontVariant() { this.__assembleFont(); }, - __afterSetAttrFont: function() { + __afterSetAttrFont() { // this.attr('width', this.measureText()); }, - __afterSetAttrText: function() { - var attrs = this.__attrs; - var text = attrs.text; - var textArr; + __afterSetAttrText() { + const attrs = this.__attrs; + const text = attrs.text; + let textArr; if (Util.isString(text) && (text.indexOf('\n') !== -1)) { textArr = text.split('\n'); - var lineCount = textArr.length; + const lineCount = textArr.length; attrs.lineCount = lineCount; attrs.textArr = textArr; } // attrs.height = this.__getTextHeight(); // attrs.width = this.measureText(); }, - __getTextHeight: function() { - var attrs = this.__attrs; - var lineCount = attrs.lineCount; - var fontSize = attrs.fontSize * 1; + __getTextHeight() { + const attrs = this.__attrs; + const lineCount = attrs.lineCount; + const fontSize = attrs.fontSize * 1; if (lineCount > 1) { - var spaceingY = this.__getSpaceingY(); + const spaceingY = this.__getSpaceingY(); return fontSize * lineCount + spaceingY * (lineCount - 1); } return fontSize; }, // 计算浪费,效率低,待优化 - __afterSetAttrAll: function(objs) { - var self = this; + __afterSetAttrAll(objs) { + const self = this; if ( 'fontSize' in objs || 'fontWeight' in objs || @@ -121,15 +121,15 @@ Util.augment(CText, { self.__afterSetAttrText(objs.text); } }, - isHitBox: function() { + isHitBox() { return false; }, - calculateBox: function() { - var self = this; - var attrs = self.__attrs; - var x = attrs.x; - var y = attrs.y; - var width = self.measureText(); // attrs.width + calculateBox() { + const self = this; + const attrs = self.__attrs; + const x = attrs.x; + const y = attrs.y; + const width = self.measureText(); // attrs.width if (!width) { // 如果width不存在,四点共其实点 return { @@ -139,12 +139,12 @@ Util.augment(CText, { maxY: y }; } - var height = self.__getTextHeight(); // attrs.height - var textAlign = attrs.textAlign; - var textBaseline = attrs.textBaseline; - var lineWidth = attrs.lineWidth; - var point = { - x: x, + const height = self.__getTextHeight(); // attrs.height + const textAlign = attrs.textAlign; + const textBaseline = attrs.textBaseline; + const lineWidth = attrs.lineWidth; + const point = { + x, y: y - height }; @@ -165,7 +165,7 @@ Util.augment(CText, { } this.set('startPoint', point); - var halfWidth = lineWidth / 2; + const halfWidth = lineWidth / 2; return { minX: point.x - halfWidth, minY: point.y - halfWidth, @@ -173,42 +173,42 @@ Util.augment(CText, { maxY: point.y + height + halfWidth }; }, - __getSpaceingY: function() { - var attrs = this.__attrs; - var lineHeight = attrs.lineHeight; - var fontSize = attrs.fontSize * 1; + __getSpaceingY() { + const attrs = this.__attrs; + const lineHeight = attrs.lineHeight; + const fontSize = attrs.fontSize * 1; return lineHeight ? (lineHeight - fontSize) : fontSize * 0.14; }, - isPointInPath: function(x, y) { - var self = this; - var box = self.getBBox(); + isPointInPath(x, y) { + const self = this; + const box = self.getBBox(); if (self.hasFill() || self.hasStroke()) { return Inside.box(box.minX, box.maxX, box.minY, box.maxY, x, y); } }, - drawInner: function(context) { - var self = this; - var attrs = self.__attrs; - var text = attrs.text; + drawInner(context) { + const self = this; + const attrs = self.__attrs; + const text = attrs.text; if (!text) { return; } - var textArr = attrs.textArr; - var fontSize = attrs.fontSize * 1; - var spaceingY = self.__getSpaceingY(); - var x = attrs.x; - var y = attrs.y; - var textBaseline = attrs.textBaseline; - var height; + const textArr = attrs.textArr; + const fontSize = attrs.fontSize * 1; + const spaceingY = self.__getSpaceingY(); + const x = attrs.x; + const y = attrs.y; + const textBaseline = attrs.textBaseline; + let height; if (textArr) { - var box = self.getBBox(); + const box = self.getBBox(); height = box.maxY - box.minY; } - var subY; + let subY; context.beginPath(); if (self.hasFill()) { - var fillOpacity = attrs.fillOpacity; + const fillOpacity = attrs.fillOpacity; if (!Util.isNil(fillOpacity) && fillOpacity !== 1) { context.globalAlpha = fillOpacity; } @@ -237,17 +237,17 @@ Util.augment(CText, { } } }, - measureText: function() { - var self = this; - var attrs = self.__attrs; - var text = attrs.text; - var font = attrs.font; - var textArr = attrs.textArr; - var measureWidth; - var width = 0; + measureText() { + const self = this; + const attrs = self.__attrs; + const text = attrs.text; + const font = attrs.font; + const textArr = attrs.textArr; + let measureWidth; + let width = 0; if (Util.isNil(text)) return undefined; - var context = Common.backupContext; + const context = Common.backupContext; context.save(); context.font = font; if (textArr) { diff --git a/src/g/shape/util/arrow.js b/src/g/shape/util/arrow.js index e25f9e5c7..8d4b5aced 100644 --- a/src/g/shape/util/arrow.js +++ b/src/g/shape/util/arrow.js @@ -1,12 +1,12 @@ -var Vector2 = require('@ali/g-matrix').Vector2; +const Vector2 = require('@ali/g-matrix').Vector2; -var THETA = Math.PI / 6; +const THETA = Math.PI / 6; function calculatePoints(vector, end, lineWidth) { - var angle = (new Vector2(1, 0)).angleTo(vector); - var downAngle = angle - THETA; - var upAngle = angle + THETA; - var length = 6 + lineWidth * 3; + const angle = (new Vector2(1, 0)).angleTo(vector); + const downAngle = angle - THETA; + const upAngle = angle + THETA; + const length = 6 + lineWidth * 3; return [ { x: end.x - length * Math.cos(downAngle), @@ -31,13 +31,13 @@ function makeArrow(context, vector, end, lineWidth) { } function getEndPoint(vector, end, lineWidth) { - var miterLimit = lineWidth / Math.sin(THETA); + const miterLimit = lineWidth / Math.sin(THETA); vector.setLength(miterLimit / 2); end.sub(vector); return end; } module.exports = { - makeArrow: makeArrow, - getEndPoint: getEndPoint + makeArrow, + getEndPoint }; diff --git a/src/g/shape/util/inside.js b/src/g/shape/util/inside.js index 0c76fcc2f..ed755b3bc 100644 --- a/src/g/shape/util/inside.js +++ b/src/g/shape/util/inside.js @@ -4,35 +4,35 @@ * @author hankaiai@126.com * @ignore */ -var Line = require('../math/line'); -var Quadratic = require('../math/quadratic'); -var Cubic = require('../math/cubic'); -var Arc = require('../math/arc'); +const Line = require('../math/line'); +const Quadratic = require('../math/quadratic'); +const Cubic = require('../math/cubic'); +const Arc = require('../math/arc'); module.exports = { - line: function(x1, y1, x2, y2, lineWidth, x, y) { - var box = Line.box(x1, y1, x2, y2, lineWidth); + line(x1, y1, x2, y2, lineWidth, x, y) { + const box = Line.box(x1, y1, x2, y2, lineWidth); if (!this.box(box.minX, box.maxX, box.minY, box.maxY, x, y)) { return false; } - var d = Line.pointDistance(x1, y1, x2, y2, x, y); + const d = Line.pointDistance(x1, y1, x2, y2, x, y); if (isNaN(d)) { return false; } return d <= lineWidth / 2; }, - polyline: function(points, lineWidth, x, y) { - var l = points.length - 1; + polyline(points, lineWidth, x, y) { + const l = points.length - 1; if (l < 1) { return false; } - for (var i = 0; i < l; i ++) { - var x1 = points[i][0]; - var y1 = points[i][1]; - var x2 = points[i + 1][0]; - var y2 = points[i + 1][1]; + for (let i = 0; i < l; i++) { + const x1 = points[i][0]; + const y1 = points[i][1]; + const x2 = points[i + 1][0]; + const y2 = points[i + 1][1]; if (this.line(x1, y1, x2, y2, lineWidth, x, y)) { return true; @@ -41,22 +41,22 @@ module.exports = { return false; }, - cubicline: function(x1, y1, x2, y2, x3, y3, x4, y4, lineWidth, x, y) { + cubicline(x1, y1, x2, y2, x3, y3, x4, y4, lineWidth, x, y) { return Cubic.pointDistance(x1, y1, x2, y2, x3, y3, x4, y4, x, y) <= lineWidth / 2; }, - quadraticline: function(x1, y1, x2, y2, x3, y3, lineWidth, x, y) { + quadraticline(x1, y1, x2, y2, x3, y3, lineWidth, x, y) { return Quadratic.pointDistance(x1, y1, x2, y2, x3, y3, x, y) <= lineWidth / 2; }, - arcline: function(cx, cy, r, startAngle, endAngle, clockwise, lineWidth, x, y) { + arcline(cx, cy, r, startAngle, endAngle, clockwise, lineWidth, x, y) { return Arc.pointDistance(cx, cy, r, startAngle, endAngle, clockwise, x, y) <= lineWidth / 2; }, - rect: function(rx, ry, width, height, x, y) { + rect(rx, ry, width, height, x, y) { return rx <= x && x <= rx + width && ry <= y && y <= ry + height; }, - circle: function(cx, cy, r, x, y) { + circle(cx, cy, r, x, y) { return Math.pow(x - cx, 2) + Math.pow(y - cy, 2) <= Math.pow(r, 2); }, - box: function(minX, maxX, minY, maxY, x, y) { + box(minX, maxX, minY, maxY, x, y) { return minX <= x && x <= maxX && minY <= y && y <= maxY; } }; diff --git a/src/g/shape/util/pathSegment.js b/src/g/shape/util/pathSegment.js index d2914d529..f74d819bf 100644 --- a/src/g/shape/util/pathSegment.js +++ b/src/g/shape/util/pathSegment.js @@ -4,18 +4,18 @@ * @author hankaiai@126.com * @ignore */ -var Util = require('../../../util/index'); -var Inside = require('./inside'); -var Cubic = require('../math/cubic'); -var Quadratic = require('../math/quadratic'); -var Ellipse = require('../math/ellipse'); -var Matrix = require('@ali/g-matrix'); -var Vector2 = Matrix.Vector2; -var Vector3 = Matrix.Vector3; -var Matrix3 = Matrix.Matrix3; +const Util = require('../../../util/index'); +const Inside = require('./inside'); +const Cubic = require('../math/cubic'); +const Quadratic = require('../math/quadratic'); +const Ellipse = require('../math/ellipse'); +const Matrix = require('@ali/g-matrix'); +const Vector2 = Matrix.Vector2; +const Vector3 = Matrix.Vector3; +const Matrix3 = Matrix.Matrix3; -var ARR_CMD = ['m', 'l', 'c', 'a', 'q', 'h', 'v', 't', 's', 'z']; +const ARR_CMD = [ 'm', 'l', 'c', 'a', 'q', 'h', 'v', 't', 's', 'z' ]; function toAbsolute(x, y, curPoint) { // 获取绝对坐标 return { @@ -44,21 +44,21 @@ function vAngle(u, v) { } function getArcParams(point1, point2, fa, fs, rx, ry, psiDeg) { - var psi = Util.mod(Util.toRadian(psiDeg), Math.PI * 2); - var x1 = point1.x; - var y1 = point1.y; - var x2 = point2.x; - var y2 = point2.y; - var xp = Math.cos(psi) * (x1 - x2) / 2.0 + Math.sin(psi) * (y1 - y2) / 2.0; - var yp = -1 * Math.sin(psi) * (x1 - x2) / 2.0 + Math.cos(psi) * (y1 - y2) / 2.0; - var lambda = (xp * xp) / (rx * rx) + (yp * yp) / (ry * ry); + const psi = Util.mod(Util.toRadian(psiDeg), Math.PI * 2); + const x1 = point1.x; + const y1 = point1.y; + const x2 = point2.x; + const y2 = point2.y; + const xp = Math.cos(psi) * (x1 - x2) / 2.0 + Math.sin(psi) * (y1 - y2) / 2.0; + const yp = -1 * Math.sin(psi) * (x1 - x2) / 2.0 + Math.cos(psi) * (y1 - y2) / 2.0; + const lambda = (xp * xp) / (rx * rx) + (yp * yp) / (ry * ry); if (lambda > 1) { rx *= Math.sqrt(lambda); ry *= Math.sqrt(lambda); } - var f = Math.sqrt((((rx * rx) * (ry * ry)) - ((rx * rx) * (yp * yp)) - ((ry * ry) * (xp * xp))) / ((rx * rx) * (yp * yp) + (ry * ry) * (xp * xp))); + let f = Math.sqrt((((rx * rx) * (ry * ry)) - ((rx * rx) * (yp * yp)) - ((ry * ry) * (xp * xp))) / ((rx * rx) * (yp * yp) + (ry * ry) * (xp * xp))); if (fa === fs) { f *= -1; @@ -67,16 +67,16 @@ function getArcParams(point1, point2, fa, fs, rx, ry, psiDeg) { f = 0; } - var cxp = f * rx * yp / ry; - var cyp = f * -ry * xp / rx; + const cxp = f * rx * yp / ry; + const cyp = f * -ry * xp / rx; - var cx = (x1 + x2) / 2.0 + Math.cos(psi) * cxp - Math.sin(psi) * cyp; - var cy = (y1 + y2) / 2.0 + Math.sin(psi) * cxp + Math.cos(psi) * cyp; + const cx = (x1 + x2) / 2.0 + Math.cos(psi) * cxp - Math.sin(psi) * cyp; + const cy = (y1 + y2) / 2.0 + Math.sin(psi) * cxp + Math.cos(psi) * cyp; - var theta = vAngle([1, 0], [(xp - cxp) / rx, (yp - cyp) / ry]); - var u = [(xp - cxp) / rx, (yp - cyp) / ry]; - var v = [(-1 * xp - cxp) / rx, (-1 * yp - cyp) / ry]; - var dTheta = vAngle(u, v); + const theta = vAngle([ 1, 0 ], [ (xp - cxp) / rx, (yp - cyp) / ry ]); + const u = [ (xp - cxp) / rx, (yp - cyp) / ry ]; + const v = [ (-1 * xp - cxp) / rx, (-1 * yp - cyp) / ry ]; + let dTheta = vAngle(u, v); if (vRatio(u, v) <= -1) { dTheta = Math.PI; @@ -90,35 +90,35 @@ function getArcParams(point1, point2, fa, fs, rx, ry, psiDeg) { if (fs === 1 && dTheta < 0) { dTheta = dTheta + 2 * Math.PI; } - return [point1, cx, cy, rx, ry, theta, dTheta, psi, fs]; + return [ point1, cx, cy, rx, ry, theta, dTheta, psi, fs ]; } -var PathSegment = function(item, preSegment, isLast) { +const PathSegment = function(item, preSegment, isLast) { this.preSegment = preSegment; this.isLast = isLast; this.init(item, preSegment); }; Util.augment(PathSegment, { - init: function(item, preSegment) { - var command = item[0]; + init(item, preSegment) { + const command = item[0]; preSegment = preSegment || { endPoint: { x: 0, y: 0 } }; - var relative = ARR_CMD.indexOf(command) >= 0; // /[a-z]/.test(command); - var cmd = relative ? command.toUpperCase() : command; - var p = item; - var point1; - var point2; - var point3; - var point; - var preEndPoint = preSegment.endPoint; + const relative = ARR_CMD.indexOf(command) >= 0; // /[a-z]/.test(command); + const cmd = relative ? command.toUpperCase() : command; + const p = item; + let point1; + let point2; + let point3; + let point; + const preEndPoint = preSegment.endPoint; - var p1 = p[1]; - var p2 = p[2]; + const p1 = p[1]; + const p2 = p[2]; switch (cmd) { default: break; case 'M': @@ -131,7 +131,7 @@ Util.augment(PathSegment, { }; } this.command = 'M'; - this.params = [preEndPoint, point]; + this.params = [ preEndPoint, point ]; this.subStart = point; this.endPoint = point; break; @@ -145,7 +145,7 @@ Util.augment(PathSegment, { }; } this.command = 'L'; - this.params = [preEndPoint, point]; + this.params = [ preEndPoint, point ]; this.subStart = preSegment.subStart; this.endPoint = point; if (this.isLast) { @@ -164,7 +164,7 @@ Util.augment(PathSegment, { }; } this.command = 'L'; - this.params = [preEndPoint, point]; + this.params = [ preEndPoint, point ]; this.subStart = preSegment.subStart; this.endPoint = point; this.endTangent = function() { @@ -181,7 +181,7 @@ Util.augment(PathSegment, { }; } this.command = 'L'; - this.params = [preEndPoint, point]; + this.params = [ preEndPoint, point ]; this.subStart = preSegment.subStart; this.endPoint = point; this.endTangent = function() { @@ -203,7 +203,7 @@ Util.augment(PathSegment, { }; } this.command = 'Q'; - this.params = [preEndPoint, point1, point2]; + this.params = [ preEndPoint, point1, point2 ]; this.subStart = preSegment.subStart; this.endPoint = point2; this.endTangent = function() { @@ -222,7 +222,7 @@ Util.augment(PathSegment, { if (preSegment.command === 'Q') { point1 = toSymmetry(preSegment.params[1], preEndPoint); this.command = 'Q'; - this.params = [preEndPoint, point1, point2]; + this.params = [ preEndPoint, point1, point2 ]; this.subStart = preSegment.subStart; this.endPoint = point2; this.endTangent = function() { @@ -230,7 +230,7 @@ Util.augment(PathSegment, { }; } else { this.command = 'TL'; - this.params = [preEndPoint, point2]; + this.params = [ preEndPoint, point2 ]; this.subStart = preSegment.subStart; this.endPoint = point2; this.endTangent = function() { @@ -259,7 +259,7 @@ Util.augment(PathSegment, { }; } this.command = 'C'; - this.params = [preEndPoint, point1, point2, point3]; + this.params = [ preEndPoint, point1, point2, point3 ]; this.subStart = preSegment.subStart; this.endPoint = point3; this.endTangent = function() { @@ -283,7 +283,7 @@ Util.augment(PathSegment, { if (preSegment.command === 'C') { point1 = toSymmetry(preSegment.params[2], preEndPoint); this.command = 'C'; - this.params = [preEndPoint, point1, point2, point3]; + this.params = [ preEndPoint, point1, point2, point3 ]; this.subStart = preSegment.subStart; this.endPoint = point3; this.endTangent = function() { @@ -291,7 +291,7 @@ Util.augment(PathSegment, { }; } else { this.command = 'SQ'; - this.params = [preEndPoint, point2, point3]; + this.params = [ preEndPoint, point2, point3 ]; this.subStart = preSegment.subStart; this.endPoint = point3; this.endTangent = function() { @@ -299,12 +299,12 @@ Util.augment(PathSegment, { }; } break; - case 'A': - var rx = p1; - var ry = p2; - var psi = p[3]; - var fa = p[4]; - var fs = p[5]; + case 'A': { + const rx = p1; + const ry = p2; + const psi = p[3]; + const fa = p[4]; + const fs = p[5]; if (relative) { point = toAbsolute(p[6], p[7], preEndPoint); } else { @@ -319,18 +319,20 @@ Util.augment(PathSegment, { this.subStart = preSegment.subStart; this.endPoint = point; break; - case 'Z': + } + case 'Z': { this.command = 'Z'; - this.params = [preEndPoint, preSegment.subStart]; + this.params = [ preEndPoint, preSegment.subStart ]; this.subStart = preSegment.subStart; this.endPoint = preSegment.subStart; + } } }, - isInside: function(x, y, lineWidth) { - var self = this; - var command = self.command; - var params = self.params; - var box = self.box; + isInside(x, y, lineWidth) { + const self = this; + const command = self.command; + const params = self.params; + const box = self.box; if (box) { if (!Inside.box(box.minX, box.maxX, box.minY, box.maxY, x, y)) { return false; @@ -356,7 +358,7 @@ Util.augment(PathSegment, { params[2].x, params[2].y, lineWidth, x, y ); - case 'C': + case 'C': { return Inside.cubicline( params[0].x, params[0].y, params[1].x, params[1].y, @@ -364,37 +366,39 @@ Util.augment(PathSegment, { params[3].x, params[3].y, lineWidth, x, y ); - case 'A': - var p = params; - var cx = p[1]; - var cy = p[2]; - var rx = p[3]; - var ry = p[4]; - var theta = p[5]; - var dTheta = p[6]; - var psi = p[7]; - var fs = p[8]; + } + case 'A': { + let p = params; + const cx = p[1]; + const cy = p[2]; + const rx = p[3]; + const ry = p[4]; + const theta = p[5]; + const dTheta = p[6]; + const psi = p[7]; + const fs = p[8]; - var r = (rx > ry) ? rx : ry; - var scaleX = (rx > ry) ? 1 : rx / ry; - var scaleY = (rx > ry) ? ry / rx : 1; + const r = (rx > ry) ? rx : ry; + const scaleX = (rx > ry) ? 1 : rx / ry; + const scaleY = (rx > ry) ? ry / rx : 1; p = new Vector3(x, y, 1); - var m = new Matrix3(); + const m = new Matrix3(); m.translate(-cx, -cy); m.rotate(-psi); m.scale(1 / scaleX, 1 / scaleY); p.applyMatrix(m); return Inside.arcline(0, 0, r, theta, theta + dTheta, 1 - fs, lineWidth, p.x, p.y); + } } return false; }, - draw: function(context) { - var command = this.command; - var params = this.params; - var point1; - var point2; - var point3; + draw(context) { + const command = this.command; + const params = this.params; + let point1; + let point2; + let point3; switch (command) { default: break; @@ -417,22 +421,22 @@ Util.augment(PathSegment, { point3 = params[3]; context.bezierCurveTo(point1.x, point1.y, point2.x, point2.y, point3.x, point3.y); break; - case 'A': - var p = params; - var p1 = p[1]; - var p2 = p[2]; - var cx = p1; - var cy = p2; - var rx = p[3]; - var ry = p[4]; - var theta = p[5]; - var dTheta = p[6]; - var psi = p[7]; - var fs = p[8]; + case 'A': { + const p = params; + const p1 = p[1]; + const p2 = p[2]; + const cx = p1; + const cy = p2; + const rx = p[3]; + const ry = p[4]; + const theta = p[5]; + const dTheta = p[6]; + const psi = p[7]; + const fs = p[8]; - var r = (rx > ry) ? rx : ry; - var scaleX = (rx > ry) ? 1 : rx / ry; - var scaleY = (rx > ry) ? ry / rx : 1; + const r = (rx > ry) ? rx : ry; + const scaleX = (rx > ry) ? 1 : rx / ry; + const scaleY = (rx > ry) ? ry / rx : 1; context.translate(cx, cy); context.rotate(psi); @@ -442,18 +446,19 @@ Util.augment(PathSegment, { context.rotate(-psi); context.translate(-cx, -cy); break; + } case 'Z': context.closePath(); break; } }, - getBBox: function(lineWidth) { - var halfWidth = lineWidth / 2; - var params = this.params; - var yDims; - var xDims; - var i; - var l; + getBBox(lineWidth) { + const halfWidth = lineWidth / 2; + const params = this.params; + let yDims; + let xDims; + let i; + let l; switch (this.command) { default: @@ -506,26 +511,26 @@ Util.augment(PathSegment, { maxY: Math.max.apply(Math, yDims) + halfWidth }; break; - case 'A': + case 'A': { // todo 待优化 - var p = params; - var cx = p[1]; - var cy = p[2]; - var rx = p[3]; - var ry = p[4]; - var theta = p[5]; - var dTheta = p[6]; - var psi = p[7]; - var fs = p[8]; - var start = theta; - var end = theta + dTheta; + const p = params; + const cx = p[1]; + const cy = p[2]; + const rx = p[3]; + const ry = p[4]; + const theta = p[5]; + const dTheta = p[6]; + const psi = p[7]; + const fs = p[8]; + const start = theta; + const end = theta + dTheta; - var xDim = Ellipse.xExtrema(psi, rx, ry); - var minX = Infinity; - var maxX = -Infinity; - var xs = [start, end]; + const xDim = Ellipse.xExtrema(psi, rx, ry); + let minX = Infinity; + let maxX = -Infinity; + const xs = [ start, end ]; for (i = -Math.PI * 2; i <= Math.PI * 2; i += Math.PI) { - var xAngle = xDim + i; + const xAngle = xDim + i; if (fs === 1) { if (start < xAngle && xAngle < end) { xs.push(xAngle); @@ -538,7 +543,7 @@ Util.augment(PathSegment, { } for (i = 0, l = xs.length; i < l; i++) { - var x = Ellipse.xAt(psi, rx, ry, cx, xs[i]); + const x = Ellipse.xAt(psi, rx, ry, cx, xs[i]); if (x < minX) { minX = x; } @@ -547,12 +552,12 @@ Util.augment(PathSegment, { } } - var yDim = Ellipse.yExtrema(psi, rx, ry); - var minY = Infinity; - var maxY = -Infinity; - var ys = [start, end]; + const yDim = Ellipse.yExtrema(psi, rx, ry); + let minY = Infinity; + let maxY = -Infinity; + const ys = [ start, end ]; for (i = -Math.PI * 2; i <= Math.PI * 2; i += Math.PI) { - var yAngle = yDim + i; + const yAngle = yDim + i; if (fs === 1) { if (start < yAngle && yAngle < end) { ys.push(yAngle); @@ -565,7 +570,7 @@ Util.augment(PathSegment, { } for (i = 0, l = ys.length; i < l; i++) { - var y = Ellipse.yAt(psi, rx, ry, cy, ys[i]); + const y = Ellipse.yAt(psi, rx, ry, cy, ys[i]); if (y < minY) { minY = y; } @@ -580,6 +585,7 @@ Util.augment(PathSegment, { maxY: maxY + halfWidth }; break; + } } } }); diff --git a/src/mouse-event.js b/src/mouse-event.js index 4cff126cb..794500972 100644 --- a/src/mouse-event.js +++ b/src/mouse-event.js @@ -1,5 +1,5 @@ -import Util from './util/index'; -import Event from '@ali/g-event'; +const Util = require('./util/index'); +const Event = require('@ali/g-event'); const MouseEvent = function(canvas) { this.canvas = canvas; @@ -9,21 +9,21 @@ const MouseEvent = function(canvas) { }; Util.augment(MouseEvent, { - tryTrigger: function(element, event) { + tryTrigger(element, event) { if (element.__listeners) { element.trigger(event); } else { return; } }, - getCurrent: function(e) { + getCurrent(e) { const canvas = this.canvas; const point = canvas.getPointByClient(e.clientX, e.clientY); this.point = point; this.pre = this.current; this.current = canvas.getShape(point.x, point.y); }, - mousemove: function(e) { + mousemove(e) { this.getCurrent(e); const point = this.point; const canvas = this.canvas; @@ -70,7 +70,7 @@ Util.augment(MouseEvent, { } } }, - mousedown: function(e) { + mousedown(e) { const point = this.point; const canvas = this.canvas; @@ -96,7 +96,7 @@ Util.augment(MouseEvent, { this.tryTrigger(this.current, mousedown); } }, - mouseup: function(e) { + mouseup(e) { const point = this.point; const canvas = this.canvas; if (canvas.has('canvas-mouseup')) { @@ -119,7 +119,7 @@ Util.augment(MouseEvent, { this.tryTrigger(this.current, mouseup); } }, - click: function(e) { + click(e) { this.getCurrent(e); const point = this.point; const canvas = this.canvas; @@ -144,7 +144,7 @@ Util.augment(MouseEvent, { this.tryTrigger(this.current, click); } }, - dblclick: function(e) { + dblclick(e) { const point = this.point; const canvas = this.canvas; @@ -170,7 +170,7 @@ Util.augment(MouseEvent, { this.tryTrigger(this.current, dblclick); } }, - mouseout: function(e) { + mouseout(e) { const point = this.point; const canvas = this.canvas; @@ -180,7 +180,7 @@ Util.augment(MouseEvent, { canvasmouseleave.currentTarget = canvas; this.tryTrigger(canvas, canvasmouseleave); }, - mouseover: function(e) { + mouseover(e) { const canvas = this.canvas; const canvasmouseenter = new Event('canvas-mouseenter', e, true, true); diff --git a/src/util/common.js b/src/util/common.js index 636a9fa0b..60ee9b5c9 100644 --- a/src/util/common.js +++ b/src/util/common.js @@ -1,43 +1,26 @@ -import { - isFunction, - isObject, - isBoolean, - isNil, - isString, - isArray, - isEmpty, - uniqueId, - clone, - assign, - merge, - upperFirst, - pull, - forEach, - toArray, -} from 'lodash'; - const PRECISION = 0.00001; // 常量,据的精度,小于这个精度认为是0 const RADIAN = Math.PI / 180; const DEGREE = 180 / Math.PI; module.exports = { - isFunction, - isObject, - isBoolean, - isNil, - isString, - isArray, - isEmpty, // isBlank - uniqueId, - clone, - assign, // simpleMix - merge, // mix - upperFirst, // ucfirst - remove: pull, - each: forEach, + isFunction: require('lodash/isFunction'), + isObject: require('lodash/isObject'), + isBoolean: require('lodash/isBoolean'), + isNil: require('lodash/isNil'), + isString: require('lodash/isString'), + isArray: require('lodash/isArray'), + isEmpty: require('lodash/isEmpty'), // isBlank + uniqueId: require('lodash/uniqueId'), + clone: require('lodash/clone'), + assign: require('lodash/assign'), // simpleMix + merge: require('lodash/merge'), // mix + upperFirst: require('lodash/upperFirst'), // ucfirst + remove: require('lodash/pull'), + each: require('lodash/forEach'), + toArray: require('lodash/toArray'), extend(subclass, superclass, overrides, staticOverrides) { - //如果只提供父类构造函数,则自动生成子类构造函数 - if (!isFunction(superclass)) { + // 如果只提供父类构造函数,则自动生成子类构造函数 + if (!this.isFunction(superclass)) { overrides = superclass; superclass = subclass; subclass = function() {}; @@ -60,21 +43,21 @@ module.exports = { return o; }; - const superObj = create(superclass.prototype, subclass); //new superclass(),//实例化父类作为子类的prototype - subclass.prototype = merge(superObj, subclass.prototype); //指定子类的prototype + const superObj = create(superclass.prototype, subclass); // new superclass(),//实例化父类作为子类的prototype + subclass.prototype = this.merge(superObj, subclass.prototype); // 指定子类的prototype subclass.superclass = create(superclass.prototype, superclass); - merge(superObj, overrides); - merge(subclass, staticOverrides); + this.merge(superObj, overrides); + this.merge(subclass, staticOverrides); return subclass; }, augment(c) { - const args = toArray(arguments); + const args = this.toArray(arguments); for (let i = 1; i < args.length; i++) { let obj = args[i]; - if (isFunction(obj)) { + if (this.isFunction(obj)) { obj = obj.prototype; } - merge(c.prototype, obj); + this.merge(c.prototype, obj); } }, /** @@ -96,7 +79,7 @@ module.exports = { }, /** * 获取弧度对应的角度 - * @param {Number} rad 弧度 + * @param {Number} radian 弧度 * @return {Number} 角度 **/ toDegree(radian) { @@ -104,10 +87,11 @@ module.exports = { }, /** * 广义取模运算 - * @param {Number} v 被取模的值 + * @param {Number} n 被取模的值 * @param {Number} m 模 + * @return {Number} 返回n 被 m 取模的结果 */ mod(n, m) { - return ( ( n % m ) + m ) % m; + return ((n % m) + m) % m; } }; diff --git a/src/util/dom.js b/src/util/dom.js index accbbb520..a4c4b9ee9 100644 --- a/src/util/dom.js +++ b/src/util/dom.js @@ -2,21 +2,16 @@ const TABLE = document.createElement('table'); const TABLE_TR = document.createElement('tr'); const FRAGMENT_REG = /^\s*<(\w+|!)[^>]*>/; const CONTAINERS = { - 'tr': document.createElement('tbody'), - 'tbody': TABLE, - 'thead': TABLE, - 'tfoot': TABLE, - 'td': TABLE_TR, - 'th': TABLE_TR, + tr: document.createElement('tbody'), + tbody: TABLE, + thead: TABLE, + tfoot: TABLE, + td: TABLE_TR, + th: TABLE_TR, '*': document.createElement('div') }; module.exports = { - /** - * 计算BoundingClientRect - * @param {HTMLElement} DOM 节点 - * @return {Object} DOM 节点 - */ getBoundingClientRect(node) { const rect = node.getBoundingClientRect(); const top = document.documentElement.clientTop; @@ -30,7 +25,7 @@ module.exports = { }, /** * 获取样式 - * @param {Object} DOM节点 + * @param {Object} dom DOM节点 * @param {String} name 样式名 * @return {String} 属性值 */ @@ -40,14 +35,8 @@ module.exports = { } return dom.currentStyle[name]; }, - /** - * 修改CSS - * @param {Object} DOM - * @param {Object} CSS键值对 - * @return {Object} DOM - */ modiCSS(dom, css) { - for (let key in css) { + for (const key in css) { if (css.hasOwnProperty(key)) { dom.style[key] = css[key]; } @@ -69,9 +58,6 @@ module.exports = { container.innerHTML = '' + str; return container.childNodes[0]; }, - /** - * 获取屏幕像素比 - */ getRatio() { return window.devicePixelRatio ? window.devicePixelRatio : 2; }, @@ -81,7 +67,7 @@ module.exports = { * @return {Number} 宽度 */ getWidth(el) { - let width = Util.getStyle(el, 'width'); + let width = this.getStyle(el, 'width'); if (width === 'auto') { width = el.offsetWidth; } @@ -89,11 +75,11 @@ module.exports = { }, /** * 获取高度 - * @param {HTMLElement} el dom节点 + * @param {HTMLElement} el dom节点 * @return {Number} 高度 */ getHeight(el) { - let height = Util.getStyle(el, 'height'); + let height = this.getStyle(el, 'height'); if (height === 'auto') { height = el.offsetHeight; } @@ -101,23 +87,23 @@ module.exports = { }, /** * 获取外层高度 - * @param {HTMLElement} el dom节点 + * @param {HTMLElement} el dom节点 * @return {Number} 高度 */ getOuterHeight(el) { - const height = Util.getHeight(el); - const bTop = parseFloat(Util.getStyle(el, 'borderTopWidth')) || 0; - const pTop = parseFloat(Util.getStyle(el, 'paddingTop')); - const pBottom = parseFloat(Util.getStyle(el, 'paddingBottom')); - const bBottom = parseFloat(Util.getStyle(el, 'borderBottomWidth')) || 0; + const height = this.getHeight(el); + const bTop = parseFloat(this.getStyle(el, 'borderTopWidth')) || 0; + const pTop = parseFloat(this.getStyle(el, 'paddingTop')); + const pBottom = parseFloat(this.getStyle(el, 'paddingBottom')); + const bBottom = parseFloat(this.getStyle(el, 'borderBottomWidth')) || 0; return height + bTop + bBottom + pTop + pBottom; }, /** * TODO: 应该移除的 * 添加时间监听器 - * @param {object} DOM对象 - * @param {Object} 事件名 - * @param {funtion} 回调函数 + * @param {Object} target DOM对象 + * @param {Object} eventType 事件名 + * @param {Funtion} callback 回调函数 * @return {Object} 返回对象 */ addEventListener(target, eventType, callback) { diff --git a/src/util/index.js b/src/util/index.js index ec8c06d90..2dde46b67 100644 --- a/src/util/index.js +++ b/src/util/index.js @@ -1,20 +1,15 @@ -import CommonUtil from './common'; -import DomUtil from './dom'; +const CommonUtil = require('./common'); +const DomUtil = require('./dom'); const Util = {}; CommonUtil.merge(Util, CommonUtil, DomUtil, { - /** - * 混合方法 适用CFG模式 - * @param {Array} arr 数组 - * @return {Array} map后的数组 - */ mixin(c, mixins) { const Param = c.CFG ? 'CFG' : 'ATTRS'; if (c && mixins) { c._mixins = mixins; c[Param] = c[Param] || {}; - let temp = {}; + const temp = {}; Util.each(mixins, function(mixin) { Util.augment(c, mixin); const attrs = mixin[Param]; @@ -24,7 +19,7 @@ CommonUtil.merge(Util, CommonUtil, DomUtil, { }); c[Param] = Util.merge(temp, c[Param]); } - }, + } }); module.exports = Util; diff --git a/src/util/matrix.js b/src/util/matrix.js index 147290f8d..2ded9d9e9 100644 --- a/src/util/matrix.js +++ b/src/util/matrix.js @@ -35,6 +35,7 @@ module.exports = { * @param {Number} sy y缩放 * @param {Number} x 坐标点 * @param {Number} y 坐标点 + * @return {Matrix} 返回变换后的矩阵 */ scale(m, sx, sy, x, y) { m = m.clone(); @@ -49,6 +50,7 @@ module.exports = { * @param {Number} r 旋转角度,用弧度表示 * @param {Number} x 坐标点 * @param {Number} y 坐标点 + * @return {Matrix} 返回变换后的矩阵 */ rotate(m, r, x, y) { m = m.clone(); @@ -60,7 +62,7 @@ module.exports = { /** * 判断是否是3阶矩阵 * @param {Object} m 矩阵 - * @return {Boolean} + * @return {Boolean} 返回是否是三阶矩阵 */ isMatrix3(m) { return m.type === 'matrix3'; diff --git a/test/support/mocha.css b/test/support/mocha.css new file mode 100644 index 000000000..ec96b003c --- /dev/null +++ b/test/support/mocha.css @@ -0,0 +1,326 @@ +@charset "utf-8"; + +body { + margin:0; +} + +#mocha { + font: 20px/1.5 "Helvetica Neue", Helvetica, Arial, sans-serif; + margin: 60px 50px; +} + +#mocha ul, +#mocha li { + margin: 0; + padding: 0; +} + +#mocha ul { + list-style: none; +} + +#mocha h1, +#mocha h2 { + margin: 0; +} + +#mocha h1 { + margin-top: 15px; + font-size: 1em; + font-weight: 200; +} + +#mocha h1 a { + text-decoration: none; + color: inherit; +} + +#mocha h1 a:hover { + text-decoration: underline; +} + +#mocha .suite .suite h1 { + margin-top: 0; + font-size: .8em; +} + +#mocha .hidden { + display: none; +} + +#mocha h2 { + font-size: 12px; + font-weight: normal; + cursor: pointer; +} + +#mocha .suite { + margin-left: 15px; +} + +#mocha .test { + margin-left: 15px; + overflow: hidden; +} + +#mocha .test.pending:hover h2::after { + content: '(pending)'; + font-family: arial, sans-serif; +} + +#mocha .test.pass.medium .duration { + background: #c09853; +} + +#mocha .test.pass.slow .duration { + background: #b94a48; +} + +#mocha .test.pass::before { + content: '✓'; + font-size: 12px; + display: block; + float: left; + margin-right: 5px; + color: #00d6b2; +} + +#mocha .test.pass .duration { + font-size: 9px; + margin-left: 5px; + padding: 2px 5px; + color: #fff; + -webkit-box-shadow: inset 0 1px 1px rgba(0,0,0,.2); + -moz-box-shadow: inset 0 1px 1px rgba(0,0,0,.2); + box-shadow: inset 0 1px 1px rgba(0,0,0,.2); + -webkit-border-radius: 5px; + -moz-border-radius: 5px; + -ms-border-radius: 5px; + -o-border-radius: 5px; + border-radius: 5px; +} + +#mocha .test.pass.fast .duration { + display: none; +} + +#mocha .test.pending { + color: #0b97c4; +} + +#mocha .test.pending::before { + content: '◦'; + color: #0b97c4; +} + +#mocha .test.fail { + color: #c00; +} + +#mocha .test.fail pre { + color: black; +} + +#mocha .test.fail::before { + content: '✖'; + font-size: 12px; + display: block; + float: left; + margin-right: 5px; + color: #c00; +} + +#mocha .test pre.error { + color: #c00; + max-height: 300px; + overflow: auto; +} + +#mocha .test .html-error { + overflow: auto; + color: black; + line-height: 1.5; + display: block; + float: left; + clear: left; + font: 12px/1.5 monaco, monospace; + margin: 5px; + padding: 15px; + border: 1px solid #eee; + max-width: 85%; /*(1)*/ + max-width: -webkit-calc(100% - 42px); + max-width: -moz-calc(100% - 42px); + max-width: calc(100% - 42px); /*(2)*/ + max-height: 300px; + word-wrap: break-word; + border-bottom-color: #ddd; + -webkit-box-shadow: 0 1px 3px #eee; + -moz-box-shadow: 0 1px 3px #eee; + box-shadow: 0 1px 3px #eee; + -webkit-border-radius: 3px; + -moz-border-radius: 3px; + border-radius: 3px; +} + +#mocha .test .html-error pre.error { + border: none; + -webkit-border-radius: 0; + -moz-border-radius: 0; + border-radius: 0; + -webkit-box-shadow: 0; + -moz-box-shadow: 0; + box-shadow: 0; + padding: 0; + margin: 0; + margin-top: 18px; + max-height: none; +} + +/** + * (1): approximate for browsers not supporting calc + * (2): 42 = 2*15 + 2*10 + 2*1 (padding + margin + border) + * ^^ seriously + */ +#mocha .test pre { + display: block; + float: left; + clear: left; + font: 12px/1.5 monaco, monospace; + margin: 5px; + padding: 15px; + border: 1px solid #eee; + max-width: 85%; /*(1)*/ + max-width: -webkit-calc(100% - 42px); + max-width: -moz-calc(100% - 42px); + max-width: calc(100% - 42px); /*(2)*/ + word-wrap: break-word; + border-bottom-color: #ddd; + -webkit-box-shadow: 0 1px 3px #eee; + -moz-box-shadow: 0 1px 3px #eee; + box-shadow: 0 1px 3px #eee; + -webkit-border-radius: 3px; + -moz-border-radius: 3px; + border-radius: 3px; +} + +#mocha .test h2 { + position: relative; +} + +#mocha .test a.replay { + position: absolute; + top: 3px; + right: 0; + text-decoration: none; + vertical-align: middle; + display: block; + width: 15px; + height: 15px; + line-height: 15px; + text-align: center; + background: #eee; + font-size: 15px; + -webkit-border-radius: 15px; + -moz-border-radius: 15px; + border-radius: 15px; + -webkit-transition:opacity 200ms; + -moz-transition:opacity 200ms; + -o-transition:opacity 200ms; + transition: opacity 200ms; + opacity: 0.3; + color: #888; +} + +#mocha .test:hover a.replay { + opacity: 1; +} + +#mocha-report.pass .test.fail { + display: none; +} + +#mocha-report.fail .test.pass { + display: none; +} + +#mocha-report.pending .test.pass, +#mocha-report.pending .test.fail { + display: none; +} +#mocha-report.pending .test.pass.pending { + display: block; +} + +#mocha-error { + color: #c00; + font-size: 1.5em; + font-weight: 100; + letter-spacing: 1px; +} + +#mocha-stats { + position: fixed; + top: 15px; + right: 10px; + font-size: 12px; + margin: 0; + color: #888; + z-index: 1; +} + +#mocha-stats .progress { + float: right; + padding-top: 0; + + /** + * Set safe initial values, so mochas .progress does not inherit these + * properties from Bootstrap .progress (which causes .progress height to + * equal line height set in Bootstrap). + */ + height: auto; + -webkit-box-shadow: none; + -moz-box-shadow: none; + box-shadow: none; + background-color: initial; +} + +#mocha-stats em { + color: black; +} + +#mocha-stats a { + text-decoration: none; + color: inherit; +} + +#mocha-stats a:hover { + border-bottom: 1px solid #eee; +} + +#mocha-stats li { + display: inline-block; + margin: 0 5px; + list-style: none; + padding-top: 11px; +} + +#mocha-stats canvas { + width: 40px; + height: 40px; +} + +#mocha code .comment { color: #ddd; } +#mocha code .init { color: #2f6fad; } +#mocha code .string { color: #5890ad; } +#mocha code .keyword { color: #8a6343; } +#mocha code .number { color: #2f6fad; } + +@media screen and (max-device-width: 480px) { + #mocha { + margin: 60px 0px; + } + + #mocha #stats { + position: absolute; + } +} diff --git a/test/support/mocha.opts b/test/support/mocha.opts new file mode 100644 index 000000000..e1a1991ca --- /dev/null +++ b/test/support/mocha.opts @@ -0,0 +1,3 @@ +--preload test/support/preload.js +--require-main test/support/requireMain.js +--reporter HTML diff --git a/test/support/preload.js b/test/support/preload.js new file mode 100644 index 000000000..0d2e39f06 --- /dev/null +++ b/test/support/preload.js @@ -0,0 +1,14 @@ +const { + remote + // ipcRenderer: ipc +} = require('electron'); +const path = remote.require('path'); +const fs = remote.require('fs'); + +// add stylesheet for mocha HTML reporter +if (!document.getElementById('mocha-style')) { + const style = document.createElement('style'); + style.id = 'mocha-style'; + style.innerHTML = fs.readFileSync(path.resolve(process.cwd(), './test/support/mocha.css'), 'utf8'); + document.head.appendChild(style); +} diff --git a/test/support/renderer.html b/test/support/renderer.html new file mode 100644 index 000000000..8d9647822 --- /dev/null +++ b/test/support/renderer.html @@ -0,0 +1,15 @@ + + + + + + +
+ + + diff --git a/test/support/requireMain.js b/test/support/requireMain.js new file mode 100644 index 000000000..1543701a0 --- /dev/null +++ b/test/support/requireMain.js @@ -0,0 +1,9 @@ +const path = require('path'); +const fs = require('fs'); + +function resolve(pathname) { + return path.resolve(process.cwd(), pathname); +} +const rendererPath = resolve('./node_modules/electron-mocha/renderer/index.html'); +const rendererContent = fs.readFileSync(resolve('./test/support/renderer.html'), 'utf8'); +fs.writeFileSync(rendererPath, rendererContent, 'utf8'); diff --git a/tests/canvas/canvas-spec.js b/test/unit/canvas-spec.js similarity index 67% rename from tests/canvas/canvas-spec.js rename to test/unit/canvas-spec.js index 3519c816d..2e1dd1147 100644 --- a/tests/canvas/canvas-spec.js +++ b/test/unit/canvas-spec.js @@ -1,51 +1,48 @@ -var $ = require('jquery'); -var Matrix = require('@ali/g-matrix'); -var expect = require('@ali/expect.js'); -var sinon = require('spm-sinon'); -var Canvas = require('../../src/canvas'); -// var Components = require('../../src/components/index'); -var G = require('../../src/g/index'); -// var PlotBack = Components.PlotBack; +const $ = require('jquery'); +const expect = require('chai').expect; +const Matrix = require('@ali/g-matrix'); +const sinon = require('spm-sinon'); +const Canvas = require('../../src/canvas'); +const G = require('../../src/g/index'); $('
').appendTo('body'); describe('Layer', function() { - it('新建图层 new Layer', function() { - var canvas = new Canvas({ + const canvas = new Canvas({ containerId: 'c1', width: 500, height: 500 }); + expect(canvas).to.be.an.instanceof(Canvas); }); - it('通过CSS 参数新建图层 new Layer by css', function() { - var canvas = new Canvas({ + it('改变尺寸 change size', function() { + const canvas = new Canvas({ containerId: 'c1', - widthStyle: "500px", - heightStyle: "500px" + width: 500, + height: 500 }); - }); - - var canvas = new Canvas({ - containerId: 'c1', - widthStyle: '500px', - heightStyle: '500px' - }); - - it('改变尺寸 change size', function() { canvas.changeSize(200, 200); + expect(canvas.get('widthStyle')).to.equal('200px'); + expect(canvas.get('heightStyle')).to.equal('200px'); }); it('清空图层 clear layer', function() { + const canvas = new Canvas({ + containerId: 'c1', + width: 500, + height: 500 + }); canvas.clear(); + expect(canvas.get('children')).to.be.an('array').that.is.empty; }); }); -describe('拓展图形 标记 Marker', function(){ - var canvas = new Canvas({ +describe('拓展图形 标记 Marker', function() { + const canvas = new Canvas({ containerId: 'c1', width: 500, height: 500 @@ -62,7 +59,7 @@ describe('拓展图形 标记 Marker', function(){ }); canvas.draw(); }); - it('circle', function(){ + it('circle', function() { canvas.addShape('Marker', { attrs: { symbol: 'circle', @@ -70,12 +67,12 @@ describe('拓展图形 标记 Marker', function(){ x: 30, y: 20, r: 10 - }, + } }); canvas.draw(); }); - it('square', function(){ + it('square', function() { canvas.addShape('Marker', { attrs: { symbol: 'square', @@ -87,7 +84,7 @@ describe('拓展图形 标记 Marker', function(){ }); canvas.draw(); }); - it('triangle', function(){ + it('triangle', function() { canvas.addShape('Marker', { attrs: { symbol: 'triangle', @@ -99,7 +96,7 @@ describe('拓展图形 标记 Marker', function(){ }); canvas.draw(); }); - it('triangle-down', function(){ + it('triangle-down', function() { canvas.addShape('Marker', { attrs: { symbol: 'triangle-down', @@ -111,16 +108,16 @@ describe('拓展图形 标记 Marker', function(){ }); canvas.draw(); }); - it('custom', function(){ + it('custom', function() { canvas.addShape('Marker', { attrs: { - symbol: function(x, y, r){ + symbol(x, y, r) { return [ - ['M', x - r, y], - ['L', x, y - r*4], - ['L', x + r, y], - ['L', x, y + r], - ['z'] + [ 'M', x - r, y ], + [ 'L', x, y - r * 4 ], + [ 'L', x + r, y ], + [ 'L', x, y + r ], + [ 'z' ] ]; }, stroke: 'red', @@ -149,12 +146,12 @@ describe('拓展图形 标记 Marker', function(){ }); describe('组拓展方法', function() { - var canvas = new Canvas({ + const canvas = new Canvas({ containerId: 'c1', width: 500, height: 500 }); - var circle = new G.Circle({ + const circle = new G.Circle({ attrs: { x: 10, y: 332, @@ -162,17 +159,17 @@ describe('组拓展方法', function() { fill: '#231' } }); - var rect = canvas.addShape('Rect', { - attrs: { - x: 0, - y: 0, - width: 21, - height: 33, - stroke: '#ff00ff' - } - }); - describe('查找元素', function(){ - /*it('通过type 查找 findByType', function() { + describe('查找元素', function() { + // const canvasRect = canvas.addShape('Rect', { + // attrs: { + // x: 0, + // y: 0, + // width: 21, + // height: 33, + // stroke: '#ff00ff' + // } + // }); + /* it('通过type 查找 findByType', function() { var group = canvas.addGroup(); var rect = group.addShape('rect', { attrs: { @@ -184,12 +181,12 @@ describe('组拓展方法', function() { } }); var findedShape = group.findByType('rect'); - expect(rect === findedShape).to.be(true); + expect(rect === findedShape).to.be.true; });*/ it('通过方法查找元素 findAllBy', function() { - var group = canvas.addGroup(); - var group1 = group.addGroup(); - var rect = group1.addShape('rect', { + const group = canvas.addGroup(); + const group1 = group.addGroup(); + const rect = group1.addShape('rect', { cls: 'heh', attrs: { x: 0, @@ -199,21 +196,21 @@ describe('组拓展方法', function() { stroke: '#ff00ff' } }); - var rst = group.findAllBy(function(item){ + const rst = group.findAllBy(function(item) { if (item.get('cls') === 'heh') { return true; - }else{ - return false; } + return false; + }); - expect(rect === rst[0]).to.be(true); + expect(rect === rst[0]).to.be.true; }); }); /* describe('新增元素', function(){ it('添加图形 add Shape 无cfg', function() { var rect = canvas.addShape('Rect'); - expect(rect).not.to.be(undefined); + expect(rect).not.to.be.undefined; }); it('添加图形 add Shape', function() { var width = canvas.get('width'); @@ -241,11 +238,11 @@ describe('组拓展方法', function() { } }); canvas.draw(); - expect(Util.isObject(plotback)).to.be(true); + expect(Util.isObject(plotback)).to.be.true; }); it('添加图组 add Group 参数undefined', function() { var plotback = canvas.addGroup(); - expect(Util.isObject(plotback)).to.be(true); + expect(Util.isObject(plotback)).to.be.true; }); it('添加图组 add Group 参数cfg', function() { var plotback = canvas.addGroup({ @@ -253,47 +250,47 @@ describe('组拓展方法', function() { fill: 'red' } }); - expect(Util.isObject(plotback)).to.be(true); + expect(Util.isObject(plotback)).to.be.true; }); it('添加图组 add Group 参数其它', function() { var plotback = canvas.addGroup([]); - expect(Util.isObject(plotback)).not.to.be(true); + expect(Util.isObject(plotback)).not.to.be.true; var plotback = canvas.addGroup(null); - expect(Util.isObject(plotback)).not.to.be(true); + expect(Util.isObject(plotback)).not.to.be.true; var plotback = canvas.addGroup(false); - expect(Util.isObject(plotback)).not.to.be(true); + expect(Util.isObject(plotback)).not.to.be.true; }); }); */ - describe('判断是否是子元素', function(){ - it('是子元素', function() { - expect(canvas.contain(rect)).to.be(true); - }); + describe('判断是否是子元素', function() { + // it('是子元素', function() { + // expect(canvas.contain(canvasRect)).to.be.true; + // }); it('非子元素', function() { - expect(canvas.contain(circle)).to.be(false); + expect(canvas.contain(circle)).to.be.false; }); it('非元素', function() { - expect(canvas.contain(12)).to.be(false); + expect(canvas.contain(12)).to.be.false; }); canvas.draw(); - }) - describe('查找子元素', function(){ - var children = canvas.get('children'); + }); + describe('查找子元素', function() { + const children = canvas.get('children'); // it('第一个子元素', function() { // expect(canvas.getFirst(rect)).to.be(children[0]); // }); it('第N个子元素', function() { - expect(canvas.getChildByIndex(2)).to.be(children[2]); + expect(canvas.getChildByIndex(2)).to.eql(children[2]); }); // it('最后一个子元素', function() { // expect(canvas.getLast(circle)).to.be(children[children.length - 1]); // }); canvas.draw(); - }) + }); }); describe('元素拓展方法', function() { - var canvas = new Canvas({ + const canvas = new Canvas({ containerId: 'c1', width: 500, height: 500 @@ -307,7 +304,7 @@ describe('元素拓展方法', function() { } }); it('测试BBox方法', function() { - var rect = canvas.addShape("Rect", { + const rect = canvas.addShape('Rect', { attrs: { x: 0, y: 0, @@ -317,27 +314,27 @@ describe('元素拓展方法', function() { lineWidth: 0 } }); - var bbox = rect.getBBox(); - expect(bbox.x).to.be(0); - expect(bbox.y).to.be(0); - expect(bbox.width).to.be(100); - expect(bbox.height).to.be(100); + const bbox = rect.getBBox(); + expect(bbox.x).to.equal(0); + expect(bbox.y).to.equal(0); + expect(bbox.width).to.equal(100); + expect(bbox.height).to.equal(100); }); it('测试BBox方法-无bbox', function() { - var text = canvas.addShape("Text", { + const text = canvas.addShape('Text', { attrs: { x: 0, y: 0, text: '' } }); - var bbox = text.getBBox(); - expect(bbox.x).to.be(0); - expect(bbox.y).to.be(0); - expect(bbox.width).to.be(0); - expect(bbox.height).to.be(0); + const bbox = text.getBBox(); + expect(bbox.x).to.equal(0); + expect(bbox.y).to.equal(0); + expect(bbox.width).to.equal(0); + expect(bbox.height).to.equal(0); }); - /*it('获取宽', function() { + /* it('获取宽', function() { var rect = canvas.addShape("Rect", { attrs: { x: 0, @@ -378,7 +375,7 @@ describe('元素拓展方法', function() { expect(center.y).to.be(50); });*/ it('属性旋转', function() { - var rect = canvas.addShape("Rect", { + const rect = canvas.addShape('Rect', { attrs: { x: 300, y: 10, @@ -389,10 +386,11 @@ describe('元素拓展方法', function() { } }); canvas.draw(); + expect(rect.attr('rotate')).to.equal(45 / 180 * Math.PI); }); it('图形动画、属性动画 Props animate', function() { - var callBack = sinon.spy(); - var rect = canvas.addShape("Rect", { + const callBack = sinon.spy(); + const rect = canvas.addShape('Rect', { attrs: { x: 0, y: 0, @@ -406,16 +404,16 @@ describe('元素拓展方法', function() { x: 100, y: 200, fill: '#4794CA' - },200, 'linear', callBack); - setTimeout(function(){ - expect(callBack.called).to.be(true); + }, 200, 'linear', callBack); + setTimeout(function() { + expect(callBack.called).to.be.true; }, 1050); }); it('图形、图组动画、矩阵动画 Matrix animate', function(done) { - var callBack = sinon.spy(); - var matrix = new Matrix.Matrix3(); - matrix.translate(100,100); - var circle = canvas.addShape("Circle", { + const callBack = sinon.spy(); + const matrix = new Matrix.Matrix3(); + matrix.translate(100, 100); + const circle = canvas.addShape('Circle', { attrs: { x: 0, y: 0, @@ -425,11 +423,11 @@ describe('元素拓展方法', function() { name: 'circle1' }); circle.animate({ - matrix: matrix - },200, 'linear', callBack); - setTimeout(function(){ + matrix + }, 200, 'linear', callBack); + setTimeout(function() { done(); - expect(callBack.called).to.be(true); + expect(callBack.called).to.be.true; }, 1050); }); }); diff --git a/test/unit/g/core-attributes-spec.js b/test/unit/g/core-attributes-spec.js new file mode 100644 index 000000000..1bc96376a --- /dev/null +++ b/test/unit/g/core-attributes-spec.js @@ -0,0 +1,106 @@ +const expect = require('chai').expect; +const Elements = require('../../../src/g/core/element'); +describe('Attributes', function() { + it('init', function() { + const e = new Elements({ + attrs: { + width: 100, + height: 50 + } + }); + + + expect(e.__attrs.width).to.equal(100); + expect(e.__attrs.height).to.equal(50); + }); + + it('attr get', function() { + const e = new Elements({ + attrs: { + width: 100, + height: 50 + } + }); + + expect(e.attr('width')).to.equal(100); + expect(e.attr('height')).to.equal(50); + }); + + it('attr set', function() { + const e = new Elements(); + + e.attr('width', 300); + expect(e.attr('width')).to.equal(300); + e.attr('height', 40); + expect(e.attr('height')).to.equal(40); + e.attr({ + width: 100, + text: '123' + }); + expect(e.attr('width')).to.equal(100); + expect(e.attr('text')).to.equal('123'); + }); + + it('attr fill', function() { + const e = new Elements({ + attrs: { + fill: '#333333' + } + }); + e.attr('fill', '#333333'); + expect(e.attr('fill')).to.equal('#333333'); + expect(e.__attrs.fillStyle).to.equal('#333333'); + + e.attr('fill', 'red'); + expect(e.attr('fill')).to.equal('red'); + expect(e.__attrs.fillStyle).to.equal('red'); + }); + + it('attr stroke', function() { + const e = new Elements({ + attrs: { + stroke: 'black' + } + }); + e.attr('stroke', 'black'); + expect(e.attr('stroke')).to.equal('black'); + expect(e.__attrs.strokeStyle).to.equal('black'); + + e.attr('stroke', '#999'); + expect(e.attr('stroke')).to.equal('#999'); + expect(e.__attrs.strokeStyle).to.equal('#999'); + }); + + it('attr opacity', function() { + const e = new Elements({ + attrs: { + opacity: 0.1 + } + }); + + expect(e.attr('opacity')).to.equal(0.1); + expect(e.__attrs.globalAlpha).to.equal(0.1); + + e.attr('opacity', 0.3); + + expect(e.attr('opacity')).to.equal(0.3); + expect(e.__attrs.globalAlpha).to.equal(0.3); + }); + + it('attrAll', function() { + const e = new Elements({ + attrs: { + width: 100, + opacity: 0.2, + stroke: '#222', + fill: '#444' + } + }); + + const attrs = e.attr(); + expect(attrs.opacity).to.equal(0.2); + expect(attrs.stroke).to.equal('#222'); + expect(attrs.fill).to.equal('#444'); + expect(attrs.width).to.equal(100); + }); +}); diff --git a/tests/g/core-clip-spec.js b/test/unit/g/core-clip-spec.js similarity index 51% rename from tests/g/core-clip-spec.js rename to test/unit/g/core-clip-spec.js index e61eaa1a2..43e55acd5 100644 --- a/tests/g/core-clip-spec.js +++ b/test/unit/g/core-clip-spec.js @@ -1,19 +1,20 @@ -var expect = require('@ali/expect.js'); -var G = require('../../src/g/index'); -var Canvas = require('../../src/canvas'); -var div = document.createElement('div'); +const expect = require('chai').expect; +const G = require('../../../src/g/index'); +const Canvas = require('../../../src/canvas'); +const div = document.createElement('div'); div.id = 'canvas-clip'; document.body.appendChild(div); + describe('clip', function() { - var canvas = new Canvas({ + const canvas = new Canvas({ containerId: 'canvas-clip', width: 200, height: 200, pixelRatio: 1 }); - var shape = new G.Circle({ + const shape = new G.Circle({ attrs: { x: 100, y: 100, @@ -25,7 +26,7 @@ describe('clip', function() { canvas.add(shape); it('shape rect', function() { - var rect = new G.Rect({ + const rect = new G.Rect({ attrs: { x: 50, y: 50, @@ -36,13 +37,13 @@ describe('clip', function() { shape.attr('clip', rect); canvas.draw(); - expect(shape.isHit(50, 50)).to.be(false); - expect(shape.isHit(100, 100)).to.be(true); - expect(shape.isHit(101, 100)).to.be(false); + expect(shape.isHit(50, 50)).to.be.false; + expect(shape.isHit(100, 100)).to.be.true; + expect(shape.isHit(101, 100)).to.be.false; }); it('shape circle', function() { - var circle = new G.Circle({ + const circle = new G.Circle({ attrs: { x: 50, y: 100, @@ -53,15 +54,15 @@ describe('clip', function() { shape.attr('clip', circle); canvas.draw(); - expect(shape.isHit(100, 100)).to.be(true); - expect(shape.isHit(101, 100)).to.be(false); - expect(shape.isHit(50, 100)).to.be(true); - expect(shape.isHit(49, 100)).to.be(false); - expect(shape.isHit(51, 100)).to.be(true); + expect(shape.isHit(100, 100)).to.be.true; + expect(shape.isHit(101, 100)).to.be.false; + expect(shape.isHit(50, 100)).to.be.true; + expect(shape.isHit(49, 100)).to.be.false; + expect(shape.isHit(51, 100)).to.be.true; }); it('shape ellipse', function() { - var ellipse = new G.Ellipse({ + const ellipse = new G.Ellipse({ attrs: { x: 100, y: 100, @@ -72,14 +73,14 @@ describe('clip', function() { shape.attr('clip', ellipse); canvas.draw(); - expect(shape.isHit(50, 100)).to.be(true); - expect(shape.isHit(49, 100)).to.be(false); - expect(shape.isHit(100, 80)).to.be(true); - expect(shape.isHit(100, 79)).to.be(false); + expect(shape.isHit(50, 100)).to.be.true; + expect(shape.isHit(49, 100)).to.be.false; + expect(shape.isHit(100, 80)).to.be.true; + expect(shape.isHit(100, 79)).to.be.false; }); it('shape fan', function() { - var fan = new G.Fan({ + const fan = new G.Fan({ attrs: { x: 100, y: 0, @@ -92,21 +93,21 @@ describe('clip', function() { shape.attr('clip', fan); canvas.draw(); - expect(shape.isHit(100, 50)).to.be(false); - expect(shape.isHit(100, 59)).to.be(false); - expect(shape.isHit(100, 60)).to.be(true); - expect(shape.isHit(100, 100)).to.be(true); - expect(shape.isHit(100, 101)).to.be(false); + expect(shape.isHit(100, 50)).to.be.false; + expect(shape.isHit(100, 59)).to.be.false; + expect(shape.isHit(100, 60)).to.be.true; + expect(shape.isHit(100, 100)).to.be.true; + expect(shape.isHit(100, 101)).to.be.false; }); it('shape ploygon', function() { - var polygon = new G.Polygon({ + const polygon = new G.Polygon({ attrs: { points: [ - [100, 40], - [40, 100], - [100, 160], - [160, 100] + [ 100, 40 ], + [ 40, 100 ], + [ 100, 160 ], + [ 160, 100 ] ] } }); @@ -114,35 +115,35 @@ describe('clip', function() { shape.attr('clip', polygon); canvas.draw(); - expect(shape.isHit(70, 70)).to.be(true); - expect(shape.isHit(69, 69)).to.be(false); + expect(shape.isHit(70, 70)).to.be.true; + expect(shape.isHit(69, 69)).to.be.false; }); it('shape path', function() { - var path = new G.Path({ + const path = new G.Path({ attrs: { path: [ - ['M', 50, 50], - ['L', 100, 50], - ['A', 25, 25, 0, 1, 1, 100, 100], - ['A', 25, 25, 0, 1, 0, 100, 150], - ['L', 50, 150], - ['Z'] + [ 'M', 50, 50 ], + [ 'L', 100, 50 ], + [ 'A', 25, 25, 0, 1, 1, 100, 100 ], + [ 'A', 25, 25, 0, 1, 0, 100, 150 ], + [ 'L', 50, 150 ], + [ 'Z' ] ] } }); shape.attr('clip', path); canvas.draw(); - expect(shape.isHit(125, 75)).to.be(true); - expect(shape.isHit(126, 75)).to.be(false); - expect(shape.isHit(75, 125)).to.be(true); - expect(shape.isHit(76, 125)).to.be(false); + expect(shape.isHit(125, 75)).to.be.true; + expect(shape.isHit(126, 75)).to.be.false; + expect(shape.isHit(75, 125)).to.be.true; + expect(shape.isHit(76, 125)).to.be.false; }); - var group = new G.Group(); + const group = new G.Group(); - var fan = new G.Fan({ + const fan = new G.Fan({ attrs: { x: 150, y: 100, @@ -153,11 +154,11 @@ describe('clip', function() { fill: 'green' } }); - group.add([shape, fan]); + group.add([ shape, fan ]); canvas.add(group); it('group rect', function() { - var rect = new G.Rect({ + const rect = new G.Rect({ attrs: { x: 80, y: 75, @@ -168,15 +169,15 @@ describe('clip', function() { group.attr('clip', rect); canvas.draw(); - // expect(canvas.getShape(100, 70)).to.be(undefined); - expect(canvas.getShape(125, 75)).to.be(shape); - expect(canvas.getShape(100, 80)).to.be(shape); + // expect(canvas.getShape(100, 70)).to.be.undefined; + expect(canvas.getShape(125, 75)).to.eql(shape); + expect(canvas.getShape(100, 80)).to.eql(shape); - //expect(canvas.getShape(150, 150)).to.be(fan); + // expect(canvas.getShape(150, 150)).to.be(fan); }); it('group circle', function() { - var circle = new G.Circle({ + const circle = new G.Circle({ attrs: { x: 130, y: 100, @@ -189,7 +190,7 @@ describe('clip', function() { }); it('group ellipse', function() { - var ellipse = new G.Ellipse({ + const ellipse = new G.Ellipse({ attrs: { x: 130, y: 100, @@ -203,7 +204,7 @@ describe('clip', function() { }); it('group fan', function() { - var fan = new G.Fan({ + const fan = new G.Fan({ attrs: { x: 130, y: 100, @@ -218,13 +219,13 @@ describe('clip', function() { }); it('group polygon', function() { - var polygon = new G.Polygon({ + const polygon = new G.Polygon({ attrs: { points: [ - [120, 40], - [60, 100], - [120, 160], - [180, 100] + [ 120, 40 ], + [ 60, 100 ], + [ 120, 160 ], + [ 180, 100 ] ] } }); diff --git a/test/unit/g/core-element-spec.js b/test/unit/g/core-element-spec.js new file mode 100644 index 000000000..64be28a44 --- /dev/null +++ b/test/unit/g/core-element-spec.js @@ -0,0 +1,40 @@ +const expect = require('chai').expect; +const Element = require('../../../src/g/core/element'); +const Matrix = require('@ali/g-matrix'); +const Matrix3 = Matrix.Matrix3; + +describe('Element', function() { + it('constructor', function() { + const e = new Element({ + id: 'aaa', + attrs: { + width: 20, + height: 30, + stroke: '#231' + } + }); + + expect(e.__cfg).not.to.be.undefined; + expect(e.__cfg.id).to.equal('aaa'); + expect(e.__attrs).not.to.be.undefined; + expect(e.__attrs.width).to.equal(20); + expect(e.__attrs.height).to.equal(30); + expect(e.__m).not.to.be.undefined; + const m = new Matrix3(); + expect(e.__m.equal(m)).to.be.true; + // expect(e.__listeners).not.to.be.undefined; + }); + + it('set and get', function() { + const e = new Element(); + let a = 123; + expect(a).to.equal(123); + e.__setTest = function(v) { + a = 321; + return v - 1; + }; + e.set('test', 1111); + expect(e.get('test')).to.equal(1110); + expect(a).to.equal(321); + }); +}); diff --git a/test/unit/g/core-eventDispatcher-spec.js b/test/unit/g/core-eventDispatcher-spec.js new file mode 100644 index 000000000..fb55b656b --- /dev/null +++ b/test/unit/g/core-eventDispatcher-spec.js @@ -0,0 +1,106 @@ +const expect = require('chai').expect; +const Util = require('../../../src/util/index'); +const Dispatcher = require('../../../src/g/core/mixin/event-dispatcher'); +const Element = function() { + this.initEventDispatcher(); +}; + +Util.augment(Element, Dispatcher); + +describe('EventDispatcher', function() { + + it('trigger', function() { + const element = new Element(); + element.on('test', function(e) { + expect(e.target).to.eql(element); + expect(e.type).to.equal('test'); + }); + element.trigger({ type: 'test' }); + }); + + it('on', function() { + const element = new Element(); + const test1 = function(e) { + expect(e.target).to.eql(element); + expect(e.type).to.equal('test'); + expect(e.target).to.eql(this); + }; + + const test2 = function(e) { + expect(e.target).to.eql(element); + expect(e.type).to.equal('test'); + expect(e.target).to.eql(this); + }; + + const exe1 = function(e) { + expect(e.target).to.eql(element); + expect(e.type).to.equal('exe'); + expect(e.target).to.eql(this); + }; + + const exe2 = function(e) { + expect(e.target).to.eql(element); + expect(e.type).to.equal('exe'); + expect(e.target).to.eql(this); + }; + + element.on('test', test1); + element.on('test', test2); + element.on('exe', exe1); + element.on('exe', exe2); + element.trigger({ type: 'test' }); + element.trigger({ type: 'exe' }); + }); + + it('has', function() { + const element = new Element(); + + const test1 = function() {}; + const test2 = function() {}; + const test3 = function() {}; + element.on('test', test2); + element.on('test', test1); + expect(element.has('test', test1)).to.be.true; + expect(element.has('test', test2)).to.be.true; + expect(element.has('test', test3)).to.be.false; + }); + + it('off', function() { + const element = new Element(); + + const test1 = function() {}; + const test2 = function() {}; + const exe1 = function() {}; + const exe2 = function() {}; + const fun1 = function() {}; + const fun2 = function() {}; + + element.on('test', test1); + element.on('test', test2); + element.on('exe', exe1); + element.on('exe', exe2); + element.on('fun', fun1); + element.on('fun', fun2); + + + expect(element.has('test', test1)).to.be.true; + expect(element.has('test', test2)).to.be.true; + expect(element.has('exe', exe1)).to.be.true; + expect(element.has('exe', exe2)).to.be.true; + expect(element.has('fun', fun1)).to.be.true; + expect(element.has('fun', fun2)).to.be.true; + expect(element.has()).to.be.true; + expect(element.has('fun')).to.be.true; + element.off('test', test1); + expect(element.has('test', test1)).to.be.false; + element.off('exe'); + expect(element.has('exe', exe1)).to.be.false; + expect(element.has('exe', exe2)).to.be.false; + element.off(); + expect(element.has('test', test2)).to.be.false; + expect(element.has('fun', fun1)).to.be.false; + expect(element.has('fun', fun2)).to.be.false; + expect(element.has()).to.be.false; + expect(element.has('fun')).to.be.false; + }); +}); diff --git a/test/unit/g/core-group-spec.js b/test/unit/g/core-group-spec.js new file mode 100644 index 000000000..99757cc10 --- /dev/null +++ b/test/unit/g/core-group-spec.js @@ -0,0 +1,389 @@ +const expect = require('chai').expect; +const G = require('../../../src/g/index'); +const Event = require('@ali/g-event'); +const Canvas = require('../../../src/canvas'); +const div = document.createElement('div'); +div.id = 'canvas-group-1'; +document.body.appendChild(div); + +describe('Group', function() { + + const canvas = new Canvas({ + containerId: 'canvas-group-1', + width: 200, + height: 200, + pixelRatio: 1 + }); + + it('constructor', function() { + const g = new G.Group({ + id: 'g1' + }); + + expect(g.isGroup).to.be.true; + expect(g.get('children')).not.to.be.undefined; + expect(g.get('children').length).to.equal(0); + }); + + it('add', function() { + const e = new G.Circle({ + id: 'e1' + }); + const e2 = new G.Circle({ + id: 'e2' + }); + + const g2 = new G.Group({ + id: 'g2' + }); + + g2.add(e); + + expect(e.get('parent')).to.eql(g2); + expect(g2.getCount()).to.equal(1); + const g3 = new G.Group({ + id: 'g3' + }); + + g3.add(e); + + expect(e.get('parent')).to.eql(g3); + expect(g3.getCount()).to.equal(1); + expect(g2.getCount()).to.equal(0); + + const g4 = new G.Group({ + id: 'g4' + }); + + g4.add(g3); + expect(g3.get('parent')).to.eql(g4); + expect(e.get('parent')).to.eql(g3); + expect(g4.getCount()).to.equal(1); + expect(g3.getCount()).to.equal(1); + + g2.add(g3); + expect(g2.getCount()).to.equal(1); + expect(g3.getCount()).to.equal(1); + expect(g3.get('parent')).to.eql(g2); + expect(e.get('parent')).to.eql(g3); + + g3.add(e2); + expect(g2.getCount()).to.equal(1); + expect(g3.getCount()).to.equal(2); + expect(e2.get('parent')).to.eql(g3); + expect(e.get('parent')).to.eql(g3); + + g2.add(e2); + expect(g2.getCount()).to.equal(2); + expect(g3.getCount()).to.equal(1); + expect(e2.get('parent')).to.eql(g2); + expect(e.get('parent')).to.eql(g3); + }); + + it('clear', function() { + const g = new G.Group({ + id: 'g' + }); + + const e1 = new G.Circle({ + id: 'e1' + }); + const e2 = new G.Circle({ + id: 'e2' + }); + const e3 = new G.Circle({ + id: 'e3' + }); + + g.add(e1); + g.add(e2); + g.add(e3); + + expect(g.getCount()).to.equal(3); + g.clear(); + expect(g.getCount()).to.equal(0); + expect(e1.get('destroyed')).to.be.true; + }); + + it('destroy', function() { + const g = new G.Group({ + id: 'g' + }); + + const e1 = new G.Circle({ + id: 'e1' + }); + const e2 = new G.Circle({ + id: 'e2' + }); + const e3 = new G.Circle({ + id: 'e3' + }); + + g.add(e1); + g.add(e2); + g.add(e3); + expect(g.getCount()).to.equal(3); + g.destroy(); + + expect(g.get('children')).to.undefined; + expect(g.get('destroyed')).to.be.true; + }); + + it('remove', function() { + const g1 = new G.Group({ + id: 'g1' + }); + + const g2 = new G.Group({ + id: 'g2' + }); + + const e1 = new G.Circle({ + id: 'e1' + }); + const e2 = new G.Circle({ + id: 'e2' + }); + const e3 = new G.Circle({ + id: 'e3' + }); + const e4 = new G.Circle({ + id: 'e4' + }); + const e5 = new G.Circle({ + id: 'e5' + }); + + g1.add(e1); + g1.add(e2); + g1.add(e3); + g1.add(e4); + g1.add(e5); + + g2.add(g1); + + expect(g2.getCount()).to.equal(1); + expect(g1.getCount()).to.equal(5); + g1.removeChild(e1, true); + expect(g1.getCount()).to.equal(4); + expect(e1.get('destroyed')).to.be.true; + g1.removeChild(e2); + expect(g1.getCount()).to.equal(3); + expect(e2.get('destroyed')).to.be.true; + g1.removeChild(e3, false); + expect(g1.getCount()).to.equal(2); + expect(e3.get('destroyed')).to.be.false; + g1.removeChild(false); + expect(g1.getCount()).to.equal(2); + expect(g2.getCount()).to.equal(0); + expect(g1.get('destroyed')).to.be.false; + g2.add(g1); + expect(g2.getCount()).to.equal(1); + g1.removeChild(); + expect(g2.getCount()).to.equal(0); + expect(g1.get('destroyed')).to.be.true; + }); + + it('zIndex', function() { + const g = new G.Group({ + id: 'g' + }); + + const e1 = new G.Circle({ + id: 'e1', + zIndex: 1 + }); + + const e2 = new G.Circle({ + id: 'e2', + zIndex: 2 + }); + + const e3 = new G.Circle({ + id: 'e3', + zIndex: 3 + }); + + g.add(e1); + g.add(e3); + + expect(g.get('children')[1]).to.eql(e3); + g.add(e2); + g.sort(); + expect(g.get('children')[1]).to.eql(e2); + + e2.set('zIndex', 5); + expect(g.get('children')[1]).to.eql(e3); + expect(g.get('children')[2]).to.eql(e2); + }); + + it('find and findBy', function() { + const g1 = new G.Group({ + id: 'g1' + }); + + const g2 = new G.Group({ + id: 'g2' + }); + + const e1 = new G.Circle({ + id: 'e1', + zIndex: 1 + }); + + const e2 = new G.Circle({ + id: 'e2', + zIndex: 2 + }); + + const e3 = new G.Circle({ + id: 'e3', + zIndex: 3 + }); + + + g1.add(g2); + g1.add(e1); + g2.add(e2); + g2.add(e3); + + expect(g1.findBy(function(item) { + return item.get('zIndex') === 3; + })).to.eql(e3); + + expect(g1.find('e1')).to.eql(e1); + }); +/* + it('fill', function() { + var g = new G.Group({ + attrs: { + fill: 'green' + } + }); + + var circle = new G.Circle({ + attrs: { + x: 100, + y: 100, + r: 50 + } + }); + expect(circle.hasFill()).to.be.undefined; + g.add(circle); + expect(circle.hasFill()).to.be('green'); + expect(circle.attr('fill')).to.be.undefined; + var arc = new G.Arc({ + attrs: { + x: 100, + y: 100, + r: 70, + startAngle: 0, + endAngle: 120, + stroke: 'red' + } + }); + expect(arc.hasFill()).to.be.undefined; + g.add(arc); + expect(arc.hasFill()).to.be.undefined; + expect(arc.hasStroke()).to.be('red'); + canvas.add(g); + canvas.draw(); + }); + + it('stroke', function() { + var g = new G.Group({ + attrs: { + stroke: 'l (0) 0:#00ffff 1:#ffff00' + } + }); + + var arc = new G.Arc({ + attrs: { + x: 100, + y: 100, + r: 70, + startAngle: 180, + endAngle: 300 + } + }); + expect(arc.hasStroke()).to.be.undefined; + g.add(arc); + expect(arc.hasStroke()).to.be('l (0) 0:#00ffff 1:#ffff00'); + canvas.add(g); + canvas.draw(); + }); +*/ + it('transform', function() { + const arc = new G.Circle({ + attrs: { + x: 100, + y: 100, + r: 50, + fill: 'red' + } + }); + canvas.add(arc); + expect(canvas.getShape(0, 120)).to.be.undefined; + expect(canvas.getShape(100, 100)).not.to.be.undefined; + canvas.draw(); + + canvas.rotate(1 / 4 * Math.PI); + canvas.draw(); + expect(canvas.getShape(0, 120)).not.to.be.undefined; + expect(canvas.getShape(100, 100)).to.be.undefined; + /**/ + }); + + it('group event', function() { + const circle = new G.Circle(); + const group = new G.Group(); + group.add(circle); + const e = new Event('group', {}, true, true); + e.currentTarget = circle; + circle.trigger(e); + let aa = 0; + const handler = function(e) { + expect(e.currentTarget).to.eql(circle); + expect(e.target).to.eql(group); + e.stopPropagation(); + aa++; + }; + group.on('group', handler); + group.on('group', handler); + circle.trigger(e); + expect(aa).to.equal(1); + }); + + it('add items & sort', function() { + const circle1 = new G.Circle({ zIndex: 2 }); + const circle2 = new G.Circle({ zIndex: 1 }); + const circle3 = new G.Circle({ zIndex: 3 }); + const text = new G.Text({ zIndex: 4 }); + + const group = new G.Group(); + + group.add([ circle1, circle2, circle3, text ]); + + const children = group.get('children'); + expect(children.length).to.equal(4); + expect(children[1]).to.eql(circle2); + group.sort(); + expect(children[1]).to.eql(circle1); + expect(children[0]).to.eql(circle2); + circle1.set('visible', true); + // const box = group.getBBox(); + }); + + it('contain', function() { + const group1 = new G.Group(); + const group2 = new G.Group(); + const r1 = new G.Rect(); + group1.add(r1); + expect(group1.contain(r1)).to.be.true; + group2.removeChild(r1); + expect(r1.get('destroyed')).to.be.false; + group1.removeChild(r1); + expect(group1.contain(r1)).to.be.false; + }); +}); diff --git a/test/unit/g/core-shape-spec.js b/test/unit/g/core-shape-spec.js new file mode 100644 index 000000000..5ff60d319 --- /dev/null +++ b/test/unit/g/core-shape-spec.js @@ -0,0 +1,6 @@ +// const expect = require('chai').expect; +// const Shape = require('../../../src/g/core/shape'); + +describe('Shape', function() { + +}); diff --git a/test/unit/g/core-transform-spec.js b/test/unit/g/core-transform-spec.js new file mode 100644 index 000000000..441f9f0c0 --- /dev/null +++ b/test/unit/g/core-transform-spec.js @@ -0,0 +1,98 @@ +const expect = require('chai').expect; +const Element = require('../../../src/g/core/element'); +const Util = require('../../../src/util/index'); +const Matrix = require('@ali/g-matrix'); +const Vector3 = Matrix.Vector3; +const Matrix3 = Matrix.Matrix3; + +describe('Transform', function() { + + it('translate and apply', function() { + const e = new Element(); + const point = new Vector3(0, 0, 1); + e.translate(10, 4); + e.apply(point); + expect(Util.isNumberEqual(point.x, 10)).to.be.true; + expect(Util.isNumberEqual(point.y, 4)).to.be.true; + }); + + it('rotate', function() { + const e = new Element(); + const point = new Vector3(10, 0, 0); + e.rotate(45 / 180 * Math.PI); + e.apply(point); + expect(Util.isNumberEqual(point.x, 5 * Math.sqrt(2))).to.be.true; + expect(Util.isNumberEqual(point.y, 5 * Math.sqrt(2))).to.be.true; + e.apply(point); + expect(Util.isNumberEqual(point.x, 0)).to.be.true; + expect(Util.isNumberEqual(point.y, 10)).to.be.true; + e.rotate(-135 / 180 * Math.PI); + e.apply(point); + expect(Util.isNumberEqual(point.x, 10)).to.be.true; + expect(Util.isNumberEqual(point.y, 0)).to.be.true; + }); + + it('scale', function() { + const e = new Element(); + const point = new Vector3(10, 10, 1); + e.scale(0.5, 0.5); + e.apply(point); + expect(Util.isNumberEqual(point.x, 5)).to.be.true; + expect(Util.isNumberEqual(point.y, 5)).to.be.true; + e.scale(4, 2); + e.apply(point); + expect(Util.isNumberEqual(point.x, 10)).to.be.true; + expect(Util.isNumberEqual(point.y, 5)).to.be.true; + }); + + it('complex', function() { + const e = new Element(); + const point1 = new Vector3(10, 10, 1); + e.translate(10, 10); + e.rotate(Math.PI / 2); + e.translate(-10, -10); + e.scale(0.5, 0.5); + e.apply(point1); + + expect(Util.isNumberEqual(point1.x, -15)).to.be.true; + expect(Util.isNumberEqual(point1.y, 5)).to.be.true; + }); + + it('transform', function() { + const e = new Element(); + e.transform([[ 'r', Math.PI / 2 ], [ 't', 10, 10 ], [ 'r', -Math.PI / 2 ]]); + const point = new Vector3(0, 0, 1); + e.apply(point); + expect(Util.isNumberEqual(point.x, 10)).to.be.true; + expect(Util.isNumberEqual(point.y, -10)).to.be.true; + }); + + it('setTransform and invert', function() { + const e = new Element(); + e.translate(10, 10); + e.setTransform([[ 'r', Math.PI / 2 ], [ 't', 10, 10 ], [ 'r', -Math.PI / 2 ], [ 's', 0.5, 0.3 ]]); + const point = new Vector3(0, 0, 1); + e.apply(point); + expect(Util.isNumberEqual(point.x, 5)).to.be.true; + expect(Util.isNumberEqual(point.y, -3)).to.be.true; + e.invert(point); + expect(Util.isNumberEqual(point.x, 0)).to.be.true; + expect(Util.isNumberEqual(point.y, 0)).to.be.true; + const e1 = new Element(); + e1.setTransform([[ 'm', e.__m ]]); + e1.apply(point); + expect(Util.isNumberEqual(point.x, 5)).to.be.true; + expect(Util.isNumberEqual(point.y, -3)).to.be.true; + e1.invert(point); + expect(Util.isNumberEqual(point.x, 0)).to.be.true; + expect(Util.isNumberEqual(point.y, 0)).to.be.true; + }); + + it('getMatrix', function() { + const e = new Element(); + const m = e.getMatrix(); + const m1 = new Matrix3(); + expect(m.equal(m1)).to.be.true; + }); +}); + diff --git a/test/unit/g/index-spec.js b/test/unit/g/index-spec.js new file mode 100644 index 000000000..c6bb1417e --- /dev/null +++ b/test/unit/g/index-spec.js @@ -0,0 +1,10 @@ +// const expect = require('chai').expect; +// const G = require('../../../src/g/index'); + +describe('G', function() { + + it('normal usage', function() { + + }); + +}); diff --git a/test/unit/g/shape-arc-spec.js b/test/unit/g/shape-arc-spec.js new file mode 100644 index 000000000..07f30cd25 --- /dev/null +++ b/test/unit/g/shape-arc-spec.js @@ -0,0 +1,139 @@ +const expect = require('chai').expect; +const G = require('../../../src/g/index'); +const Util = require('../../../src/util/index'); +const Canvas = require('../../../src/canvas'); +const div = document.createElement('div'); +div.id = 'canvas-arc'; +document.body.appendChild(div); +const ratio = Util.getRatio(); +describe('Arc line', function() { + + const canvas = new Canvas({ + containerId: 'canvas-arc', + width: 200, + height: 200 + }); + + canvas.on('canvas-click', function(ev) { + console.log(ev); + }); + const arc = new G.Arc(); + G.debug(true); + it('init attrs', function() { + expect(arc.attr('x')).to.equal(0); + expect(arc.attr('y')).to.equal(0); + expect(arc.attr('r')).to.equal(0); + expect(arc.attr('startAngle')).to.equal(0); + expect(arc.attr('endAngle')).to.equal(0); + expect(arc.attr('clockwise')).to.be.false; + expect(arc.attr('lineWidth')).to.equal(1); + expect(arc.attr('stroke')).to.be.undefined; + + const box = arc.getBBox(); + expect(box.minX).to.equal(-0.5); + expect(box.maxX).to.equal(0.5); + expect(box.minY).to.equal(-0.5); + expect(box.maxY).to.equal(0.5); + }); + + it('x', function() { + arc.attr('x', 10); + expect(arc.attr('x')).to.equal(10); + const box = arc.getBBox(); + expect(box.minX).to.equal(9.5); + expect(box.maxX).to.equal(10.5); + }); + + it('y', function() { + arc.attr('y', 20); + expect(arc.attr('y')).to.equal(20); + const box = arc.getBBox(); + expect(box.minY).to.equal(19.5); + expect(box.maxY).to.equal(20.5); + }); + + it('r', function() { + arc.attr('r', 30); + const box = arc.getBBox(); + expect(box.minX).to.equal(39.5); + expect(box.maxX).to.equal(40.5); + expect(box.minY).to.equal(19.5); + expect(box.maxY).to.equal(20.5); + }); + + it('startAngle', function() { + arc.attr('startAngle', 1 / 3 * Math.PI); + expect(Util.isNumberEqual(arc.attr('startAngle'), 1 / 3 * Math.PI)).to.be.true; + const box = arc.getBBox(); + expect(box.minX).to.equal(-20.5); + expect(box.maxX).to.equal(40.5); + expect(box.minY).to.equal(-10.5); + expect(box.maxY).to.equal(50.5); + }); + + it('endAngle', function() { + arc.attr('endAngle', 120 / 180 * Math.PI); + expect(Util.isNumberEqual(arc.attr('endAngle'), 120 / 180 * Math.PI)).to.be.true; + const box = arc.getBBox(); + expect(Util.isNumberEqual(box.minX, -5.5)).to.be.true; + expect(Util.isNumberEqual(box.maxX, 25.5)).to.be.true; + expect(Util.isNumberEqual(box.minY, 45.48076211353316)).to.be.true; + expect(Util.isNumberEqual(box.maxY, 50.5)).to.be.true; + }); + + it('clockwise', function() { + expect(arc.attr('clockwise')).to.be.false; + arc.attr('clockwise', true); + expect(arc.attr('clockwise')).to.be.true; + const box = arc.getBBox(); + expect(Util.isNumberEqual(box.minX, -20.5)).to.be.true; + expect(Util.isNumberEqual(box.maxX, 40.5)).to.be.true; + expect(Util.isNumberEqual(box.minY, -10.5)).to.be.true; + expect(Util.isNumberEqual(box.maxY, 46.48076211353316)).to.be.true; + }); + + it('lineWidth', function() { + expect(arc.attr('lineWidth')).to.equal(1); + arc.attr('lineWidth', 2); + expect(arc.attr('lineWidth')).to.equal(2); + const box = arc.getBBox(); + expect(Util.isNumberEqual(box.minX, -21)).to.be.true; + expect(Util.isNumberEqual(box.maxX, 41)).to.be.true; + expect(Util.isNumberEqual(box.minY, -11)).to.be.true; + expect(Util.isNumberEqual(box.maxY, 46.98076211353316)).to.be.true; + }); + + it('stroke', function() { + arc.attr({ + startAngle: -Math.PI / 2, + endAngle: Math.PI / 2, + clockwise: false, + x: 60, + y: 60, + r: 20 + }); + arc.attr('stroke', 'l (0) 0:#ff00ff 1:#00ffff'); + expect(arc.attr('stroke')).to.equal('l (0) 0:#ff00ff 1:#00ffff'); + canvas.add(arc); + canvas.draw(); + }); + + it('isHit', function() { + expect(arc.isHit(60 * ratio, 80 * ratio)).to.be.true; + }); + + it('normal', function() { + const arc = new G.Arc({ + attrs: { + x: 50, + y: 50, + r: 40, + startAngle: 0, + endAngle: 110 / 180 * Math.PI, + stroke: 'red' + } + }); + canvas.add(arc); + canvas.draw(); + }); +}); diff --git a/test/unit/g/shape-circle-spec.js b/test/unit/g/shape-circle-spec.js new file mode 100644 index 000000000..a2d47de54 --- /dev/null +++ b/test/unit/g/shape-circle-spec.js @@ -0,0 +1,159 @@ +const expect = require('chai').expect; +const G = require('../../../src/g/index'); +const Canvas = require('../../../src/canvas'); +const div = document.createElement('div'); +div.id = 'canvas-circle'; +document.body.appendChild(div); +describe('Circle', function() { + const canvas = new Canvas({ + containerId: 'canvas-circle', + width: 200, + height: 200, + pixelRatio: 1 + }); + + const circle = new G.Circle({ + attrs: { + x: 0, + y: 0, + r: 0 + } + }); + + G.debug(true); + it('init attr', function() { + expect(circle.attr('lineWidth')).to.equal(1); + expect(circle.attr('stroke')).to.be.undefined; + expect(circle.attr('fill')).to.be.undefined; + const box = circle.getBBox(); + expect(box.minX).to.equal(-0.5); + expect(box.maxX).to.equal(0.5); + expect(box.minY).to.equal(-0.5); + expect(box.maxY).to.equal(0.5); + }); + + it('x', function() { + circle.attr('x', 10); + expect(circle.attr('x')).to.equal(10); + const box = circle.getBBox(); + expect(box.minX).to.equal(9.5); + expect(box.maxX).to.equal(10.5); + expect(box.minY).to.equal(-0.5); + expect(box.maxY).to.equal(0.5); + }); + + it('y', function() { + circle.attr('y', 20); + expect(circle.attr('y')).to.equal(20); + const box = circle.getBBox(); + expect(box.minX).to.equal(9.5); + expect(box.maxX).to.equal(10.5); + expect(box.minY).to.equal(19.5); + expect(box.maxY).to.equal(20.5); + }); + + it('r', function() { + expect(circle.attr('r')).to.equal(0); + circle.attr('r', 10); + expect(circle.attr('r')).to.equal(10); + const box = circle.getBBox(); + expect(box.minX).to.equal(-0.5); + expect(box.maxX).to.equal(20.5); + expect(box.minY).to.equal(9.5); + expect(box.maxY).to.equal(30.5); + }); + + it('lineWidth', function() { + expect(circle.attr('lineWidth')).to.equal(1); + circle.attr('lineWidth', 2); + expect(circle.attr('lineWidth')).to.equal(2); + const box = circle.getBBox(); + expect(box.minX).to.equal(-1); + expect(box.maxX).to.equal(21); + expect(box.minY).to.equal(9); + expect(box.maxY).to.equal(31); + }); + + it('stroke', function() { + circle.attr('stroke', 'l (30) 0:#00ffff 1:#ff00ff'); + expect(circle.attr('stroke')).to.equal('l (30) 0:#00ffff 1:#ff00ff'); + canvas.add(circle); + canvas.draw(circle); + }); + + it('fill', function() { + circle.attr('fill', 'r (0.5, 0.5, 0) 0:#00ffff 1:#ffff00'); + expect(circle.attr('fill')).to.equal('r (0.5, 0.5, 0) 0:#00ffff 1:#ffff00'); + canvas.draw(circle); + }); + + it('isHit', function() { + const circle1 = new G.Circle({ + attrs: { + x: 50, + y: 50, + r: 50 + } + }); + + expect(circle1.isHit(0, 50)).to.be.false; + expect(circle1.isHit(50, 0)).to.be.false; + expect(circle1.isHit(100, 50)).to.be.false; + expect(circle1.isHit(50, 100)).to.be.false; + circle1.attr('stroke', 'red'); + + expect(circle1.isHit(0, 50)).to.be.true; + expect(circle1.isHit(50, 0)).to.be.true; + expect(circle1.isHit(100, 50)).to.be.true; + expect(circle1.isHit(50, 100)).to.be.true; + expect(circle1.isHit(20, 50)).to.be.false; + expect(circle1.isHit(50, 20)).to.be.false; + expect(circle1.isHit(80, 50)).to.be.false; + expect(circle1.isHit(50, 80)).to.be.false; + + const circle2 = new G.Circle({ + attrs: { + x: 50, + y: 50, + r: 50 + } + }); + + expect(circle2.isHit(20, 50)).to.be.false; + expect(circle2.isHit(50, 20)).to.be.false; + expect(circle2.isHit(80, 50)).to.be.false; + expect(circle2.isHit(50, 80)).to.be.false; + circle2.attr('fill', 'green'); + expect(circle2.isHit(20, 50)).to.be.true; + expect(circle2.isHit(50, 20)).to.be.true; + expect(circle2.isHit(80, 50)).to.be.true; + expect(circle2.isHit(50, 80)).to.be.true; + + circle2.attr('stroke', 'red'); + expect(circle2.isHit(0, 50)).to.be.true; + expect(circle2.isHit(50, 0)).to.be.true; + expect(circle2.isHit(100, 50)).to.be.true; + expect(circle2.isHit(50, 100)).to.be.true; + expect(circle2.isHit(20, 50)).to.be.true; + expect(circle2.isHit(50, 20)).to.be.true; + expect(circle2.isHit(80, 50)).to.be.true; + expect(circle2.isHit(50, 80)).to.be.true; + }); + + it('strokeOpactiy', function() { + const circle = new G.Circle({ + attrs: { + x: 150, + y: 150, + r: 100, + stroke: 'red', + strokeOpactiy: 0.4 + } + }); + + canvas.add(circle); + canvas.draw(); + }); + +}); + diff --git a/test/unit/g/shape-cubic-spec.js b/test/unit/g/shape-cubic-spec.js new file mode 100644 index 000000000..78da5d0a7 --- /dev/null +++ b/test/unit/g/shape-cubic-spec.js @@ -0,0 +1,158 @@ +const expect = require('chai').expect; +const G = require('../../../src/g/index'); +const Canvas = require('../../../src/canvas'); +const Util = require('../../../src/util/index'); +const div = document.createElement('div'); +div.id = 'canvas-cubic'; +document.body.appendChild(div); + +describe('Cubic line', function() { + const canvas = new Canvas({ + containerId: 'canvas-cubic', + width: 200, + height: 200, + pixelRatio: 1 + }); + + G.debug(true); + const cubic = new G.Cubic(); + it('init cubic', function() { + expect(cubic.attr('p1')).to.be.undefined; + expect(cubic.attr('p2')).to.be.undefined; + expect(cubic.attr('p3')).to.be.undefined; + expect(cubic.attr('p4')).to.be.undefined; + expect(cubic.attr('lineWidth')).to.equal(1); + expect(cubic.attr('arrow')).to.be.undefined; + + expect(cubic.getBBox()).to.be.null; + }); + + it('p1, p2, p3, p4', function() { + cubic.attr({ + p1: [ 50, 50 ], + p2: [ 80, 12 ], + p3: [ 120, 150 ], + p4: [ 150, 50 ] + }); + expect(cubic.attr('p1')[0]).to.equal(50); + expect(cubic.attr('p2')[1]).to.equal(12); + expect(cubic.attr('p3')[0]).to.equal(120); + expect(cubic.attr('p4')[0]).to.equal(150); + + const box = cubic.getBBox(); + expect(Util.isNumberEqual(box.minX, 49.5)).to.be.true; + expect(Util.isNumberEqual(box.maxX, 150.5)).to.be.true; + expect(Util.isNumberEqual(box.minY, 42.690077140818396)).to.be.true; + expect(Util.isNumberEqual(box.maxY, 87.61466742731623)).to.be.true; + }); + + it('stroke', function() { + cubic.attr('lineWidth', 5); + cubic.attr('stroke', 'l (0) 0:#ff00ff 1:#00ffff'); + expect(cubic.attr('stroke')).to.equal('l (0) 0:#ff00ff 1:#00ffff'); + + canvas.add(cubic); + canvas.draw(); + }); + + it('p1', function() { + cubic.attr('p1', [ 70, 39 ]); + expect(cubic.attr('p1')[0]).to.equal(70); + expect(cubic.attr('p1')[1]).to.equal(39); + const box = cubic.getBBox(); + expect(Util.isNumberEqual(box.minX, 67.5)).to.be.true; + expect(Util.isNumberEqual(box.maxX, 152.5)).to.be.true; + expect(Util.isNumberEqual(box.minY, 32.923853488303024)).to.be.true; + expect(Util.isNumberEqual(box.maxY, 89.38594461401888)).to.be.true; + canvas.draw(); + }); + + it('p2', function() { + cubic.attr('p2', [ 90, 80 ]); + expect(cubic.attr('p2')[0]).to.equal(90); + expect(cubic.attr('p2')[1]).to.equal(80); + const box = cubic.getBBox(); + expect(Util.isNumberEqual(box.minX, 67.5)).to.be.true; + expect(Util.isNumberEqual(box.maxX, 152.5)).to.be.true; + expect(Util.isNumberEqual(box.minY, 36.5)).to.be.true; + expect(Util.isNumberEqual(box.maxY, 103.77723887000138)).to.be.true; + canvas.draw(); + }); + + it('p3', function() { + cubic.attr('p3', [ 110, 0 ]); + expect(cubic.attr('p3')[0]).to.equal(110); + expect(cubic.attr('p3')[1]).to.equal(0); + const box = cubic.getBBox(); + expect(Util.isNumberEqual(box.minX, 67.5)).to.be.true; + expect(Util.isNumberEqual(box.maxX, 152.5)).to.be.true; + expect(Util.isNumberEqual(box.minY, 30.447819730085683)).to.be.true; + expect(Util.isNumberEqual(box.maxY, 53.66354358160779)).to.be.true; + canvas.draw(); + }); + + it('p4', function() { + console.log(cubic.getBBox()); + cubic.attr('p4', [ 150, 90 ]); + expect(cubic.attr('p4')[0]).to.equal(150); + expect(cubic.attr('p4')[1]).to.equal(90); + /* var box = cubic.getBBox(); + expect(Util.isNumberEqual(box.minX, 67.5)).to.be.true; + expect(Util.isNumberEqual(box.maxX, 152.5)).to.be.true; + expect(Util.isNumberEqual(box.minY, 36.5)).to.be.true; + expect(Util.isNumberEqual(box.maxY, 92.5)).to.be.true; + */ + canvas.draw(); + }); + + it('lineWidth', function() { + cubic.attr('lineWidth', 2); + expect(cubic.attr('lineWidth')).to.equal(2); + const box = cubic.getBBox(); + expect(Util.isNumberEqual(box.minX, 69)).to.be.true; + expect(Util.isNumberEqual(box.maxX, 151)).to.be.true; + expect(Util.isNumberEqual(box.minY, 38)).to.be.true; + expect(Util.isNumberEqual(box.maxY, 91)).to.be.true; + canvas.draw(); + }); + + it('isHit', function() { + expect(cubic.isHit(70, 39)).to.be.true; + expect(cubic.isHit(102.5, 46.2)).to.be.true; + expect(cubic.isHit(150, 90)).to.be.true; + }); + + it('getPoint', function() { + const cubic = new G.Cubic({ + attrs: { + p1: [ 100, 100 ], + p2: [ 200, 200 ], + p3: [ 300, 0 ], + p4: [ 400, 100 ] + } + }); + + const point = cubic.getPoint(0); + expect(point.x).to.equal(100); + expect(point.y).to.equal(100); + const point1 = cubic.getPoint(1); + expect(point1.x).to.equal(400); + expect(point1.y).to.equal(100); + const point2 = cubic.getPoint(0.25); + expect(point2.x).to.equal(175); + expect(point2.y).to.equal(128.125); + expect(cubic.isHit(point2.x, point2.y)).to.be.true; + const point3 = cubic.getPoint(0.5); + expect(point3.x).to.equal(250); + expect(point3.y).to.equal(100); + expect(cubic.isHit(point3.x, point3.y)).to.be.true; + const point4 = cubic.getPoint(0.75); + expect(point4.x).to.equal(325); + expect(point4.y).to.equal(71.875); + expect(cubic.isHit(point4.x, point4.y)).to.be.true; + const point5 = cubic.getPoint(0.3); + expect(Util.isNumberEqual(point5.x, 190)).to.be.true; + expect(Util.isNumberEqual(point5.y, 125.2)).to.be.true; + expect(cubic.isHit(point5.x, point5.y)).to.be.true; + }); +}); diff --git a/test/unit/g/shape-ellipse-spec.js b/test/unit/g/shape-ellipse-spec.js new file mode 100644 index 000000000..eee72d60a --- /dev/null +++ b/test/unit/g/shape-ellipse-spec.js @@ -0,0 +1,176 @@ +const expect = require('chai').expect; +const G = require('../../../src/g/index'); +const Canvas = require('../../../src/canvas'); +const div = document.createElement('div'); +div.id = 'canvas-ellipse'; +document.body.appendChild(div); + + +describe('Ellipse', function() { + + const canvas = new Canvas({ + containerId: 'canvas-ellipse', + width: 200, + height: 200, + pixelRatio: 1 + }); + + const ellipse = new G.Ellipse({ + attrs: { + x: 0, + y: 0, + rx: 1, + ry: 1 + } + }); + G.debug(true); + it('init attr', function() { + expect(ellipse.attr('x')).to.equal(0); + expect(ellipse.attr('y')).to.equal(0); + expect(ellipse.attr('rx')).to.equal(1); + expect(ellipse.attr('ry')).to.equal(1); + expect(ellipse.attr('lineWidth')).to.equal(1); + expect(ellipse.attr('stroke')).to.be.undefined; + expect(ellipse.attr('fill')).to.be.undefined; + const box = ellipse.getBBox(); + expect(box.minX).to.equal(-1.5); + expect(box.maxX).to.equal(1.5); + expect(box.minY).to.equal(-1.5); + expect(box.maxY).to.equal(1.5); + }); + + it('x', function() { + ellipse.attr('x', 20); + expect(ellipse.attr('x')).to.equal(20); + const box = ellipse.getBBox(); + expect(box.minX).to.equal(18.5); + expect(box.maxX).to.equal(21.5); + expect(box.minY).to.equal(-1.5); + expect(box.maxY).to.equal(1.5); + }); + + it('y', function() { + ellipse.attr('y', 30); + expect(ellipse.attr('y')).to.equal(30); + const box = ellipse.getBBox(); + expect(box.minX).to.equal(18.5); + expect(box.maxX).to.equal(21.5); + expect(box.minY).to.equal(28.5); + expect(box.maxY).to.equal(31.5); + }); + + it('rx', function() { + expect(ellipse.attr('rx')).to.equal(1); + ellipse.attr('rx', 5); + expect(ellipse.attr('rx')).to.equal(5); + const box = ellipse.getBBox(); + expect(box.minX).to.equal(14.5); + expect(box.maxX).to.equal(25.5); + expect(box.minY).to.equal(28.5); + expect(box.maxY).to.equal(31.5); + }); + + it('ry', function() { + expect(ellipse.attr('ry')).to.equal(1); + ellipse.attr('ry', 10); + expect(ellipse.attr('ry')).to.equal(10); + const box = ellipse.getBBox(); + expect(box.minX).to.equal(14.5); + expect(box.maxX).to.equal(25.5); + expect(box.minY).to.equal(19.5); + expect(box.maxY).to.equal(40.5); + }); + + + it('lineWidth', function() { + expect(ellipse.attr('lineWidth')).to.equal(1); + ellipse.attr('lineWidth', 2); + expect(ellipse.attr('lineWidth')).to.equal(2); + const box = ellipse.getBBox(); + expect(box.minX).to.equal(14); + expect(box.maxX).to.equal(26); + expect(box.minY).to.equal(19); + expect(box.maxY).to.equal(41); + }); + + it('stroke', function() { + ellipse.attr('stroke', 'l (0) 0:#959231 1:#00cd54'); + expect(ellipse.attr('stroke')).to.equal('l (0) 0:#959231 1:#00cd54'); + canvas.add(ellipse); + canvas.draw(); + }); + + it('fill', function() { + ellipse.attr('fill', 'l (90) 0:#959231 1:#00cd54'); + expect(ellipse.attr('fill')).to.equal('l (90) 0:#959231 1:#00cd54'); + canvas.draw(); + }); + + + it('isHit', function() { + const ellipse1 = new G.Ellipse({ + attrs: { + x: 50, + y: 50, + rx: 200, + ry: 100 + } + }); + + expect(ellipse1.isHit(-150, 50)).to.be.false; + expect(ellipse1.isHit(50, -50)).to.be.false; + expect(ellipse1.isHit(250, 50)).to.be.false; + expect(ellipse1.isHit(50, 150)).to.be.false; + + ellipse1.attr('stroke', 'red'); + expect(ellipse1.isHit(-150, 50)).to.be.true; + expect(ellipse1.isHit(50, -50)).to.be.true; + expect(ellipse1.isHit(250, 50)).to.be.true; + expect(ellipse1.isHit(50, 150)).to.be.true; + + const ellipse2 = new G.Ellipse({ + attrs: { + x: 100, + y: 200, + rx: 50, + ry: 80 + } + }); + + expect(ellipse2.isHit(70, 200)).to.be.false; + expect(ellipse2.isHit(100, 150)).to.be.false; + expect(ellipse2.isHit(130, 200)).to.be.false; + expect(ellipse2.isHit(100, 230)).to.be.false; + + ellipse2.attr('fill', 'green'); + + expect(ellipse2.isHit(70, 200)).to.be.true; + expect(ellipse2.isHit(100, 150)).to.be.true; + expect(ellipse2.isHit(130, 200)).to.be.true; + expect(ellipse2.isHit(100, 230)).to.be.true; + + const ellipse3 = new G.Ellipse({ + attrs: { + x: 200, + y: 200, + rx: 50, + ry: 100 + } + }); + + expect(ellipse3.isHit(150, 200)).to.be.false; + expect(ellipse3.isHit(250, 200)).to.be.false; + expect(ellipse3.isHit(200, 100)).to.be.false; + expect(ellipse3.isHit(200, 300)).to.be.false; + expect(ellipse3.isHit(170, 200)).to.be.false; + ellipse3.attr({ + fill: 'green', + stroke: 'red' + }); + expect(ellipse3.isHit(150, 200)).to.be.true; + expect(ellipse3.isHit(250, 200)).to.be.true; + expect(ellipse3.isHit(200, 100)).to.be.true; + expect(ellipse3.isHit(200, 300)).to.be.true; + expect(ellipse3.isHit(170, 200)).to.be.true; + }); +}); diff --git a/test/unit/g/shape-fan-spec.js b/test/unit/g/shape-fan-spec.js new file mode 100644 index 000000000..7ec8030ca --- /dev/null +++ b/test/unit/g/shape-fan-spec.js @@ -0,0 +1,138 @@ +const expect = require('chai').expect; +const G = require('../../../src/g/index'); +const Canvas = require('../../../src/canvas'); +const Util = require('../../../src/util/index'); +const div = document.createElement('div'); +div.id = 'canvas-fan'; +document.body.appendChild(div); + + +describe('CFan', function() { + const canvas = new Canvas({ + containerId: 'canvas-fan', + width: 200, + heigth: 200, + pixelRatio: 1 + }); + G.debug(true); + const fan = new G.Fan({ + attrs: { + x: 0, + y: 0, + rs: 0, + re: 0, + startAngle: 0, + endAngle: 0, + clockwise: false + } + }); + it('init attr', function() { + expect(fan.attr('x')).to.equal(0); + expect(fan.attr('y')).to.equal(0); + expect(fan.attr('rs')).to.equal(0); + expect(fan.attr('re')).to.equal(0); + expect(fan.attr('startAngle')).to.equal(0); + expect(fan.attr('endAngle')).to.equal(0); + expect(fan.attr('clockwise')).to.be.false; + expect(fan.attr('lineWidth')).to.equal(1); + const box = fan.getBBox(); + expect(box.minX).to.equal(-0.5); + expect(box.maxX).to.equal(0.5); + expect(box.minY).to.equal(-0.5); + expect(box.maxY).to.equal(0.5); + }); + + it('x', function() { + fan.attr('x', 10); + expect(fan.attr('x')).to.equal(10); + const box = fan.getBBox(); + expect(box.minX).to.equal(9.5); + expect(box.maxX).to.equal(10.5); + }); + + it('y', function() { + fan.attr('y', 20); + expect(fan.attr('y')).to.equal(20); + const box = fan.getBBox(); + expect(box.minY).to.equal(19.5); + expect(box.maxY).to.equal(20.5); + }); + + it('startAngle', function() { + fan.attr('startAngle', Math.PI); + expect(Util.isNumberEqual(fan.attr('startAngle'), Math.PI)).to.be.true; + }); + + it('endAngle', function() { + fan.attr('endAngle', Math.PI * 3 / 2); + expect(Util.isNumberEqual(fan.attr('endAngle'), Math.PI * 3 / 2)).to.be.true; + }); + + it('rs', function() { + expect(fan.attr('rs')).to.equal(0); + fan.attr('rs', 10); + expect(fan.attr('rs')).to.equal(10); + const box = fan.getBBox(); + expect(Util.isNumberEqual(box.minX, -0.5)).to.be.true; + expect(Util.isNumberEqual(box.maxX, 10.5)).to.be.true; + expect(Util.isNumberEqual(box.minY, 9.5)).to.be.true; + expect(Util.isNumberEqual(box.maxY, 20.5)).to.be.true; + }); + + it('re', function() { + expect(fan.attr('re')).to.equal(0); + fan.attr('re', 30); + expect(fan.attr('re')).to.equal(30); + canvas.draw(); + const box = fan.getBBox(); + expect(Util.isNumberEqual(box.minX, -20.5)).to.be.true; + expect(Util.isNumberEqual(box.maxX, 10.5)).to.be.true; + expect(Util.isNumberEqual(box.minY, -10.5)).to.be.true; + expect(Util.isNumberEqual(box.maxY, 20.5)).to.be.true; + }); + + it('clockwise', function() { + expect(fan.attr('clockwise')).to.be.false; + fan.attr('clockwise', true); + expect(fan.attr('clockwise')).to.be.true; + const box = fan.getBBox(); + expect(Util.isNumberEqual(box.minX, -20.5)).to.be.true; + expect(Util.isNumberEqual(box.maxX, 40.5)).to.be.true; + expect(Util.isNumberEqual(box.minY, -10.5)).to.be.true; + expect(Util.isNumberEqual(box.maxY, 50.5)).to.be.true; + }); + + it('lineWidth', function() { + expect(fan.attr('lineWidth')).to.equal(1); + fan.attr('lineWidth', 2); + expect(fan.attr('lineWidth')).to.equal(2); + const box = fan.getBBox(); + expect(Util.isNumberEqual(box.minX, -21)).to.be.true; + expect(Util.isNumberEqual(box.maxX, 41)).to.be.true; + expect(Util.isNumberEqual(box.minY, -11)).to.be.true; + expect(Util.isNumberEqual(box.maxY, 51)).to.be.true; + }); + + it('stroke', function() { + fan.attr({ + x: 40, + y: 40 + }); + fan.attr('stroke', 'l (210) 0:#ff0000 1:#ffffff'); + expect(fan.attr('stroke')).to.equal('l (210) 0:#ff0000 1:#ffffff'); + canvas.add(fan); + canvas.draw(); + }); + + it('fill', function() { + fan.attr('fill', 'l (130) 0:#0000ff 1:#ffffff'); + expect(fan.attr('fill')).to.equal('l (130) 0:#0000ff 1:#ffffff'); + canvas.draw(); + }); + + it('isHit', function() { + expect(fan.isHit(40, 40)).to.be.false; + expect(fan.isHit(40, 60)).to.be.true; + }); +}); + diff --git a/test/unit/g/shape-image-spec.js b/test/unit/g/shape-image-spec.js new file mode 100644 index 000000000..0ad2a77bf --- /dev/null +++ b/test/unit/g/shape-image-spec.js @@ -0,0 +1,180 @@ +const expect = require('chai').expect; +const G = require('../../../src/g/index'); +const Canvas = require('../../../src/canvas'); +const div = document.createElement('div'); +div.id = 'canvas-img'; +document.body.appendChild(div); + +describe('Image', function() { + + const can1 = document.createElement('canvas'); + can1.id = 'img1'; + can1.width = 800; + can1.height = 800; + const canvas = new Canvas({ + containerId: 'canvas-img', + width: 200, + height: 200, + pixelRatio: 1 + }); + G.debug(true); + const image = new G.Image({ + attrs: { + x: 0, + y: 0, + width: 0, + height: 0 + } + }); + it('init attr', function() { + expect(image.attr('x')).to.equal(0); + expect(image.attr('y')).to.equal(0); + expect(image.attr('img')).to.be.undefined; + expect(image.attr('width')).to.equal(0); + expect(image.attr('height')).to.equal(0); + expect(image.attr('sx')).to.be.undefined; + expect(image.attr('sy')).to.be.undefined; + expect(image.attr('swidth')).to.be.undefined; + expect(image.attr('sheight')).to.be.undefined; + const box = image.getBBox(); + expect(box.minX).to.equal(0); + expect(box.maxX).to.equal(0); + expect(box.minY).to.equal(0); + expect(box.maxY).to.equal(0); + }); + + it('img', function(done) { + const img = new Image(); + img.onload = function() { + image.attr('img', img); + const box = image.getBBox(); + expect(box.minX).to.equal(0); + expect(box.minY).to.equal(0); + expect(box.maxX).to.equal(768); + expect(box.maxY).to.equal(1024); + canvas.add(image); + canvas.draw(); + done(); + }; + img.src = '../../../demos/test1.jpg'; + }); + + it('canvas', function() { + const image = new G.Image({ + attrs: { + x: 0, + y: 0 + } + }); + const img = can1; + image.attr('img', img); + const box = image.getBBox(); + expect(box.minX).to.equal(0); + expect(box.minY).to.equal(0); + expect(box.maxX).to.equal(800); + expect(box.maxY).to.equal(800); + canvas.add(image); + canvas.draw(); + }); + + it('imageData', function(done) { + const image = new G.Image({ + attrs: { + x: 0, + y: 0 + } + }); + const img = can1.getContext('2d').getImageData(0, 0, 800, 800); + image.attr('img', img); + const box = image.getBBox(); + expect(box.minX).to.equal(0); + expect(box.minY).to.equal(0); + expect(box.maxX).to.equal(800); + expect(box.maxY).to.equal(800); + canvas.add(image); + canvas.draw(); + done(); + }); + + it('width', function() { + expect(image.attr('width')).to.equal(768); + image.attr('width', 200); + expect(image.attr('width')).to.equal(200); + const box = image.getBBox(); + expect(box.minX).to.equal(0); + expect(box.maxX).to.equal(200); + canvas.draw(); + }); + + it('height', function() { + expect(image.attr('height')).to.equal(1024); + image.attr('height', 200); + expect(image.attr('height')).to.equal(200); + const box = image.getBBox(); + expect(box.minY).to.equal(0); + expect(box.maxY).to.equal(200); + canvas.draw(); + }); + + it('x', function() { + image.attr('x', 10); + expect(image.attr('x')).to.equal(10); + const box = image.getBBox(); + expect(box.minX).to.equal(10); + expect(box.maxX).to.equal(210); + canvas.draw(); + }); + + it('y', function() { + image.attr('y', 10); + expect(image.attr('y')).to.equal(10); + const box = image.getBBox(); + expect(box.minY).to.equal(10); + expect(box.maxY).to.equal(210); + canvas.draw(); + }); + + it('sx, sy, swidth, sheight', function() { + image.attr({ + sx: 20, + sy: 20, + swidth: 100, + sheight: 200 + }); + canvas.draw(); + }); + + it('normal use', function() { + const image1 = new G.Image({ + attrs: { + x: 300, + y: 300, + width: 300, + height: 300, + img: '../../../demos/test2.jpg' + } + }); + + canvas.add(image1); + canvas.draw(); + }); + + it('isHit', function() { + expect(image.isHit(10, 10)).to.be.true; + expect(image.isHit(210, 210)).to.be.true; + expect(image.isHit(20, 20)).to.be.true; + expect(image.isHit(31, 43)).to.be.true; + expect(image.isHit(300, 300)).to.be.false; + }); + + it('image onload && image.remove(true)', function() { + const image = new G.Image({ + attrs: { + img: 'http://alipay-rmsdeploy-assets-private.cn-hangzhou.alipay.aliyun-inc.com/rmsportal/IHJtPedUbTUPQCx.png' + } + }); + canvas.add(image); + image.remove(true); + canvas.draw(); + }); +}); diff --git a/test/unit/g/shape-line-spec.js b/test/unit/g/shape-line-spec.js new file mode 100644 index 000000000..5d4e75c39 --- /dev/null +++ b/test/unit/g/shape-line-spec.js @@ -0,0 +1,132 @@ +const expect = require('chai').expect; +const G = require('../../../src/g/index'); +const Canvas = require('../../../src/canvas'); +const div = document.createElement('div'); +div.id = 'canvas-line'; +document.body.appendChild(div); + +describe('Line', function() { + + const canvas = new Canvas({ + containerId: 'canvas-line', + width: 200, + height: 200, + pixelRatio: 1 + }); + G.debug(true); + const line = new G.Line({ + attrs: { + x1: 0, + x2: 0, + y1: 0, + y2: 0, + arrow: false + } + }); + it('init attrs', function() { + expect(line.attr('x1')).to.equal(0); + expect(line.attr('y1')).to.equal(0); + expect(line.attr('x2')).to.equal(0); + expect(line.attr('y2')).to.equal(0); + expect(line.attr('lineWidth')).to.equal(1); + expect(line.attr('stroke')).to.be.undefined; + expect(line.attr('fill')).to.be.undefined; + expect(line.attr('arrow')).to.be.false; + const box = line.getBBox(); + expect(box.minX).to.equal(-0.5); + expect(box.maxX).to.equal(0.5); + expect(box.minY).to.equal(-0.5); + expect(box.maxY).to.equal(0.5); + }); + + it('x1', function() { + line.attr('x1', 10); + expect(line.attr('x1')).to.equal(10); + const box = line.getBBox(); + expect(box.minX).to.equal(-0.5); + expect(box.maxX).to.equal(10.5); + }); + + it('y1', function() { + line.attr('y1', 15); + expect(line.attr('y1')).to.equal(15); + const box = line.getBBox(); + expect(box.minY).to.equal(-0.5); + expect(box.maxY).to.equal(15.5); + }); + + it('x2', function() { + line.attr('x2', 59); + expect(line.attr('x2')).to.equal(59); + const box = line.getBBox(); + expect(box.minX).to.equal(9.5); + expect(box.maxX).to.equal(59.5); + }); + + it('y2', function() { + line.attr('y2', 80); + expect(line.attr('y2')).to.equal(80); + const box = line.getBBox(); + expect(box.minY).to.equal(14.5); + expect(box.maxY).to.equal(80.5); + }); + + it('lineWidth', function() { + expect(line.attr('lineWidth')).to.equal(1); + line.attr('lineWidth', 2); + expect(line.attr('lineWidth')).to.equal(2); + const box = line.getBBox(); + expect(box.minX).to.equal(9); + expect(box.maxX).to.equal(60); + expect(box.minY).to.equal(14); + expect(box.maxY).to.equal(81); + }); + + it('stroke', function() { + line.attr('stroke', 'l (0) 0.1:#0fedae 1:#6542da'); + expect(line.attr('stroke')).to.equal('l (0) 0.1:#0fedae 1:#6542da'); + canvas.add(line); + canvas.draw(); + }); + + it('isHit', function() { + expect(line.isHit(9, 14)).to.be.true; + expect(line.isHit(34.5, 47.5)).to.be.true; + expect(line.isHit(8, 11)).to.be.false; + const line1 = new G.Line({ + attrs: { + x1: 0, + y1: 0, + x2: 100, + y2: 100 + } + }); + expect(line1.isHit(101, 101)).to.be.false; + expect(line1.isHit(100, 100)).to.be.false; + line1.attr('stroke', 'red'); + expect(line1.isHit(101, 101)).to.be.false; + expect(line1.isHit(100, 100)).to.be.true; + }); + + it('arrow', function() { + line.attr('arrow', true); + expect(line.attr('arrow')).to.be.true; + canvas.draw(); + }); + + it('getPoint', function() { + const line = new G.Line({ + attrs: { + x1: 0, + y1: 0, + x2: 200, + y2: 300 + } + }); + + const point = line.getPoint(0.5); + expect(point.x).to.equal(100); + expect(point.y).to.equal(150); + }); +}); + diff --git a/test/unit/g/shape-marker-spec.js b/test/unit/g/shape-marker-spec.js new file mode 100644 index 000000000..130af6fa3 --- /dev/null +++ b/test/unit/g/shape-marker-spec.js @@ -0,0 +1,42 @@ +const expect = require('chai').expect; +const Canvas = require('../../../src/canvas'); +const div = document.createElement('div'); +div.id = 'canvas-marker'; +document.body.appendChild(div); + + +describe('Marker', function() { + const canvas = new Canvas({ + containerId: 'canvas-marker', + width: 200, + height: 200, + pixelRatio: 1 + }); + it('init', function() { + const marker = canvas.addShape('marker', { + attrs: { + x: 10, + y: 10, + radius: 10, + fill: 'red', + symbol: 'circle' + } + }); + expect(marker.attr('x')).to.equal(10); + expect(marker.attr('y')).to.equal(10); + }); + + it('hit', function() { + const marker = canvas.addShape('marker', { + attrs: { + x: 20, + y: 20, + radius: 10, + fill: 'blue', + symbol: 'circle' + } + }); + expect(marker.isHit(20, 20)).to.be.true; + expect(marker.isHit(10, 10)).to.be.false; + }); +}); diff --git a/test/unit/g/shape-math-arc-spec.js b/test/unit/g/shape-math-arc-spec.js new file mode 100644 index 000000000..9a26743a0 --- /dev/null +++ b/test/unit/g/shape-math-arc-spec.js @@ -0,0 +1,60 @@ +const expect = require('chai').expect; +const Arc = require('../../../src/g/shape/math/arc'); +const Util = require('../../../src/util/index'); + + +describe('Arc math', function() { + it('nearAngle', function() { + const angle = Util.toRadian(20); + const startAngle = Util.toRadian(0); + const endAngle = Util.toRadian(90); + + expect(Util.isNumberEqual(Util.toDegree(Arc.nearAngle(angle, startAngle, endAngle)), 20)).to.be.true; + }); + + it('nearAngle1', function() { + const angle = Util.toRadian(-20); + const startAngle = Util.toRadian(0); + const endAngle = Util.toRadian(90); + + expect(Util.isNumberEqual(Util.toDegree(Arc.nearAngle(angle, startAngle, endAngle)), 0)).to.be.true; + }); + + it('nearAngle2', function() { + const angle = Util.toRadian(110); + const startAngle = Util.toRadian(90); + const endAngle = Util.toRadian(-30); + + expect(Util.isNumberEqual(Util.toDegree(Arc.nearAngle(angle, startAngle, endAngle)), 110)).to.be.true; + }); + + it('nearAngle3', function() { + const angle = Util.toRadian(110); + const startAngle = Util.toRadian(90); + const endAngle = Util.toRadian(-30); + + expect(Util.isNumberEqual(Util.toDegree(Arc.nearAngle(angle, startAngle, endAngle)), 110)).to.be.true; + }); + + it('nearAngle4', function() { + const angle = Util.toRadian(110); + const startAngle = Util.toRadian(90); + const endAngle = Util.toRadian(-30); + + expect(Util.isNumberEqual(Util.toDegree(Arc.nearAngle(angle, startAngle, endAngle, true)), 90)).to.be.true; + }); + + // it('nearAngle', function() { + // const angle = Util.toRadian(30); + // const startAngle = Util.toRadian(0); + // const endAngle = Util.toRadian(360); + // }); + + + it('arcProjectPoint', function() { + expect(Util.isNumberEqual( + Arc.pointDistance(10, 10, 10, -Math.PI / 2, Math.PI / 2, false, 20, 0), + Math.sqrt(2) * 10 - 10 + )).to.be.true; + }); +}); diff --git a/test/unit/g/shape-path-spec.js b/test/unit/g/shape-path-spec.js new file mode 100644 index 000000000..0b69ff6f3 --- /dev/null +++ b/test/unit/g/shape-path-spec.js @@ -0,0 +1,534 @@ +const expect = require('chai').expect; +const G = require('../../../src/g/index'); +const Canvas = require('../../../src/canvas'); +const div = document.createElement('div'); +div.id = 'canvas-path'; +document.body.appendChild(div); + +describe('Path', function() { + + const canvas = new Canvas({ + containerId: 'canvas-path', + width: 800, + height: 800, + pixelRatio: 1 + }); + G.debug(true); + const img = document.createElement('img'); + img.src = '../../../demos/test1.jpg'; + img.id = 'img'; + document.body.appendChild(img); + + const path = new G.Path(); + + it('init attrs', function() { + expect(path.attr('path')).to.undefined; + expect(path.attr('lineWidth')).to.equal(1); + expect(path.getBBox()).to.be.null; + canvas.add(path); + canvas.draw(); + }); + + it('path', function() { + path.attr('path', null); + expect(path.getBBox()).to.be.null; + path.attr('path', []); + expect(path.getBBox()).to.be.null; + path.attr('path', [ + [ 'a' ] + ]); + expect(path.getBBox()).to.be.null; + path.attr('path', [ + [ 'M', 200, 200 ], + [ 'L', 300, 300 ] + ]); + + expect(path.get('segments').length).to.equal(2); + const box = path.getBBox(); + expect(box.minX).to.equal(199.5); + expect(box.maxX).to.equal(300.5); + expect(box.minY).to.equal(199.5); + expect(box.maxY).to.equal(300.5); + }); + + it('lineWidth', function() { + expect(path.attr('lineWidth')).to.equal(1); + path.attr('lineWidth', 2); + expect(path.attr('lineWidth')).to.equal(2); + const box = path.getBBox(); + expect(box.minX).to.equal(199); + expect(box.maxX).to.equal(301); + expect(box.minY).to.equal(199); + expect(box.maxY).to.equal(301); + }); + + it('stroke', function() { + path.attr('stroke', 'l (0) 0:#fff000 1:#000fff'); + expect(path.attr('stroke')).to.equal('l (0) 0:#fff000 1:#000fff'); + canvas.add(path); + canvas.draw(); + }); + + it('fill', function() { + const path = new G.Path({ + attrs: { + path: [ + [ 'M', 200, 200 ], + [ 'L', 300, 200 ], + [ 'L', 300, 300 ], + [ 'Z' ] + ], + fill: 'red' + } + }); + expect(path.attr('fill')).to.equal('red'); + canvas.add(path); + canvas.draw(); + }); + + it('path string', function() { + const path = new G.Path({ + attrs: { + path: 'M100,600' + + 'l 50,-25' + + 'a25,25 -30 0,1 50,-25' + + 'l 50,-25' + + 'a25,50 -30 0,1 50,-25' + + 'l 50,-25' + + 'a25,75 -30 0,1 50,-25' + + 'l 50,-25' + + 'a25,100 -30 0,1 50,-25' + + 'l 50,-25' + + 'l 0, 200,' + + 'z', + lineWidth: 10, + lineJoin: 'round', + stroke: 'red' + } + }); + + canvas.add(path); + canvas.draw(); + }); + + it('l and L', function() { + const path = new G.Path({ + attrs: { + path: [ + [ 'M', 400, 400 ], + [ 'L', 400, 500 ], + [ 'l', 50, 50 ], + [ 'Z' ] + ], + stroke: 'red', + fill: 'green', + arrow: true + } + }); + expect(path.isHit(400, 400)).to.be.true; + expect(path.isHit(400, 500)).to.be.true; + expect(path.isHit(450, 550)).to.be.true; + expect(path.isHit(405, 450)).to.be.false; + canvas.add(path); + expect(path.isHit(405, 450)).to.be.true; + canvas.draw(); + }); + + it('h and H', function() { + const path = new G.Path({ + attrs: { + path: [ + [ 'M', 200, 400 ], + [ 'H', 400 ], + [ 'h', 100 ] + ], + stroke: 'red', + arrow: true + } + }); + expect(path.isHit(200, 400)).to.be.true; + expect(path.isHit(300, 400)).to.be.true; + expect(path.isHit(400, 400)).to.be.true; + expect(path.isHit(500, 400)).to.be.true; + canvas.add([ path ]); + canvas.draw(); + }); + + it('v and V', function() { + const path = new G.Path({ + attrs: { + path: [ + [ 'M', 200, 400 ], + [ 'V', 600 ], + [ 'v', 100 ] + ], + stroke: 'red', + arrow: true + } + }); + expect(path.isHit(200, 400)).to.be.true; + expect(path.isHit(200, 500)).to.be.true; + expect(path.isHit(200, 600)).to.be.true; + expect(path.isHit(200, 700)).to.be.true; + canvas.add([ path ]); + canvas.draw(); + }); + + it('q and Q', function() { + const path = new G.Path({ + attrs: { + path: [ + [ 'M', 200, 400 ], + [ 'Q', 300, 300, 400, 400 ] + ], + stroke: 'red', + arrow: true + } + }); + expect(path.isHit(200, 400)).to.be.true; + expect(path.isHit(300, 350)).to.be.true; + expect(path.isHit(400, 400)).to.be.true; + + const path1 = new G.Path({ + attrs: { + path: [ + [ 'M', 200, 400 ], + [ 'q', 50, 50, 100, 0 ] + ], + stroke: 'red', + arrow: true + } + }); + + expect(path1.isHit(200, 400)).to.be.true; + expect(path1.isHit(250, 425)).to.be.true; + expect(path1.isHit(300, 400)).to.be.true; + canvas.add([ path, path1 ]); + canvas.draw(); + }); + + it('t and T', function() { + const path = new G.Path({ + attrs: { + path: [ + [ 'M', 200, 400 ], + [ 'Q', 300, 300, 400, 400 ], + [ 'T', 600, 400 ] + ], + stroke: 'red', + arrow: true + } + }); + expect(path.isHit(200, 400)).to.be.true; + expect(path.isHit(300, 350)).to.be.true; + expect(path.isHit(400, 400)).to.be.true; + expect(path.isHit(500, 450)).to.be.true; + expect(path.isHit(600, 400)).to.be.true; + + const path1 = new G.Path({ + attrs: { + path: [ + [ 'M', 200, 400 ], + [ 'Q', 300, 300, 400, 400 ], + [ 't', 100, 0 ] + ], + stroke: 'red', + arrow: true + } + }); + expect(path1.isHit(200, 400)).to.be.true; + expect(path1.isHit(300, 350)).to.be.true; + expect(path1.isHit(400, 400)).to.be.true; + expect(path1.isHit(475, 450)).to.be.true; + expect(path1.isHit(500, 400)).to.be.true; + + + const path2 = new G.Path({ + attrs: { + path: [ + [ 'M', 200, 400 ], + [ 'L', 400, 400 ], + [ 't', 100, 0 ] + ], + stroke: 'red', + arrow: true + } + }); + expect(path2.isHit(200, 400)).to.be.true; + expect(path2.isHit(400, 400)).to.be.true; + expect(path2.isHit(475, 450)).to.be.false; + expect(path2.isHit(500, 400)).to.be.true; + canvas.add([ path, path1, path2 ]); + canvas.draw(); + }); + + it('c and C', function() { + const path = new G.Path({ + attrs: { + path: [ + [ 'M', 200, 400 ], + [ 'C', 300, 300, 400, 500, 500, 400 ] + ], + stroke: 'red', + arrow: true + } + }); + + expect(path.isHit(200, 400)).to.be.true; + expect(path.isHit(350, 400)).to.be.true; + expect(path.isHit(500, 400)).to.be.true; + + const path1 = new G.Path({ + attrs: { + path: [ + [ 'M', 200, 400 ], + [ 'c', 100, -100, 200, 100, 300, 0 ] + ], + stroke: 'red' + } + }); + + expect(path1.isHit(200, 400)).to.be.true; + expect(path1.isHit(350, 400)).to.be.true; + expect(path1.isHit(500, 400)).to.be.true; + canvas.add([ path, path1 ]); + canvas.draw(); + }); + + it('s and S', function() { + const path = new G.Path({ + attrs: { + path: [ + [ 'M', 200, 400 ], + [ 'C', 300, 300, 400, 500, 500, 400 ], + [ 'S', 700, 500, 800, 400 ] + ], + stroke: 'red' + } + }); + expect(path.isHit(200, 400)).to.be.true; + expect(path.isHit(350, 400)).to.be.true; + expect(path.isHit(500, 400)).to.be.true; + expect(path.isHit(650, 400)).to.be.true; + expect(path.isHit(800, 400)).to.be.true; + + const path1 = new G.Path({ + attrs: { + path: [ + [ 'M', 200, 400 ], + [ 'C', 300, 300, 400, 500, 500, 400 ], + [ 's', 200, 100, 300, 0 ] + ], + stroke: 'blue' + } + }); + expect(path1.isHit(200, 400)).to.be.true; + expect(path1.isHit(350, 400)).to.be.true; + expect(path1.isHit(500, 400)).to.be.true; + expect(path1.isHit(650, 400)).to.be.true; + expect(path1.isHit(800, 400)).to.be.true; + + const path2 = new G.Path({ + attrs: { + path: [ + [ 'M', 200, 400 ], + [ 'L', 500, 400 ], + [ 's', 200, 100, 300, 0 ] + ], + stroke: 'red', + arrow: true + } + }); + expect(path2.isHit(200, 400)).to.be.true; + expect(path2.isHit(500, 400)).to.be.true; + expect(path2.isHit(650, 400)).to.be.false; + expect(path2.isHit(675, 450)).to.be.true; + expect(path2.isHit(800, 400)).to.be.true; + canvas.add([ path, path1, path2 ]); + canvas.draw(); + }); + + it('a And A', function() { + const path = new G.Path({ + attrs: { + path: [ + [ 'M', 300, 300 ], + [ 'A', 50, 50, 0, 0, 1, 400, 400 ] + ], + stroke: 'red' + } + }); + + expect(path.isHit(300, 300)).to.be.true; + expect(path.isHit(400, 400)).to.be.true; + expect(path.isHit(400, 300)).to.be.true; + + const path1 = new G.Path({ + attrs: { + path: [ + [ 'M', 300, 300 ], + [ 'A', 50, 50, 0, 0, 1, 400, 400 ] + ], + stroke: 'red' + } + }); + expect(path1.isHit(300, 300)).to.be.true; + expect(path1.isHit(400, 400)).to.be.true; + expect(path1.isHit(400, 300)).to.be.true; + + /* var img = new Image(); + + img.onload = function() { + + }; + + var path2 = new G.Path({ + attrs: { + path: [ + ['M', 300, 300], + ['A', 50, 50, 0, 1, 1, 300, 400], + ['z'] + ], + stroke: 'p a img' + } + }); + expect(path2.isHit(300, 300)).to.be.true; + expect(path2.isHit(300, 400)).to.be.true; + expect(path2.isHit(350, 350)).to.be.true; + expect(path2.isHit(300, 350)).to.be.true; + canvas.add(path2); + canvas.draw(); + path2.set('attrs', { + path: [ + ['M', 300, 300], + ['A', 50, 50, 0, 1, 1, 300, 400], + ['z'] + ], + stroke: 'p x img' + }); + path2.hide(); + path2.show(); + canvas.draw(); + + var path3 = new G.Path({ + attrs: { + path: [ + ['M', 300, 300], + ['A', 50, 50, 0, 1, 1, 300, 400], + ['z'] + ], + stroke: 'p y img' + } + }); + canvas.add(path3); + canvas.draw(); + + var path4 = new G.Path({ + attrs: { + path: [ + ['M', 300, 300], + ['A', 50, 50, 0, 1, 1, 300, 400], + ['z'] + ], + stroke: 'p n img' + } + }); + canvas.add(path4); + canvas.draw(); + + + var path5 = new G.Path({ + attrs: { + path: [ + ['M', 300, 300], + ['A', 50, 50, 0, 1, 1, 300, 400], + ['z'] + ], + stroke: 'p e img' + } + }); + canvas.add(path5); + canvas.draw(); + + var path6 = new G.Path({ + attrs: { + path: [ + ['M', 300, 300], + ['A', 50, 50, 0, 1, 1, 300, 400], + ['z'] + ], + stroke: 'p a img' + } + }); + canvas.add(path6); + */ + canvas.draw(); + }); + + it('getPoint', function() { + const path = [ + [ 'M', 300, 300 ], + [ 'L', 300, 50 ], + [ 'L', 50, 50 ], + [ 'L', 50, 300 ] + ]; + const path7 = new G.Path({ + attrs: { + path, + stroke: 'red' + } + }); + const point0 = path7.getPoint(0); + const point1 = path7.getPoint(0.5); + const point2 = path7.getPoint(1); + const point3 = path7.getPoint(0.225); + // var point = point3; + // var circle = new G.Circle({ + // attrs:{ + // x: point.x, + // y: point.y, + // r: 3, + // fill: 'blue' + // } + // }); + // var path7Cureve = new G.Path({ + // attrs: { + // path: curve, + // stroke: 'blue' + // } + // }); + // path7Cureve.translate(100, 200); + canvas.add(path7); + // canvas.add(path7Cureve); + // canvas.add(circle); + canvas.draw(); + expect(point0).to.eql({ x: 300, y: 300 }); + expect(point1).to.eql({ x: 174.99999999999997, y: 50 }); + expect(point2).to.eql({ x: 50, y: 300 }); + expect(point3).to.eql({ x: 300, y: 112.0546875 }); + }); + + it('appendWidth', function() { + const path = [ + [ 'M', 200, 200 ], + [ 'L', 200, 50 ], + [ 'L', 50, 50 ], + [ 'L', 50, 300 ] + ]; + + const path8 = new G.Path({ + attrs: { + path, + lineAppendWidth: 10, + stroke: 'blue' + } + }); + + expect(path8.isHit(196, 200)).to.be.true; + expect(path8.isHit(52, 250)).to.be.true; + + canvas.add(path8); + canvas.draw(); + }); + +}); diff --git a/test/unit/g/shape-polygon-spec.js b/test/unit/g/shape-polygon-spec.js new file mode 100644 index 000000000..d3fb0993b --- /dev/null +++ b/test/unit/g/shape-polygon-spec.js @@ -0,0 +1,148 @@ +const expect = require('chai').expect; +const G = require('../../../src/g/index'); +const Canvas = require('../../../src/canvas'); +const div = document.createElement('div'); +div.id = 'canvas-polygon'; +document.body.appendChild(div); + + +describe('Polygon', function() { + + const canvas = new Canvas({ + containerId: 'canvas-polygon', + width: 200, + height: 200, + pixelRatio: 1 + }); + G.debug(true); + const polygon = new G.Polygon(); + it('init attr', function() { + expect(polygon.attr('points')).to.be.undefined; + expect(polygon.attr('lineWidth')).to.equal(1); + expect(polygon.attr('stroke')).to.be.undefined; + expect(polygon.attr('fill')).to.be.undefined; + expect(polygon.getBBox()).to.be.null; + }); + + it('points', function() { + polygon.attr('points', []); + expect(polygon.attr('points').length).to.equal(0); + expect(polygon.getBBox()).to.be.null; + polygon.attr('points', [[ 30, 30 ], [ 40, 20 ], [ 30, 50 ], [ 60, 100 ]]); + expect(polygon.attr('points').length).to.equal(4); + let box = polygon.getBBox(); + expect(box.minX).to.equal(29.5); + expect(box.maxX).to.equal(60.5); + expect(box.minY).to.equal(19.5); + expect(box.maxY).to.equal(100.5); + + const polygon1 = new G.Polygon({ + attrs: { + points: [[ 58, 60 ], [ 80, 190 ], [ 32, 53 ], [ 45, 32 ]] + } + }); + box = polygon1.getBBox(); + expect(box.minX).to.equal(31.5); + expect(box.minY).to.equal(31.5); + expect(box.maxX).to.equal(80.5); + expect(box.maxY).to.equal(190.5); + }); + + it('lineWidth', function() { + expect(polygon.attr('lineWidth')).to.equal(1); + polygon.attr('lineWidth', 2); + expect(polygon.attr('lineWidth')).to.equal(2); + let box = polygon.getBBox(); + expect(box.minX).to.equal(29); + expect(box.maxX).to.equal(61); + expect(box.minY).to.equal(19); + expect(box.maxY).to.equal(101); + + const polygon1 = new G.Polygon({ + attrs: { + points: [[ 58, 60 ], [ 80, 190 ], [ 32, 53 ], [ 45, 32 ]], + lineWidth: 2 + } + }); + box = polygon1.getBBox(); + expect(box.minX).to.equal(31); + expect(box.minY).to.equal(31); + expect(box.maxX).to.equal(81); + expect(box.maxY).to.equal(191); + }); + + it('stroke', function() { + polygon.attr('stroke', 'l (90) 0:#f0ff0f 1:#ff0e0d'); + expect(polygon.attr('stroke')).to.equal('l (90) 0:#f0ff0f 1:#ff0e0d'); + canvas.add(polygon); + canvas.draw(); + }); + + it('fill', function() { + polygon.attr('fill', 'r (0.3, 0.2, 0) 0:#edda2f 1:#23edfa'); + expect(polygon.attr('fill')).to.equal('r (0.3, 0.2, 0) 0:#edda2f 1:#23edfa'); + canvas.draw(); + }); + + it('isHit', function() { + expect(polygon.isHit(30, 30)).to.be.true; + expect(polygon.isHit(40, 20)).to.be.true; + expect(polygon.isHit(30, 50)).to.be.true; + expect(polygon.isHit(60, 100)).to.be.true; + + const polygon1 = new G.Polygon({ + attrs: { + points: [[ 31, 23 ], [ 43, 12 ], [ 53, 23 ], [ 64, 33 ]], + lineWidth: 2, + stroke: 'red' + } + }); + expect(polygon1.isHit(30, 23)).to.be.true; + expect(polygon1.isHit(31, 23)).to.be.true; + expect(polygon1.isHit(43, 12)).to.be.true; + expect(polygon1.isHit(53, 23)).to.be.true; + expect(polygon1.isHit(64, 33)).to.be.true; + expect(polygon1.isHit(37, 17.5)).to.be.true; + expect(polygon1.isHit(48, 17.5)).to.be.true; + expect(polygon1.isHit(47.5, 28)).to.be.true; + expect(polygon1.isHit(42.5, 17.5)).to.be.false; + + const polygon2 = new G.Polygon({ + attrs: { + points: [[ 31, 23 ], [ 43, 12 ], [ 53, 23 ], [ 64, 33 ]], + lineWidth: 2, + fill: 'red' + } + }); + canvas.add(polygon2); + expect(polygon2.isHit(30, 23)).to.be.false; + expect(polygon2.isHit(32, 23)).to.be.true; + expect(polygon2.isHit(43, 13)).to.be.true; + expect(polygon2.isHit(53, 23)).to.be.true; + expect(polygon2.isHit(37, 17.5)).to.be.true; + expect(polygon2.isHit(48, 17.5)).to.be.true; + expect(polygon2.isHit(47.5, 28)).to.be.true; + expect(polygon2.isHit(42.5, 17.5)).to.be.true; + + const polygon3 = new G.Polygon({ + attrs: { + points: [[ 31, 23 ], [ 43, 12 ], [ 53, 23 ], [ 64, 33 ]], + lineWidth: 2, + stroke: 'green', + fill: 'red' + } + }); + canvas.add(polygon3); + expect(polygon3.isHit(30, 23)).to.be.true; + expect(polygon3.isHit(31, 23)).to.be.true; + expect(polygon3.isHit(43, 12)).to.be.true; + expect(polygon3.isHit(53, 23)).to.be.true; + expect(polygon3.isHit(64, 33)).to.be.true; + expect(polygon3.isHit(37, 17.5)).to.be.true; + expect(polygon3.isHit(48, 17.5)).to.be.true; + expect(polygon3.isHit(47.5, 28)).to.be.true; + expect(polygon3.isHit(42.5, 17.5)).to.be.true; + }); + +}); + diff --git a/test/unit/g/shape-polyline-spec.js b/test/unit/g/shape-polyline-spec.js new file mode 100644 index 000000000..6a51f35e8 --- /dev/null +++ b/test/unit/g/shape-polyline-spec.js @@ -0,0 +1,116 @@ +const expect = require('chai').expect; +const G = require('../../../src/g/index'); +const Canvas = require('../../../src/canvas'); +const div = document.createElement('div'); +div.id = 'canvas-polyline'; +document.body.appendChild(div); + + +describe('Polyline', function() { + const canvas = new Canvas({ + containerId: 'canvas-polyline', + width: 200, + height: 200, + pixelRatio: 1 + }); + G.debug(true); + const polyline = new G.Polyline(); + + it('init attrs', function() { + expect(polyline.attr('points')).to.be.undefined; + expect(polyline.attr('lineWidth')).to.equal(1); + expect(polyline.attr('arrow')).to.be.false; + const box = polyline.getBBox(); + expect(box).to.be.null; + }); + + it('points', function() { + polyline.attr('points', []); + let points = polyline.attr('points'); + expect(points.length).to.equal(0); + let box = polyline.getBBox(); + expect(box).to.be.null; + polyline.attr('points', [[ 20, 30 ], [ 50, 40 ], [ 100, 110 ], [ 130, 70 ]]); + points = polyline.attr('points'); + expect(points.length).to.equal(4); + box = polyline.getBBox(); + expect(box.minX).to.equal(19.5); + expect(box.maxX).to.equal(130.5); + expect(box.minY).to.equal(29.5); + expect(box.maxY).to.equal(110.5); + + const polyline1 = new G.Polyline({ + attrs: { + points: [[ 40, 23 ], [ 53, 64 ], [ 79, 120 ], [ 234, 56 ]] + } + }); + points = polyline1.attr('points'); + expect(points.length).to.equal(4); + box = polyline1.getBBox(); + expect(box.minX).to.equal(39.5); + expect(box.maxX).to.equal(234.5); + expect(box.minY).to.equal(22.5); + expect(box.maxY).to.equal(120.5); + }); + + it('lineWidth', function() { + expect(polyline.attr('lineWidth')).to.equal(1); + polyline.attr('lineWidth', 2); + let box = polyline.getBBox(); + expect(box.minX).to.equal(19); + expect(box.maxX).to.equal(131); + expect(box.minY).to.equal(29); + expect(box.maxY).to.equal(111); + + const polyline1 = new G.Polyline({ + attrs: { + points: [[ 23, 12 ], [ 42, 52 ]], + lineWidth: 2 + } + }); + box = polyline1.getBBox(); + expect(box.minX).to.equal(22); + expect(box.maxX).to.equal(43); + expect(box.minY).to.equal(11); + expect(box.maxY).to.equal(53); + }); + + it('stroke', function() { + polyline.attr('stroke', 'l (0) 0.2:#ff00ff 1:#0000ff'); + expect(polyline.attr('stroke')).to.equal('l (0) 0.2:#ff00ff 1:#0000ff'); + canvas.add(polyline); + canvas.draw(); + }); + + it('isHit', function() { + expect(polyline.isHit(20, 30)).to.be.true; + expect(polyline.isHit(35, 35)).to.be.true; + expect(polyline.isHit(50, 40)).to.be.true; + expect(polyline.isHit(100, 110)).to.be.true; + expect(polyline.isHit(130, 70)).to.be.true; + expect(polyline.isHit(18, 29)).to.be.false; + const polyline1 = new G.Polyline({ + attrs: { + points: [[ 10, 10 ]] + } + }); + expect(polyline1.isHit(10, 10)).to.be.false; + polyline1.attr('stroke', 'red'); + expect(polyline1.isHit(10, 10)).to.be.false; + canvas.add(polyline1); + canvas.draw(); + }); + + it('arrow', function() { + polyline.attr('arrow', true); + expect(polyline.attr('arrow')).to.be.true; + canvas.draw(); + }); + + it('getPoint', function() { + expect(polyline.getPoint(1)).to.eql({ x: 130, y: 70 }); + expect(polyline.getPoint(0.5)).to.eql({ x: 80.34077206680482, y: 82.47708089352673 }); + expect(polyline.getPoint(0)).to.eql({ x: 20, y: 30 }); + }); +}); + diff --git a/test/unit/g/shape-quadratic-spec.js b/test/unit/g/shape-quadratic-spec.js new file mode 100644 index 000000000..fd7e3f322 --- /dev/null +++ b/test/unit/g/shape-quadratic-spec.js @@ -0,0 +1,131 @@ +const expect = require('chai').expect; +const G = require('../../../src/g/index'); +const Util = require('../../../src/util/index'); +const Canvas = require('../../../src/canvas'); +const div = document.createElement('div'); +div.id = 'canvas-quadratic'; +document.body.appendChild(div); + + +describe('Quadratic line', function() { + + const canvas = new Canvas({ + containerId: 'canvas-quadratic', + width: 200, + height: 200, + pixelRatio: 1 + }); + G.debug(true); + const quadratic = new G.Quadratic(); + it('init quadratic', function() { + expect(quadratic.attr('p1')).to.be.undefined; + expect(quadratic.attr('p2')).to.be.undefined; + expect(quadratic.attr('p3')).to.be.undefined; + expect(quadratic.attr('lineWidth')).to.equal(1); + expect(quadratic.attr('arrow')).to.be.false; + + expect(quadratic.getBBox()).to.be.null; + }); + + it('p1, p2, p3', function() { + quadratic.attr({ + p1: [ 50, 50 ], + p2: [ 80, 12 ], + p3: [ 120, 150 ] + }); + expect(quadratic.attr('p1')[0]).to.equal(50); + expect(quadratic.attr('p2')[1]).to.equal(12); + expect(quadratic.attr('p3')[0]).to.equal(120); + + const box = quadratic.getBBox('box'); + expect(Util.isNumberEqual(box.minX, 49.5)).to.be.true; + expect(Util.isNumberEqual(box.maxX, 120.5)).to.be.true; + expect(Util.isNumberEqual(box.minY, 41.29545454545454)).to.be.true; + expect(Util.isNumberEqual(box.maxY, 150.5)).to.be.true; + }); + + it('stroke', function() { + quadratic.attr('stroke', 'l (0) 0:#ff00ff 1:#00ffff'); + expect(quadratic.attr('stroke')).to.equal('l (0) 0:#ff00ff 1:#00ffff'); + + canvas.add(quadratic); + canvas.draw(); + }); + + it('p1', function() { + quadratic.attr('p1', [ 70, 39 ]); + expect(quadratic.attr('p1')[0]).to.equal(70); + expect(quadratic.attr('p1')[1]).to.equal(39); + const box = quadratic.getBBox(); + expect(Util.isNumberEqual(box.minX, 69.5)).to.be.true; + expect(Util.isNumberEqual(box.maxX, 120.5)).to.be.true; + expect(Util.isNumberEqual(box.minY, 34.081818181818186)).to.be.true; + expect(Util.isNumberEqual(box.maxY, 150.5)).to.be.true; + canvas.draw(); + }); + + it('p2', function() { + quadratic.attr('p2', [ 90, 80 ]); + expect(quadratic.attr('p2')[0]).to.equal(90); + expect(quadratic.attr('p2')[1]).to.equal(80); + const box = quadratic.getBBox(); + expect(Util.isNumberEqual(box.minX, 69.5)).to.be.true; + expect(Util.isNumberEqual(box.maxX, 120.5)).to.be.true; + expect(Util.isNumberEqual(box.minY, 38.5)).to.be.true; + expect(Util.isNumberEqual(box.maxY, 150.5)).to.be.true; + canvas.draw(); + }); + + it('p3', function() { + quadratic.attr('p3', [ 110, 10 ]); + expect(quadratic.attr('p3')[0]).to.equal(110); + expect(quadratic.attr('p3')[1]).to.equal(10); + const box = quadratic.getBBox(); + expect(Util.isNumberEqual(box.minX, 69.5)).to.be.true; + expect(Util.isNumberEqual(box.maxX, 110.5)).to.be.true; + expect(Util.isNumberEqual(box.minY, 9.5)).to.be.true; + expect(Util.isNumberEqual(box.maxY, 54.644144144144136)).to.be.true; + canvas.draw(); + }); + + it('lineWidth', function() { + quadratic.attr('lineWidth', 2); + expect(quadratic.attr('lineWidth')).to.equal(2); + const box = quadratic.getBBox(); + expect(Util.isNumberEqual(box.minX, 69)).to.be.true; + expect(Util.isNumberEqual(box.maxX, 111)).to.be.true; + expect(Util.isNumberEqual(box.minY, 9)).to.be.true; + expect(Util.isNumberEqual(box.maxY, 55.144144144144136)).to.be.true; + canvas.draw(); + }); + + it('isHit', function() { + expect(quadratic.isHit(70, 39)).to.be.true; + expect(quadratic.isHit(90, 52.2)).to.be.true; + expect(quadratic.isHit(110, 10)).to.be.true; + }); + + it('getPoint', function() { + const quadratic = new G.Quadratic({ + attrs: { + p1: [ 100, 100 ], + p2: [ 200, 200 ], + p3: [ 300, 100 ] + } + }); + + const point1 = quadratic.getPoint(0); + expect(point1.x).to.equal(100); + expect(point1.y).to.equal(100); + const point2 = quadratic.getPoint(1); + expect(point2.x).to.equal(300); + expect(point2.y).to.equal(100); + const point3 = quadratic.getPoint(0.5); + expect(point3.x).to.equal(200); + expect(point3.y).to.equal(150); + const point4 = quadratic.getPoint(0.3); + expect(point4.x).to.equal(160); + expect(point4.y).to.equal(142); + expect(quadratic.isHit(160, 142)).to.be.true; + }); +}); diff --git a/test/unit/g/shape-rect-spec.js b/test/unit/g/shape-rect-spec.js new file mode 100644 index 000000000..9b7c44f64 --- /dev/null +++ b/test/unit/g/shape-rect-spec.js @@ -0,0 +1,312 @@ +const expect = require('chai').expect; +const G = require('../../../src/g/index'); +const Canvas = require('../../../src/canvas'); +const div = document.createElement('div'); +div.id = 'canvas-rect'; +document.body.appendChild(div); + +describe('Rect', function() { + const canvas = new Canvas({ + containerId: 'canvas-rect', + width: 200, + height: 200, + pixelRatio: 1 + }); + + const rect = new G.Rect({ + attrs: { + x: 0, + y: 0, + width: 0, + height: 0 + } + }); + G.debug(true); + it('init attrs', function() { + expect(rect.attr('x')).to.equal(0); + expect(rect.attr('y')).to.equal(0); + expect(rect.attr('width')).to.equal(0); + expect(rect.attr('height')).to.equal(0); + expect(rect.attr('radius')).to.equal(0); + expect(rect.attr('lineWidth')).to.equal(1); + expect(rect.attr('stroke')).to.be.undefined; + expect(rect.attr('fill')).to.be.undefined; + const box = rect.getBBox(); + expect(box.minX).to.equal(-0.5); + expect(box.minY).to.equal(-0.5); + expect(box.maxX).to.equal(0.5); + expect(box.maxY).to.equal(0.5); + }); + + it('width', function() { + expect(rect.attr('width')).to.equal(0); + rect.attr('width', 10); + expect(rect.attr('width')).to.equal(10); + let box = rect.getBBox(); + expect(box.minX).to.equal(-0.5); + expect(box.maxX).to.equal(10.5); + const rect1 = new G.Rect({ + attrs: { + x: 0, + y: 0, + height: 1, + width: 15 + } + }); + expect(rect1.attr('width')).to.equal(15); + box = rect1.getBBox(); + expect(box.minX).to.equal(-0.5); + expect(box.maxX).to.equal(15.5); + const rect2 = new G.Rect({ + attrs: { + x: 10, + y: 0, + width: 15, + height: 1 + } + }); + expect(rect2.attr('width')).to.equal(15); + box = rect2.getBBox(); + expect(box.minX).to.equal(9.5); + expect(box.maxX).to.equal(25.5); + }); + + it('height', function() { + expect(rect.attr('height')).to.equal(0); + rect.attr('height', 20); + expect(rect.attr('height')).to.equal(20); + let box = rect.getBBox(); + expect(box.minY).to.equal(-0.5); + expect(box.maxY).to.equal(20.5); + const rect1 = new G.Rect({ + attrs: { + x: 0, + y: 0, + height: 25, + width: 1 + } + }); + expect(rect1.attr('height')).to.equal(25); + box = rect1.getBBox(); + expect(box.minY).to.equal(-0.5); + expect(box.maxY).to.equal(25.5); + const rect2 = new G.Rect({ + attrs: { + x: 0, + y: 10, + height: 25, + width: 1 + } + }); + expect(rect2.attr('height')).to.equal(25); + box = rect2.getBBox(); + expect(box.minY).to.equal(9.5); + expect(box.maxY).to.equal(35.5); + }); + + it('x', function() { + rect.attr('x', 10); + expect(rect.attr('x')).to.equal(10); + let box = rect.getBBox(); + expect(box.minX).to.equal(9.5); + expect(box.maxX).to.equal(20.5); + const rect1 = new G.Rect({ + attrs: { + x: 10, + y: 0, + width: 0, + height: 0 + } + }); + expect(rect1.attr('x')).to.equal(10); + box = rect1.getBBox(); + expect(box.minX).to.equal(9.5); + expect(box.maxX).to.equal(10.5); + const rect2 = new G.Rect({ + attrs: { + x: 20, + y: 0, + width: 15, + height: 0 + } + }); + expect(rect2.attr('x')).to.equal(20); + box = rect2.getBBox(); + expect(box.minX).to.equal(19.5); + expect(box.maxX).to.equal(35.5); + }); + + it('y', function() { + rect.attr('y', 20); + expect(rect.attr('y')).to.equal(20); + let box = rect.getBBox(); + expect(box.minY).to.equal(19.5); + expect(box.maxY).to.equal(40.5); + const rect1 = new G.Rect({ + attrs: { + x: 0, + y: 12, + height: 0, + width: 0 + } + }); + expect(rect1.attr('y')).to.equal(12); + box = rect1.getBBox(); + expect(box.minY).to.equal(11.5); + expect(box.maxY).to.equal(12.5); + const rect2 = new G.Rect({ + attrs: { + x: 0, + y: 12, + height: 20, + width: 0 + } + }); + expect(rect2.attr('y')).to.equal(12); + box = rect2.getBBox(); + expect(box.minY).to.equal(11.5); + expect(box.maxY).to.equal(32.5); + }); + + it('lineWidth', function() { + expect(rect.attr('lineWidth')).to.equal(1); + rect.attr('lineWidth', 2); + expect(rect.attr('lineWidth')).to.equal(2); + let box = rect.getBBox(); + expect(box.minY).to.equal(19); + expect(box.minX).to.equal(9); + expect(box.maxX).to.equal(21); + expect(box.maxY).to.equal(41); + const rect1 = new G.Rect({ + attrs: { + x: 0, + y: 0, + width: 0, + height: 0, + lineWidth: 2 + } + }); + expect(rect1.attr('lineWidth')).to.equal(2); + box = rect1.getBBox(); + expect(box.minY).to.equal(-1); + expect(box.minX).to.equal(-1); + expect(box.maxX).to.equal(1); + expect(box.maxY).to.equal(1); + + const rect2 = new G.Rect({ + attrs: { + x: 30, + y: 40, + width: 200, + height: 100, + lineWidth: 2 + } + }); + expect(rect2.attr('lineWidth')).to.equal(2); + box = rect2.getBBox(); + expect(box.minX).to.equal(29); + expect(box.minY).to.equal(39); + expect(box.maxX).to.equal(231); + expect(box.maxY).to.equal(141); + }); + + it('radius', function() { + expect(rect.attr('radius')).to.equal(0); + rect.attr('radius', 3); + expect(rect.attr('radius')).to.equal(3); + }); + + it('stroke', function() { + rect.attr('stroke', 'l (0) 0:#ff00ff 1:#00ff00'); + expect(rect.attr('stroke')).to.equal('l (0) 0:#ff00ff 1:#00ff00'); + canvas.add(rect); + canvas.draw(); + }); + + it('fill', function() { + rect.attr('fill', 'l (90) 0:#00ffff 1:#ffff00'); + expect(rect.attr('fill')).to.equal('l (90) 0:#00ffff 1:#ffff00'); + canvas.draw(); + }); + + it('isHit', function() { + const rect1 = new G.Rect({ + attrs: { + x: 40, + y: 40, + width: 50, + height: 70 + } + }); + + expect(rect1.isHit(39.5, 39.5)).to.be.false; + expect(rect1.isHit(40.5, 40.5)).to.be.false; + expect(rect1.isHit(41, 41)).to.be.false; + expect(rect1.isHit(70, 39)).to.be.false; + expect(rect1.isHit(90.5, 110.5)).to.be.false; + expect(rect1.isHit(43, 43)).to.be.false; + rect1.attr('stroke', 'red'); + expect(rect1.isHit(39.5, 39.5)).to.be.true; + expect(rect1.isHit(40.5, 40.5)).to.be.true; + expect(rect1.isHit(41, 41)).to.be.false; + expect(rect1.isHit(70, 39)).to.be.false; + expect(rect1.isHit(70, 39.5)).to.be.true; + expect(rect1.isHit(90.5, 110.5)).to.be.true; + expect(rect1.isHit(43, 43)).to.be.false; + rect1.attr('lineWidth', 2); + expect(rect1.isHit(70, 39)).to.be.true; + expect(rect1.isHit(41, 41)).to.be.true; + rect1.attr('radius', 6); + expect(rect1.isHit(41, 41)).to.be.false; + + + const rect2 = new G.Rect({ + attrs: { + x: 50, + y: 50, + width: 40, + height: 50 + } + }); + expect(rect2.isHit(50, 50)).to.be.false; + expect(rect2.isHit(49.5, 50)).to.be.false; + expect(rect2.isHit(50, 51)).to.be.false; + expect(rect2.isHit(51, 51)).to.be.false; + expect(rect2.isHit(90, 100)).to.be.false; + expect(rect2.isHit(89, 99)).to.be.false; + rect2.attr('fill', 'blue'); + expect(rect2.isHit(50, 50)).to.be.false; + expect(rect2.isHit(49.5, 50)).to.be.false; + expect(rect2.isHit(50, 51)).to.be.false; + expect(rect2.isHit(51, 51)).to.be.false; + expect(rect2.isHit(90, 100)).to.be.false; + expect(rect2.isHit(89, 99)).to.be.false; + canvas.add(rect2); + expect(rect2.isHit(50, 50)).to.be.true; + expect(rect2.isHit(49.5, 50)).to.be.false; + expect(rect2.isHit(50, 51)).to.be.true; + expect(rect2.isHit(51, 51)).to.be.true; + expect(rect2.isHit(90, 100)).to.be.true; + expect(rect2.isHit(89, 99)).to.be.true; + rect2.attr('radius', 5); + expect(rect2.isHit(50, 50)).to.be.false; + expect(rect2.isHit(89, 99)).to.be.false; + + const rect3 = new G.Rect({ + attrs: { + x: 20, + y: 30, + width: 100, + height: 120, + stroke: 'red', + fill: 'green', + lineWidth: 4 + } + }); + + canvas.add(rect3); + expect(rect3.isHit(18, 28)).to.be.true; + expect(rect3.isHit(50, 70)).to.be.true; + }); + +}); diff --git a/test/unit/g/shape-text-spec.js b/test/unit/g/shape-text-spec.js new file mode 100644 index 000000000..2f8f8fd6e --- /dev/null +++ b/test/unit/g/shape-text-spec.js @@ -0,0 +1,569 @@ +const expect = require('chai').expect; +const G = require('../../../src/g/index'); +const Canvas = require('../../../src/canvas'); +const div = document.createElement('div'); +div.id = 'canvas-text'; +document.body.appendChild(div); + + +describe('Text', function() { + const canvas = new Canvas({ + containerId: 'canvas-text', + width: 200, + height: 200, + pixelRatio: 1 + }); + + const text = new G.Text({ + attrs: { + x: 0, + y: 0 + } + }); + G.debug(true); + it('init attrs', function() { + expect(text.attr('x')).to.equal(0); + expect(text.attr('y')).to.equal(0); + expect(text.attr('text')).to.be.undefined; + expect(text.attr('textAlign')).to.equal('start'); + expect(text.attr('fontSize')).to.equal(12); + expect(text.attr('fontFamily')).to.equal('sans-serif'); + expect(text.attr('fontStyle')).to.equal('normal'); + expect(text.attr('fontWeight')).to.equal('normal'); + expect(text.attr('fontVariant')).to.equal('normal'); + expect(text.attr('font')).to.equal('normal normal normal 12px sans-serif'); + expect(text.attr('textBaseline')).to.equal('bottom'); + expect(text.attr('lineWidth')).to.equal(1); + expect(text.getBBox()).to.eql({ minX: 0, + minY: 0, + maxX: 0, + maxY: 0, + x: 0, + y: 0, + width: 0, + height: 0 + }); + }); + + it('text', function() { + text.attr('text', '你好啊'); + let box = text.getBBox(); + expect(box).not.to.be.undefined; + expect(box.minX).to.equal(-0.5); + expect(box.minY).to.equal(-12.5); + expect(box.maxX).to.equal(36.5); + expect(box.maxY).to.equal(0.5); + const text1 = new G.Text({ + attrs: { + x: 0, + y: 0, + text: '你好啊' + } + }); + box = text1.getBBox(); + expect(box).not.to.be.undefined; + expect(box.minX).to.equal(-0.5); + expect(box.minY).to.equal(-12.5); + expect(box.maxX).to.equal(36.5); + expect(box.maxY).to.equal(0.5); + }); + + it('x', function() { + text.attr('x', 10); + let box = text.getBBox(); + expect(box.minX).to.equal(9.5); + expect(box.minY).to.equal(-12.5); + expect(box.maxX).to.equal(46.5); + expect(box.maxY).to.equal(0.5); + const text1 = new G.Text({ + attrs: { + x: 10, + y: 0 + } + }); + expect(text1.attr('x')).to.equal(10); + box = text1.getBBox(); + expect(box).to.eql({ minX: 10, + minY: 0, + maxX: 10, + maxY: 0, + x: 10, + y: 0, + width: 0, + height: 0 + }); + const text2 = new G.Text({ + attrs: { + x: 10, + y: 0, + text: '你好啊' + } + }); + expect(text2.attr('x')).to.equal(10); + box = text2.getBBox(); + expect(box.minX).to.equal(9.5); + expect(box.minY).to.equal(-12.5); + expect(box.maxX).to.equal(46.5); + expect(box.maxY).to.equal(0.5); + }); + + it('y', function() { + text.attr('y', 20); + let box = text.getBBox(); + expect(box.minX).to.equal(9.5); + expect(box.minY).to.equal(7.5); + expect(box.maxX).to.equal(46.5); + expect(box.maxY).to.equal(20.5); + const text1 = new G.Text({ + attrs: { + x: 0, + y: 20 + } + }); + expect(text1.attr('y')).to.equal(20); + box = text1.getBBox(); + expect(box).to.eql({ minX: 0, + minY: 20, + maxX: 0, + maxY: 20, + x: 0, + y: 20, + width: 0, + height: 0 + }); + text1.attr({ + x: 0, + y: 20, + text: '你好啊' + }); + expect(text1.attr('y')).to.equal(20); + box = text1.getBBox(); + expect(box.minX).to.equal(-0.5); + expect(box.minY).to.equal(7.5); + expect(box.maxX).to.equal(36.5); + expect(box.maxY).to.equal(20.5); + }); + + it('stroke', function() { + text.attr({ + stroke: 'l (0) 0:#ffff00 1:rgb(0, 255, 255)' + }); + expect(text.attr('stroke')).to.equal('l (0) 0:#ffff00 1:rgb(0, 255, 255)'); + canvas.add(text); + canvas.draw(); + }); + + it('fill', function() { + const text1 = new G.Text({ + attrs: { + x: 50, + y: 150, + text: 'fill测试', + font: '40px Arial', + fill: 'r (0.5, 0.5, 0) 0:rgb(255, 0, 255) 0.5:#dddddd' + } + }); + expect(text1.attr('fill')).to.equal('r (0.5, 0.5, 0) 0:rgb(255, 0, 255) 0.5:#dddddd'); + canvas.add(text1); + + + canvas.draw(); + }); + + + it('fontSize', function() { + expect(text.attr('fontSize')).to.equal(12); + expect(text.attr('font')).to.equal('normal normal normal 12px sans-serif'); + text.attr('fontSize', 20); + expect(text.attr('fontSize')).to.equal(20); + expect(text.attr('font')).to.equal('normal normal normal 20px sans-serif'); + const text1 = new G.Text({ + attrs: { + fontSize: 20, + text: '你好啊啊', + x: 20, + y: 180, + stroke: '#000' + } + }); + expect(text1.attr('fontSize')).to.equal(20); + expect(text1.attr('font')).to.equal('normal normal normal 20px sans-serif'); + canvas.add(text1); + canvas.draw(); + }); + + it('fontStyle', function() { + expect(text.attr('fontStyle')).to.equal('normal'); + text.attr('fontStyle', 'italic'); + expect(text.attr('fontStyle')).to.equal('italic'); + expect(text.attr('font')).to.equal('italic normal normal 20px sans-serif'); + canvas.draw(); + text.attr('fontStyle', 'oblique'); + expect(text.attr('fontStyle')).to.equal('oblique'); + expect(text.attr('font')).to.equal('oblique normal normal 20px sans-serif'); + canvas.draw(); + }); + + it('fontWeight', function() { + expect(text.attr('fontWeight')).to.equal('normal'); + text.attr('fontWeight', 'bolder'); + expect(text.attr('fontWeight')).to.equal('bolder'); + expect(text.attr('font')).to.equal('oblique normal bolder 20px sans-serif'); + canvas.draw(); + }); + + it('fontVariant', function() { + expect(text.attr('fontVariant')).to.equal('normal'); + text.attr('fontVariant', 'small-caps'); + expect(text.attr('fontVariant')).to.equal('small-caps'); + expect(text.attr('font')).to.equal('oblique small-caps bolder 20px sans-serif'); + canvas.draw(); + }); + + it('fontFamily', function() { + text.attr('fontFamily', '宋体'); + expect(text.attr('fontFamily')).to.equal('宋体'); + expect(text.attr('font')).to.equal('oblique small-caps bolder 20px 宋体'); + canvas.draw(); + }); + + it('textAlign', function() { + expect(text.attr('textAlign')).to.equal('start'); + text.attr('textAlign', 'right'); + let box = text.getBBox(); + expect(box.minX, -50.5); + expect(box.maxX, 10.5); + text.attr('textAlign', 'left'); + box = text.getBBox(); + expect(box.minX, 9.5); + expect(box.maxX, 70.5); + text.attr('textAlign', 'end'); + box = text.getBBox(); + expect(box.minX, -50.5); + expect(box.maxX, 10.5); + text.attr('textAlign', 'center'); + box = text.getBBox(); + expect(box.minX, -20.5); + expect(box.maxX, 40.5); + text.attr('textAlign', 'start'); + box = text.getBBox(); + expect(box.minX, 9.5); + expect(box.maxX, 70.5); + + + const text1 = new G.Text({ + attrs: { + x: 0, + y: 0, + textAlign: 'center' + } + }); + expect(text1.attr('textAlign')).to.equal('center'); + expect(text1.getBBox()).eql({ minX: 0, + minY: 0, + maxX: 0, + maxY: 0, + x: 0, + y: 0, + width: 0, + height: 0 + }); + + const text2 = new G.Text({ + attrs: { + x: 0, + y: 0, + textAlign: 'center', + text: '你好啊' + } + }); + expect(text2.attr('textAlign')).to.equal('center'); + box = text2.getBBox(); + expect(box.minX).to.equal(-18.5); + expect(box.maxX).to.equal(18.5); + }); + + it('textBaseline', function() { + expect(text.attr('textBaseline')).to.equal('bottom'); + text.attr('textBaseline', 'top'); + let box = text.getBBox(); + expect(box.minY).to.equal(19.5); + expect(box.maxY).to.equal(40.5); + text.attr('textBaseline', 'middle'); + box = text.getBBox(); + expect(box.minY).to.equal(9.5); + expect(box.maxY).to.equal(30.5); + text.attr('textBaseline', 'bottom'); + box = text.getBBox(); + expect(box.minY).to.equal(-0.5); + expect(box.maxY).to.equal(20.5); + + const text1 = new G.Text({ + attrs: { + x: 0, + y: 0, + textBaseline: 'middle' + } + }); + expect(text1.attr('textBaseline')).to.equal('middle'); + expect(text1.getBBox()).eql({ minX: 0, + minY: 0, + maxX: 0, + maxY: 0, + x: 0, + y: 0, + width: 0, + height: 0 + }); + + const text2 = new G.Text({ + attrs: { + x: 0, + y: 0, + textBaseline: 'middle', + text: '你好啊' + } + }); + expect(text2.attr('textBaseline')).to.equal('middle'); + box = text2.getBBox(); + expect(box.minY).to.equal(-6.5); + expect(box.maxY).to.equal(6.5); + }); + + it('lineWidth', function() { + expect(text.attr('lineWidth')).to.equal(1); + text.attr('lineWidth', 4); + expect(text.attr('lineWidth')).to.equal(4); + const box = text.getBBox(); + expect(box.minX).to.equal(8); + expect(box.maxX).to.equal(72); + expect(box.maxY).to.equal(22); + expect(box.minY).to.equal(-2); + }); + + it('isHit', function() { + expect(text.isHit(48, 0)).to.be.true; + expect(text.isHit(48, 24)).to.be.false; + }); + + + it('normal use', function() { + const text = new G.Text({ + attrs: { + text: 'hello world', + x: 50, + y: 50, + fill: 'red' + } + }); + canvas.add(text); + canvas.draw(); + }); + + it('add text fontFamily', function() { + const text1 = canvas.addShape('text', { + attrs: { + x: 0, + y: 0, + text: 'abc' + } + }); + expect(text1.attr('fontFamily')).to.equal('sans-serif'); + const text2 = canvas.addShape('text', { + attrs: { + x: 0, + y: 0, + fontFamily: 'Arial', + text: 'bcd' + } + }); + expect(text2.attr('fontFamily')).to.equal('Arial'); + + canvas.set('fontFamily', '宋体'); + const text3 = canvas.addShape('text', { + attrs: { + x: 0, + y: 0, + text: 'bde' + } + }); + expect(text3.attr('fontFamily')).to.equal('宋体'); + + canvas.set('fontFamily', null); + const text4 = canvas.addShape('text', { + attrs: { + x: 0, + y: 0, + text: 'bde' + } + }); + + expect(text4.attr('fontFamily')).to.equal('sans-serif'); + }); + +}); + +describe('Text \n', function() { + + const canvas = new Canvas({ + containerId: 'canvas-text', + width: 200, + height: 200 + }); + + const text = new G.Text({ + attrs: { + x: 50, + y: 50, + text: '你好\nHello\nworkd', + fill: 'black', + stroke: 'red', + textBaseline: 'top' + } + }); + const bbox = text.getBBox(); + const rect = new G.Rect({ + attrs: { + x: bbox.minX, + y: bbox.minY, + width: bbox.maxX - bbox.minX, + height: bbox.maxY - bbox.minY, + stroke: 'red' + } + }); + + G.debug(true); + it('text /n', function() { + expect(text.attr('x')).to.equal(50); + expect(text.attr('y')).to.equal(50); + expect(text.attr('text')).to.equal('你好\nHello\nworkd'); + expect(text.attr('textAlign')).to.equal('start'); + expect(text.attr('fontSize')).to.equal(12); + expect(text.attr('fill')).to.equal('black'); + expect(text.attr('fontFamily')).to.equal('sans-serif'); + expect(text.attr('fontStyle')).to.equal('normal'); + expect(text.attr('fontWeight')).to.equal('normal'); + expect(text.attr('fontVariant')).to.equal('normal'); + expect(text.attr('font')).to.equal('normal normal normal 12px sans-serif'); + expect(text.attr('textBaseline')).to.equal('top'); + expect(text.attr('lineWidth')).to.equal(1); + }); + canvas.add(rect); + canvas.add(text); + canvas.draw(); +}); + +describe('Text 不存在', function() { + + const canvas = new Canvas({ + containerId: 'canvas-text', + width: 200, + height: 200 + }); + + const text = new G.Text({ + attrs: { + x: 50, + y: 50, + text: '', + fill: 'black', + stroke: 'red', + textBaseline: 'top' + } + }); + const bbox = text.getBBox(); + const rect = new G.Rect({ + attrs: { + x: bbox.minX, + y: bbox.minY, + width: bbox.maxX - bbox.minX, + height: bbox.maxY - bbox.minY, + stroke: 'red' + } + }); + + G.debug(true); + it('text 空 "" ', function() { + expect(text.attr('x')).to.equal(50); + expect(text.attr('y')).to.equal(50); + expect(text.attr('text')).to.equal(''); + expect(text.attr('textAlign')).to.equal('start'); + expect(text.attr('fontSize')).to.equal(12); + expect(text.attr('fill')).to.equal('black'); + expect(text.attr('fontFamily')).to.equal('sans-serif'); + expect(text.attr('fontStyle')).to.equal('normal'); + expect(text.attr('fontWeight')).to.equal('normal'); + expect(text.attr('fontVariant')).to.equal('normal'); + expect(text.attr('font')).to.equal('normal normal normal 12px sans-serif'); + expect(text.attr('textBaseline')).to.equal('top'); + expect(text.attr('lineWidth')).to.equal(1); + expect(text.getBBox()).to.eql({ minX: 50, + minY: 50, + maxX: 50, + maxY: 50, + x: 50, + y: 50, + width: 0, + height: 0 + }); + }); + canvas.add(rect); + canvas.add(text); + canvas.draw(); + it('text null ', function() { + text.attr('text', null); + expect(text.attr('x')).to.equal(50); + expect(text.attr('y')).to.equal(50); + expect(text.attr('text')).to.be.null; + expect(text.attr('textAlign')).to.equal('start'); + expect(text.attr('fontSize')).to.equal(12); + expect(text.attr('fill')).to.equal('black'); + expect(text.attr('fontFamily')).to.equal('sans-serif'); + expect(text.attr('fontStyle')).to.equal('normal'); + expect(text.attr('fontWeight')).to.equal('normal'); + expect(text.attr('fontVariant')).to.equal('normal'); + expect(text.attr('font')).to.equal('normal normal normal 12px sans-serif'); + expect(text.attr('textBaseline')).to.equal('top'); + expect(text.attr('lineWidth')).to.equal(1); + expect(text.getBBox()).to.eql({ minX: 50, + minY: 50, + maxX: 50, + maxY: 50, + x: 50, + y: 50, + width: 0, + height: 0 + }); + }); + canvas.add(rect); + canvas.add(text); + canvas.draw(); + it('text undefined ', function() { + text.attr('text', undefined); + expect(text.attr('x')).to.equal(50); + expect(text.attr('y')).to.equal(50); + expect(text.attr('text')).to.be.undefined; + expect(text.attr('textAlign')).to.equal('start'); + expect(text.attr('fontSize')).to.equal(12); + expect(text.attr('fill')).to.equal('black'); + expect(text.attr('fontFamily')).to.equal('sans-serif'); + expect(text.attr('fontStyle')).to.equal('normal'); + expect(text.attr('fontWeight')).to.equal('normal'); + expect(text.attr('fontVariant')).to.equal('normal'); + expect(text.attr('font')).to.equal('normal normal normal 12px sans-serif'); + expect(text.attr('textBaseline')).to.equal('top'); + expect(text.attr('lineWidth')).to.equal(1); + expect(text.getBBox()).to.eql({ minX: 50, + minY: 50, + maxX: 50, + maxY: 50, + x: 50, + y: 50, + width: 0, + height: 0 + }); + }); + canvas.add(rect); + canvas.add(text); + canvas.draw(); +}); diff --git a/test/unit/mouse-event-spec.js b/test/unit/mouse-event-spec.js new file mode 100644 index 000000000..ac739d91a --- /dev/null +++ b/test/unit/mouse-event-spec.js @@ -0,0 +1,6 @@ +// const expect = require('chai').expect; +// const MouseEvent = require('../../src/mouse-event'); + +describe('MouseEvent', () => { + +}); diff --git a/test/unit/util/matrix-spec.js b/test/unit/util/matrix-spec.js new file mode 100644 index 000000000..1443614ba --- /dev/null +++ b/test/unit/util/matrix-spec.js @@ -0,0 +1,74 @@ +const $ = require('jquery'); +const expect = require('chai').expect; +const MatrixUtil = require('../../../src/util/matrix'); +const Matrix = require('@ali/g-matrix'); +const Matrix3 = Matrix.Matrix3; +const Canvas = require('../../../src/canvas'); + +$('
').appendTo('body'); + +const canvas = new Canvas({ + containerId: 'test_matrixUtil', + width: 500, + height: 500 +}); + +describe('测试矩阵工具', function() { + it('基于某点缩放', function() { + const group = canvas.addGroup(); + const circle = group.addShape('circle', { + attrs: { + x: 250, + y: 250, + r: 50, + fill: '#FED443' + } + }); + // const animPoint = canvas.addShape('circle', { + // attrs: { + // x: 250, + // y: 250, + // r: 3, + // fill: 'blue' + // } + // }); + let matrix = new Matrix3(); + // const bboxOrigin = circle.getBBox(); + matrix = MatrixUtil.scale(matrix, 2, 2, 250, 250); + circle.setMatrix(matrix); + const bbox = group.getBBox(); + expect(bbox.x + bbox.width / 2).to.equal(250); + expect(bbox.y + bbox.height / 2).to.equal(250); + expect(bbox.width).to.equal(202); // 边框有值 +2 + expect(bbox.height).to.equal(202); // 边框有值 +2 + canvas.draw(); + }); + it('基于某点旋转', function() { + const matrix = new Matrix3(); + const rst = MatrixUtil.rotate(matrix, parseFloat(10) / 180 * Math.PI, 300, 300); + matrix.translate(-300, -300); + matrix.rotate(parseFloat(10) / 180 * Math.PI); + matrix.translate(300, 300); + expect(Matrix3.equal(matrix, rst)).to.be.true; + }); + it('变换 transform', function() { + const matrix = new Matrix3(); + const rst = MatrixUtil.transform(matrix, [ + [ 't', 100, 200 ], + [ 's', 0.2, 0.3 ], + [ 'r', Math.PI ], + [ 'm', new Matrix3() ], + [ 'null', 10101010101 ] + ]); + matrix.translate(100, 200); + matrix.scale(0.2, 0.3); + matrix.rotate(Math.PI); + matrix.multiply(new Matrix3()); + expect(Matrix3.equal(matrix, rst)).to.be.true; + }); + it('判断是否是3阶矩阵', function() { + const matrix = new Matrix3(); + expect(MatrixUtil.isMatrix3(matrix)).to.be.true; + expect(MatrixUtil.isMatrix3(9999)).to.be.false; + }); +}); diff --git a/tests/canvas/animate-performance-spec.js b/tests/canvas/animate-performance-spec.js deleted file mode 100644 index 310b6c9e2..000000000 --- a/tests/canvas/animate-performance-spec.js +++ /dev/null @@ -1,34 +0,0 @@ -var $ = require('jquery'); -var expect = require('@ali/expect.js'); -var Matrix = require('@ali/g-matrix'); -var Canvas = require('../../src/canvas'); - -$('
').appendTo('body'); - -xdescribe('动画', function() { - // var canvas = new Canvas({ - // containerId: 'c1', - // width: 500, - // height: 500 - // }); - // it('停止动画', function() { - // var callBack = sinon.spy(); - // var matrix = new Matrix.Matrix3(); - // matrix.translate(400,400); - // var circle = canvas.addShape("Circle", { - // attrs: { - // x: 100, - // y: 0, - // r: 100, - // fill: '#FED23C' - // } - // }); - // circle.animate({ - // x: 20, - // matrix: matrix - // },1000, 'linear', callBack); - // setTimeout(function(){ - // canvas.clear(); - // }, 400); - // }); -}); diff --git a/tests/canvas/performance-spec.js b/tests/canvas/performance-spec.js deleted file mode 100644 index bc62e3ddb..000000000 --- a/tests/canvas/performance-spec.js +++ /dev/null @@ -1,28 +0,0 @@ -var $ = require('jquery'); -var expect = require('@ali/expect.js'); -var Matrix = require('@ali/g-matrix'); -var Canvas = require('../../src/canvas'); - -$('
').appendTo('body'); - -xdescribe('动画', function() { - // var canvas = new Canvas({ - // containerId: 'c1', - // width: 500, - // height: 500 - // }); - // setInterval(function(){ - // canvas.clear(); - // for (var i = 0; i < 5000; i++) { - // canvas.addShape('circle',{ - // attrs: { - // x: Math.random() * 500, - // y: Math.random() * 500, - // r: 4, - // fill: '#FB7A6B' - // } - // }) - // } - // canvas.draw(); - // }, 200); -}); diff --git a/tests/g/core-attributes-spec.js b/tests/g/core-attributes-spec.js deleted file mode 100644 index 44d92238b..000000000 --- a/tests/g/core-attributes-spec.js +++ /dev/null @@ -1,106 +0,0 @@ -var expect = require('@ali/expect.js'); -var Elements = require('../../src/g/core/element'); -describe('Attributes', function() { - it ('init', function() { - var e = new Elements({ - attrs: { - width: 100, - height: 50 - } - }); - - - expect(e.__attrs.width).to.be(100); - expect(e.__attrs.height).to.be(50); - }); - - it('attr get', function(){ - var e = new Elements({ - attrs: { - width: 100, - height: 50 - } - }); - - expect(e.attr('width')).to.be(100); - expect(e.attr('height')).to.be(50); - }); - - it('attr set', function() { - var e = new Elements(); - - e.attr('width', 300); - expect(e.attr('width')).to.be(300); - e.attr('height', 40); - expect(e.attr('height')).to.be(40); - e.attr({ - width: 100, - text: '123' - }); - expect(e.attr('width')).to.be(100); - expect(e.attr('text')).to.be('123'); - }); - - it('attr fill', function() { - var e = new Elements({ - attrs: { - fill: '#333333' - } - }); - e.attr('fill', '#333333') - expect(e.attr('fill')).to.be('#333333'); - expect(e.__attrs['fillStyle']).to.be('#333333'); - - e.attr('fill', 'red'); - expect(e.attr('fill')).to.be('red'); - expect(e.__attrs['fillStyle']).to.be('red'); - }); - - it('attr stroke', function() { - var e = new Elements({ - attrs: { - stroke: 'black' - } - }); - e.attr('stroke', 'black'); - expect(e.attr('stroke')).to.be('black'); - expect(e.__attrs['strokeStyle']).to.be('black'); - - e.attr('stroke', '#999'); - expect(e.attr('stroke')).to.be('#999'); - expect(e.__attrs['strokeStyle']).to.be('#999'); - }); - - it('attr opacity', function() { - var e = new Elements({ - attrs: { - opacity: 0.1 - } - }); - - expect(e.attr('opacity')).to.be(0.1); - expect(e.__attrs['globalAlpha']).to.be(0.1); - - e.attr('opacity', 0.3); - - expect(e.attr('opacity')).to.be(0.3); - expect(e.__attrs['globalAlpha']).to.be(0.3); - }); - - it('attrAll', function() { - var e = new Elements({ - attrs: { - width: 100, - opacity: 0.2, - stroke: '#222', - fill: '#444' - } - }); - - var attrs = e.attr(); - expect(attrs.opacity).to.be(0.2); - expect(attrs.stroke).to.be('#222'); - expect(attrs.fill).to.be('#444'); - expect(attrs.width).to.be(100); - }); -}); diff --git a/tests/g/core-element-spec.js b/tests/g/core-element-spec.js deleted file mode 100644 index 2e61f99ca..000000000 --- a/tests/g/core-element-spec.js +++ /dev/null @@ -1,40 +0,0 @@ -var expect = require('@ali/expect.js'); -var Element = require('../../src/g/core/element'); -var Matrix = require('@ali/g-matrix'); -var Matrix3 = Matrix.Matrix3; - -describe('Element', function() { - it('constructor', function() { - var e = new Element({ - id: 'aaa', - attrs: { - width: 20, - height: 30, - stroke: '#231' - } - }); - - expect(e.__cfg).not.to.be(undefined); - expect(e.__cfg.id).to.be('aaa'); - expect(e.__attrs).not.to.be(undefined); - expect(e.__attrs['width']).to.be(20); - expect(e.__attrs['height']).to.be(30); - expect(e.__m).not.to.be(undefined); - var m = new Matrix3(); - expect(e.__m.equal(m)).to.be(true); - // expect(e.__listeners).not.to.be(undefined); - }); - - it('set and get', function() { - var e = new Element(); - var a = 123; - expect(a).to.be(123); - e.__setTest = function(v) { - a = 321; - return v - 1; - }; - e.set('test', 1111); - expect(e.get('test')).to.be(1110); - expect(a).to.be(321); - }); -}); diff --git a/tests/g/core-eventDispatcher-spec.js b/tests/g/core-eventDispatcher-spec.js deleted file mode 100644 index acdee1311..000000000 --- a/tests/g/core-eventDispatcher-spec.js +++ /dev/null @@ -1,106 +0,0 @@ -var expect = require('@ali/expect.js'); -var Util = require('../../src/util/index'); -var Dispatcher = require('../../src/g/core/mixin/event-dispatcher'); -var Element = function() { - this.initEventDispatcher(); -}; - -Util.augment(Element, Dispatcher); - -describe('EventDispatcher', function() { - - it('trigger', function() { - var element = new Element(); - element.on('test', function(e) { - expect(e.target).to.be(element); - expect(e.type).to.be('test'); - }); - element.trigger({type: 'test'}); - }); - - it('on', function() { - var element = new Element(); - var test1 = function(e) { - expect(e.target).to.be(element); - expect(e.type).to.be('test'); - expect(e.target).to.be(this); - }; - - var test2 = function(e) { - expect(e.target).to.be(element); - expect(e.type).to.be('test'); - expect(e.target).to.be(this); - }; - - var exe1 = function(e) { - expect(e.target).to.be(element); - expect(e.type).to.be('exe'); - expect(e.target).to.be(this); - }; - - var exe2 = function(e) { - expect(e.target).to.be(element); - expect(e.type).to.be('exe'); - expect(e.target).to.be(this); - }; - - element.on('test', test1); - element.on('test', test2); - element.on('exe', exe1); - element.on('exe', exe2); - element.trigger({type: 'test'}); - element.trigger({type: 'exe'}); - }); - - it('has', function() { - var element = new Element(); - - var test1 = function() {}; - var test2 = function() {}; - var test3 = function() {}; - element.on('test', test2); - element.on('test', test1); - expect(element.has('test', test1)).to.be(true); - expect(element.has('test', test2)).to.be(true); - expect(element.has('test', test3)).to.be(false); - }); - - it('off', function() { - var element = new Element(); - - var test1 = function() {}; - var test2 = function() {}; - var exe1 = function() {}; - var exe2 = function() {}; - var fun1 = function() {}; - var fun2 = function() {}; - - element.on('test', test1); - element.on('test', test2); - element.on('exe', exe1); - element.on('exe', exe2); - element.on('fun', fun1); - element.on('fun', fun2); - - - expect(element.has('test', test1)).to.be(true); - expect(element.has('test', test2)).to.be(true); - expect(element.has('exe', exe1)).to.be(true); - expect(element.has('exe', exe2)).to.be(true); - expect(element.has('fun', fun1)).to.be(true); - expect(element.has('fun', fun2)).to.be(true); - expect(element.has()).to.be(true); - expect(element.has('fun')).to.be(true); - element.off('test', test1); - expect(element.has('test', test1)).to.be(false); - element.off('exe'); - expect(element.has('exe', exe1)).to.be(false); - expect(element.has('exe', exe2)).to.be(false); - element.off(); - expect(element.has('test', test2)).to.be(false); - expect(element.has('fun', fun1)).to.be(false); - expect(element.has('fun', fun2)).to.be(false); - expect(element.has()).to.be(false); - expect(element.has('fun')).to.be(false); - }); -}); diff --git a/tests/g/core-group-spec.js b/tests/g/core-group-spec.js deleted file mode 100644 index 321af87db..000000000 --- a/tests/g/core-group-spec.js +++ /dev/null @@ -1,391 +0,0 @@ -var expect = require('@ali/expect.js'); -var G = require('../../src/g/index'); -var Matrix = require('@ali/g-matrix'); -var Matrix3 = Matrix.Matrix3; -var Event = require('@ali/g-event'); -var Canvas = require('../../src/canvas'); -var div = document.createElement('div'); -div.id = 'canvas-group-1'; -document.body.appendChild(div); - -describe('Group', function() { - - var canvas = new Canvas({ - containerId: 'canvas-group-1', - width: 200, - height: 200, - pixelRatio: 1 - }); - - it('constructor', function() { - var g = new G.Group({ - id: 'g1' - }); - - expect(g.isGroup).to.be(true); - expect(g.get('children')).not.to.be(undefined); - expect(g.get('children').length).to.be(0); - }); - - it('add', function() { - var e = new G.Circle({ - id: 'e1' - }); - var e2 = new G.Circle({ - id: 'e2' - }); - - var g2 = new G.Group({ - id: 'g2' - }); - - g2.add(e); - - expect(e.get('parent')).to.be(g2); - expect(g2.getCount()).to.be(1); - var g3 = new G.Group({ - id: 'g3' - }); - - g3.add(e); - - expect(e.get('parent')).to.be(g3); - expect(g3.getCount()).to.be(1); - expect(g2.getCount()).to.be(0); - - var g4 = new G.Group({ - id: 'g4' - }); - - g4.add(g3); - expect(g3.get('parent')).to.be(g4); - expect(e.get('parent')).to.be(g3); - expect(g4.getCount()).to.be(1); - expect(g3.getCount()).to.be(1); - - g2.add(g3); - expect(g2.getCount()).to.be(1); - expect(g3.getCount()).to.be(1); - expect(g3.get('parent')).to.be(g2); - expect(e.get('parent')).to.be(g3); - - g3.add(e2); - expect(g2.getCount()).to.be(1); - expect(g3.getCount()).to.be(2); - expect(e2.get('parent')).to.be(g3); - expect(e.get('parent')).to.be(g3); - - g2.add(e2); - expect(g2.getCount()).to.be(2); - expect(g3.getCount()).to.be(1); - expect(e2.get('parent')).to.be(g2); - expect(e.get('parent')).to.be(g3); - }); - - it('clear', function() { - var g = new G.Group({ - id: 'g' - }); - - var e1 = new G.Circle({ - id: 'e1' - }); - var e2 = new G.Circle({ - id: 'e2' - }); - var e3 = new G.Circle({ - id: 'e3' - }); - - g.add(e1); - g.add(e2); - g.add(e3); - - expect(g.getCount()).to.be(3); - g.clear(); - expect(g.getCount()).to.be(0); - expect(e1.get('destroyed')).to.be(true); - }); - - it('destroy', function() { - var g = new G.Group({ - id: 'g' - }); - - var e1 = new G.Circle({ - id: 'e1' - }); - var e2 = new G.Circle({ - id: 'e2' - }); - var e3 = new G.Circle({ - id: 'e3' - }); - - g.add(e1); - g.add(e2); - g.add(e3); - expect(g.getCount()).to.be(3); - g.destroy(); - - expect(g.get('children')).to.be(undefined); - expect(g.get('destroyed')).to.be(true); - }); - - it('remove', function() { - var g1 = new G.Group({ - id: 'g1' - }); - - var g2 = new G.Group({ - id: 'g2' - }); - - var e1 = new G.Circle({ - id: 'e1' - }); - var e2 = new G.Circle({ - id: 'e2' - }); - var e3 = new G.Circle({ - id: 'e3' - }); - var e4 = new G.Circle({ - id: 'e4' - }); - var e5 = new G.Circle({ - id: 'e5' - }); - - g1.add(e1); - g1.add(e2); - g1.add(e3); - g1.add(e4); - g1.add(e5); - - g2.add(g1); - - expect(g2.getCount()).to.be(1); - expect(g1.getCount()).to.be(5); - g1.removeChild(e1, true); - expect(g1.getCount()).to.be(4); - expect(e1.get('destroyed')).to.be(true); - g1.removeChild(e2); - expect(g1.getCount()).to.be(3); - expect(e2.get('destroyed')).to.be(true); - g1.removeChild(e3, false); - expect(g1.getCount()).to.be(2); - expect(e3.get('destroyed')).to.be(false); - g1.removeChild(false); - expect(g1.getCount()).to.be(2); - expect(g2.getCount()).to.be(0); - expect(g1.get('destroyed')).to.be(false); - g2.add(g1); - expect(g2.getCount()).to.be(1); - g1.removeChild(); - expect(g2.getCount()).to.be(0); - expect(g1.get('destroyed')).to.be(true); - }); - - it('zIndex', function() { - var g = new G.Group({ - id: 'g' - }); - - var e1 = new G.Circle({ - id: 'e1', - zIndex: 1 - }); - - var e2 = new G.Circle({ - id: 'e2', - zIndex: 2 - }); - - var e3 = new G.Circle({ - id: 'e3', - zIndex: 3 - }); - - g.add(e1); - g.add(e3); - - expect(g.get('children')[1]).to.be(e3); - g.add(e2); - g.sort(); - expect(g.get('children')[1]).to.be(e2); - - e2.set('zIndex', 5); - expect(g.get('children')[1]).to.be(e3); - expect(g.get('children')[2]).to.be(e2); - }); - - it('find and findBy', function() { - var g1 = new G.Group({ - id: 'g1' - }); - - var g2 = new G.Group({ - id: 'g2' - }); - - var e1 = new G.Circle({ - id: 'e1', - zIndex: 1 - }); - - var e2 = new G.Circle({ - id: 'e2', - zIndex: 2 - }); - - var e3 = new G.Circle({ - id: 'e3', - zIndex: 3 - }); - - - g1.add(g2); - g1.add(e1); - g2.add(e2); - g2.add(e3); - - expect(g1.findBy(function(item) { - return item.get('zIndex') === 3; - })).to.be(e3); - - expect(g1.find('e1')).to.be(e1); - }); -/* - it('fill', function() { - var g = new G.Group({ - attrs: { - fill: 'green' - } - }); - - var circle = new G.Circle({ - attrs: { - x: 100, - y: 100, - r: 50 - } - }); - expect(circle.hasFill()).to.be(undefined); - g.add(circle); - expect(circle.hasFill()).to.be('green'); - expect(circle.attr('fill')).to.be(undefined); - var arc = new G.Arc({ - attrs: { - x: 100, - y: 100, - r: 70, - startAngle: 0, - endAngle: 120, - stroke: 'red' - } - }); - expect(arc.hasFill()).to.be(undefined); - g.add(arc); - expect(arc.hasFill()).to.be(undefined); - expect(arc.hasStroke()).to.be('red'); - canvas.add(g); - canvas.draw(); - }); - - it('stroke', function() { - var g = new G.Group({ - attrs: { - stroke: 'l (0) 0:#00ffff 1:#ffff00' - } - }); - - var arc = new G.Arc({ - attrs: { - x: 100, - y: 100, - r: 70, - startAngle: 180, - endAngle: 300 - } - }); - expect(arc.hasStroke()).to.be(undefined); - g.add(arc); - expect(arc.hasStroke()).to.be('l (0) 0:#00ffff 1:#ffff00'); - canvas.add(g); - canvas.draw(); - }); -*/ - it('transform', function() { - var arc = new G.Circle({ - attrs: { - x: 100, - y: 100, - r: 50, - fill: 'red' - } - }); - canvas.add(arc); - expect(canvas.getShape(0, 120)).to.be(undefined); - expect(canvas.getShape(100, 100)).not.to.be(undefined); - canvas.draw(); - - canvas.rotate(1 / 4 * Math.PI); - canvas.draw(); - expect(canvas.getShape(0, 120)).not.to.be(undefined); - expect(canvas.getShape(100, 100)).to.be(undefined); - /**/ - }); - - it('group event', function() { - var circle = new G.Circle(); - var group = new G.Group(); - group.add(circle); - var e = new Event('group', {}, true, true); - e.currentTarget = circle; - circle.trigger(e); - var aa = 0; - var handler = function(e) { - expect(e.currentTarget).to.be(circle); - expect(e.target).to.be(group); - e.stopPropagation(); - aa++; - }; - group.on('group', handler); - group.on('group', handler); - circle.trigger(e); - expect(aa).to.be(1);; - }); - - it('add items & sort', function() { - var circle1 = new G.Circle({zIndex: 2}); - var circle2 = new G.Circle({zIndex: 1}); - var circle3 = new G.Circle({zIndex: 3}); - var text = new G.Text({zIndex: 4}); - - var group = new G.Group(); - - group.add([circle1, circle2, circle3, text]); - - var children = group.get('children'); - expect(children.length).to.be(4); - expect(children[1]).to.be(circle2); - group.sort(); - expect(children[1]).to.be(circle1); - expect(children[0]).to.be(circle2); - circle1.set('visible', true); - var box = group.getBBox(); - }); - - it('contain', function() { - var group1 = new G.Group(); - var group2 = new G.Group(); - var r1 = new G.Rect(); - group1.add(r1); - expect(group1.contain(r1)).to.be(true); - group2.removeChild(r1); - expect(r1.get('destroyed')).to.be(false); - group1.removeChild(r1); - expect(group1.contain(r1)).to.be(false); - }); -}); diff --git a/tests/g/core-shape-spec.js b/tests/g/core-shape-spec.js deleted file mode 100644 index 50761825b..000000000 --- a/tests/g/core-shape-spec.js +++ /dev/null @@ -1,12 +0,0 @@ -var expect = require('@ali/expect.js'); -var Shape = require('../../src/g/core/shape'); - -describe('Shape', function() { - it('constructor', function() { - // var s = new Shape({ - // id: 'shape' - // }); - - // expect(s.isShape).to.be(true); - }); -}); diff --git a/tests/g/core-transform-spec.js b/tests/g/core-transform-spec.js deleted file mode 100644 index a5195c4ca..000000000 --- a/tests/g/core-transform-spec.js +++ /dev/null @@ -1,107 +0,0 @@ -var expect = require('@ali/expect.js'); -var Element = require('../../src/g/core/element'); -var Matrix = require('@ali/g-matrix'); -var Vector3 = Matrix.Vector3; -var Matrix3 = Matrix.Matrix3; -var gMath = require('@ali/g-math'); - -describe('Transform', function() { - - it('translate and apply', function() { - var e = new Element(); - var point = new Vector3(0, 0, 1); - e.translate(10, 4); - e.apply(point); - expect(gMath.equal(point.x, 10)).to.be(true); - expect(gMath.equal(point.y, 4)).to.be(true); - }); - - it('rotate', function() { - var e = new Element(); - var point = new Vector3(10, 0, 0); - e.rotate(45 / 180 * Math.PI); - e.apply(point); - expect(gMath.equal(point.x, 5 * Math.sqrt(2))).to.be(true); - expect(gMath.equal(point.y, 5 * Math.sqrt(2))).to.be(true); - e.apply(point); - expect(gMath.equal(point.x, 0)).to.be(true); - expect(gMath.equal(point.y, 10)).to.be(true); - e.rotate(-135 / 180 * Math.PI); - e.apply(point); - expect(gMath.equal(point.x, 10)).to.be(true); - expect(gMath.equal(point.y, 0)).to.be(true); - }); - - it('scale', function() { - var e = new Element(); - var point = new Vector3(10, 10, 1); - e.scale(0.5, 0.5); - e.apply(point); - expect(gMath.equal(point.x, 5)).to.be(true); - expect(gMath.equal(point.y, 5)).to.be(true); - e.scale(4, 2); - e.apply(point); - expect(gMath.equal(point.x, 10)).to.be(true); - expect(gMath.equal(point.y, 5)).to.be(true); - }); - - it('complex', function() { - var e = new Element(); - var point1 = new Vector3(10, 10, 1); - var point2 = new Vector3(); - e.translate(10, 10); - e.rotate(Math.PI / 2); - e.translate(-10, -10); - e.scale(0.5, 0.5); - e.apply(point1); - - expect(gMath.equal(point1.x, -15)).to.be(true); - expect(gMath.equal(point1.y, 5)).to.be(true); - }); - - it('transform', function() { - var e = new Element(); - e.transform([['r', Math.PI / 2], ['t', 10, 10], ['r', - Math.PI / 2]]); - var point = new Vector3(0, 0, 1); - e.apply(point); - expect(gMath.equal(point.x, 10)).to.be(true); - expect(gMath.equal(point.y, -10)).to.be(true); - }); - - it('setTransform and invert', function() { - var e = new Element(); - e.translate(10, 10); - e.setTransform([['r', Math.PI / 2], ['t', 10, 10], ['r', -Math.PI / 2], ['s', 0.5, 0.3]]); - var point = new Vector3(0, 0, 1); - e.apply(point); - expect(gMath.equal(point.x, 5)).to.be(true); - expect(gMath.equal(point.y, -3)).to.be(true); - e.invert(point); - expect(gMath.equal(point.x, 0)).to.be(true); - expect(gMath.equal(point.y, 0)).to.be(true); - var e1 = new Element(); - e1.setTransform([['m', e.__m]]); - e1.apply(point); - expect(gMath.equal(point.x, 5)).to.be(true); - expect(gMath.equal(point.y, -3)).to.be(true); - e1.invert(point); - expect(gMath.equal(point.x, 0)).to.be(true); - expect(gMath.equal(point.y, 0)).to.be(true); - }); - - it('getMatrix', function() { - var e = new Element(); - var m = e.getMatrix(); - var m1 = new Matrix3(); - expect(m.equal(m1)).to.be(true); - }); -}); - - - - - - - - - diff --git a/tests/g/index-spec.js b/tests/g/index-spec.js deleted file mode 100644 index c362ab287..000000000 --- a/tests/g/index-spec.js +++ /dev/null @@ -1,10 +0,0 @@ -var expect = require('@ali/expect.js'); -var G = require('../../src/g/index'); - -describe('G', function() { - - it('normal usage', function() { - - }); - -}); diff --git a/tests/g/shape-arc-spec.js b/tests/g/shape-arc-spec.js deleted file mode 100644 index dd505d386..000000000 --- a/tests/g/shape-arc-spec.js +++ /dev/null @@ -1,140 +0,0 @@ -var expect = require('@ali/expect.js'); -var G = require('../../src/g/index'); -var Util = require('../../src/util/index'); -var gMath = require('@ali/g-math'); -var Canvas = require('../../src/canvas'); -var div = document.createElement('div'); -div.id = 'canvas-arc'; -document.body.appendChild(div); -var ratio = Util.getRatio(); -describe('Arc line', function() { - - var canvas = new Canvas({ - containerId: 'canvas-arc', - width: 200, - height: 200 - }); - - canvas.on('canvas-click', function(ev){ - console.log(ev) - }); - var arc = new G.Arc(); - G.debug(true); - it('init attrs', function() { - expect(arc.attr('x')).to.be(0); - expect(arc.attr('y')).to.be(0); - expect(arc.attr('r')).to.be(0); - expect(arc.attr('startAngle')).to.be(0); - expect(arc.attr('endAngle')).to.be(0); - expect(arc.attr('clockwise')).to.be(false); - expect(arc.attr('lineWidth')).to.be(1); - expect(arc.attr('stroke')).to.be(undefined); - - var box = arc.getBBox(); - expect(box.minX).to.be(-0.5); - expect(box.maxX).to.be(0.5); - expect(box.minY).to.be(-0.5); - expect(box.maxY).to.be(0.5); - }); - - it('x', function() { - arc.attr('x', 10); - expect(arc.attr('x')).to.be(10); - var box = arc.getBBox(); - expect(box.minX).to.be(9.5); - expect(box.maxX).to.be(10.5); - }); - - it('y', function() { - arc.attr('y', 20); - expect(arc.attr('y')).to.be(20); - var box = arc.getBBox(); - expect(box.minY).to.be(19.5); - expect(box.maxY).to.be(20.5); - }); - - it('r', function() { - arc.attr('r', 30); - var box = arc.getBBox(); - expect(box.minX).to.be(39.5); - expect(box.maxX).to.be(40.5); - expect(box.minY).to.be(19.5); - expect(box.maxY).to.be(20.5); - }); - - it('startAngle', function() { - arc.attr('startAngle', 1 / 3 * Math.PI); - expect(gMath.equal(arc.attr('startAngle'), 1 / 3 * Math.PI)).to.be(true); - var box = arc.getBBox(); - expect(box.minX).to.be(-20.5); - expect(box.maxX).to.be(40.5); - expect(box.minY).to.be(-10.5); - expect(box.maxY).to.be(50.5); - }); - - it('endAngle', function() { - arc.attr('endAngle', 120 / 180 * Math.PI); - expect(gMath.equal(arc.attr('endAngle'), 120 / 180 * Math.PI)).to.be(true); - var box = arc.getBBox(); - expect(gMath.equal(box.minX, -5.5)).to.be(true); - expect(gMath.equal(box.maxX, 25.5)).to.be(true); - expect(gMath.equal(box.minY, 45.48076211353316)).to.be(true); - expect(gMath.equal(box.maxY, 50.5)).to.be(true); - }); - - it('clockwise', function() { - expect(arc.attr('clockwise')).to.be(false); - arc.attr('clockwise', true); - expect(arc.attr('clockwise')).to.be(true); - var box = arc.getBBox(); - expect(gMath.equal(box.minX, -20.5)).to.be(true); - expect(gMath.equal(box.maxX, 40.5)).to.be(true); - expect(gMath.equal(box.minY, -10.5)).to.be(true); - expect(gMath.equal(box.maxY, 46.48076211353316)).to.be(true); - }); - - it('lineWidth', function() { - expect(arc.attr('lineWidth')).to.be(1); - arc.attr('lineWidth', 2); - expect(arc.attr('lineWidth')).to.be(2); - var box = arc.getBBox(); - expect(gMath.equal(box.minX, -21)).to.be(true); - expect(gMath.equal(box.maxX, 41)).to.be(true); - expect(gMath.equal(box.minY, -11)).to.be(true); - expect(gMath.equal(box.maxY, 46.98076211353316)).to.be(true); - }); - - it('stroke', function() { - arc.attr({ - startAngle: -Math.PI / 2, - endAngle: Math.PI / 2, - clockwise: false, - x: 60, - y: 60, - r: 20 - }) - arc.attr('stroke', 'l (0) 0:#ff00ff 1:#00ffff'); - expect(arc.attr('stroke')).to.be('l (0) 0:#ff00ff 1:#00ffff'); - canvas.add(arc); - canvas.draw(); - }); - - it('isHit', function() { - expect(arc.isHit(60 * ratio, 80 * ratio)).to.be(true); - }); - - it('normal', function() { - var arc = new G.Arc({ - attrs: { - x: 50, - y: 50, - r: 40, - startAngle: 0, - endAngle: 110 / 180 * Math.PI, - stroke: 'red' - } - }); - canvas.add(arc); - canvas.draw(); - }); -}); diff --git a/tests/g/shape-circle-spec.js b/tests/g/shape-circle-spec.js deleted file mode 100644 index 8f6fbbcbb..000000000 --- a/tests/g/shape-circle-spec.js +++ /dev/null @@ -1,160 +0,0 @@ -var expect = require('@ali/expect.js'); -var G = require('../../src/g/index'); -var gMath = require('@ali/g-math'); -var Canvas = require('../../src/canvas'); -var div = document.createElement('div'); -div.id = 'canvas-circle'; -document.body.appendChild(div); -describe('Circle', function() { - var canvas = new Canvas({ - containerId: 'canvas-circle', - width: 200, - height: 200, - pixelRatio: 1 - }); - - var circle = new G.Circle({ - attrs: { - x: 0, - y: 0, - r: 0 - } - }); - - G.debug(true); - it('init attr', function() { - expect(circle.attr('lineWidth')).to.be(1); - expect(circle.attr('stroke')).to.be(undefined); - expect(circle.attr('fill')).to.be(undefined); - var box = circle.getBBox(); - expect(box.minX).to.be(-0.5); - expect(box.maxX).to.be(0.5); - expect(box.minY).to.be(-0.5); - expect(box.maxY).to.be(0.5); - }); - - it('x', function() { - circle.attr('x', 10); - expect(circle.attr('x')).to.be(10); - var box = circle.getBBox(); - expect(box.minX).to.be(9.5); - expect(box.maxX).to.be(10.5); - expect(box.minY).to.be(-0.5); - expect(box.maxY).to.be(0.5); - }); - - it('y', function() { - circle.attr('y', 20); - expect(circle.attr('y')).to.be(20); - var box = circle.getBBox(); - expect(box.minX).to.be(9.5); - expect(box.maxX).to.be(10.5); - expect(box.minY).to.be(19.5); - expect(box.maxY).to.be(20.5); - }); - - it('r', function() { - expect(circle.attr('r')).to.be(0); - circle.attr('r', 10); - expect(circle.attr('r')).to.be(10); - var box = circle.getBBox(); - expect(box.minX).to.be(-0.5); - expect(box.maxX).to.be(20.5); - expect(box.minY).to.be(9.5); - expect(box.maxY).to.be(30.5); - }); - - it('lineWidth', function() { - expect(circle.attr('lineWidth')).to.be(1); - circle.attr('lineWidth', 2); - expect(circle.attr('lineWidth')).to.be(2); - var box = circle.getBBox(); - expect(box.minX).to.be(-1); - expect(box.maxX).to.be(21); - expect(box.minY).to.be(9); - expect(box.maxY).to.be(31); - }); - - it('stroke', function() { - circle.attr('stroke', 'l (30) 0:#00ffff 1:#ff00ff'); - expect(circle.attr('stroke')).to.be('l (30) 0:#00ffff 1:#ff00ff'); - canvas.add(circle); - canvas.draw(circle); - }); - - it('fill', function() { - circle.attr('fill', 'r (0.5, 0.5, 0) 0:#00ffff 1:#ffff00'); - expect(circle.attr('fill')).to.be('r (0.5, 0.5, 0) 0:#00ffff 1:#ffff00'); - canvas.draw(circle); - }); - - it('isHit', function() { - var circle1 = new G.Circle({ - attrs: { - x: 50, - y: 50, - r: 50 - } - }); - - expect(circle1.isHit(0, 50)).to.be(false); - expect(circle1.isHit(50, 0)).to.be(false); - expect(circle1.isHit(100, 50)).to.be(false); - expect(circle1.isHit(50, 100)).to.be(false); - circle1.attr('stroke', 'red'); - - expect(circle1.isHit(0, 50)).to.be(true); - expect(circle1.isHit(50, 0)).to.be(true); - expect(circle1.isHit(100, 50)).to.be(true); - expect(circle1.isHit(50, 100)).to.be(true); - expect(circle1.isHit(20, 50)).to.be(false); - expect(circle1.isHit(50, 20)).to.be(false); - expect(circle1.isHit(80, 50)).to.be(false); - expect(circle1.isHit(50, 80)).to.be(false); - - var circle2 = new G.Circle({ - attrs: { - x: 50, - y: 50, - r: 50 - } - }); - - expect(circle2.isHit(20, 50)).to.be(false); - expect(circle2.isHit(50, 20)).to.be(false); - expect(circle2.isHit(80, 50)).to.be(false); - expect(circle2.isHit(50, 80)).to.be(false); - circle2.attr('fill', 'green'); - expect(circle2.isHit(20, 50)).to.be(true); - expect(circle2.isHit(50, 20)).to.be(true); - expect(circle2.isHit(80, 50)).to.be(true); - expect(circle2.isHit(50, 80)).to.be(true); - - circle2.attr('stroke', 'red'); - expect(circle2.isHit(0, 50)).to.be(true); - expect(circle2.isHit(50, 0)).to.be(true); - expect(circle2.isHit(100, 50)).to.be(true); - expect(circle2.isHit(50, 100)).to.be(true); - expect(circle2.isHit(20, 50)).to.be(true); - expect(circle2.isHit(50, 20)).to.be(true); - expect(circle2.isHit(80, 50)).to.be(true); - expect(circle2.isHit(50, 80)).to.be(true); - }); - - it('strokeOpactiy', function() { - var circle = new G.Circle({ - attrs: { - x: 150, - y: 150, - r: 100, - stroke: 'red', - strokeOpactiy: 0.4 - } - }); - - canvas.add(circle); - canvas.draw(); - }); - -}); - diff --git a/tests/g/shape-cubic-spec.js b/tests/g/shape-cubic-spec.js deleted file mode 100644 index d40ef5316..000000000 --- a/tests/g/shape-cubic-spec.js +++ /dev/null @@ -1,158 +0,0 @@ -var expect = require('@ali/expect.js'); -var G = require('../../src/g/index'); -var gMath = require('@ali/g-math'); -var Canvas = require('../../src/canvas'); -var div = document.createElement('div'); -div.id = 'canvas-cubic'; -document.body.appendChild(div); - -describe('Cubic line', function() { - var canvas = new Canvas({ - containerId: 'canvas-cubic', - width: 200, - height: 200, - pixelRatio: 1 - }); - - G.debug(true); - var cubic = new G.Cubic(); - it('init cubic', function() { - expect(cubic.attr('p1')).to.be(undefined); - expect(cubic.attr('p2')).to.be(undefined); - expect(cubic.attr('p3')).to.be(undefined); - expect(cubic.attr('p4')).to.be(undefined); - expect(cubic.attr('lineWidth')).to.be(1); - expect(cubic.attr('arrow')).to.be(undefined); - - expect(cubic.getBBox()).to.be(null); - }); - - it('p1, p2, p3, p4', function() { - cubic.attr({ - p1: [50, 50], - p2: [80, 12], - p3: [120, 150], - p4: [150, 50] - }); - expect(cubic.attr('p1')[0]).to.be(50); - expect(cubic.attr('p2')[1]).to.be(12); - expect(cubic.attr('p3')[0]).to.be(120); - expect(cubic.attr('p4')[0]).to.be(150); - - var box = cubic.getBBox(); - expect(gMath.equal(box.minX, 49.5)).to.be(true); - expect(gMath.equal(box.maxX, 150.5)).to.be(true); - expect(gMath.equal(box.minY, 42.690077140818396)).to.be(true); - expect(gMath.equal(box.maxY, 87.61466742731623)).to.be(true); - }); - - it('stroke', function() { - cubic.attr('lineWidth', 5); - cubic.attr('stroke', 'l (0) 0:#ff00ff 1:#00ffff'); - expect(cubic.attr('stroke')).to.be('l (0) 0:#ff00ff 1:#00ffff'); - - canvas.add(cubic); - canvas.draw(); - }); - - it('p1', function() { - cubic.attr('p1', [70, 39]); - expect(cubic.attr('p1')[0]).to.be(70); - expect(cubic.attr('p1')[1]).to.be(39); - var box = cubic.getBBox(); - expect(gMath.equal(box.minX, 67.5)).to.be(true); - expect(gMath.equal(box.maxX, 152.5)).to.be(true); - expect(gMath.equal(box.minY, 32.923853488303024)).to.be(true); - expect(gMath.equal(box.maxY, 89.38594461401888)).to.be(true); - canvas.draw(); - }); - - it('p2', function() { - cubic.attr('p2', [90, 80]); - expect(cubic.attr('p2')[0]).to.be(90); - expect(cubic.attr('p2')[1]).to.be(80); - var box = cubic.getBBox(); - expect(gMath.equal(box.minX, 67.5)).to.be(true); - expect(gMath.equal(box.maxX, 152.5)).to.be(true); - expect(gMath.equal(box.minY, 36.5)).to.be(true); - expect(gMath.equal(box.maxY, 103.77723887000138)).to.be(true); - canvas.draw(); - }); - - it('p3', function() { - cubic.attr('p3', [110, 0]); - expect(cubic.attr('p3')[0]).to.be(110); - expect(cubic.attr('p3')[1]).to.be(0); - var box = cubic.getBBox(); - expect(gMath.equal(box.minX, 67.5)).to.be(true); - expect(gMath.equal(box.maxX, 152.5)).to.be(true); - expect(gMath.equal(box.minY, 30.447819730085683)).to.be(true); - expect(gMath.equal(box.maxY, 53.66354358160779)).to.be(true); - canvas.draw(); - }); - - it('p4', function() { - console.log(cubic.getBBox()); - cubic.attr('p4', [150, 90]); - expect(cubic.attr('p4')[0]).to.be(150); - expect(cubic.attr('p4')[1]).to.be(90); - /*var box = cubic.getBBox(); - expect(gMath.equal(box.minX, 67.5)).to.be(true); - expect(gMath.equal(box.maxX, 152.5)).to.be(true); - expect(gMath.equal(box.minY, 36.5)).to.be(true); - expect(gMath.equal(box.maxY, 92.5)).to.be(true); - */ - canvas.draw(); - }); - - it('lineWidth', function() { - cubic.attr('lineWidth', 2); - expect(cubic.attr('lineWidth')).to.be(2); - var box = cubic.getBBox(); - expect(gMath.equal(box.minX, 69)).to.be(true); - expect(gMath.equal(box.maxX, 151)).to.be(true); - expect(gMath.equal(box.minY, 38)).to.be(true); - expect(gMath.equal(box.maxY, 91)).to.be(true); - canvas.draw(); - }); - - it('isHit', function() { - expect(cubic.isHit(70, 39)).to.be(true); - expect(cubic.isHit(102.5, 46.2)).to.be(true); - expect(cubic.isHit(150, 90)).to.be(true); - }); - - it('getPoint', function() { - var cubic = new G.Cubic({ - attrs: { - p1: [100, 100], - p2: [200, 200], - p3: [300, 0], - p4: [400, 100] - } - }); - - var point = cubic.getPoint(0); - expect(point.x).to.be(100); - expect(point.y).to.be(100); - var point1 = cubic.getPoint(1); - expect(point1.x).to.be(400); - expect(point1.y).to.be(100); - var point2 = cubic.getPoint(0.25); - expect(point2.x).to.be(175); - expect(point2.y).to.be(128.125); - expect(cubic.isHit(point2.x, point2.y)).to.be(true); - var point3 = cubic.getPoint(0.5); - expect(point3.x).to.be(250); - expect(point3.y).to.be(100); - expect(cubic.isHit(point3.x, point3.y)).to.be(true); - var point4 = cubic.getPoint(0.75); - expect(point4.x).to.be(325); - expect(point4.y).to.be(71.875); - expect(cubic.isHit(point4.x, point4.y)).to.be(true); - var point5 = cubic.getPoint(0.3); - expect(gMath.equal(point5.x, 190)).to.be(true); - expect(gMath.equal(point5.y, 125.2)).to.be(true); - expect(cubic.isHit(point5.x, point5.y)).to.be(true); - }); -}); diff --git a/tests/g/shape-ellipse-spec.js b/tests/g/shape-ellipse-spec.js deleted file mode 100644 index d90e24166..000000000 --- a/tests/g/shape-ellipse-spec.js +++ /dev/null @@ -1,184 +0,0 @@ -var expect = require('@ali/expect.js'); -var G = require('../../src/g/index'); -var gMath = require('@ali/g-math'); -var Canvas = require('../../src/canvas'); -var div = document.createElement('div'); -div.id = 'canvas-ellipse'; -document.body.appendChild(div); - - -describe('Ellipse', function() { - - var canvas = new Canvas({ - containerId: 'canvas-ellipse', - width: 200, - height: 200, - pixelRatio: 1 - }); - - var ellipse = new G.Ellipse({ - attrs: { - x: 0, - y: 0, - rx: 1, - ry: 1 - } - }); - G.debug(true); - it('init attr', function() { - expect(ellipse.attr('x')).to.be(0); - expect(ellipse.attr('y')).to.be(0); - expect(ellipse.attr('rx')).to.be(1); - expect(ellipse.attr('ry')).to.be(1); - expect(ellipse.attr('lineWidth')).to.be(1); - expect(ellipse.attr('stroke')).to.be(undefined); - expect(ellipse.attr('fill')).to.be(undefined); - var box = ellipse.getBBox(); - expect(box.minX).to.be(-1.5); - expect(box.maxX).to.be(1.5); - expect(box.minY).to.be(-1.5); - expect(box.maxY).to.be(1.5); - }); - - it('x', function() { - ellipse.attr('x', 20); - expect(ellipse.attr('x')).to.be(20); - var box = ellipse.getBBox(); - expect(box.minX).to.be(18.5); - expect(box.maxX).to.be(21.5); - expect(box.minY).to.be(-1.5); - expect(box.maxY).to.be(1.5); - }); - - it('y', function() { - ellipse.attr('y', 30); - expect(ellipse.attr('y')).to.be(30); - var box = ellipse.getBBox(); - expect(box.minX).to.be(18.5); - expect(box.maxX).to.be(21.5); - expect(box.minY).to.be(28.5); - expect(box.maxY).to.be(31.5); - }); - - it('rx', function() { - expect(ellipse.attr('rx')).to.be(1); - ellipse.attr('rx', 5); - expect(ellipse.attr('rx')).to.be(5); - var box = ellipse.getBBox(); - expect(box.minX).to.be(14.5); - expect(box.maxX).to.be(25.5); - expect(box.minY).to.be(28.5); - expect(box.maxY).to.be(31.5); - }); - - it('ry', function() { - expect(ellipse.attr('ry')).to.be(1); - ellipse.attr('ry', 10); - expect(ellipse.attr('ry')).to.be(10); - var box = ellipse.getBBox(); - expect(box.minX).to.be(14.5); - expect(box.maxX).to.be(25.5); - expect(box.minY).to.be(19.5); - expect(box.maxY).to.be(40.5); - }); - - - it('lineWidth', function() { - expect(ellipse.attr('lineWidth')).to.be(1); - ellipse.attr('lineWidth', 2); - expect(ellipse.attr('lineWidth')).to.be(2); - var box = ellipse.getBBox(); - expect(box.minX).to.be(14); - expect(box.maxX).to.be(26); - expect(box.minY).to.be(19); - expect(box.maxY).to.be(41); - }); - - it('stroke', function() { - ellipse.attr('stroke', 'l (0) 0:#959231 1:#00cd54'); - expect(ellipse.attr('stroke')).to.be('l (0) 0:#959231 1:#00cd54'); - canvas.add(ellipse); - canvas.draw(); - }); - - it('fill', function() { - ellipse.attr('fill', 'l (90) 0:#959231 1:#00cd54'); - expect(ellipse.attr('fill')).to.be('l (90) 0:#959231 1:#00cd54'); - canvas.draw(); - }); - - - it('isHit', function() { - var ellipse1 = new G.Ellipse({ - attrs: { - x: 50, - y: 50, - rx: 200, - ry: 100 - } - }); - - expect(ellipse1.isHit(-150, 50)).to.be(false); - expect(ellipse1.isHit(50, -50)).to.be(false); - expect(ellipse1.isHit(250, 50)).to.be(false); - expect(ellipse1.isHit(50, 150)).to.be(false); - - ellipse1.attr('stroke', 'red'); - expect(ellipse1.isHit(-150, 50)).to.be(true); - expect(ellipse1.isHit(50, -50)).to.be(true); - expect(ellipse1.isHit(250, 50)).to.be(true); - expect(ellipse1.isHit(50, 150)).to.be(true); - - var ellipse2 = new G.Ellipse({ - attrs: { - x: 100, - y: 200, - rx: 50, - ry: 80 - } - }); - - expect(ellipse2.isHit(70, 200)).to.be(false); - expect(ellipse2.isHit(100, 150)).to.be(false); - expect(ellipse2.isHit(130, 200)).to.be(false); - expect(ellipse2.isHit(100, 230)).to.be(false); - - ellipse2.attr('fill', 'green'); - - expect(ellipse2.isHit(70, 200)).to.be(true); - expect(ellipse2.isHit(100, 150)).to.be(true); - expect(ellipse2.isHit(130, 200)).to.be(true); - expect(ellipse2.isHit(100, 230)).to.be(true); - - var ellipse3 = new G.Ellipse({ - attrs: { - x: 200, - y: 200, - rx: 50, - ry: 100 - } - }); - - expect(ellipse3.isHit(150, 200)).to.be(false); - expect(ellipse3.isHit(250, 200)).to.be(false); - expect(ellipse3.isHit(200, 100)).to.be(false); - expect(ellipse3.isHit(200, 300)).to.be(false); - expect(ellipse3.isHit(170, 200)).to.be(false); - ellipse3.attr({ - fill: 'green', - stroke: 'red' - }); - expect(ellipse3.isHit(150, 200)).to.be(true); - expect(ellipse3.isHit(250, 200)).to.be(true); - expect(ellipse3.isHit(200, 100)).to.be(true); - expect(ellipse3.isHit(200, 300)).to.be(true); - expect(ellipse3.isHit(170, 200)).to.be(true); - }); - - - - - - - -}); diff --git a/tests/g/shape-fan-spec.js b/tests/g/shape-fan-spec.js deleted file mode 100644 index 4502e933f..000000000 --- a/tests/g/shape-fan-spec.js +++ /dev/null @@ -1,159 +0,0 @@ -var expect = require('@ali/expect.js'); -var G = require('../../src/g/index'); -var gMath = require('@ali/g-math'); -var Canvas = require('../../src/canvas'); -var div = document.createElement('div'); -div.id = 'canvas-fan'; -document.body.appendChild(div); - - -describe('CFan', function() { - var canvas = new Canvas({ - containerId: 'canvas-fan', - width: 200, - heigth: 200, - pixelRatio: 1 - }); - G.debug(true); - var fan = new G.Fan({ - attrs: { - x: 0, - y: 0, - rs: 0, - re: 0, - startAngle: 0, - endAngle: 0, - clockwise: false - } - }); - it('init attr', function() { - expect(fan.attr('x')).to.be(0); - expect(fan.attr('y')).to.be(0); - expect(fan.attr('rs')).to.be(0); - expect(fan.attr('re')).to.be(0); - expect(fan.attr('startAngle')).to.be(0); - expect(fan.attr('endAngle')).to.be(0); - expect(fan.attr('clockwise')).to.be(false); - expect(fan.attr('lineWidth')).to.be(1); - var box = fan.getBBox(); - expect(box.minX).to.be(-0.5); - expect(box.maxX).to.be(0.5); - expect(box.minY).to.be(-0.5); - expect(box.maxY).to.be(0.5); - }); - - it('x', function() { - fan.attr('x', 10); - expect(fan.attr('x')).to.be(10); - var box = fan.getBBox(); - expect(box.minX).to.be(9.5); - expect(box.maxX).to.be(10.5); - }); - - it('y', function() { - fan.attr('y', 20); - expect(fan.attr('y')).to.be(20); - var box = fan.getBBox(); - expect(box.minY).to.be(19.5); - expect(box.maxY).to.be(20.5); - }); - - it('startAngle', function() { - fan.attr('startAngle', Math.PI); - expect(gMath.equal(fan.attr('startAngle'), Math.PI)).to.be(true); - }); - - it('endAngle', function() { - fan.attr('endAngle', Math.PI * 3 / 2); - expect(gMath.equal(fan.attr('endAngle'), Math.PI * 3 / 2)).to.be(true); - }); - - it('rs', function() { - expect(fan.attr('rs')).to.be(0); - fan.attr('rs', 10); - expect(fan.attr('rs')).to.be(10); - var box = fan.getBBox(); - expect(gMath.equal(box.minX, -0.5)).to.be(true); - expect(gMath.equal(box.maxX, 10.5)).to.be(true); - expect(gMath.equal(box.minY, 9.5)).to.be(true); - expect(gMath.equal(box.maxY, 20.5)).to.be(true); - }); - - it('re', function() { - expect(fan.attr('re')).to.be(0); - fan.attr('re', 30); - expect(fan.attr('re')).to.be(30); - canvas.draw(); - var box = fan.getBBox(); - expect(gMath.equal(box.minX, -20.5)).to.be(true); - expect(gMath.equal(box.maxX, 10.5)).to.be(true); - expect(gMath.equal(box.minY, -10.5)).to.be(true); - expect(gMath.equal(box.maxY, 20.5)).to.be(true); - }); - - it('clockwise', function() { - expect(fan.attr('clockwise')).to.be(false); - fan.attr('clockwise', true); - expect(fan.attr('clockwise')).to.be(true); - var box = fan.getBBox(); - expect(gMath.equal(box.minX, -20.5)).to.be(true); - expect(gMath.equal(box.maxX, 40.5)).to.be(true); - expect(gMath.equal(box.minY, -10.5)).to.be(true); - expect(gMath.equal(box.maxY, 50.5)).to.be(true); - }); - - it('lineWidth', function() { - expect(fan.attr('lineWidth')).to.be(1); - fan.attr('lineWidth', 2); - expect(fan.attr('lineWidth')).to.be(2); - var box = fan.getBBox(); - expect(gMath.equal(box.minX, -21)).to.be(true); - expect(gMath.equal(box.maxX, 41)).to.be(true); - expect(gMath.equal(box.minY, -11)).to.be(true); - expect(gMath.equal(box.maxY, 51)).to.be(true); - }); - - it('stroke', function() { - fan.attr({ - x: 40, - y: 40 - }); - fan.attr('stroke', 'l (210) 0:#ff0000 1:#ffffff'); - expect(fan.attr('stroke')).to.be('l (210) 0:#ff0000 1:#ffffff'); - canvas.add(fan); - canvas.draw(); - }); - - it('fill', function() { - fan.attr('fill', 'l (130) 0:#0000ff 1:#ffffff'); - expect(fan.attr('fill')).to.be('l (130) 0:#0000ff 1:#ffffff'); - canvas.draw(); - }); - - it('isHit', function() { - expect(fan.isHit(40, 40)).to.be(false); - expect(fan.isHit(40, 60)).to.be(true); - }); -}); - - - - - - - - - - - - - - - - - - - - - - diff --git a/tests/g/shape-image-spec.js b/tests/g/shape-image-spec.js deleted file mode 100644 index 1f775dbed..000000000 --- a/tests/g/shape-image-spec.js +++ /dev/null @@ -1,180 +0,0 @@ -var expect = require('@ali/expect.js'); -var G = require('../../src/g/index'); -var Canvas = require('../../src/canvas'); -var div = document.createElement('div'); -div.id = 'canvas-img'; -document.body.appendChild(div); - -describe('Image', function() { - - var can1 = document.createElement('canvas'); - can1.id = 'img1'; - can1.width = 800; - can1.height = 800; - var canvas = new Canvas({ - containerId: 'canvas-img', - width: 200, - height: 200, - pixelRatio: 1 - }); - G.debug(true); - var image = new G.Image({ - attrs: { - x: 0, - y: 0, - width: 0, - height: 0 - } - }); - it('init attr', function(){ - expect(image.attr('x')).to.be(0); - expect(image.attr('y')).to.be(0); - expect(image.attr('img')).to.be(undefined); - expect(image.attr('width')).to.be(0); - expect(image.attr('height')).to.be(0); - expect(image.attr('sx')).to.be(undefined); - expect(image.attr('sy')).to.be(undefined); - expect(image.attr('swidth')).to.be(undefined); - expect(image.attr('sheight')).to.be(undefined); - var box = image.getBBox(); - expect(box.minX).to.be(0); - expect(box.maxX).to.be(0); - expect(box.minY).to.be(0); - expect(box.maxY).to.be(0); - }); - - it('img', function(done) { - var img = new Image(); - img.onload = function() { - image.attr('img', img); - var box = image.getBBox(); - expect(box.minX).to.be(0); - expect(box.minY).to.be(0); - expect(box.maxX).to.be(768); - expect(box.maxY).to.be(1024); - canvas.add(image); - canvas.draw(); - done(); - }; - img.src = '../examples/test1.jpg'; - }); - - it('canvas', function() { - var image = new G.Image({ - attrs: { - x: 0, - y: 0 - } - }); - var img = can1; - image.attr('img', img); - var box = image.getBBox(); - expect(box.minX).to.be(0); - expect(box.minY).to.be(0); - expect(box.maxX).to.be(800); - expect(box.maxY).to.be(800); - canvas.add(image); - canvas.draw(); - }); - - it('imageData', function(done) { - var image = new G.Image({ - attrs: { - x: 0, - y: 0 - } - }); - var img = can1.getContext('2d').getImageData(0,0,800,800); - image.attr('img', img); - var box = image.getBBox(); - expect(box.minX).to.be(0); - expect(box.minY).to.be(0); - expect(box.maxX).to.be(800); - expect(box.maxY).to.be(800); - canvas.add(image); - canvas.draw(); - done(); - }); - - it('width', function() { - expect(image.attr('width')).to.be(768); - image.attr('width', 200); - expect(image.attr('width')).to.be(200); - var box = image.getBBox(); - expect(box.minX).to.be(0); - expect(box.maxX).to.be(200); - canvas.draw(); - }); - - it('height', function() { - expect(image.attr('height')).to.be(1024); - image.attr('height', 200); - expect(image.attr('height')).to.be(200); - var box = image.getBBox(); - expect(box.minY).to.be(0); - expect(box.maxY).to.be(200); - canvas.draw(); - }); - - it('x', function() { - image.attr('x', 10); - expect(image.attr('x')).to.be(10); - var box = image.getBBox(); - expect(box.minX).to.be(10); - expect(box.maxX).to.be(210); - canvas.draw(); - }); - - it('y', function() { - image.attr('y', 10); - expect(image.attr('y')).to.be(10); - var box = image.getBBox(); - expect(box.minY).to.be(10); - expect(box.maxY).to.be(210); - canvas.draw(); - }); - - it('sx, sy, swidth, sheight', function() { - image.attr({ - sx: 20, - sy: 20, - swidth: 100, - sheight: 200 - }); - canvas.draw(); - }); - - it('normal use', function() { - var image1 = new G.Image({ - attrs: { - x: 300, - y: 300, - width: 300, - height: 300, - img: '../examples/test2.jpg' - } - }); - - canvas.add(image1); - canvas.draw(); - }); - - it('isHit', function() { - expect(image.isHit(10, 10)).to.be(true); - expect(image.isHit(210, 210)).to.be(true); - expect(image.isHit(20, 20)).to.be(true); - expect(image.isHit(31, 43)).to.be(true); - expect(image.isHit(300, 300)).to.be(false); - }); - - it('image onload && image.remove(true)', function() { - var image = new G.Image({ - attrs: { - img: 'http://alipay-rmsdeploy-assets-private.cn-hangzhou.alipay.aliyun-inc.com/rmsportal/IHJtPedUbTUPQCx.png' - } - }); - canvas.add(image); - image.remove(true); - canvas.draw(); - }); -}); diff --git a/tests/g/shape-line-spec.js b/tests/g/shape-line-spec.js deleted file mode 100644 index c09a62c34..000000000 --- a/tests/g/shape-line-spec.js +++ /dev/null @@ -1,144 +0,0 @@ -var expect = require('@ali/expect.js'); -var G = require('../../src/g/index'); -var Canvas = require('../../src/canvas'); -var div = document.createElement('div'); -div.id = 'canvas-line'; -document.body.appendChild(div); - -describe('Line', function() { - - var canvas = new Canvas({ - containerId: 'canvas-line', - width: 200, - height: 200, - pixelRatio: 1 - }); - G.debug(true); - var line = new G.Line({ - attrs: { - x1: 0, - x2: 0, - y1: 0, - y2: 0, - arrow: false - } - }); - it('init attrs', function() { - expect(line.attr('x1')).to.be(0); - expect(line.attr('y1')).to.be(0); - expect(line.attr('x2')).to.be(0); - expect(line.attr('y2')).to.be(0); - expect(line.attr('lineWidth')).to.be(1); - expect(line.attr('stroke')).to.be(undefined); - expect(line.attr('fill')).to.be(undefined); - expect(line.attr('arrow')).to.be(false); - var box = line.getBBox(); - expect(box.minX).to.be(-0.5); - expect(box.maxX).to.be(0.5); - expect(box.minY).to.be(-0.5); - expect(box.maxY).to.be(0.5); - }); - - it('x1', function() { - line.attr('x1', 10); - expect(line.attr('x1')).to.be(10); - var box = line.getBBox(); - expect(box.minX).to.be(-0.5); - expect(box.maxX).to.be(10.5); - }); - - it('y1', function() { - line.attr('y1', 15); - expect(line.attr('y1')).to.be(15); - var box = line.getBBox(); - expect(box.minY).to.be(-0.5); - expect(box.maxY).to.be(15.5); - }); - - it('x2', function() { - line.attr('x2', 59); - expect(line.attr('x2')).to.be(59); - var box = line.getBBox(); - expect(box.minX).to.be(9.5); - expect(box.maxX).to.be(59.5); - }); - - it('y2', function() { - line.attr('y2', 80); - expect(line.attr('y2')).to.be(80); - var box = line.getBBox(); - expect(box.minY).to.be(14.5); - expect(box.maxY).to.be(80.5); - }); - - it('lineWidth', function() { - expect(line.attr('lineWidth')).to.be(1); - line.attr('lineWidth', 2); - expect(line.attr('lineWidth')).to.be(2); - var box = line.getBBox(); - expect(box.minX).to.be(9); - expect(box.maxX).to.be(60); - expect(box.minY).to.be(14); - expect(box.maxY).to.be(81); - }); - - it('stroke', function() { - line.attr('stroke', 'l (0) 0.1:#0fedae 1:#6542da'); - expect(line.attr('stroke')).to.be('l (0) 0.1:#0fedae 1:#6542da'); - canvas.add(line); - canvas.draw(); - }); - - it('isHit', function() { - expect(line.isHit(9, 14)).to.be(true); - expect(line.isHit(34.5, 47.5)).to.be(true); - expect(line.isHit(8, 11)).to.be(false); - var line1 = new G.Line({ - attrs: { - x1: 0, - y1: 0, - x2: 100, - y2: 100 - } - }); - expect(line1.isHit(101, 101)).to.be(false); - expect(line1.isHit(100, 100)).to.be(false); - line1.attr('stroke', 'red'); - expect(line1.isHit(101, 101)).to.be(false); - expect(line1.isHit(100, 100)).to.be(true); - }); - - it('arrow', function() { - line.attr('arrow', true); - expect(line.attr('arrow')).to.be(true); - canvas.draw(); - }); - - it('getPoint', function() { - var line = new G.Line({ - attrs: { - x1: 0, - y1: 0, - x2: 200, - y2: 300 - } - }); - - var point = line.getPoint(0.5); - expect(point.x).to.be(100); - expect(point.y).to.be(150); - }); -}); - - - - - - - - - - - - - diff --git a/tests/g/shape-marker-spec.js b/tests/g/shape-marker-spec.js deleted file mode 100644 index 7b7e37c48..000000000 --- a/tests/g/shape-marker-spec.js +++ /dev/null @@ -1,43 +0,0 @@ -var expect = require('@ali/expect.js'); -var G = require('../../src/g/index'); -var Canvas = require('../../src/canvas'); -var div = document.createElement('div'); -div.id = 'canvas-marker'; -document.body.appendChild(div); - - -describe('Marker', function () { - var canvas = new Canvas({ - containerId: 'canvas-marker', - width: 200, - height: 200, - pixelRatio: 1 - }); - it ('init', function() { - var marker = canvas.addShape('marker', { - attrs: { - x: 10, - y: 10, - radius: 10, - fill: 'red', - symbol: 'circle' - } - }); - expect(marker.attr('x')).to.be(10); - expect(marker.attr('y')).to.be(10); - }); - - it('hit', function() { - var marker = canvas.addShape('marker', { - attrs: { - x: 20, - y: 20, - radius: 10, - fill: 'blue', - symbol: 'circle' - } - }); - expect(marker.isHit(20, 20)).to.be(true); - expect(marker.isHit(10, 10)).to.be(false); - }); -}); diff --git a/tests/g/shape-math-arc-spec.js b/tests/g/shape-math-arc-spec.js deleted file mode 100644 index 7abac6f70..000000000 --- a/tests/g/shape-math-arc-spec.js +++ /dev/null @@ -1,60 +0,0 @@ -var expect = require('@ali/expect.js'); -var Arc = require('../../src/g/shape/math/arc'); -var gMath = require('@ali/g-math'); - - -describe('Arc math', function() { - it('nearAngle', function() { - var angle = gMath.degreeToRad(20); - var startAngle = gMath.degreeToRad(0); - var endAngle = gMath.degreeToRad(90); - - expect(gMath.equal(gMath.radToDegree(Arc.nearAngle(angle, startAngle, endAngle)), 20)).to.be(true); - }); - - it('nearAngle1', function() { - var angle = gMath.degreeToRad(-20); - var startAngle = gMath.degreeToRad(0); - var endAngle = gMath.degreeToRad(90); - - expect(gMath.equal(gMath.radToDegree(Arc.nearAngle(angle, startAngle, endAngle)), 0)).to.be(true); - }); - - it('nearAngle2', function() { - var angle = gMath.degreeToRad(110); - var startAngle = gMath.degreeToRad(90); - var endAngle = gMath.degreeToRad(-30); - - expect(gMath.equal(gMath.radToDegree(Arc.nearAngle(angle, startAngle, endAngle)), 110)).to.be(true); - }); - - it('nearAngle3', function() { - var angle = gMath.degreeToRad(110); - var startAngle = gMath.degreeToRad(90); - var endAngle = gMath.degreeToRad(-30); - - expect(gMath.equal(gMath.radToDegree(Arc.nearAngle(angle, startAngle, endAngle)), 110)).to.be(true); - }); - - it('nearAngle4', function() { - var angle = gMath.degreeToRad(110); - var startAngle = gMath.degreeToRad(90); - var endAngle = gMath.degreeToRad(-30); - - expect(gMath.equal(gMath.radToDegree(Arc.nearAngle(angle, startAngle, endAngle, true)), 90)).to.be(true); - }); - - it('nearAngle', function() { - var angle = gMath.degreeToRad(30); - var startAngle = gMath.degreeToRad(0); - var endAngle = gMath.degreeToRad(360); - }); - - - it('arcProjectPoint', function() { - expect(gMath.equal( - Arc.pointDistance(10, 10, 10, -Math.PI / 2, Math.PI / 2, false, 20, 0), - Math.sqrt(2) * 10 - 10 - )).to.be(true); - }); -}); diff --git a/tests/g/shape-path-spec.js b/tests/g/shape-path-spec.js deleted file mode 100644 index 8411f67ca..000000000 --- a/tests/g/shape-path-spec.js +++ /dev/null @@ -1,537 +0,0 @@ -var expect = require('@ali/expect.js'); -var G = require('../../src/g/index'); -var gMath = require('@ali/g-math'); -var pathUtil = require('@ali/g-path-util'); -var Canvas = require('../../src/canvas'); -var div = document.createElement('div'); -div.id = 'canvas-path'; -document.body.appendChild(div); - -describe('Path', function() { - - var canvas = new Canvas({ - containerId: 'canvas-path', - width: 800, - height: 800, - pixelRatio: 1 - }); - G.debug(true); - var img = document.createElement('img'); - img.src = '../examples/test1.jpg'; - img.id = 'img'; - document.body.appendChild(img); - - var path = new G.Path(); - - it('init attrs', function() { - expect(path.attr('path')).to.be(undefined); - expect(path.attr('lineWidth')).to.be(1); - expect(path.getBBox()).to.be(null); - canvas.add(path); - canvas.draw(); - }); - - it('path', function() { - path.attr('path', null); - expect(path.getBBox()).to.be(null); - path.attr('path', []); - expect(path.getBBox()).to.be(null); - path.attr('path', [ - ['a'] - ]); - expect(path.getBBox()).to.be(null); - path.attr('path', [ - ['M', 200, 200], - ['L', 300, 300] - ]); - - expect(path.get('segments').length).to.be(2); - var box = path.getBBox(); - expect(box.minX).to.be(199.5); - expect(box.maxX).to.be(300.5); - expect(box.minY).to.be(199.5); - expect(box.maxY).to.be(300.5); - }); - - it('lineWidth', function() { - expect(path.attr('lineWidth')).to.be(1); - path.attr('lineWidth', 2); - expect(path.attr('lineWidth')).to.be(2); - var box = path.getBBox(); - expect(box.minX).to.be(199); - expect(box.maxX).to.be(301); - expect(box.minY).to.be(199); - expect(box.maxY).to.be(301); - }); - - it('stroke', function() { - path.attr('stroke', 'l (0) 0:#fff000 1:#000fff'); - expect(path.attr('stroke')).to.be('l (0) 0:#fff000 1:#000fff'); - canvas.add(path); - canvas.draw(); - }); - - it('fill', function() { - var path = new G.Path({ - attrs: { - path: [ - ['M', 200, 200], - ['L', 300, 200], - ['L', 300, 300], - ['Z'] - ], - fill: 'red' - } - }); - expect(path.attr('fill')).to.be('red'); - canvas.add(path); - canvas.draw(); - }); - - it('path string', function() { - var path = new G.Path({ - attrs: { - path: 'M100,600' + - 'l 50,-25' + - 'a25,25 -30 0,1 50,-25' + - 'l 50,-25' + - 'a25,50 -30 0,1 50,-25' + - 'l 50,-25' + - 'a25,75 -30 0,1 50,-25' + - 'l 50,-25' + - 'a25,100 -30 0,1 50,-25' + - 'l 50,-25' + - 'l 0, 200,' + - 'z', - lineWidth: 10, - lineJoin: 'round', - stroke: 'red' - } - }); - - canvas.add(path); - canvas.draw(); - }); - - it('l and L', function() { - var path = new G.Path({ - attrs: { - path: [ - ['M', 400, 400], - ['L', 400, 500], - ['l', 50, 50], - ['Z'] - ], - stroke: 'red', - fill: 'green', - arrow: true - } - }); - expect(path.isHit(400, 400)).to.be(true); - expect(path.isHit(400, 500)).to.be(true); - expect(path.isHit(450, 550)).to.be(true); - expect(path.isHit(405, 450)).to.be(false); - canvas.add(path); - expect(path.isHit(405, 450)).to.be(true); - canvas.draw(); - }); - - it('h and H', function() { - var path = new G.Path({ - attrs: { - path: [ - ['M', 200, 400], - ['H', 400], - ['h', 100] - ], - stroke: 'red', - arrow: true - } - }); - expect(path.isHit(200, 400)).to.be(true); - expect(path.isHit(300, 400)).to.be(true); - expect(path.isHit(400, 400)).to.be(true); - expect(path.isHit(500, 400)).to.be(true); - canvas.add([path]); - canvas.draw(); - }); - - it('v and V', function() { - var path = new G.Path({ - attrs: { - path: [ - ['M', 200, 400], - ['V', 600], - ['v', 100] - ], - stroke: 'red', - arrow: true - } - }); - expect(path.isHit(200, 400)).to.be(true); - expect(path.isHit(200, 500)).to.be(true); - expect(path.isHit(200, 600)).to.be(true); - expect(path.isHit(200, 700)).to.be(true); - canvas.add([path]); - canvas.draw(); - }); - - it('q and Q', function() { - var path = new G.Path({ - attrs: { - path: [ - ['M', 200, 400], - ['Q', 300, 300, 400, 400] - ], - stroke: 'red', - arrow: true - } - }); - expect(path.isHit(200, 400)).to.be(true); - expect(path.isHit(300, 350)).to.be(true); - expect(path.isHit(400, 400)).to.be(true); - - var path1 = new G.Path({ - attrs: { - path: [ - ['M', 200, 400], - ['q', 50, 50, 100, 0] - ], - stroke: 'red', - arrow: true - } - }); - - expect(path1.isHit(200, 400)).to.be(true); - expect(path1.isHit(250, 425)).to.be(true); - expect(path1.isHit(300, 400)).to.be(true); - canvas.add([path, path1]); - canvas.draw(); - }); - - it('t and T', function() { - var path = new G.Path({ - attrs: { - path: [ - ['M', 200, 400], - ['Q', 300, 300, 400, 400], - ['T', 600, 400] - ], - stroke: 'red', - arrow: true - } - }); - expect(path.isHit(200, 400)).to.be(true); - expect(path.isHit(300, 350)).to.be(true); - expect(path.isHit(400, 400)).to.be(true); - expect(path.isHit(500, 450)).to.be(true); - expect(path.isHit(600, 400)).to.be(true); - - var path1 = new G.Path({ - attrs: { - path: [ - ['M', 200, 400], - ['Q', 300, 300, 400, 400], - ['t', 100, 0] - ], - stroke: 'red', - arrow: true - } - }); - expect(path1.isHit(200, 400)).to.be(true); - expect(path1.isHit(300, 350)).to.be(true); - expect(path1.isHit(400, 400)).to.be(true); - expect(path1.isHit(475, 450)).to.be(true); - expect(path1.isHit(500, 400)).to.be(true); - - - var path2 = new G.Path({ - attrs: { - path: [ - ['M', 200, 400], - ['L', 400, 400], - ['t', 100, 0] - ], - stroke: 'red', - arrow: true - } - }); - expect(path2.isHit(200, 400)).to.be(true); - expect(path2.isHit(400, 400)).to.be(true); - expect(path2.isHit(475, 450)).to.be(false); - expect(path2.isHit(500, 400)).to.be(true); - canvas.add([path, path1, path2]); - canvas.draw() - }); - - it('c and C', function() { - var path = new G.Path({ - attrs: { - path: [ - ['M', 200, 400], - ['C', 300, 300, 400, 500, 500, 400] - ], - stroke: 'red', - arrow: true - } - }); - - expect(path.isHit(200, 400)).to.be(true); - expect(path.isHit(350, 400)).to.be(true); - expect(path.isHit(500, 400)).to.be(true); - - var path1 = new G.Path({ - attrs: { - path: [ - ['M', 200, 400], - ['c', 100, -100, 200, 100, 300, 0] - ], - stroke: 'red' - } - }); - - expect(path1.isHit(200, 400)).to.be(true); - expect(path1.isHit(350, 400)).to.be(true); - expect(path1.isHit(500, 400)).to.be(true); - canvas.add([path, path1]); - canvas.draw() - }); - - it('s and S', function() { - var path = new G.Path({ - attrs: { - path: [ - ['M', 200, 400], - ['C', 300, 300, 400, 500, 500, 400], - ['S', 700, 500, 800, 400] - ], - stroke: 'red' - } - }); - expect(path.isHit(200, 400)).to.be(true); - expect(path.isHit(350, 400)).to.be(true); - expect(path.isHit(500, 400)).to.be(true); - expect(path.isHit(650, 400)).to.be(true); - expect(path.isHit(800, 400)).to.be(true); - - var path1 = new G.Path({ - attrs: { - path: [ - ['M', 200, 400], - ['C', 300, 300, 400, 500, 500, 400], - ['s', 200, 100, 300, 0] - ], - stroke: 'blue' - } - }); - expect(path1.isHit(200, 400)).to.be(true); - expect(path1.isHit(350, 400)).to.be(true); - expect(path1.isHit(500, 400)).to.be(true); - expect(path1.isHit(650, 400)).to.be(true); - expect(path1.isHit(800, 400)).to.be(true); - - var path2 = new G.Path({ - attrs: { - path: [ - ['M', 200, 400], - ['L', 500, 400], - ['s', 200, 100, 300, 0] - ], - stroke: 'red', - arrow: true - } - }); - expect(path2.isHit(200, 400)).to.be(true); - expect(path2.isHit(500, 400)).to.be(true); - expect(path2.isHit(650, 400)).to.be(false); - expect(path2.isHit(675, 450)).to.be(true); - expect(path2.isHit(800, 400)).to.be(true); - canvas.add([path, path1, path2]); - canvas.draw(); - }); - - it('a And A', function() { - var path = new G.Path({ - attrs: { - path: [ - ['M', 300, 300], - ['A', 50, 50, 0, 0, 1, 400, 400] - ], - stroke: 'red' - } - }); - - expect(path.isHit(300, 300)).to.be(true); - expect(path.isHit(400, 400)).to.be(true); - expect(path.isHit(400, 300)).to.be(true); - - var path1 = new G.Path({ - attrs: { - path: [ - ['M', 300, 300], - ['A', 50, 50, 0, 0, 1, 400, 400] - ], - stroke: 'red' - } - }); - expect(path1.isHit(300, 300)).to.be(true); - expect(path1.isHit(400, 400)).to.be(true); - expect(path1.isHit(400, 300)).to.be(true); - - /* var img = new Image(); - - img.onload = function() { - - }; - - var path2 = new G.Path({ - attrs: { - path: [ - ['M', 300, 300], - ['A', 50, 50, 0, 1, 1, 300, 400], - ['z'] - ], - stroke: 'p a img' - } - }); - expect(path2.isHit(300, 300)).to.be(true); - expect(path2.isHit(300, 400)).to.be(true); - expect(path2.isHit(350, 350)).to.be(true); - expect(path2.isHit(300, 350)).to.be(true); - canvas.add(path2); - canvas.draw(); - path2.set('attrs', { - path: [ - ['M', 300, 300], - ['A', 50, 50, 0, 1, 1, 300, 400], - ['z'] - ], - stroke: 'p x img' - }); - path2.hide(); - path2.show(); - canvas.draw(); - - var path3 = new G.Path({ - attrs: { - path: [ - ['M', 300, 300], - ['A', 50, 50, 0, 1, 1, 300, 400], - ['z'] - ], - stroke: 'p y img' - } - }); - canvas.add(path3); - canvas.draw(); - - var path4 = new G.Path({ - attrs: { - path: [ - ['M', 300, 300], - ['A', 50, 50, 0, 1, 1, 300, 400], - ['z'] - ], - stroke: 'p n img' - } - }); - canvas.add(path4); - canvas.draw(); - - - var path5 = new G.Path({ - attrs: { - path: [ - ['M', 300, 300], - ['A', 50, 50, 0, 1, 1, 300, 400], - ['z'] - ], - stroke: 'p e img' - } - }); - canvas.add(path5); - canvas.draw(); - - var path6 = new G.Path({ - attrs: { - path: [ - ['M', 300, 300], - ['A', 50, 50, 0, 1, 1, 300, 400], - ['z'] - ], - stroke: 'p a img' - } - }); - canvas.add(path6); - */ - canvas.draw(); - }); - - it('getPoint', function(){ - var path = [ - ['M', 300, 300], - ['L', 300, 50], - ['L', 50, 50], - ['L', 50, 300], - ]; - // var curve = pathUtil.toCurve(path); - var path7 = new G.Path({ - attrs: { - path: path, - stroke: 'red' - } - }); - var point0 = path7.getPoint(0); - var point1 = path7.getPoint(0.5); - var point2 = path7.getPoint(1); - var point3 = path7.getPoint(0.225); - // var point = point3; - // var circle = new G.Circle({ - // attrs:{ - // x: point.x, - // y: point.y, - // r: 3, - // fill: 'blue' - // } - // }); - // var path7Cureve = new G.Path({ - // attrs: { - // path: curve, - // stroke: 'blue' - // } - // }); - // path7Cureve.translate(100, 200); - canvas.add(path7); - // canvas.add(path7Cureve); - // canvas.add(circle); - canvas.draw(); - expect(point0).eql({ x: 300, y: 300 }); - expect(point1).eql({ x: 174.99999999999997, y: 50}); - expect(point2).eql({ x: 50, y: 300 }); - expect(point3).eql({ x: 300, y: 112.0546875 }); - }); - - it('appendWidth', function() { - var path = [ - ['M', 200, 200], - ['L', 200, 50], - ['L', 50, 50], - ['L', 50, 300], - ]; - - var path8 = new G.Path({ - attrs: { - path: path, - lineAppendWidth: 10, - stroke: 'blue' - } - }); - - expect(path8.isHit(196, 200)).to.be(true); - expect(path8.isHit(52, 250)).to.be(true); - - canvas.add(path8); - canvas.draw(); - }); - -}); diff --git a/tests/g/shape-polygon-spec.js b/tests/g/shape-polygon-spec.js deleted file mode 100644 index 52633fc16..000000000 --- a/tests/g/shape-polygon-spec.js +++ /dev/null @@ -1,151 +0,0 @@ -var expect = require('@ali/expect.js'); -var G = require('../../src/g/index'); -var Canvas = require('../../src/canvas'); -var div = document.createElement('div'); -div.id = 'canvas-polygon'; -document.body.appendChild(div); - - -describe('Polygon', function() { - - var canvas = new Canvas({ - containerId: 'canvas-polygon', - width: 200, - height: 200, - pixelRatio: 1 - }); - G.debug(true); - var polygon = new G.Polygon(); - it('init attr', function() { - expect(polygon.attr('points')).to.be(undefined); - expect(polygon.attr('lineWidth')).to.be(1); - expect(polygon.attr('stroke')).to.be(undefined); - expect(polygon.attr('fill')).to.be(undefined); - expect(polygon.getBBox()).to.be(null); - }); - - it('points', function() { - polygon.attr('points', []); - expect(polygon.attr('points').length).to.be(0); - expect(polygon.getBBox()).to.be(null); - polygon.attr('points', [[30, 30], [40, 20], [30, 50], [60, 100]]); - expect(polygon.attr('points').length).to.be(4); - var box = polygon.getBBox(); - expect(box.minX).to.be(29.5); - expect(box.maxX).to.be(60.5); - expect(box.minY).to.be(19.5); - expect(box.maxY).to.be(100.5); - - var polygon1 = new G.Polygon({ - attrs: { - points: [[58, 60], [80, 190], [32, 53], [45, 32]] - } - }); - var box = polygon1.getBBox(); - expect(box.minX).to.be(31.5); - expect(box.minY).to.be(31.5); - expect(box.maxX).to.be(80.5); - expect(box.maxY).to.be(190.5); - }); - - it('lineWidth', function() { - expect(polygon.attr('lineWidth')).to.be(1); - polygon.attr('lineWidth', 2); - expect(polygon.attr('lineWidth')).to.be(2); - var box = polygon.getBBox(); - expect(box.minX).to.be(29); - expect(box.maxX).to.be(61); - expect(box.minY).to.be(19); - expect(box.maxY).to.be(101); - - var polygon1 = new G.Polygon({ - attrs: { - points: [[58, 60], [80, 190], [32, 53], [45, 32]], - lineWidth: 2 - } - }); - var box = polygon1.getBBox(); - expect(box.minX).to.be(31); - expect(box.minY).to.be(31); - expect(box.maxX).to.be(81); - expect(box.maxY).to.be(191); - }); - - it('stroke', function() { - polygon.attr('stroke', 'l (90) 0:#f0ff0f 1:#ff0e0d'); - expect(polygon.attr('stroke')).to.be('l (90) 0:#f0ff0f 1:#ff0e0d'); - canvas.add(polygon); - canvas.draw(); - }); - - it('fill', function() { - polygon.attr('fill', 'r (0.3, 0.2, 0) 0:#edda2f 1:#23edfa'); - expect(polygon.attr('fill')).to.be('r (0.3, 0.2, 0) 0:#edda2f 1:#23edfa'); - canvas.draw(); - }); - - it('isHit', function() { - expect(polygon.isHit(30, 30)).to.be(true); - expect(polygon.isHit(40, 20)).to.be(true); - expect(polygon.isHit(30, 50)).to.be(true); - expect(polygon.isHit(60, 100)).to.be(true); - - var polygon1 = new G.Polygon({ - attrs: { - points: [[31, 23], [43, 12], [53, 23], [64, 33]], - lineWidth: 2, - stroke: 'red' - } - }); - expect(polygon1.isHit(30, 23)).to.be(true); - expect(polygon1.isHit(31, 23)).to.be(true); - expect(polygon1.isHit(43, 12)).to.be(true); - expect(polygon1.isHit(53, 23)).to.be(true); - expect(polygon1.isHit(64, 33)).to.be(true); - expect(polygon1.isHit(37, 17.5)).to.be(true); - expect(polygon1.isHit(48, 17.5)).to.be(true); - expect(polygon1.isHit(47.5, 28)).to.be(true); - expect(polygon1.isHit(42.5, 17.5)).to.be(false); - - var polygon2 = new G.Polygon({ - attrs: { - points: [[31, 23], [43, 12], [53, 23], [64, 33]], - lineWidth: 2, - fill: 'red' - } - }); - canvas.add(polygon2); - expect(polygon2.isHit(30, 23)).to.be(false); - expect(polygon2.isHit(32, 23)).to.be(true); - expect(polygon2.isHit(43, 13)).to.be(true); - expect(polygon2.isHit(53, 23)).to.be(true); - expect(polygon2.isHit(37, 17.5)).to.be(true); - expect(polygon2.isHit(48, 17.5)).to.be(true); - expect(polygon2.isHit(47.5, 28)).to.be(true); - expect(polygon2.isHit(42.5, 17.5)).to.be(true); - - var polygon3 = new G.Polygon({ - attrs: { - points: [[31, 23], [43, 12], [53, 23], [64, 33]], - lineWidth: 2, - stroke: 'green', - fill: 'red' - } - }); - canvas.add(polygon3); - expect(polygon3.isHit(30, 23)).to.be(true); - expect(polygon3.isHit(31, 23)).to.be(true); - expect(polygon3.isHit(43, 12)).to.be(true); - expect(polygon3.isHit(53, 23)).to.be(true); - expect(polygon3.isHit(64, 33)).to.be(true); - expect(polygon3.isHit(37, 17.5)).to.be(true); - expect(polygon3.isHit(48, 17.5)).to.be(true); - expect(polygon3.isHit(47.5, 28)).to.be(true); - expect(polygon3.isHit(42.5, 17.5)).to.be(true); - }); - -}); - - - - diff --git a/tests/g/shape-polyline-spec.js b/tests/g/shape-polyline-spec.js deleted file mode 100644 index 3d6e6a198..000000000 --- a/tests/g/shape-polyline-spec.js +++ /dev/null @@ -1,123 +0,0 @@ -var expect = require('@ali/expect.js'); -var G = require('../../src/g/index'); -var Canvas = require('../../src/canvas'); -var div = document.createElement('div'); -div.id = 'canvas-polyline'; -document.body.appendChild(div); - - -describe('Polyline', function() { - var canvas = new Canvas({ - containerId: 'canvas-polyline', - width: 200, - height: 200, - pixelRatio: 1 - }); - G.debug(true); - var polyline = new G.Polyline(); - - it('init attrs', function() { - expect(polyline.attr('points')).to.be(undefined); - expect(polyline.attr('lineWidth')).to.be(1); - expect(polyline.attr('arrow')).to.be(false); - var box = polyline.getBBox(); - expect(box).to.be(null); - }); - - it('points', function() { - polyline.attr('points', []); - var points = polyline.attr('points'); - expect(points.length).to.be(0); - var box = polyline.getBBox(); - expect(box).to.be(null); - polyline.attr('points', [[20, 30], [50, 40], [100, 110], [130, 70]]); - var points = polyline.attr('points'); - expect(points.length).to.be(4); - var box = polyline.getBBox(); - expect(box.minX).to.be(19.5); - expect(box.maxX).to.be(130.5); - expect(box.minY).to.be(29.5); - expect(box.maxY).to.be(110.5); - - var polyline1 = new G.Polyline({ - attrs: { - points: [[40, 23], [53, 64], [79, 120], [234, 56]] - } - }); - var points = polyline1.attr('points'); - expect(points.length).to.be(4); - var box = polyline1.getBBox(); - expect(box.minX).to.be(39.5); - expect(box.maxX).to.be(234.5); - expect(box.minY).to.be(22.5); - expect(box.maxY).to.be(120.5); - }); - - it('lineWidth', function() { - expect(polyline.attr('lineWidth')).to.be(1); - polyline.attr('lineWidth', 2); - var box = polyline.getBBox(); - expect(box.minX).to.be(19); - expect(box.maxX).to.be(131); - expect(box.minY).to.be(29); - expect(box.maxY).to.be(111); - - var polyline1 = new G.Polyline({ - attrs: { - points: [[23, 12], [42, 52]], - lineWidth: 2 - } - }); - var box = polyline1.getBBox(); - expect(box.minX).to.be(22); - expect(box.maxX).to.be(43); - expect(box.minY).to.be(11); - expect(box.maxY).to.be(53); - }); - - it('stroke', function() { - polyline.attr('stroke', 'l (0) 0.2:#ff00ff 1:#0000ff'); - expect(polyline.attr('stroke')).to.be('l (0) 0.2:#ff00ff 1:#0000ff'); - canvas.add(polyline); - canvas.draw(); - }); - - it('isHit', function() { - expect(polyline.isHit(20, 30)).to.be(true); - expect(polyline.isHit(35, 35)).to.be(true); - expect(polyline.isHit(50, 40)).to.be(true); - expect(polyline.isHit(100, 110)).to.be(true); - expect(polyline.isHit(130, 70)).to.be(true); - expect(polyline.isHit(18, 29)).to.be(false); - var polyline1 = new G.Polyline({ - attrs: { - points: [[10, 10]] - } - }); - expect(polyline1.isHit(10, 10)).to.be(false); - polyline1.attr('stroke', 'red'); - expect(polyline1.isHit(10, 10)).to.be(false); - canvas.add(polyline1); - canvas.draw(); - }); - - it('arrow', function() { - polyline.attr('arrow', true); - expect(polyline.attr('arrow')).to.be(true); - canvas.draw(); - }); - - it('getPoint', function() { - expect(polyline.getPoint(1)).eql({x: 130, y: 70}); - expect(polyline.getPoint(0.5)).eql({x: 80.34077206680482, y: 82.47708089352673}); - expect(polyline.getPoint(0)).eql({x: 20, y: 30}); - }); -}); - - - - - - - - diff --git a/tests/g/shape-quadratic-spec.js b/tests/g/shape-quadratic-spec.js deleted file mode 100644 index 3b56835f5..000000000 --- a/tests/g/shape-quadratic-spec.js +++ /dev/null @@ -1,131 +0,0 @@ -var expect = require('@ali/expect.js'); -var G = require('../../src/g/index'); -var gMath = require('@ali/g-math'); -var Canvas = require('../../src/canvas'); -var div = document.createElement('div'); -div.id = 'canvas-quadratic'; -document.body.appendChild(div); - - -describe('Quadratic line', function() { - - var canvas = new Canvas({ - containerId: 'canvas-quadratic', - width: 200, - height: 200, - pixelRatio: 1 - }); - G.debug(true); - var quadratic = new G.Quadratic(); - it('init quadratic', function() { - expect(quadratic.attr('p1')).to.be(undefined); - expect(quadratic.attr('p2')).to.be(undefined); - expect(quadratic.attr('p3')).to.be(undefined); - expect(quadratic.attr('lineWidth')).to.be(1); - expect(quadratic.attr('arrow')).to.be(false); - - expect(quadratic.getBBox()).to.be(null); - }); - - it('p1, p2, p3', function() { - quadratic.attr({ - p1: [50, 50], - p2: [80, 12], - p3: [120, 150] - }); - expect(quadratic.attr('p1')[0]).to.be(50); - expect(quadratic.attr('p2')[1]).to.be(12); - expect(quadratic.attr('p3')[0]).to.be(120); - - var box = quadratic.getBBox('box'); - expect(gMath.equal(box.minX, 49.5)).to.be(true); - expect(gMath.equal(box.maxX, 120.5)).to.be(true); - expect(gMath.equal(box.minY, 41.29545454545454)).to.be(true); - expect(gMath.equal(box.maxY, 150.5)).to.be(true); - }); - - it('stroke', function() { - quadratic.attr('stroke', 'l (0) 0:#ff00ff 1:#00ffff'); - expect(quadratic.attr('stroke')).to.be('l (0) 0:#ff00ff 1:#00ffff'); - - canvas.add(quadratic); - canvas.draw(); - }); - - it('p1', function() { - quadratic.attr('p1', [70, 39]); - expect(quadratic.attr('p1')[0]).to.be(70); - expect(quadratic.attr('p1')[1]).to.be(39); - var box = quadratic.getBBox(); - expect(gMath.equal(box.minX, 69.5)).to.be(true); - expect(gMath.equal(box.maxX, 120.5)).to.be(true); - expect(gMath.equal(box.minY, 34.081818181818186)).to.be(true); - expect(gMath.equal(box.maxY, 150.5)).to.be(true); - canvas.draw(); - }); - - it('p2', function() { - quadratic.attr('p2', [90, 80]); - expect(quadratic.attr('p2')[0]).to.be(90); - expect(quadratic.attr('p2')[1]).to.be(80); - var box = quadratic.getBBox(); - expect(gMath.equal(box.minX, 69.5)).to.be(true); - expect(gMath.equal(box.maxX, 120.5)).to.be(true); - expect(gMath.equal(box.minY, 38.5)).to.be(true); - expect(gMath.equal(box.maxY, 150.5)).to.be(true); - canvas.draw(); - }); - - it('p3', function() { - quadratic.attr('p3', [110, 10]); - expect(quadratic.attr('p3')[0]).to.be(110); - expect(quadratic.attr('p3')[1]).to.be(10); - var box = quadratic.getBBox(); - expect(gMath.equal(box.minX, 69.5)).to.be(true); - expect(gMath.equal(box.maxX, 110.5)).to.be(true); - expect(gMath.equal(box.minY, 9.5)).to.be(true); - expect(gMath.equal(box.maxY, 54.644144144144136)).to.be(true); - canvas.draw(); - }); - - it('lineWidth', function() { - quadratic.attr('lineWidth', 2); - expect(quadratic.attr('lineWidth')).to.be(2); - var box = quadratic.getBBox(); - expect(gMath.equal(box.minX, 69)).to.be(true); - expect(gMath.equal(box.maxX, 111)).to.be(true); - expect(gMath.equal(box.minY, 9)).to.be(true); - expect(gMath.equal(box.maxY, 55.144144144144136)).to.be(true); - canvas.draw(); - }); - - it('isHit', function() { - expect(quadratic.isHit(70, 39)).to.be(true); - expect(quadratic.isHit(90, 52.2)).to.be(true); - expect(quadratic.isHit(110, 10)).to.be(true); - }); - - it('getPoint', function() { - var quadratic = new G.Quadratic({ - attrs: { - p1: [100, 100], - p2: [200, 200], - p3: [300, 100] - } - }); - - var point1 = quadratic.getPoint(0); - expect(point1.x).to.be(100); - expect(point1.y).to.be(100); - var point2 = quadratic.getPoint(1); - expect(point2.x).to.be(300); - expect(point2.y).to.be(100); - var point3 = quadratic.getPoint(0.5); - expect(point3.x).to.be(200); - expect(point3.y).to.be(150); - var point4 = quadratic.getPoint(0.3); - expect(point4.x).to.be(160); - expect(point4.y).to.be(142); - expect(quadratic.isHit(160, 142)).to.be(true); - }); -}); diff --git a/tests/g/shape-rect-spec.js b/tests/g/shape-rect-spec.js deleted file mode 100644 index e8646ebe9..000000000 --- a/tests/g/shape-rect-spec.js +++ /dev/null @@ -1,313 +0,0 @@ -var expect = require('@ali/expect.js'); -var G = require('../../src/g/index'); -var Canvas = require('../../src/canvas'); -var div = document.createElement('div'); -div.id = 'canvas-rect'; -document.body.appendChild(div); - - -describe('Rect', function() { - var canvas = new Canvas({ - containerId: 'canvas-rect', - width: 200, - height: 200, - pixelRatio: 1 - }); - - var rect = new G.Rect({ - attrs: { - x: 0, - y: 0, - width: 0, - height: 0 - } - }); - G.debug(true); - it('init attrs', function() { - expect(rect.attr('x')).to.be(0); - expect(rect.attr('y')).to.be(0); - expect(rect.attr('width')).to.be(0); - expect(rect.attr('height')).to.be(0); - expect(rect.attr('radius')).to.be(0); - expect(rect.attr('lineWidth')).to.be(1); - expect(rect.attr('stroke')).to.be(undefined); - expect(rect.attr('fill')).to.be(undefined); - var box = rect.getBBox(); - expect(box.minX).to.be(-0.5); - expect(box.minY).to.be(-0.5); - expect(box.maxX).to.be(0.5); - expect(box.maxY).to.be(0.5); - }); - - it('width', function() { - expect(rect.attr('width')).to.be(0); - rect.attr('width', 10); - expect(rect.attr('width')).to.be(10); - var box = rect.getBBox(); - expect(box.minX).to.be(-0.5); - expect(box.maxX).to.be(10.5); - var rect1 = new G.Rect({ - attrs: { - x: 0, - y: 0, - height: 1, - width: 15 - } - }); - expect(rect1.attr('width')).to.be(15); - var box = rect1.getBBox(); - expect(box.minX).to.be(-0.5); - expect(box.maxX).to.be(15.5); - var rect2 = new G.Rect({ - attrs: { - x: 10, - y: 0, - width: 15, - height: 1 - } - }); - expect(rect2.attr('width')).to.be(15); - var box = rect2.getBBox(); - expect(box.minX).to.be(9.5); - expect(box.maxX).to.be(25.5); - }); - - it('height', function() { - expect(rect.attr('height')).to.be(0); - rect.attr('height', 20); - expect(rect.attr('height')).to.be(20); - var box = rect.getBBox(); - expect(box.minY).to.be(-0.5); - expect(box.maxY).to.be(20.5); - var rect1 = new G.Rect({ - attrs: { - x: 0, - y: 0, - height: 25, - width: 1 - } - }); - expect(rect1.attr('height')).to.be(25); - var box = rect1.getBBox(); - expect(box.minY).to.be(-0.5); - expect(box.maxY).to.be(25.5); - var rect2 = new G.Rect({ - attrs: { - x: 0, - y: 10, - height: 25, - width: 1 - } - }); - expect(rect2.attr('height')).to.be(25); - var box = rect2.getBBox(); - expect(box.minY).to.be(9.5); - expect(box.maxY).to.be(35.5); - }); - - it('x', function() { - rect.attr('x', 10); - expect(rect.attr('x')).to.be(10); - var box = rect.getBBox(); - expect(box.minX).to.be(9.5); - expect(box.maxX).to.be(20.5); - var rect1 = new G.Rect({ - attrs: { - x: 10, - y: 0, - width: 0, - height: 0 - } - }); - expect(rect1.attr('x')).to.be(10); - var box = rect1.getBBox(); - expect(box.minX).to.be(9.5); - expect(box.maxX).to.be(10.5); - var rect2 = new G.Rect({ - attrs: { - x: 20, - y: 0, - width: 15, - height: 0 - } - }); - expect(rect2.attr('x')).to.be(20); - var box = rect2.getBBox(); - expect(box.minX).to.be(19.5); - expect(box.maxX).to.be(35.5); - }); - - it('y', function() { - rect.attr('y', 20); - expect(rect.attr('y')).to.be(20); - var box = rect.getBBox(); - expect(box.minY).to.be(19.5); - expect(box.maxY).to.be(40.5); - var rect1 = new G.Rect({ - attrs: { - x: 0, - y: 12, - height: 0, - width: 0 - } - }); - expect(rect1.attr('y')).to.be(12); - var box = rect1.getBBox(); - expect(box.minY).to.be(11.5); - expect(box.maxY).to.be(12.5); - var rect2 = new G.Rect({ - attrs: { - x: 0, - y: 12, - height: 20, - width: 0 - } - }); - expect(rect2.attr('y')).to.be(12); - var box = rect2.getBBox(); - expect(box.minY).to.be(11.5); - expect(box.maxY).to.be(32.5); - }); - - it('lineWidth', function() { - expect(rect.attr('lineWidth')).to.be(1); - rect.attr('lineWidth', 2); - expect(rect.attr('lineWidth')).to.be(2); - var box = rect.getBBox(); - expect(box.minY).to.be(19); - expect(box.minX).to.be(9); - expect(box.maxX).to.be(21); - expect(box.maxY).to.be(41); - var rect1 = new G.Rect({ - attrs: { - x: 0, - y: 0, - width: 0, - height: 0, - lineWidth: 2 - } - }); - expect(rect1.attr('lineWidth')).to.be(2); - var box = rect1.getBBox(); - expect(box.minY).to.be(-1); - expect(box.minX).to.be(-1); - expect(box.maxX).to.be(1); - expect(box.maxY).to.be(1); - - var rect2 = new G.Rect({ - attrs: { - x: 30, - y: 40, - width: 200, - height: 100, - lineWidth: 2 - } - }); - expect(rect2.attr('lineWidth')).to.be(2); - var box = rect2.getBBox(); - expect(box.minX).to.be(29); - expect(box.minY).to.be(39); - expect(box.maxX).to.be(231); - expect(box.maxY).to.be(141); - }); - - it('radius', function() { - expect(rect.attr('radius')).to.be(0); - rect.attr('radius', 3); - expect(rect.attr('radius')).to.be(3); - }); - - it('stroke', function() { - rect.attr('stroke', 'l (0) 0:#ff00ff 1:#00ff00'); - expect(rect.attr('stroke')).to.be('l (0) 0:#ff00ff 1:#00ff00'); - canvas.add(rect); - canvas.draw(); - }); - - it('fill',function() { - rect.attr('fill', 'l (90) 0:#00ffff 1:#ffff00'); - expect(rect.attr('fill')).to.be('l (90) 0:#00ffff 1:#ffff00'); - canvas.draw(); - }); - - it('isHit', function() { - var rect1 = new G.Rect({ - attrs: { - x: 40, - y: 40, - width: 50, - height: 70 - } - }); - - expect(rect1.isHit(39.5, 39.5)).to.be(false); - expect(rect1.isHit(40.5, 40.5)).to.be(false); - expect(rect1.isHit(41, 41)).to.be(false); - expect(rect1.isHit(70, 39)).to.be(false); - expect(rect1.isHit(90.5, 110.5)).to.be(false); - expect(rect1.isHit(43, 43)).to.be(false); - rect1.attr('stroke', 'red'); - expect(rect1.isHit(39.5, 39.5)).to.be(true); - expect(rect1.isHit(40.5, 40.5)).to.be(true); - expect(rect1.isHit(41, 41)).to.be(false); - expect(rect1.isHit(70, 39)).to.be(false); - expect(rect1.isHit(70, 39.5)).to.be(true); - expect(rect1.isHit(90.5, 110.5)).to.be(true); - expect(rect1.isHit(43, 43)).to.be(false); - rect1.attr('lineWidth', 2); - expect(rect1.isHit(70, 39)).to.be(true); - expect(rect1.isHit(41, 41)).to.be(true); - rect1.attr('radius', 6); - expect(rect1.isHit(41, 41)).to.be(false); - - - var rect2 = new G.Rect({ - attrs: { - x: 50, - y: 50, - width: 40, - height: 50 - } - }); - expect(rect2.isHit(50, 50)).to.be(false); - expect(rect2.isHit(49.5, 50)).to.be(false); - expect(rect2.isHit(50, 51)).to.be(false); - expect(rect2.isHit(51, 51)).to.be(false); - expect(rect2.isHit(90, 100)).to.be(false); - expect(rect2.isHit(89, 99)).to.be(false); - rect2.attr('fill', 'blue'); - expect(rect2.isHit(50, 50)).to.be(false); - expect(rect2.isHit(49.5, 50)).to.be(false); - expect(rect2.isHit(50, 51)).to.be(false); - expect(rect2.isHit(51, 51)).to.be(false); - expect(rect2.isHit(90, 100)).to.be(false); - expect(rect2.isHit(89, 99)).to.be(false); - canvas.add(rect2); - expect(rect2.isHit(50, 50)).to.be(true); - expect(rect2.isHit(49.5, 50)).to.be(false); - expect(rect2.isHit(50, 51)).to.be(true); - expect(rect2.isHit(51, 51)).to.be(true); - expect(rect2.isHit(90, 100)).to.be(true); - expect(rect2.isHit(89, 99)).to.be(true); - rect2.attr('radius', 5); - expect(rect2.isHit(50, 50)).to.be(false); - expect(rect2.isHit(89, 99)).to.be(false); - - var rect3 = new G.Rect({ - attrs: { - x: 20, - y: 30, - width: 100, - height: 120, - stroke: 'red', - fill: 'green', - lineWidth: 4 - } - }); - - canvas.add(rect3); - expect(rect3.isHit(18, 28)).to.be(true); - expect(rect3.isHit(50, 70)).to.be(true); - }); - -}); diff --git a/tests/g/shape-text-spec.js b/tests/g/shape-text-spec.js deleted file mode 100644 index 518765915..000000000 --- a/tests/g/shape-text-spec.js +++ /dev/null @@ -1,577 +0,0 @@ -var expect = require('@ali/expect.js'); -var G = require('../../src/g/index'); -var Canvas = require('../../src/canvas'); -var div = document.createElement('div'); -div.id = 'canvas-text'; -document.body.appendChild(div); - - -describe('Text', function() { - var canvas = new Canvas({ - containerId: 'canvas-text', - width: 200, - height: 200, - pixelRatio: 1 - }); - - var text = new G.Text({ - attrs: { - x: 0, - y: 0 - } - }); - G.debug(true); - it('init attrs', function() { - expect(text.attr('x')).to.be(0); - expect(text.attr('y')).to.be(0); - expect(text.attr('text')).to.be(undefined); - expect(text.attr('textAlign')).to.be('start'); - expect(text.attr('fontSize')).to.be(12); - expect(text.attr('fontFamily')).to.be('sans-serif'); - expect(text.attr('fontStyle')).to.be('normal'); - expect(text.attr('fontWeight')).to.be('normal'); - expect(text.attr('fontVariant')).to.be('normal'); - expect(text.attr('font')).to.be('normal normal normal 12px sans-serif'); - expect(text.attr('textBaseline')).to.be('bottom'); - expect(text.attr('lineWidth')).to.be(1); - expect(text.getBBox()).eql({ minX: 0, - minY: 0, - maxX: 0, - maxY: 0, - x: 0, - y: 0, - width: 0, - height: 0 - }); - }); - - it('text', function() { - text.attr('text', '你好啊'); - var box = text.getBBox(); - expect(box).not.to.be(undefined); - expect(box.minX).to.be(-0.5); - expect(box.minY).to.be(-12.5); - expect(box.maxX).to.be(36.5); - expect(box.maxY).to.be(0.5); - var text1 = new G.Text({ - attrs: { - x: 0, - y: 0, - text: '你好啊' - } - }); - var box = text1.getBBox(); - expect(box).not.to.be(undefined); - expect(box.minX).to.be(-0.5); - expect(box.minY).to.be(-12.5); - expect(box.maxX).to.be(36.5); - expect(box.maxY).to.be(0.5); - }); - - it('x', function() { - text.attr('x', 10); - var box = text.getBBox(); - expect(box.minX).to.be(9.5); - expect(box.minY).to.be(-12.5); - expect(box.maxX).to.be(46.5); - expect(box.maxY).to.be(0.5); - var text1 = new G.Text({ - attrs: { - x: 10, - y: 0 - } - }); - expect(text1.attr('x')).to.be(10); - var box = text1.getBBox(); - expect(box).eql({ minX: 10, - minY: 0, - maxX: 10, - maxY: 0, - x: 10, - y: 0, - width: 0, - height: 0 - }); - var text2 = new G.Text({ - attrs: { - x: 10, - y: 0, - text: '你好啊' - } - }); - expect(text2.attr('x')).to.be(10); - var box = text2.getBBox(); - expect(box.minX).to.be(9.5); - expect(box.minY).to.be(-12.5); - expect(box.maxX).to.be(46.5); - expect(box.maxY).to.be(0.5); - }); - - it('y', function() { - text.attr('y', 20); - var box = text.getBBox(); - expect(box.minX).to.be(9.5); - expect(box.minY).to.be(7.5); - expect(box.maxX).to.be(46.5); - expect(box.maxY).to.be(20.5); - var text1 = new G.Text({ - attrs: { - x: 0, - y: 20 - } - }); - expect(text1.attr('y')).to.be(20); - var box = text1.getBBox(); - expect(box).eql({ minX: 0, - minY: 20, - maxX: 0, - maxY: 20, - x: 0, - y: 20, - width: 0, - height: 0 - }); - text1.attr({ - x: 0, - y: 20, - text: '你好啊' - }); - expect(text1.attr('y')).to.be(20); - var box = text1.getBBox(); - expect(box.minX).to.be(-0.5); - expect(box.minY).to.be(7.5); - expect(box.maxX).to.be(36.5); - expect(box.maxY).to.be(20.5); - }); - - it('stroke', function() { - text.attr({ - stroke: 'l (0) 0:#ffff00 1:rgb(0, 255, 255)' - }); - expect(text.attr('stroke')).to.be('l (0) 0:#ffff00 1:rgb(0, 255, 255)'); - canvas.add(text); - canvas.draw(); - }); - - it('fill', function() { - var text1 = new G.Text({ - attrs: { - x: 50, - y: 150, - text: 'fill测试', - font: '40px Arial', - fill: 'r (0.5, 0.5, 0) 0:rgb(255, 0, 255) 0.5:#dddddd' - } - }); - expect(text1.attr('fill')).to.be('r (0.5, 0.5, 0) 0:rgb(255, 0, 255) 0.5:#dddddd'); - canvas.add(text1); - - - canvas.draw(); - }); - - - it('fontSize', function() { - expect(text.attr('fontSize')).to.be(12); - expect(text.attr('font')).to.be('normal normal normal 12px sans-serif'); - text.attr('fontSize', 20); - expect(text.attr('fontSize')).to.be(20); - expect(text.attr('font')).to.be('normal normal normal 20px sans-serif'); - var text1 = new G.Text({ - attrs: { - fontSize: 20, - text: '你好啊啊', - x: 20, - y: 180, - stroke: '#000' - } - }); - expect(text1.attr('fontSize')).to.be(20); - expect(text1.attr('font')).to.be('normal normal normal 20px sans-serif'); - canvas.add(text1); - canvas.draw(); - }); - - it('fontStyle', function() { - expect(text.attr('fontStyle')).to.be('normal'); - text.attr('fontStyle', 'italic'); - expect(text.attr('fontStyle')).to.be('italic'); - expect(text.attr('font')).to.be('italic normal normal 20px sans-serif'); - canvas.draw(); - text.attr('fontStyle', 'oblique'); - expect(text.attr('fontStyle')).to.be('oblique'); - expect(text.attr('font')).to.be('oblique normal normal 20px sans-serif'); - canvas.draw(); - }); - - it('fontWeight', function() { - expect(text.attr('fontWeight')).to.be('normal'); - text.attr('fontWeight', 'bolder'); - expect(text.attr('fontWeight')).to.be('bolder'); - expect(text.attr('font')).to.be('oblique normal bolder 20px sans-serif'); - canvas.draw(); - }); - - it('fontVariant', function() { - expect(text.attr('fontVariant')).to.be('normal'); - text.attr('fontVariant', 'small-caps'); - expect(text.attr('fontVariant')).to.be('small-caps'); - expect(text.attr('font')).to.be('oblique small-caps bolder 20px sans-serif'); - canvas.draw(); - }); - - it('fontFamily', function() { - text.attr('fontFamily', '宋体'); - expect(text.attr('fontFamily')).to.be('宋体'); - expect(text.attr('font')).to.be('oblique small-caps bolder 20px 宋体'); - canvas.draw(); - }); - - it('textAlign', function() { - expect(text.attr('textAlign')).to.be('start'); - text.attr('textAlign', 'right'); - var box = text.getBBox(); - expect(box.minX, -50.5); - expect(box.maxX, 10.5); - text.attr('textAlign', 'left'); - var box = text.getBBox(); - expect(box.minX, 9.5); - expect(box.maxX, 70.5); - text.attr('textAlign', 'end'); - var box = text.getBBox(); - expect(box.minX, -50.5); - expect(box.maxX, 10.5); - text.attr('textAlign', 'center'); - var box = text.getBBox(); - expect(box.minX, -20.5); - expect(box.maxX, 40.5); - text.attr('textAlign', 'start'); - var box = text.getBBox(); - expect(box.minX, 9.5); - expect(box.maxX, 70.5); - - - var text1 = new G.Text({ - attrs: { - x: 0, - y: 0, - textAlign: 'center' - } - }); - expect(text1.attr('textAlign')).to.be('center'); - expect(text1.getBBox()).eql({ minX: 0, - minY: 0, - maxX: 0, - maxY: 0, - x: 0, - y: 0, - width: 0, - height: 0 - }); - - var text2 = new G.Text({ - attrs: { - x: 0, - y: 0, - textAlign: 'center', - text: '你好啊' - } - }); - expect(text2.attr('textAlign')).to.be('center'); - var box = text2.getBBox(); - expect(box.minX).to.be(-18.5); - expect(box.maxX).to.be(18.5); - }); - - it('textBaseline', function() { - expect(text.attr('textBaseline')).to.be('bottom'); - text.attr('textBaseline', 'top'); - var box = text.getBBox(); - expect(box.minY).to.be(19.5); - expect(box.maxY).to.be(40.5); - text.attr('textBaseline', 'middle'); - var box = text.getBBox(); - expect(box.minY).to.be(9.5); - expect(box.maxY).to.be(30.5); - text.attr('textBaseline', 'bottom'); - var box = text.getBBox(); - expect(box.minY).to.be(-0.5); - expect(box.maxY).to.be(20.5); - - var text1 = new G.Text({ - attrs: { - x: 0, - y: 0, - textBaseline: 'middle' - } - }); - expect(text1.attr('textBaseline')).to.be('middle'); - expect(text1.getBBox()).eql({ minX: 0, - minY: 0, - maxX: 0, - maxY: 0, - x: 0, - y: 0, - width: 0, - height: 0 - }); - - var text2 = new G.Text({ - attrs: { - x: 0, - y: 0, - textBaseline: 'middle', - text: '你好啊' - } - }); - expect(text2.attr('textBaseline')).to.be('middle'); - var box = text2.getBBox(); - expect(box.minY).to.be(-6.5); - expect(box.maxY).to.be(6.5); - }); - - it('lineWidth', function() { - expect(text.attr('lineWidth')).to.be(1); - text.attr('lineWidth', 4); - expect(text.attr('lineWidth')).to.be(4); - var box = text.getBBox(); - expect(box.minX).to.be(8); - expect(box.maxX).to.be(72); - expect(box.maxY).to.be(22); - expect(box.minY).to.be(-2); - }); - - it('isHit', function() { - expect(text.isHit(48, 0)).to.be(true); - expect(text.isHit(48, 24)).to.be(false); - }); - - - it('normal use', function() { - var text = new G.Text({ - attrs: { - text: 'hello world', - x: 50, - y: 50, - fill: 'red' - } - }); - canvas.add(text); - canvas.draw(); - }); - - it('add text fontFamily', function() { - var text1 = canvas.addShape('text', { - attrs: { - x: 0, - y: 0, - text: 'abc' - } - }); - expect(text1.attr('fontFamily')).to.be('sans-serif'); - var text2 = canvas.addShape('text', { - attrs: { - x: 0, - y: 0, - fontFamily: 'Arial', - text: 'bcd' - } - }); - expect(text2.attr('fontFamily')).to.be('Arial'); - - canvas.set('fontFamily', '宋体'); - var text3 = canvas.addShape('text', { - attrs: { - x: 0, - y: 0, - text: 'bde' - } - }); - expect(text3.attr('fontFamily')).to.be('宋体'); - - canvas.set('fontFamily', null); - var text4 = canvas.addShape('text', { - attrs: { - x: 0, - y: 0, - text: 'bde' - } - }); - - expect(text4.attr('fontFamily')).to.be('sans-serif'); - }); - -}); - -describe('Text \n', function() { - - var canvas = new Canvas({ - containerId: 'canvas-text', - width: 200, - height: 200 - }); - - var text = new G.Text({ - attrs:{ - x: 50, - y: 50, - text: '你好\nHello\nworkd', - fill: 'black', - stroke: 'red', - textBaseline: 'top' - } - }); - var bbox = text.getBBox(); - var rect = new G.Rect({ - attrs: { - x: bbox.minX, - y: bbox.minY, - width: bbox.maxX - bbox.minX, - height: bbox.maxY - bbox.minY, - stroke: 'red' - } - }); - - G.debug(true); - it('text /n', function() { - expect(text.attr('x')).to.be(50); - expect(text.attr('y')).to.be(50); - expect(text.attr('text')).to.be('你好\nHello\nworkd'); - // expect(text.attr('width')).to.be(35.68794250488281); - // expect(text.attr('height')).to.be(39.36); - expect(text.attr('textAlign')).to.be('start'); - expect(text.attr('fontSize')).to.be(12); - expect(text.attr('fill')).to.be('black'); - expect(text.attr('fontFamily')).to.be('sans-serif'); - expect(text.attr('fontStyle')).to.be('normal'); - expect(text.attr('fontWeight')).to.be('normal'); - expect(text.attr('fontVariant')).to.be('normal'); - expect(text.attr('font')).to.be('normal normal normal 12px sans-serif'); - expect(text.attr('textBaseline')).to.be('top'); - expect(text.attr('lineWidth')).to.be(1); - }); - canvas.add(rect); - canvas.add(text); - canvas.draw(); -}); - -describe('Text 不存在', function() { - - var canvas = new Canvas({ - containerId: 'canvas-text', - width: 200, - height: 200 - }); - - var text = new G.Text({ - attrs:{ - x: 50, - y: 50, - text: '', - fill: 'black', - stroke: 'red', - textBaseline: 'top' - } - }); - var bbox = text.getBBox(); - var rect = new G.Rect({ - attrs: { - x: bbox.minX, - y: bbox.minY, - width: bbox.maxX - bbox.minX, - height: bbox.maxY - bbox.minY, - stroke: 'red' - } - }); - - G.debug(true); - it('text 空 "" ', function() { - expect(text.attr('x')).to.be(50); - expect(text.attr('y')).to.be(50); - expect(text.attr('text')).to.be(''); - // expect(text.attr('width')).to.be(35.68794250488281); - // expect(text.attr('height')).to.be(39.36); - expect(text.attr('textAlign')).to.be('start'); - expect(text.attr('fontSize')).to.be(12); - expect(text.attr('fill')).to.be('black'); - expect(text.attr('fontFamily')).to.be('sans-serif'); - expect(text.attr('fontStyle')).to.be('normal'); - expect(text.attr('fontWeight')).to.be('normal'); - expect(text.attr('fontVariant')).to.be('normal'); - expect(text.attr('font')).to.be('normal normal normal 12px sans-serif'); - expect(text.attr('textBaseline')).to.be('top'); - expect(text.attr('lineWidth')).to.be(1); - expect(text.getBBox()).eql({ minX: 50, - minY: 50, - maxX: 50, - maxY: 50, - x: 50, - y: 50, - width: 0, - height: 0 - }); - }); - canvas.add(rect); - canvas.add(text); - canvas.draw(); - it('text null ', function() { - text.attr('text', null); - expect(text.attr('x')).to.be(50); - expect(text.attr('y')).to.be(50); - expect(text.attr('text')).to.be(null); - // expect(text.attr('width')).to.be(35.68794250488281); - // expect(text.attr('height')).to.be(39.36); - expect(text.attr('textAlign')).to.be('start'); - expect(text.attr('fontSize')).to.be(12); - expect(text.attr('fill')).to.be('black'); - expect(text.attr('fontFamily')).to.be('sans-serif'); - expect(text.attr('fontStyle')).to.be('normal'); - expect(text.attr('fontWeight')).to.be('normal'); - expect(text.attr('fontVariant')).to.be('normal'); - expect(text.attr('font')).to.be('normal normal normal 12px sans-serif'); - expect(text.attr('textBaseline')).to.be('top'); - expect(text.attr('lineWidth')).to.be(1); - expect(text.getBBox()).eql({ minX: 50, - minY: 50, - maxX: 50, - maxY: 50, - x: 50, - y: 50, - width: 0, - height: 0 - }); - }); - canvas.add(rect); - canvas.add(text); - canvas.draw(); - it('text undefined ', function() { - text.attr('text', undefined); - expect(text.attr('x')).to.be(50); - expect(text.attr('y')).to.be(50); - expect(text.attr('text')).to.be(undefined); - // expect(text.attr('width')).to.be(35.68794250488281); - // expect(text.attr('height')).to.be(39.36); - expect(text.attr('textAlign')).to.be('start'); - expect(text.attr('fontSize')).to.be(12); - expect(text.attr('fill')).to.be('black'); - expect(text.attr('fontFamily')).to.be('sans-serif'); - expect(text.attr('fontStyle')).to.be('normal'); - expect(text.attr('fontWeight')).to.be('normal'); - expect(text.attr('fontVariant')).to.be('normal'); - expect(text.attr('font')).to.be('normal normal normal 12px sans-serif'); - expect(text.attr('textBaseline')).to.be('top'); - expect(text.attr('lineWidth')).to.be(1); - expect(text.getBBox()).eql({ minX: 50, - minY: 50, - maxX: 50, - maxY: 50, - x: 50, - y: 50, - width: 0, - height: 0 - }); - }); - canvas.add(rect); - canvas.add(text); - canvas.draw(); -}); diff --git a/tests/matrixUtil/matrixUtil-spec.js b/tests/matrixUtil/matrixUtil-spec.js deleted file mode 100644 index b41241f89..000000000 --- a/tests/matrixUtil/matrixUtil-spec.js +++ /dev/null @@ -1,76 +0,0 @@ -var $ = require('jquery'); - -var expect = require('@ali/expect.js'); -var matrixUtil = require('../../src/util/matrix'); -var Matrix = require('@ali/g-matrix'); -var Matrix3 = Matrix.Matrix3; -var Canvas = require('../../src/canvas'); - -$('
').appendTo('body'); - -var canvas = new Canvas({ - containerId: 'test_matrixUtil', - width: 500, - height: 500 -}); - -describe('测试矩阵工具',function(){ - it('基于某点缩放', function(){ - var group = canvas.addGroup(); - var circle = group.addShape("circle", { - attrs: { - x: 250, - y: 250, - r: 50, - fill: '#FED443' - } - }); - var animPoint = canvas.addShape("circle", { - attrs: { - x: 250, - y: 250, - r:3, - fill: 'blue' - } - }); - var matrix = new Matrix3(); - var bboxOrigin = circle.getBBox(); - var bbox; - matrix = matrixUtil.scale(matrix, 2, 2, 250, 250); - circle.setMatrix(matrix); - bbox = group.getBBox(); - expect(bbox.x + bbox.width / 2).to.be(250); - expect(bbox.y + bbox.height / 2).to.be(250); - expect(bbox.width).to.be(202); //边框有值 +2 - expect(bbox.height).to.be(202); //边框有值 +2 - canvas.draw(); - }); - it('基于某点旋转', function(){ - var matrix = new Matrix3(); - var rst = matrixUtil.rotate(matrix, parseFloat(10) / 180 * Math.PI, 300, 300); - matrix.translate(-300, -300); - matrix.rotate(parseFloat(10) / 180 * Math.PI); - matrix.translate(300, 300); - expect(Matrix3.equal(matrix, rst)).to.be(true); - }); - it('变换 transform', function(){ - var matrix = new Matrix3(); - var rst = matrixUtil.transform(matrix, [ - ['t', 100, 200], - ['s', 0.2, 0.3], - ['r', Math.PI], - ['m', new Matrix3()], - ['null', 10101010101] - ]); - matrix.translate(100, 200); - matrix.scale(0.2, 0.3); - matrix.rotate(Math.PI); - matrix.multiply(new Matrix3()); - expect(Matrix3.equal(matrix, rst)).to.be(true); - }); - it('判断是否是3阶矩阵', function(){ - var matrix = new Matrix3(); - expect(matrixUtil.isMatrix3(matrix)).to.be(true); - expect(matrixUtil.isMatrix3(9999)).to.be(false); - }); -}); diff --git a/webpack.config.js b/webpack.config.js deleted file mode 100644 index 0b7c6e2ae..000000000 --- a/webpack.config.js +++ /dev/null @@ -1,18 +0,0 @@ -var webpack = require('atool-build/lib/webpack'); - -module.exports = function(webpackConfig) { - - webpackConfig.plugins.some(function(plugin, i){ - if(plugin instanceof webpack.optimize.CommonsChunkPlugin) { - webpackConfig.plugins.splice(i, 1); - - return true; - } - }); - - webpackConfig.output.library = 'G'; - webpackConfig.output.libraryTarget = 'var'; - // webpackConfig.entry=['./tests/debug.js']; - - return webpackConfig; -};