UNPKG

chartx_48

Version:

chartpark专用npm包

1,576 lines (1,404 loc) 431 kB
'use strict'; var commonjsGlobal = typeof window !== 'undefined' ? window : typeof global !== 'undefined' ? global : typeof self !== 'undefined' ? self : {}; var _typeof = typeof Symbol === "function" && typeof Symbol.iterator === "symbol" ? function (obj) { return typeof obj; } : function (obj) { return obj && typeof Symbol === "function" && obj.constructor === Symbol && obj !== Symbol.prototype ? "symbol" : typeof obj; }; var classCallCheck = function (instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } }; var createClass = function () { function defineProperties(target, props) { for (var i = 0; i < props.length; i++) { var descriptor = props[i]; descriptor.enumerable = descriptor.enumerable || false; descriptor.configurable = true; if ("value" in descriptor) descriptor.writable = true; Object.defineProperty(target, descriptor.key, descriptor); } } return function (Constructor, protoProps, staticProps) { if (protoProps) defineProperties(Constructor.prototype, protoProps); if (staticProps) defineProperties(Constructor, staticProps); return Constructor; }; }(); var inherits = function (subClass, superClass) { if (typeof superClass !== "function" && superClass !== null) { throw new TypeError("Super expression must either be null or a function, not " + typeof superClass); } subClass.prototype = Object.create(superClass && superClass.prototype, { constructor: { value: subClass, enumerable: false, writable: true, configurable: true } }); if (superClass) Object.setPrototypeOf ? Object.setPrototypeOf(subClass, superClass) : subClass.__proto__ = superClass; }; var possibleConstructorReturn = function (self, call) { if (!self) { throw new ReferenceError("this hasn't been initialised - super() hasn't been called"); } return call && (typeof call === "object" || typeof call === "function") ? call : self; }; var _typeof$1 = typeof Symbol === "function" && _typeof(Symbol.iterator) === "symbol" ? function (obj) { return typeof obj === 'undefined' ? 'undefined' : _typeof(obj); } : function (obj) { return obj && typeof Symbol === "function" && obj.constructor === Symbol && obj !== Symbol.prototype ? "symbol" : typeof obj === 'undefined' ? 'undefined' : _typeof(obj); }; var classCallCheck$1 = function classCallCheck$$1(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } }; var createClass$1 = function () { function defineProperties(target, props) { for (var i = 0; i < props.length; i++) { var descriptor = props[i]; descriptor.enumerable = descriptor.enumerable || false; descriptor.configurable = true; if ("value" in descriptor) descriptor.writable = true; Object.defineProperty(target, descriptor.key, descriptor); } } return function (Constructor, protoProps, staticProps) { if (protoProps) defineProperties(Constructor.prototype, protoProps); if (staticProps) defineProperties(Constructor, staticProps); return Constructor; }; }(); var inherits$1 = function inherits$$1(subClass, superClass) { if (typeof superClass !== "function" && superClass !== null) { throw new TypeError("Super expression must either be null or a function, not " + (typeof superClass === 'undefined' ? 'undefined' : _typeof(superClass))); } subClass.prototype = Object.create(superClass && superClass.prototype, { constructor: { value: subClass, enumerable: false, writable: true, configurable: true } }); if (superClass) Object.setPrototypeOf ? Object.setPrototypeOf(subClass, superClass) : subClass.__proto__ = superClass; }; var possibleConstructorReturn$1 = function possibleConstructorReturn$$1(self, call) { if (!self) { throw new ReferenceError("this hasn't been initialised - super() hasn't been called"); } return call && ((typeof call === 'undefined' ? 'undefined' : _typeof(call)) === "object" || typeof call === "function") ? call : self; }; var _ = {}; var breaker = {}; var ArrayProto = Array.prototype; var ObjProto = Object.prototype; // Create quick reference variables for speed access to core prototypes. var push = ArrayProto.push; var slice = ArrayProto.slice; var concat = ArrayProto.concat; var toString = ObjProto.toString; var hasOwnProperty = ObjProto.hasOwnProperty; // All **ECMAScript 5** native function implementations that we hope to use // are declared here. var nativeForEach = ArrayProto.forEach; var nativeMap = ArrayProto.map; var nativeFilter = ArrayProto.filter; var nativeEvery = ArrayProto.every; var nativeSome = ArrayProto.some; var nativeIndexOf = ArrayProto.indexOf; var nativeIsArray = Array.isArray; var nativeKeys = Object.keys; var shallowProperty = function shallowProperty(key) { return function (obj) { return obj == null ? void 0 : obj[key]; }; }; var MAX_ARRAY_INDEX = Math.pow(2, 53) - 1; var getLength = shallowProperty('length'); var isArrayLike = function isArrayLike(collection) { var length = getLength(collection); return typeof length == 'number' && length >= 0 && length <= MAX_ARRAY_INDEX; }; _.values = function (obj) { var keys = _.keys(obj); var length = keys.length; var values = new Array(length); for (var i = 0; i < length; i++) { values[i] = obj[keys[i]]; } return values; }; _.keys = nativeKeys || function (obj) { if (obj !== Object(obj)) throw new TypeError('Invalid object'); var keys = []; for (var key in obj) { if (_.has(obj, key)) keys.push(key); }return keys; }; _.has = function (obj, key) { return hasOwnProperty.call(obj, key); }; var each = _.each = _.forEach = function (obj, iterator, context) { if (obj == null) return; if (nativeForEach && obj.forEach === nativeForEach) { obj.forEach(iterator, context); } else if (obj.length === +obj.length) { for (var i = 0, length = obj.length; i < length; i++) { if (iterator.call(context, obj[i], i, obj) === breaker) return; } } else { var keys = _.keys(obj); for (var i = 0, length = keys.length; i < length; i++) { if (iterator.call(context, obj[keys[i]], keys[i], obj) === breaker) return; } } }; _.compact = function (array) { return _.filter(array, _.identity); }; _.filter = _.select = function (obj, iterator, context) { var results = []; if (obj == null) return results; if (nativeFilter && obj.filter === nativeFilter) return obj.filter(iterator, context); each(obj, function (value, index, list) { if (iterator.call(context, value, index, list)) results.push(value); }); return results; }; each(['Arguments', 'Function', 'String', 'Number', 'Date', 'RegExp'], function (name) { _['is' + name] = function (obj) { return toString.call(obj) == '[object ' + name + ']'; }; }); if (!_.isArguments(arguments)) { _.isArguments = function (obj) { return !!(obj && _.has(obj, 'callee')); }; } { _.isFunction = function (obj) { return typeof obj === 'function'; }; } _.isFinite = function (obj) { return isFinite(obj) && !isNaN(parseFloat(obj)); }; _.isNaN = function (obj) { return _.isNumber(obj) && obj != +obj; }; _.isBoolean = function (obj) { return obj === true || obj === false || toString.call(obj) == '[object Boolean]'; }; _.isNull = function (obj) { return obj === null; }; _.isEmpty = function (obj) { if (obj == null) return true; if (_.isArray(obj) || _.isString(obj)) return obj.length === 0; for (var key in obj) { if (_.has(obj, key)) return false; }return true; }; _.isElement = function (obj) { return !!(obj && obj.nodeType === 1); }; _.isArray = nativeIsArray || function (obj) { return toString.call(obj) == '[object Array]'; }; _.isObject = function (obj) { return obj === Object(obj); }; _.identity = function (value) { return value; }; _.indexOf = function (array, item, isSorted) { if (array == null) return -1; var i = 0, length = array.length; if (isSorted) { if (typeof isSorted == 'number') { i = isSorted < 0 ? Math.max(0, length + isSorted) : isSorted; } else { i = _.sortedIndex(array, item); return array[i] === item ? i : -1; } } if (nativeIndexOf && array.indexOf === nativeIndexOf) return array.indexOf(item, isSorted); for (; i < length; i++) { if (array[i] === item) return i; }return -1; }; _.isWindow = function (obj) { return obj != null && obj == obj.window; }; // Internal implementation of a recursive `flatten` function. var flatten = function flatten(input, shallow, output) { if (shallow && _.every(input, _.isArray)) { return concat.apply(output, input); } each(input, function (value) { if (_.isArray(value) || _.isArguments(value)) { shallow ? push.apply(output, value) : flatten(value, shallow, output); } else { output.push(value); } }); return output; }; // Flatten out an array, either recursively (by default), or just one level. _.flatten = function (array, shallow) { return flatten(array, shallow, []); }; _.every = _.all = function (obj, iterator, context) { iterator || (iterator = _.identity); var result = true; if (obj == null) return result; if (nativeEvery && obj.every === nativeEvery) return obj.every(iterator, context); each(obj, function (value, index, list) { if (!(result = result && iterator.call(context, value, index, list))) return breaker; }); return !!result; }; // Return the minimum element (or element-based computation). _.min = function (obj, iterator, context) { if (!iterator && _.isArray(obj) && obj[0] === +obj[0] && obj.length < 65535) { return Math.min.apply(Math, obj); } if (!iterator && _.isEmpty(obj)) return Infinity; var result = { computed: Infinity, value: Infinity }; each(obj, function (value, index, list) { var computed = iterator ? iterator.call(context, value, index, list) : value; computed < result.computed && (result = { value: value, computed: computed }); }); return result.value; }; // Return the maximum element or (element-based computation). // Can't optimize arrays of integers longer than 65,535 elements. // See [WebKit Bug 80797](https://bugs.webkit.org/show_bug.cgi?id=80797) _.max = function (obj, iterator, context) { if (!iterator && _.isArray(obj) && obj[0] === +obj[0] && obj.length < 65535) { return Math.max.apply(Math, obj); } if (!iterator && _.isEmpty(obj)) return -Infinity; var result = { computed: -Infinity, value: -Infinity }; each(obj, function (value, index, list) { var computed = iterator ? iterator.call(context, value, index, list) : value; computed > result.computed && (result = { value: value, computed: computed }); }); return result.value; }; // Return the first value which passes a truth test. Aliased as `detect`. _.find = _.detect = function (obj, iterator, context) { var result; any(obj, function (value, index, list) { if (iterator.call(context, value, index, list)) { result = value; return true; } }); return result; }; // Determine if at least one element in the object matches a truth test. // Delegates to **ECMAScript 5**'s native `some` if available. // Aliased as `any`. var any = _.some = _.any = function (obj, iterator, context) { iterator || (iterator = _.identity); var result = false; if (obj == null) return result; if (nativeSome && obj.some === nativeSome) return obj.some(iterator, context); each(obj, function (value, index, list) { if (result || (result = iterator.call(context, value, index, list))) return breaker; }); return !!result; }; // Return a version of the array that does not contain the specified value(s). _.without = function (array) { return _.difference(array, slice.call(arguments, 1)); }; // Take the difference between one array and a number of other arrays. // Only the elements present in just the first array will remain. _.difference = function (array) { var rest = concat.apply(ArrayProto, slice.call(arguments, 1)); return _.filter(array, function (value) { return !_.contains(rest, value); }); }; // Produce a duplicate-free version of the array. If the array has already // been sorted, you have the option of using a faster algorithm. // Aliased as `unique`. _.uniq = _.unique = function (array, isSorted, iterator, context) { if (_.isFunction(isSorted)) { context = iterator; iterator = isSorted; isSorted = false; } var initial = iterator ? _.map(array, iterator, context) : array; var results = []; var seen = []; each(initial, function (value, index) { if (isSorted ? !index || seen[seen.length - 1] !== value : !_.contains(seen, value)) { seen.push(value); results.push(array[index]); } }); return results; }; // Return the results of applying the iterator to each element. // Delegates to **ECMAScript 5**'s native `map` if available. _.map = _.collect = function (obj, iterator, context) { var results = []; if (obj == null) return results; if (nativeMap && obj.map === nativeMap) return obj.map(iterator, context); each(obj, function (value, index, list) { results.push(iterator.call(context, value, index, list)); }); return results; }; // Determine if the array or object contains a given value (using `===`). // Aliased as `include`. _.contains = _.include = function (obj, target) { if (obj == null) return false; if (nativeIndexOf && obj.indexOf === nativeIndexOf) return obj.indexOf(target) != -1; return any(obj, function (value) { return value === target; }); }; // Convenience version of a common use case of `map`: fetching a property. _.pluck = function (obj, key) { return _.map(obj, function (value) { return value[key]; }); }; // Return a random integer between min and max (inclusive). _.random = function (min, max) { if (max == null) { max = min; min = 0; } return min + Math.floor(Math.random() * (max - min + 1)); }; // Shuffle a collection. _.shuffle = function (obj) { return _.sample(obj, Infinity); }; _.sample = function (obj, n, guard) { if (n == null || guard) { if (!isArrayLike(obj)) obj = _.values(obj); return obj[_.random(obj.length - 1)]; } var sample = isArrayLike(obj) ? _.clone(obj) : _.values(obj); var length = getLength(sample); n = Math.max(Math.min(n, length), 0); var last = length - 1; for (var index = 0; index < n; index++) { var rand = _.random(index, last); var temp = sample[index]; sample[index] = sample[rand]; sample[rand] = temp; } return sample.slice(0, n); }; /** * *如果是深度extend,第一个参数就设置为true */ _.extend = function () { var options, name, src, copy, target = arguments[0] || {}, i = 1, length = arguments.length, deep = false; if (typeof target === "boolean") { deep = target; target = arguments[1] || {}; i = 2; } if ((typeof target === 'undefined' ? 'undefined' : _typeof$1(target)) !== "object" && !_.isFunction(target)) { target = {}; } if (length === i) { target = this; --i; } for (; i < length; i++) { if ((options = arguments[i]) != null) { for (name in options) { src = target[name]; copy = options[name]; if (target === copy) { continue; } //if( deep && copy && _.isObject( copy ) && && !_.isArray( copy ) && !_.isFunction( copy ) ){ if (deep && copy && _.isObject(copy) && copy.constructor === Object) { target[name] = _.extend(deep, src, copy); } else { target[name] = copy; } } } } return target; }; _.clone = function (obj) { if (!_.isObject(obj)) return obj; return _.isArray(obj) ? obj.slice() : _.extend(true, {}, obj); }; var settings = { //设备分辨率 RESOLUTION: window.devicePixelRatio || 1, /** * Target frames per millisecond. */ TARGET_FPMS: 0.06, /** * If set to true WebGL will attempt make textures mimpaped by default. * Mipmapping will only succeed if the base texture uploaded has power of two dimensions. */ MIPMAP_TEXTURES: true, /** * Default filter resolution. */ FILTER_RESOLUTION: 1, // TODO: maybe change to SPRITE.BATCH_SIZE: 2000 // TODO: maybe add PARTICLE.BATCH_SIZE: 15000 /** * The default sprite batch size. * * The default aims to balance desktop and mobile devices. */ SPRITE_BATCH_SIZE: 4096, /** * The prefix that denotes a URL is for a retina asset. */ RETINA_PREFIX: /@(.+)x/, RENDER_OPTIONS: { view: null, antialias: true, forceFXAA: false, autoResize: false, transparent: true, backgroundColor: 0x000000, clearBeforeRender: true, preserveDrawingBuffer: false, roundPixels: false }, TRANSFORM_MODE: 0, GC_MODE: 0, GC_MAX_IDLE: 60 * 60, GC_MAX_CHECK_COUNT: 60 * 10, WRAP_MODE: 0, SCALE_MODE: 0, PRECISION: 'mediump' }; var addOrRmoveEventHand = function addOrRmoveEventHand(domHand, ieHand) { if (document[domHand]) { var _ret = function () { var eventDomFn = function eventDomFn(el, type, fn) { if (el.length) { for (var i = 0; i < el.length; i++) { eventDomFn(el[i], type, fn); } } else { el[domHand](type, fn, false); } }; return { v: eventDomFn }; }(); if ((typeof _ret === "undefined" ? "undefined" : _typeof$1(_ret)) === "object") return _ret.v; } else { var _ret2 = function () { var eventFn = function eventFn(el, type, fn) { if (el.length) { for (var i = 0; i < el.length; i++) { eventFn(el[i], type, fn); } } else { el[ieHand]("on" + type, function () { return fn.call(el, window.event); }); } }; return { v: eventFn }; }(); if ((typeof _ret2 === "undefined" ? "undefined" : _typeof$1(_ret2)) === "object") return _ret2.v; } }; var $ = { // dom操作相关代码 query: function query(el) { if (_.isString(el)) { return document.getElementById(el); } if (el.nodeType == 1) { //则为一个element本身 return el; } if (el.length) { return el[0]; } return null; }, offset: function offset(el) { var box = el.getBoundingClientRect(), doc = el.ownerDocument, body = doc.body, docElem = doc.documentElement, // for ie clientTop = docElem.clientTop || body.clientTop || 0, clientLeft = docElem.clientLeft || body.clientLeft || 0, // In Internet Explorer 7 getBoundingClientRect property is treated as physical, // while others are logical. Make all logical, like in IE8. zoom = 1; if (body.getBoundingClientRect) { var bound = body.getBoundingClientRect(); zoom = (bound.right - bound.left) / body.clientWidth; } if (zoom > 1) { clientTop = 0; clientLeft = 0; } var top = box.top / zoom + (window.pageYOffset || docElem && docElem.scrollTop / zoom || body.scrollTop / zoom) - clientTop, left = box.left / zoom + (window.pageXOffset || docElem && docElem.scrollLeft / zoom || body.scrollLeft / zoom) - clientLeft; return { top: top, left: left }; }, addEvent: addOrRmoveEventHand("addEventListener", "attachEvent"), removeEvent: addOrRmoveEventHand("removeEventListener", "detachEvent"), pageX: function pageX(e) { if (e.pageX) return e.pageX;else if (e.clientX) return e.clientX + (document.documentElement.scrollLeft ? document.documentElement.scrollLeft : document.body.scrollLeft);else return null; }, pageY: function pageY(e) { if (e.pageY) return e.pageY;else if (e.clientY) return e.clientY + (document.documentElement.scrollTop ? document.documentElement.scrollTop : document.body.scrollTop);else return null; }, /** * 创建dom * @param {string} id dom id 待用 * @param {string} type : dom type, such as canvas, div etc. */ createCanvas: function createCanvas(_width, _height, id) { var canvas = document.createElement("canvas"); canvas.style.position = 'absolute'; canvas.style.width = _width + 'px'; canvas.style.height = _height + 'px'; canvas.style.left = 0; canvas.style.top = 0; canvas.setAttribute('width', _width * settings.RESOLUTION); canvas.setAttribute('height', _height * settings.RESOLUTION); canvas.setAttribute('id', id); return canvas; }, createView: function createView(_width, _height, id) { var view = document.createElement("div"); view.className = "canvax-view"; view.style.cssText += "position:relative;width:100%;height:100%;"; var stageView = document.createElement("div"); stageView.style.cssText += "position:absolute;width:" + _width + "px;height:" + _height + "px;"; //用来存放一些dom元素 var domView = document.createElement("div"); domView.style.cssText += "position:absolute;width:" + _width + "px;height:" + _height + "px;"; view.appendChild(stageView); view.appendChild(domView); return { view: view, stageView: stageView, domView: domView }; } //dom相关代码结束 }; /** * Canvax * * @author 释剑 (李涛, litao.lt@alibaba-inc.com */ var Utils = { mainFrameRate: 60, //默认主帧率 now: 0, /*给文本检测高宽专用*/ _pixelCtx: null, __emptyFunc: function __emptyFunc() {}, //retina 屏幕优化 _devicePixelRatio: window.devicePixelRatio || 1, _UID: 0, //该值为向上的自增长整数值 getUID: function getUID() { return this._UID++; }, createId: function createId(name) { //if end with a digit, then append an undersBase before appending var charCode = name.charCodeAt(name.length - 1); if (charCode >= 48 && charCode <= 57) name += "_"; return name + Utils.getUID(); }, canvasSupport: function canvasSupport() { return !!document.createElement('canvas').getContext; }, initElement: function initElement(canvas) { if (window.FlashCanvas && FlashCanvas.initElement) { FlashCanvas.initElement(canvas); } return canvas; }, /** * 按照css的顺序,返回一个[上,右,下,左] */ getCssOrderArr: function getCssOrderArr(r) { var r1; var r2; var r3; var r4; if (typeof r === 'number') { r1 = r2 = r3 = r4 = r; } else if (r instanceof Array) { if (r.length === 1) { r1 = r2 = r3 = r4 = r[0]; } else if (r.length === 2) { r1 = r3 = r[0]; r2 = r4 = r[1]; } else if (r.length === 3) { r1 = r[0]; r2 = r4 = r[1]; r3 = r[2]; } else { r1 = r[0]; r2 = r[1]; r3 = r[2]; r4 = r[3]; } } else { r1 = r2 = r3 = r4 = 0; } return [r1, r2, r3, r4]; }, isWebGLSupported: function isWebGLSupported() { var contextOptions = { stencil: true }; try { if (!window.WebGLRenderingContext) //不存在直接return { return false; } var canvas = document.createElement('canvas'), gl = canvas.getContext('webgl', contextOptions) || canvas.getContext('experimental-webgl', contextOptions); return !!(gl && gl.getContextAttributes().stencil); //还要确实检测是否支持webGL模式 } catch (e) { return false; } }, checkOpt: function checkOpt(opt) { if (!opt) { opt = { context: {} }; } else { if (!opt.context) { opt.context = {}; } } return opt; } }; Utils._pixelCtx = Utils.initElement($.createCanvas(1, 1, "_pixelCanvas")).getContext('2d'); /** * Point * * @author 释剑 (李涛, litao.lt@alibaba-inc.com) */ var Point = function () { function Point() { var x = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : 0; var y = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : 0; classCallCheck$1(this, Point); if (arguments.length == 1 && _typeof$1(arguments[0]) == 'object') { var arg = arguments[0]; if ("x" in arg && "y" in arg) { this.x = arg.x * 1; this.y = arg.y * 1; } else { var i = 0; for (var p in arg) { if (i == 0) { this.x = arg[p] * 1; } else { this.y = arg[p] * 1; break; } i++; } } } else { this.x = x * 1; this.y = y * 1; } } createClass$1(Point, [{ key: "toArray", value: function toArray$$1() { return [this.x, this.y]; } }]); return Point; }(); /** * Canvax * * @author 释剑 (李涛, litao.lt@alibaba-inc.com) * * canvas 上委托的事件管理 */ var CanvaxEvent = function CanvaxEvent(evt, params) { var eventType = "CanvaxEvent"; if (_.isString(evt)) { eventType = evt; } if (_.isObject(evt) && evt.type) { eventType = evt.type; } this.target = null; this.currentTarget = null; this.type = eventType; this.point = null; this._stopPropagation = false; //默认不阻止事件冒泡 }; CanvaxEvent.prototype = { stopPropagation: function stopPropagation() { this._stopPropagation = true; } }; /** * Canvax * * @author 释剑 (李涛, litao.lt@alibaba-inc.com) * */ var _mouseEventTypes = ["click", "dblclick", "mousedown", "mousemove", "mouseup", "mouseout"]; var _hammerEventTypes = ["pan", "panstart", "panmove", "panend", "pancancel", "panleft", "panright", "panup", "pandown", "press", "pressup", "swipe", "swipeleft", "swiperight", "swipeup", "swipedown", "tap"]; var EventHandler = function EventHandler(canvax, opt) { this.canvax = canvax; this.curPoints = [new Point(0, 0)]; //X,Y 的 point 集合, 在touch下面则为 touch的集合,只是这个touch被添加了对应的x,y //当前激活的点对应的obj,在touch下可以是个数组,和上面的 curPoints 对应 this.curPointsTarget = []; this._touching = false; //正在拖动,前提是_touching=true this._draging = false; //当前的鼠标状态 this._cursor = "default"; this.target = this.canvax.view; this.types = []; //mouse体统中不需要配置drag,touch中会用到第三方的touch库,每个库的事件名称可能不一样, //就要这里配置,默认实现的是hammerjs的,所以默认可以在项目里引入hammerjs http://hammerjs.github.io/ this.drag = { start: "panstart", move: "panmove", end: "panend" }; _.extend(true, this, opt); }; //这样的好处是document.compareDocumentPosition只会在定义的时候执行一次。 var contains = document.compareDocumentPosition ? function (parent, child) { if (!child) { return false; } return !!(parent.compareDocumentPosition(child) & 16); } : function (parent, child) { if (!child) { return false; } return child !== child && (parent.contains ? parent.contains(child) : true); }; EventHandler.prototype = { init: function init() { //依次添加上浏览器的自带事件侦听 var me = this; if (me.target.nodeType == undefined) { //如果target.nodeType没有的话, 说明该target为一个jQuery对象 or kissy 对象or hammer对象 //即为第三方库,那么就要对接第三方库的事件系统。默认实现hammer的大部分事件系统 if (!me.types || me.types.length == 0) { me.types = _hammerEventTypes; } } else if (me.target.nodeType == 1) { me.types = _mouseEventTypes; } _.each(me.types, function (type) { //不再关心浏览器环境是否 'ontouchstart' in window //而是直接只管传给事件模块的是一个原生dom还是 jq对象 or hammer对象等 if (me.target.nodeType == 1) { $.addEvent(me.target, type, function (e) { me.__mouseHandler(e); }); } else { me.target.on(type, function (e) { me.__libHandler(e); }); } }); }, /* * 原生事件系统------------------------------------------------begin * 鼠标事件处理函数 **/ __mouseHandler: function __mouseHandler(e) { var me = this; var root = me.canvax; root.updateViewOffset(); me.curPoints = [new Point($.pageX(e) - root.viewOffset.left, $.pageY(e) - root.viewOffset.top)]; //理论上来说,这里拿到point了后,就要计算这个point对应的target来push到curPointsTarget里, //但是因为在drag的时候其实是可以不用计算对应target的。 //所以放在了下面的me.__getcurPointsTarget( e , curMousePoint );常规mousemove中执行 var curMousePoint = me.curPoints[0]; var curMouseTarget = me.curPointsTarget[0]; //模拟drag,mouseover,mouseout 部分代码 begin------------------------------------------------- //mousedown的时候 如果 curMouseTarget.dragEnabled 为true。就要开始准备drag了 if (e.type == "mousedown") { //如果curTarget 的数组为空或者第一个为false ,,, if (!curMouseTarget) { var obj = root.getObjectsUnderPoint(curMousePoint, 1)[0]; if (obj) { me.curPointsTarget = [obj]; } } curMouseTarget = me.curPointsTarget[0]; if (curMouseTarget && curMouseTarget.dragEnabled) { //鼠标事件已经摸到了一个 me._touching = true; } } if (e.type == "mouseup" || e.type == "mouseout" && !contains(root.view, e.toElement || e.relatedTarget)) { if (me._draging == true) { //说明刚刚在拖动 me._dragEnd(e, curMouseTarget, 0); curMouseTarget.fire("dragend"); } me._draging = false; me._touching = false; } if (e.type == "mouseout") { if (!contains(root.view, e.toElement || e.relatedTarget)) { me.__getcurPointsTarget(e, curMousePoint, true); } } else if (e.type == "mousemove") { //|| e.type == "mousedown" ){ //拖动过程中就不在做其他的mouseover检测,drag优先 if (me._touching && e.type == "mousemove" && curMouseTarget) { //说明正在拖动啊 if (!me._draging) { //begin drag curMouseTarget.fire("dragstart"); //有可能该child没有hover style if (!curMouseTarget._globalAlpha) { curMouseTarget._globalAlpha = curMouseTarget.context.$model.globalAlpha; } //先把本尊给隐藏了 curMouseTarget.context.globalAlpha = 0; //然后克隆一个副本到activeStage var cloneObject = me._clone2hoverStage(curMouseTarget, 0); cloneObject.context.globalAlpha = curMouseTarget._globalAlpha; } else { //drag move ing me._dragIngHander(e, curMouseTarget, 0); } me._draging = true; } else { //常规mousemove检测 //move事件中,需要不停的搜索target,这个开销挺大, //后续可以优化,加上和帧率相当的延迟处理 me.__getcurPointsTarget(e, curMousePoint); } } else { //其他的事件就直接在target上面派发事件 var child = curMouseTarget; if (!child) { child = root; } me.__dispatchEventInChilds(e, [child]); me._cursorHander(child); } if (root.preventDefault) { //阻止默认浏览器动作(W3C) if (e && e.preventDefault) { e.preventDefault(); } else { window.event.returnValue = false; } } }, //notInRootView 真正的mouseout,鼠标已经不在图表的节点内了 __getcurPointsTarget: function __getcurPointsTarget(e, point, notInRootView) { var me = this; var root = me.canvax; var oldObj = me.curPointsTarget[0]; if (oldObj && !oldObj.context) { oldObj = null; } var e = new CanvaxEvent(e); if (e.type == "mousemove" && oldObj && oldObj._hoverClass && oldObj.hoverClone && oldObj.pointChkPriority && oldObj.getChildInPoint(point)) { //小优化,鼠标move的时候。计算频率太大,所以。做此优化 //如果有target存在,而且当前元素正在hoverStage中,而且当前鼠标还在target内,就没必要取检测整个displayList了 //开发派发常规mousemove事件 e.target = e.currentTarget = oldObj; e.point = oldObj.globalToLocal(point); oldObj.dispatchEvent(e); return; } var obj = notInRootView ? null : root.getObjectsUnderPoint(point, 1)[0]; if (oldObj && oldObj != obj || e.type == "mouseout") { if (oldObj && oldObj.context) { me.curPointsTarget[0] = null; e.type = "mouseout"; e.toTarget = obj; e.target = e.currentTarget = oldObj; e.point = oldObj.globalToLocal(point); oldObj.dispatchEvent(e); } } if (obj && oldObj != obj) { me.curPointsTarget[0] = obj; e.type = "mouseover"; e.fromTarget = oldObj; e.target = e.currentTarget = obj; e.point = obj.globalToLocal(point); obj.dispatchEvent(e); } if (e.type == "mousemove" && obj) { e.target = e.currentTarget = oldObj; e.point = oldObj.globalToLocal(point); oldObj.dispatchEvent(e); } me._cursorHander(obj, oldObj); }, _cursorHander: function _cursorHander(obj, oldObj) { if (!obj && !oldObj) { this._setCursor("default"); } if (obj && oldObj != obj && obj.context) { this._setCursor(obj.context.$model.cursor); } }, _setCursor: function _setCursor(cursor) { if (this._cursor == cursor) { //如果两次要设置的鼠标状态是一样的 return; } this.canvax.view.style.cursor = cursor; this._cursor = cursor; }, /* * 原生事件系统------------------------------------------------end */ /* *第三方库的事件系统------------------------------------------------begin *触屏事件处理函数 * */ __libHandler: function __libHandler(e) { var me = this; var root = me.canvax; root.updateViewOffset(); // touch 下的 curPointsTarget 从touches中来 //获取canvax坐标系统里面的坐标 me.curPoints = me.__getCanvaxPointInTouchs(e); if (!me._draging) { //如果在draging的话,target已经是选中了的,可以不用 检测了 me.curPointsTarget = me.__getChildInTouchs(me.curPoints); } if (me.curPointsTarget.length > 0) { //drag开始 if (e.type == me.drag.start) { //dragstart的时候touch已经准备好了target, curPointsTarget 里面只要有一个是有效的 //就认为drags开始 _.each(me.curPointsTarget, function (child, i) { if (child && child.dragEnabled) { //只要有一个元素就认为正在准备drag了 me._draging = true; //有可能该child没有hover style if (!child._globalAlpha) { child._globalAlpha = child.context.$model.globalAlpha; } //然后克隆一个副本到activeStage me._clone2hoverStage(child, i); //先把本尊给隐藏了 child.context.globalAlpha = 0; child.fire("dragstart"); return false; } }); } //dragIng if (e.type == me.drag.move) { if (me._draging) { _.each(me.curPointsTarget, function (child, i) { if (child && child.dragEnabled) { me._dragIngHander(e, child, i); } }); } } //drag结束 if (e.type == me.drag.end) { if (me._draging) { _.each(me.curPointsTarget, function (child, i) { if (child && child.dragEnabled) { me._dragEnd(e, child, 0); child.fire("dragend"); } }); me._draging = false; } } me.__dispatchEventInChilds(e, me.curPointsTarget); } else { //如果当前没有一个target,就把事件派发到canvax上面 me.__dispatchEventInChilds(e, [root]); } }, //从touchs中获取到对应touch , 在上面添加上canvax坐标系统的x,y __getCanvaxPointInTouchs: function __getCanvaxPointInTouchs(e) { var me = this; var root = me.canvax; var curTouchs = []; _.each(e.point, function (touch) { curTouchs.push({ x: CanvaxEvent.pageX(touch) - root.viewOffset.left, y: CanvaxEvent.pageY(touch) - root.viewOffset.top }); }); return curTouchs; }, __getChildInTouchs: function __getChildInTouchs(touchs) { var me = this; var root = me.canvax; var touchesTarget = []; _.each(touchs, function (touch) { touchesTarget.push(root.getObjectsUnderPoint(touch, 1)[0]); }); return touchesTarget; }, /* *第三方库的事件系统------------------------------------------------end */ /* *@param {array} childs * */ __dispatchEventInChilds: function __dispatchEventInChilds(e, childs) { if (!childs && !("length" in childs)) { return false; } var me = this; var hasChild = false; _.each(childs, function (child, i) { if (child) { hasChild = true; var ce = new CanvaxEvent(e); ce.target = ce.currentTarget = child || this; ce.stagePoint = me.curPoints[i]; ce.point = ce.target.globalToLocal(ce.stagePoint); child.dispatchEvent(ce); } }); return hasChild; }, //克隆一个元素到hover stage中去 _clone2hoverStage: function _clone2hoverStage(target, i) { var me = this; var root = me.canvax; var _dragDuplicate = root._bufferStage.getChildById(target.id); if (!_dragDuplicate) { _dragDuplicate = target.clone(true); _dragDuplicate._transform = target.getConcatenatedMatrix(); /** *TODO: 因为后续可能会有手动添加的 元素到_bufferStage 里面来 *比如tips *这类手动添加进来的肯定是因为需要显示在最外层的。在hover元素之上。 *所有自动添加的hover元素都默认添加在_bufferStage的最底层 **/ root._bufferStage.addChildAt(_dragDuplicate, 0); } _dragDuplicate.context.globalAlpha = target._globalAlpha; target._dragPoint = target.globalToLocal(me.curPoints[i]); return _dragDuplicate; }, //drag 中 的处理函数 _dragIngHander: function _dragIngHander(e, target, i) { var me = this; var root = me.canvax; var _point = target.globalToLocal(me.curPoints[i]); //要对应的修改本尊的位置,但是要告诉引擎不要watch这个时候的变化 target._noHeart = true; var _moveStage = target.moveing; target.moveing = true; target.context.x += _point.x - target._dragPoint.x; target.context.y += _point.y - target._dragPoint.y; target.fire("draging"); target.moveing = _moveStage; target._noHeart = false; //同步完毕本尊的位置 //这里只能直接修改_transform 。 不能用下面的修改x,y的方式。 var _dragDuplicate = root._bufferStage.getChildById(target.id); _dragDuplicate._transform = target.getConcatenatedMatrix(); //worldTransform在renderer的时候计算 _dragDuplicate.worldTransform = null; //setWorldTransform都统一在render中执行,这里注释掉 //_dragDuplicate.setWorldTransform(); //直接修改的_transform不会出发心跳上报, 渲染引擎不制动这个stage需要绘制。 //所以要手动出发心跳包 _dragDuplicate.heartBeat(); }, //drag结束的处理函数 //TODO: dragend的还需要处理end的点是否还在元素上面,要恢复hover状态 _dragEnd: function _dragEnd(e, target, i) { var me = this; var root = me.canvax; //_dragDuplicate 复制在_bufferStage 中的副本 var _dragDuplicate = root._bufferStage.getChildById(target.id); _dragDuplicate && _dragDuplicate.destroy(); target.context.globalAlpha = target._globalAlpha; } }; /** * Canvax * * @author 释剑 (李涛, litao.lt@alibaba-inc.com) * * 事件管理类 */ /** * 构造函数. * @name EventDispatcher * @class EventDispatcher类是可调度事件的类的基类,它允许显示列表上的任何对象都是一个事件目标。 */ var EventManager = function EventManager() { //事件映射表,格式为:{type1:[listener1, listener2], type2:[listener3, listener4]} this._eventMap = {}; }; EventManager.prototype = { /* * 注册事件侦听器对象,以使侦听器能够接收事件通知。 */ _addEventListener: function _addEventListener(type, listener) { if (typeof listener != "function") { //listener必须是个function呐亲 return false; } var addResult = true; var self = this; _.each(type.split(" "), function (type) { var map = self._eventMap[type]; if (!map) { map = self._eventMap[type] = []; map.push(listener); self._eventEnabled = true; return true; } if (_.indexOf(map, listener) == -1) { map.push(listener); self._eventEnabled = true; return true; } addResult = false; }); return addResult; }, /** * 删除事件侦听器。 */ _removeEventListener: function _removeEventListener(type, listener) { if (arguments.length == 1) return this.removeEventListenerByType(type); var map = this._eventMap[type]; if (!map) { return false; } for (var i = 0; i < map.length; i++) { var li = map[i]; if (li === listener) { map.splice(i, 1); if (map.length == 0) { delete this._eventMap[type]; //如果这个如果这个时候child没有任何事件侦听 if (_.isEmpty(this._eventMap)) { //那么该元素不再接受事件的检测 this._eventEnabled = false; } } return true; } } return false; }, /** * 删除指定类型的所有事件侦听器。 */ _removeEventListenerByType: function _removeEventListenerByType(type) { var map = this._eventMap[type]; if (!map) { delete this._eventMap[type]; //如果这个如果这个时候child没有任何事件侦听 if (_.isEmpty(this._eventMap)) { //那么该元素不再接受事件的检测 this._eventEnabled = false; } return true; } return false; }, /** * 删除所有事件侦听器。 */ _removeAllEventListeners: function _removeAllEventListeners() { this._eventMap = {}; this._eventEnabled = false; }, /** * 派发事件,调用事件侦听器。 */ _dispatchEvent: function _dispatchEvent(e) { var map = this._eventMap[e.type]; if (map) { if (!e.target) e.target = this; map = map.slice(); for (var i = 0; i < map.length; i++) { var listener = map[i]; if (typeof listener == "function") { listener.call(this, e); } } } if (!e._stopPropagation) { //向上冒泡 if (this.parent) { e.currentTarget = this.parent; this.parent._dispatchEvent(e); } } return true; }, /** * 检查是否为指定事件类型注册了任何侦听器。 */ _hasEventListener: function _hasEventListener(type) { var map = this._eventMap[type]; return map != null && map.length > 0; } }; /** * Canvax * * @author 释剑 (李涛, litao.lt@alibaba-inc.com) * * 事件派发类 */ var EventDispatcher = function (_EventManager) { inherits$1(EventDispatcher, _EventManager); function EventDispatcher() { classCallCheck$1(this, EventDispatcher); return possibleConstructorReturn$1(this, (EventDispatcher.__proto__ || Object.getPrototypeOf(EventDispatcher)).call(this)); } createClass$1(EventDispatcher, [{ key: "on", value: function on(type, listener) { this._addEventListener(type, listener); return this; } }, { key: "addEventListener", value: function addEventListener(type, listener) { this._addEventListener(type, listener); return this; } }, { key: "un", value: function un(type, listener) { this._removeEventListener(type, listener); return this; } }, { key: "removeEventListener", value: function removeEventListener(type, listener) { this._removeEventListener(type, listener); return this; } }, { key: "removeEventListenerByType", value: function removeEventListenerByType(type) { this._removeEventListenerByType(type); return this; } }, { key: "removeAllEventListeners", value: function removeAllEventListeners() { this._removeAllEventListeners(); return this; } //params 要传给evt的eventhandler处理函数的参数,会被merge到Canvax event中 }, { key: "fire", value: function fire(eventType, params) { //{currentTarget,point,target,type,_stopPropagation} var e = new CanvaxEvent(eventType); if (params) { for (var p in params) { if (p != "type") { e[p] = params[p]; } //然后,currentTarget要修正为自己 e.currentTarget = this; } } var me = this; _.each(eventType.split(" "), function (eType) { e.currentTarget = me; me.dispatchEvent(e); }); return this; } }, { key: "dispatchEvent", value: function dispatchEvent(event) { //this instanceof DisplayObjectContainer ==> this.children //TODO: 这里import DisplayObjectContainer 的话,在displayObject里面的import EventDispatcher from "../event/EventDispatcher"; //会得到一个undefined,感觉是成了一个循环依赖的问题,所以这里换用简单的判断来判断自己是一个容易,拥有children if (this.children && event.point) { var target = this.getObjectsUnderPoint(event.point, 1)[0]; if (target) { target.dispatchEvent(event); } return; } if (this.context && event.type == "mouseover") { //记录dispatchEvent之前的心跳 var preHeartBeat = this._heartBeatNum; var pregAlpha = this.context.$model.globalAlpha; this._dispatchEvent(event); if (preHeartBeat != this._heartBeatNum) { this._hoverClass = true; if (this.hoverClone) { var canvax = this.getStage().parent; //然后clone一份obj,添加到_bufferStage 中 var activShape = this.clone(true); activShape._transform = this.getConcatenatedMatrix(); canvax._bufferStage.addChildAt(activShape, 0); //然后把自己隐藏了 //用一个临时变量_globalAlpha 来存储自己之前的alpha this._globalAlpha = pregAlpha; this.context.globalAlpha = 0; } } return; } this._dispatchEvent(event); if (this.context && event.type == "mouseout") { if (this._hoverClass && this.hoverClone) { //说明刚刚over的时候有添加样式 var canvax = this.getStage().parent; this._hoverClass = false; canvax._bufferStage.removeChildById(this.id); if (t