@egjs/axes
Version:
A module used to change the information of user action entered by various input devices such as touch screen or mouse into the logical virtual coordinates. You can easily create a UI that responds to user actions.
1,502 lines (1,478 loc) • 131 kB
JavaScript
/*
Copyright (c) NAVER Corp.
name: @egjs/axes
license: MIT
author: NAVER Corp.
repository: https://github.com/naver/egjs-axes
version: 3.9.2
*/
'use strict';
var getAgent = require('@egjs/agent');
var Component = require('@egjs/component');
var core = require('@cfcs/core');
/*! *****************************************************************************
Copyright (c) Microsoft Corporation. All rights reserved.
Licensed under the Apache License, Version 2.0 (the "License"); you may not use
this file except in compliance with the License. You may obtain a copy of the
License at http://www.apache.org/licenses/LICENSE-2.0
THIS CODE IS PROVIDED ON AN *AS IS* BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
KIND, EITHER EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION ANY IMPLIED
WARRANTIES OR CONDITIONS OF TITLE, FITNESS FOR A PARTICULAR PURPOSE,
MERCHANTABLITY OR NON-INFRINGEMENT.
See the Apache Version 2.0 License for specific language governing permissions
and limitations under the License.
***************************************************************************** */
/* global Reflect, Promise */
var extendStatics = function (d, b) {
extendStatics = Object.setPrototypeOf || {
__proto__: []
} instanceof Array && function (d, b) {
d.__proto__ = b;
} || function (d, b) {
for (var p in b) if (b.hasOwnProperty(p)) d[p] = b[p];
};
return extendStatics(d, b);
};
function __extends(d, b) {
extendStatics(d, b);
function __() {
this.constructor = d;
}
d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __());
}
var __assign = function () {
__assign = Object.assign || function __assign(t) {
for (var s, i = 1, n = arguments.length; i < n; i++) {
s = arguments[i];
for (var p in s) if (Object.prototype.hasOwnProperty.call(s, p)) t[p] = s[p];
}
return t;
};
return __assign.apply(this, arguments);
};
function __decorate(decorators, target, key, desc) {
var c = arguments.length,
r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc,
d;
if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
return c > 3 && r && Object.defineProperty(target, key, r), r;
}
/*
* Copyright (c) 2015 NAVER Corp.
* egjs projects are licensed under the MIT license
*/
/* eslint-disable no-new-func, no-nested-ternary */
var win;
if (typeof window === "undefined") {
// window is undefined in node.js
win = {
navigator: {
userAgent: ""
}
};
} else {
win = window;
}
/*
* Copyright (c) 2015 NAVER Corp.
* egjs projects are licensed under the MIT license
*/
var DIRECTION_NONE = 1;
var DIRECTION_LEFT = 2;
var DIRECTION_RIGHT = 4;
var DIRECTION_HORIZONTAL = 2 | 4;
var DIRECTION_UP = 8;
var DIRECTION_DOWN = 16;
var DIRECTION_VERTICAL = 8 | 16;
var DIRECTION_ALL = 2 | 4 | 8 | 16;
var MOUSE_LEFT = "left";
var MOUSE_RIGHT = "right";
var MOUSE_MIDDLE = "middle";
var MOUSE_BUTTON_CODE_MAP = {
1: MOUSE_LEFT,
2: MOUSE_MIDDLE,
3: MOUSE_RIGHT
};
var ANY = "any";
var NONE = "none";
var SHIFT = "shift";
var CTRL = "ctrl";
var ALT = "alt";
var META = "meta";
var VELOCITY_INTERVAL = 16;
var AXES_METHODS = ["connect", "disconnect", "get", "setTo", "setBy", "setOptions", "setAxis", "stopAnimation", "updateAnimation", "isBounceArea"];
var AXES_EVENTS = ["hold", "release", "change", "animationStart", "animationEnd", "finish"];
var IOS_EDGE_THRESHOLD = 30;
var IS_IOS_SAFARI = "ontouchstart" in win && getAgent().browser.name === "safari";
var TRANSFORM = function () {
if (typeof document === "undefined") {
return "";
}
var bodyStyle = (document.head || document.getElementsByTagName("head")[0]).style;
var target = ["transform", "webkitTransform", "msTransform", "mozTransform"];
for (var i = 0, len = target.length; i < len; i++) {
if (target[i] in bodyStyle) {
return target[i];
}
}
return "";
}();
var PREVENT_DRAG_CSSPROPS = {
"-webkit-user-select": "none",
"-ms-user-select": "none",
"-moz-user-select": "none",
"user-select": "none",
"-webkit-user-drag": "none"
};
var toArray = function (nodes) {
// const el = Array.prototype.slice.call(nodes);
// for IE8
var el = [];
for (var i = 0, len = nodes.length; i < len; i++) {
el.push(nodes[i]);
}
return el;
};
var $ = function (param, multi) {
if (multi === void 0) {
multi = false;
}
var el;
if (typeof param === "string") {
// String (HTML, Selector)
// check if string is HTML tag format
var match = param.match(/^<([a-z]+)\s*([^>]*)>/);
// creating element
if (match) {
// HTML
var dummy = document.createElement("div");
dummy.innerHTML = param;
el = toArray(dummy.childNodes);
} else {
// Selector
el = toArray(document.querySelectorAll(param));
}
if (!multi) {
el = el.length >= 1 ? el[0] : undefined;
}
} else if (param === win) {
// window
el = param;
} else if ("value" in param || "current" in param) {
el = param.value || param.current;
} else if (param.nodeName && (param.nodeType === 1 || param.nodeType === 9)) {
// HTMLElement, Document
el = param;
} else if ("jQuery" in win && param instanceof jQuery || param.constructor.prototype.jquery) {
// jQuery
el = multi ? param.toArray() : param.get(0);
} else if (Array.isArray(param)) {
el = param.map(function (v) {
return $(v);
});
if (!multi) {
el = el.length >= 1 ? el[0] : undefined;
}
}
return el;
};
var raf = win.requestAnimationFrame || win.webkitRequestAnimationFrame;
var caf = win.cancelAnimationFrame || win.webkitCancelAnimationFrame;
if (raf && !caf) {
var keyInfo_1 = {};
var oldraf_1 = raf;
raf = function (callback) {
var wrapCallback = function (timestamp) {
if (keyInfo_1[key]) {
callback(timestamp);
}
};
var key = oldraf_1(wrapCallback);
keyInfo_1[key] = true;
return key;
};
caf = function (key) {
delete keyInfo_1[key];
};
} else if (!(raf && caf)) {
raf = function (callback) {
return win.setTimeout(function () {
callback(win.performance && win.performance.now && win.performance.now() || new Date().getTime());
}, 16);
};
caf = win.clearTimeout;
}
/**
* A polyfill for the window.requestAnimationFrame() method.
* @see https://developer.mozilla.org/en-US/docs/Web/API/window/requestAnimationFrame
* @private
*/
var requestAnimationFrame = function (fp) {
return raf(fp);
};
/**
* A polyfill for the window.cancelAnimationFrame() method. It cancels an animation executed through a call to the requestAnimationFrame() method.
* @param {Number} key − The ID value returned through a call to the requestAnimationFrame() method. <ko>requestAnimationFrame() 메서드가 반환한 아이디 값</ko>
* @see https://developer.mozilla.org/en-US/docs/Web/API/Window/cancelAnimationFrame
* @private
*/
var cancelAnimationFrame = function (key) {
caf(key);
};
var map = function (obj, callback) {
var tranformed = {};
for (var k in obj) {
if (k) {
tranformed[k] = callback(obj[k], k);
}
}
return tranformed;
};
var filter = function (obj, callback) {
var filtered = {};
for (var k in obj) {
if (k && callback(obj[k], k)) {
filtered[k] = obj[k];
}
}
return filtered;
};
var every = function (obj, callback) {
for (var k in obj) {
if (k && !callback(obj[k], k)) {
return false;
}
}
return true;
};
var equal = function (target, base) {
return every(target, function (v, k) {
return v === base[k];
});
};
var roundNumFunc = {};
var roundNumber = function (num, roundUnit) {
// Cache for performance
if (!roundNumFunc[roundUnit]) {
roundNumFunc[roundUnit] = getRoundFunc(roundUnit);
}
return roundNumFunc[roundUnit](num);
};
var roundNumbers = function (num, roundUnit) {
if (!num || !roundUnit) {
return num;
}
return map(num, function (value, key) {
return roundNumber(value, typeof roundUnit === "number" ? roundUnit : roundUnit[key]);
});
};
var getDecimalPlace = function (val) {
if (!isFinite(val)) {
return 0;
}
var v = "".concat(val);
if (v.indexOf("e") >= 0) {
// Exponential Format
// 1e-10, 1e-12
var p = 0;
var e = 1;
while (Math.round(val * e) / e !== val) {
e *= 10;
p++;
}
return p;
}
// In general, following has performance benefit.
// https://jsperf.com/precision-calculation
return v.indexOf(".") >= 0 ? v.length - v.indexOf(".") - 1 : 0;
};
var inversePow = function (n) {
// replace Math.pow(10, -n) to solve floating point issue.
// eg. Math.pow(10, -4) => 0.00009999999999999999
return 1 / Math.pow(10, n);
};
var getRoundFunc = function (v) {
var p = v < 1 ? Math.pow(10, getDecimalPlace(v)) : 1;
return function (n) {
if (v === 0) {
return 0;
}
return Math.round(Math.round(n / v) * v * p) / p;
};
};
var getAngle = function (posX, posY) {
return Math.atan2(posY, posX) * 180 / Math.PI;
};
var isCssPropsFromAxes = function (originalCssProps) {
var same = true;
Object.keys(PREVENT_DRAG_CSSPROPS).forEach(function (prop) {
if (!originalCssProps || originalCssProps[prop] !== PREVENT_DRAG_CSSPROPS[prop]) {
same = false;
}
});
return same;
};
var getDirection = function (useHorizontal, useVertical) {
if (useHorizontal && useVertical) {
return DIRECTION_ALL;
} else if (useHorizontal) {
return DIRECTION_HORIZONTAL;
} else if (useVertical) {
return DIRECTION_VERTICAL;
} else {
return DIRECTION_NONE;
}
};
var useDirection = function (checkType, direction, userDirection) {
if (userDirection) {
return !!(direction === DIRECTION_ALL || direction & checkType && userDirection & checkType);
} else {
return !!(direction & checkType);
}
};
var setCssProps = function (element, option, direction) {
var _a;
var touchActionMap = (_a = {}, _a[DIRECTION_NONE] = "auto", _a[DIRECTION_ALL] = "none", _a[DIRECTION_VERTICAL] = "pan-x", _a[DIRECTION_HORIZONTAL] = "pan-y", _a);
var oldCssProps = {};
if (element && element.style) {
var touchAction = option.touchAction ? option.touchAction : touchActionMap[direction];
var newCssProps_1 = __assign(__assign({}, PREVENT_DRAG_CSSPROPS), {
"touch-action": element.style["touch-action"] === "none" ? "none" : touchAction
});
Object.keys(newCssProps_1).forEach(function (prop) {
oldCssProps[prop] = element.style[prop];
});
// Old style props like user-select can be corrupted if you change the style directly in the logic above.
Object.keys(newCssProps_1).forEach(function (prop) {
element.style[prop] = newCssProps_1[prop];
});
}
return oldCssProps;
};
var revertCssProps = function (element, originalCssProps) {
if (element && element.style && originalCssProps) {
Object.keys(originalCssProps).forEach(function (prop) {
element.style[prop] = originalCssProps[prop];
});
}
return;
};
var EventManager = /*#__PURE__*/function () {
function EventManager(_axes) {
this._axes = _axes;
this.holdingCount = 0;
}
/**
* This event is fired when a user holds an element on the screen of the device.
* @ko 사용자가 기기의 화면에 손을 대고 있을 때 발생하는 이벤트
* @event Axes#hold
* @type {object}
* @property {Object.<string, number>} pos coordinate <ko>좌표 정보</ko>
* @property {Object} input The instance of inputType where the event occurred<ko>이벤트가 발생한 inputType 인스턴스</ko>
* @property {Object} inputEvent The event object received from inputType <ko>inputType으로 부터 받은 이벤트 객체</ko>
* @property {Boolean} isTrusted Returns true if an event was generated by the user action, or false if it was caused by a script or API call <ko>사용자의 액션에 의해 이벤트가 발생하였으면 true, 스크립트나 API호출에 의해 발생하였을 경우에는 false를 반환한다.</ko>
*
* @example
* ```js
* const axes = new eg.Axes({
* "x": {
* range: [0, 100]
* },
* "zoom": {
* range: [50, 30]
* }
* }).on("hold", function(event) {
* // event.pos
* // event.input
* // event.inputEvent
* // isTrusted
* });
* ```
*/
var __proto = EventManager.prototype;
__proto.hold = function (pos, option) {
var roundPos = this._getRoundPos(pos).roundPos;
this._axes.trigger(new Component.ComponentEvent("hold", {
pos: roundPos,
input: option.input || null,
inputEvent: option.event || null,
isTrusted: true
}));
};
/**
* Specifies the coordinates to move after the 'change' event. It works when the holding value of the change event is true.
* @ko 'change' 이벤트 이후 이동할 좌표를 지정한다. change이벤트의 holding 값이 true일 경우에 동작한다
* @param {Object.<string, number>} pos The coordinate to move to <ko>이동할 좌표</ko>
* @example
* ```js
* const axes = new eg.Axes({
* "x": {
* range: [0, 100]
* },
* "zoom": {
* range: [50, 30]
* }
* }).on("change", function(event) {
* event.holding && event.set({x: 10});
* });
* ```
*/
/** Specifies the animation coordinates to move after the 'release' or 'animationStart' events.
* @ko 'release' 또는 'animationStart' 이벤트 이후 이동할 좌표를 지정한다.
* @param {Object.<string, number>} pos The coordinate to move to <ko>이동할 좌표</ko>
* @param {Number} [duration=0] Duration of the animation (unit: ms) <ko>애니메이션 진행 시간(단위: ms)</ko>
* @example
* ```js
* const axes = new eg.Axes({
* "x": {
* range: [0, 100]
* },
* "zoom": {
* range: [50, 30]
* }
* }).on("animationStart", function(event) {
* event.setTo({x: 10}, 2000);
* });
* ```
*/
/**
* This event is fired when a user release an element on the screen of the device.
* @ko 사용자가 기기의 화면에서 손을 뗐을 때 발생하는 이벤트
* @event Axes#release
* @type {object}
* @property {Object.<string, number>} depaPos The coordinates when releasing an element<ko>손을 뗐을 때의 좌표 </ko>
* @property {Object.<string, number>} destPos The coordinates to move to after releasing an element<ko>손을 뗀 뒤에 이동할 좌표</ko>
* @property {Object.<string, number>} delta The movement variation of coordinate <ko>좌표의 변화량</ko>
* @property {Object.<string, number>} bounceRatio If the coordinates at the time of release are in the bounce area, the current bounce value divided by the maximum bounce value <ko>손을 뗐을 때의 좌표가 bounce 영역에 있는 경우 현재 bounce된 값을 최대 bounce 값으로 나눈 수치.</ko>
* @property {Object} inputEvent The event object received from inputType <ko>inputType으로 부터 받은 이벤트 객체</ko>
* @property {Object} input The instance of inputType where the event occurred<ko>이벤트가 발생한 inputType 인스턴스</ko>
* @property {setTo} setTo Specifies the animation coordinates to move after the event <ko>이벤트 이후 이동할 애니메이션 좌표를 지정한다</ko>
* @property {Boolean} isTrusted Returns true if an event was generated by the user action, or false if it was caused by a script or API call <ko>사용자의 액션에 의해 이벤트가 발생하였으면 true, 스크립트나 API호출에 의해 발생하였을 경우에는 false를 반환한다.</ko>
*
* @example
* ```js
* const axes = new eg.Axes({
* "x": {
* range: [0, 100]
* },
* "zoom": {
* range: [50, 30]
* }
* }).on("release", function(event) {
* // event.depaPos
* // event.destPos
* // event.delta
* // event.input
* // event.inputEvent
* // event.setTo
* // event.isTrusted
*
* // if you want to change the animation coordinates to move after the 'release' event.
* event.setTo({x: 10}, 2000);
* });
* ```
*/
__proto.triggerRelease = function (param) {
var _a = this._getRoundPos(param.destPos, param.depaPos),
roundPos = _a.roundPos,
roundDepa = _a.roundDepa;
param.destPos = roundPos;
param.depaPos = roundDepa;
param.setTo = this._createUserControll(param.destPos, param.duration);
this._axes.trigger(new Component.ComponentEvent("release", __assign(__assign({}, param), {
bounceRatio: this._getBounceRatio(roundPos)
})));
};
/**
* This event is fired when coordinate changes.
* @ko 좌표가 변경됐을 때 발생하는 이벤트
* @event Axes#change
* @type {object}
* @property {Object.<string, number>} pos The coordinate <ko>좌표</ko>
* @property {Object.<string, number>} delta The movement variation of coordinate <ko>좌표의 변화량</ko>
* @property {Object.<string, number>} bounceRatio If the current coordinates are in the bounce area, the current bounce value divided by the maximum bounce value <ko>현재 좌표가 bounce 영역에 있는 경우 현재 bounce된 값을 최대 bounce 값으로 나눈 수치.</ko>
* @property {Boolean} holding Indicates whether a user holds an element on the screen of the device.<ko>사용자가 기기의 화면을 누르고 있는지 여부</ko>
* @property {Object} input The instance of inputType where the event occurred. If the value is changed by animation, it returns 'null'.<ko>이벤트가 발생한 inputType 인스턴스. 애니메이션에 의해 값이 변경될 경우에는 'null'을 반환한다.</ko>
* @property {Object} inputEvent The event object received from inputType. If the value is changed by animation, it returns 'null'.<ko>inputType으로 부터 받은 이벤트 객체. 애니메이션에 의해 값이 변경될 경우에는 'null'을 반환한다.</ko>
* @property {set} set Specifies the coordinates to move after the event. It works when the holding value is true <ko>이벤트 이후 이동할 좌표를 지정한다. holding 값이 true일 경우에 동작한다.</ko>
* @property {Boolean} isTrusted Returns true if an event was generated by the user action, or false if it was caused by a script or API call <ko>사용자의 액션에 의해 이벤트가 발생하였으면 true, 스크립트나 API호출에 의해 발생하였을 경우에는 false를 반환한다.</ko>
*
* @example
* ```js
* const axes = new eg.Axes({
* "x": {
* range: [0, 100]
* },
* "zoom": {
* range: [50, 30]
* }
* }).on("change", function(event) {
* // event.pos
* // event.delta
* // event.input
* // event.inputEvent
* // event.holding
* // event.set
* // event.isTrusted
*
* // if you want to change the coordinates to move after the 'change' event.
* // it works when the holding value of the change event is true.
* event.holding && event.set({x: 10});
* });
* ```
*/
__proto.triggerChange = function (pos, depaPos, option, holding) {
var _this = this;
if (holding === void 0) {
holding = false;
}
var animationManager = this.animationManager;
var axisManager = animationManager.axisManager;
var eventInfo = animationManager.getEventInfo();
var _a = this._getRoundPos(pos, depaPos),
roundPos = _a.roundPos,
roundDepa = _a.roundDepa;
var moveTo = axisManager.moveTo(roundPos, roundDepa);
var inputEvent = (option === null || option === void 0 ? void 0 : option.event) || (eventInfo === null || eventInfo === void 0 ? void 0 : eventInfo.event) || null;
var param = {
pos: moveTo.pos,
delta: moveTo.delta,
bounceRatio: this._getBounceRatio(moveTo.pos),
holding: holding,
inputEvent: inputEvent,
isTrusted: !!inputEvent,
input: (option === null || option === void 0 ? void 0 : option.input) || (eventInfo === null || eventInfo === void 0 ? void 0 : eventInfo.input) || null,
set: inputEvent ? this._createUserControll(moveTo.pos) : function () {} // eslint-disable-line @typescript-eslint/no-empty-function
};
var event = new Component.ComponentEvent("change", param);
this._axes.trigger(event);
Object.keys(moveTo.pos).forEach(function (axis) {
var p = moveTo.pos[axis];
core.getObserver(_this._axes, axis, p).current = p;
});
if (inputEvent) {
axisManager.set(param.set().destPos);
}
return !event.isCanceled();
};
/**
* This event is fired when animation starts.
* @ko 에니메이션이 시작할 때 발생한다.
* @event Axes#animationStart
* @type {object}
* @property {Object.<string, number>} depaPos The coordinates when animation starts<ko>애니메이션이 시작 되었을 때의 좌표 </ko>
* @property {Object.<string, number>} destPos The coordinates to move to. If you change this value, you can run the animation<ko>이동할 좌표. 이값을 변경하여 애니메이션을 동작시킬수 있다</ko>
* @property {Object.<string, number>} delta The movement variation of coordinate <ko>좌표의 변화량</ko>
* @property {Number} duration Duration of the animation (unit: ms). If you change this value, you can control the animation duration time.<ko>애니메이션 진행 시간(단위: ms). 이값을 변경하여 애니메이션의 이동시간을 조절할 수 있다.</ko>
* @property {Object} input The instance of inputType where the event occurred. If the value is changed by animation, it returns 'null'.<ko>이벤트가 발생한 inputType 인스턴스. 애니메이션에 의해 값이 변경될 경우에는 'null'을 반환한다.</ko>
* @property {Object} inputEvent The event object received from inputType <ko>inputType으로 부터 받은 이벤트 객체</ko>
* @property {setTo} setTo Specifies the animation coordinates to move after the event <ko>이벤트 이후 이동할 애니메이션 좌표를 지정한다</ko>
* @property {Boolean} isTrusted Returns true if an event was generated by the user action, or false if it was caused by a script or API call <ko>사용자의 액션에 의해 이벤트가 발생하였으면 true, 스크립트나 API호출에 의해 발생하였을 경우에는 false를 반환한다.</ko>
*
* @example
* ```js
* const axes = new eg.Axes({
* "x": {
* range: [0, 100]
* },
* "zoom": {
* range: [50, 30]
* }
* }).on("release", function(event) {
* // event.depaPos
* // event.destPos
* // event.delta
* // event.input
* // event.inputEvent
* // event.setTo
* // event.isTrusted
*
* // if you want to change the animation coordinates to move after the 'animationStart' event.
* event.setTo({x: 10}, 2000);
* });
* ```
*/
__proto.triggerAnimationStart = function (param) {
var _a = this._getRoundPos(param.destPos, param.depaPos),
roundPos = _a.roundPos,
roundDepa = _a.roundDepa;
param.destPos = roundPos;
param.depaPos = roundDepa;
param.setTo = this._createUserControll(param.destPos, param.duration);
var event = new Component.ComponentEvent("animationStart", param);
this._axes.trigger(event);
return !event.isCanceled();
};
/**
* This event is fired when animation ends.
* @ko 에니메이션이 끝났을 때 발생한다.
* @event Axes#animationEnd
* @type {object}
* @property {Boolean} isTrusted Returns true if an event was generated by the user action, or false if it was caused by a script or API call <ko>사용자의 액션에 의해 이벤트가 발생하였으면 true, 스크립트나 API호출에 의해 발생하였을 경우에는 false를 반환한다.</ko>
*
* @example
* ```js
* const axes = new eg.Axes({
* "x": {
* range: [0, 100]
* },
* "zoom": {
* range: [50, 30]
* }
* }).on("animationEnd", function(event) {
* // event.isTrusted
* });
* ```
*/
__proto.triggerAnimationEnd = function (isTrusted) {
if (isTrusted === void 0) {
isTrusted = false;
}
this._axes.trigger(new Component.ComponentEvent("animationEnd", {
isTrusted: isTrusted
}));
};
/**
* This event is fired when all actions have been completed.
* @ko 에니메이션이 끝났을 때 발생한다.
* @event Axes#finish
* @type {object}
* @property {Boolean} isTrusted Returns true if an event was generated by the user action, or false if it was caused by a script or API call <ko>사용자의 액션에 의해 이벤트가 발생하였으면 true, 스크립트나 API호출에 의해 발생하였을 경우에는 false를 반환한다.</ko>
*
* @example
* ```js
* const axes = new eg.Axes({
* "x": {
* range: [0, 100]
* },
* "zoom": {
* range: [50, 30]
* }
* }).on("finish", function(event) {
* // event.isTrusted
* });
* ```
*/
__proto.triggerFinish = function (isTrusted) {
if (isTrusted === void 0) {
isTrusted = false;
}
this._axes.trigger(new Component.ComponentEvent("finish", {
isTrusted: isTrusted
}));
};
__proto.setAnimationManager = function (animationManager) {
this.animationManager = animationManager;
};
__proto.destroy = function () {
this._axes.off();
};
__proto._createUserControll = function (pos, duration) {
if (duration === void 0) {
duration = 0;
}
// to controll
var userControl = {
destPos: __assign({}, pos),
duration: duration
};
return function (toPos, userDuration) {
if (toPos) {
userControl.destPos = __assign({}, toPos);
}
if (userDuration !== undefined) {
userControl.duration = userDuration;
}
return userControl;
};
};
__proto._getRoundPos = function (pos, depaPos) {
// round value if round exist
var roundUnit = this._axes.options.round;
// if (round == null) {
// return {pos, depaPos}; // undefined, undefined
// }
return {
roundPos: roundNumbers(pos, roundUnit),
roundDepa: roundNumbers(depaPos, roundUnit)
};
};
__proto._getBounceRatio = function (pos) {
return this._axes.axisManager.map(pos, function (v, opt) {
if (v < opt.range[0] && opt.bounce[0] !== 0) {
return (opt.range[0] - v) / opt.bounce[0];
} else if (v > opt.range[1] && opt.bounce[1] !== 0) {
return (v - opt.range[1]) / opt.bounce[1];
} else {
return 0;
}
});
};
__decorate([core.Observe], EventManager.prototype, "holdingCount", void 0);
return EventManager;
}();
var InterruptManager = /*#__PURE__*/function () {
function InterruptManager(_options) {
this._options = _options;
this._prevented = false; // check whether the animation event was prevented
}
var __proto = InterruptManager.prototype;
__proto.isInterrupting = function () {
// when interruptable is 'true', return value is always 'true'.
return this._options.interruptable || this._prevented;
};
__proto.isInterrupted = function () {
return !this._options.interruptable && this._prevented;
};
__proto.setInterrupt = function (prevented) {
if (!this._options.interruptable) {
this._prevented = prevented;
}
};
return InterruptManager;
}();
/*
* Copyright (c) 2015 NAVER Corp.
* egjs projects are licensed under the MIT license
*/
var getInsidePosition = function (destPos, range, circular, bounce) {
var toDestPos = destPos;
var targetRange = [circular[0] ? range[0] : bounce ? range[0] - bounce[0] : range[0], circular[1] ? range[1] : bounce ? range[1] + bounce[1] : range[1]];
toDestPos = Math.max(targetRange[0], toDestPos);
toDestPos = Math.min(targetRange[1], toDestPos);
return toDestPos;
};
// determine outside
var isOutside = function (pos, range) {
return pos < range[0] || pos > range[1];
};
// determine whether position has reached the maximum moveable area
var isEndofBounce = function (pos, range, bounce, circular) {
return !circular[0] && pos === range[0] - bounce[0] || !circular[1] && pos === range[1] + bounce[1];
};
var getDuration = function (distance, deceleration) {
var duration = Math.sqrt(distance / deceleration * 2);
// when duration is under 100, then value is zero
return duration < 100 ? 0 : duration;
};
var isCircularable = function (destPos, range, circular) {
return circular[1] && destPos > range[1] || circular[0] && destPos < range[0];
};
var getCirculatedPos = function (pos, range, circular) {
var toPos = pos;
var min = range[0];
var max = range[1];
var length = max - min;
if (circular[1] && pos > max) {
// right
toPos = (toPos - max) % length + min;
}
if (circular[0] && pos < min) {
// left
toPos = (toPos - min) % length + max;
}
return toPos;
};
var AxisManager = /*#__PURE__*/function () {
function AxisManager(_axis) {
var _this = this;
this._axis = _axis;
this._complementOptions();
this._pos = Object.keys(this._axis).reduce(function (pos, v) {
pos[v] = _this._axis[v].startPos;
return pos;
}, {});
}
var __proto = AxisManager.prototype;
__proto.getDelta = function (depaPos, destPos) {
var fullDepaPos = this.get(depaPos);
return map(this.get(destPos), function (v, k) {
return v - fullDepaPos[k];
});
};
__proto.get = function (axes) {
var _this = this;
if (axes && Array.isArray(axes)) {
return axes.reduce(function (acc, v) {
if (v && v in _this._pos) {
acc[v] = _this._pos[v];
}
return acc;
}, {});
} else {
return __assign(__assign({}, this._pos), axes || {});
}
};
__proto.moveTo = function (pos, depaPos) {
if (depaPos === void 0) {
depaPos = this._pos;
}
var delta = map(this._pos, function (v, key) {
return key in pos && key in depaPos ? pos[key] - depaPos[key] : 0;
});
this.set(this.map(pos, function (v, opt) {
return opt ? getCirculatedPos(v, opt.range, opt.circular) : 0;
}));
return {
pos: __assign({}, this._pos),
delta: delta
};
};
__proto.set = function (pos) {
for (var k in pos) {
if (k && k in this._pos) {
this._pos[k] = pos[k];
}
}
};
__proto.every = function (pos, callback) {
var axisOptions = this._axis;
return every(pos, function (value, key) {
return callback(value, axisOptions[key], key);
});
};
__proto.filter = function (pos, callback) {
var axisOptions = this._axis;
return filter(pos, function (value, key) {
return callback(value, axisOptions[key], key);
});
};
__proto.map = function (pos, callback) {
var axisOptions = this._axis;
return map(pos, function (value, key) {
return callback(value, axisOptions[key], key);
});
};
__proto.isOutside = function (axes) {
return !this.every(axes ? this.get(axes) : this._pos, function (v, opt) {
return !isOutside(v, opt.range);
});
};
__proto.getAxisOptions = function (key) {
return this._axis[key];
};
__proto.setAxis = function (axis) {
var _this = this;
Object.keys(axis).forEach(function (key) {
if (!_this._axis[key]) {
throw new Error("Axis ".concat(key, " does not exist in Axes instance"));
}
_this._axis[key] = __assign(__assign({}, _this._axis[key]), axis[key]);
});
this._complementOptions();
};
/**
* set up 'css' expression
* @private
*/
__proto._complementOptions = function () {
var _this = this;
Object.keys(this._axis).forEach(function (axis) {
_this._axis[axis] = __assign({
range: [0, 100],
startPos: _this._axis[axis].range[0],
bounce: [0, 0],
circular: [false, false]
}, _this._axis[axis]);
["bounce", "circular"].forEach(function (v) {
var axisOption = _this._axis;
var key = axisOption[axis][v];
if (/string|number|boolean/.test(typeof key)) {
axisOption[axis][v] = [key, key];
}
});
});
};
return AxisManager;
}();
var SUPPORT_TOUCH = ("ontouchstart" in win);
var SUPPORT_POINTER = ("PointerEvent" in win);
var SUPPORT_MSPOINTER = ("MSPointerEvent" in win);
var SUPPORT_POINTER_EVENTS = SUPPORT_POINTER || SUPPORT_MSPOINTER;
var isValidKey = function (event, inputKey) {
if (!inputKey || inputKey.indexOf(ANY) > -1 || inputKey.indexOf(NONE) > -1 && !event.shiftKey && !event.ctrlKey && !event.altKey && !event.metaKey || inputKey.indexOf(SHIFT) > -1 && event.shiftKey || inputKey.indexOf(CTRL) > -1 && event.ctrlKey || inputKey.indexOf(ALT) > -1 && event.altKey || inputKey.indexOf(META) > -1 && event.metaKey) {
return true;
}
return false;
};
var EventInput = /*#__PURE__*/function () {
function EventInput() {
var _this = this;
this._stopContextMenu = function (event) {
event.preventDefault();
win.removeEventListener("contextmenu", _this._stopContextMenu);
};
}
var __proto = EventInput.prototype;
__proto.extendEvent = function (event) {
var _a;
var prevEvent = this.prevEvent;
var center = this._getCenter(event);
var movement = prevEvent ? this._getMovement(event) : {
x: 0,
y: 0
};
var scale = prevEvent ? this._getScale(event) : 1;
var angle = prevEvent ? getAngle(center.x - prevEvent.center.x, center.y - prevEvent.center.y) : 0;
var deltaX = prevEvent ? prevEvent.deltaX + movement.x : movement.x;
var deltaY = prevEvent ? prevEvent.deltaY + movement.y : movement.y;
var offsetX = movement.x;
var offsetY = movement.y;
var latestInterval = this._latestInterval;
var timeStamp = Date.now();
var deltaTime = latestInterval ? timeStamp - latestInterval.timestamp : 0;
var velocityX = prevEvent ? prevEvent.velocityX : 0;
var velocityY = prevEvent ? prevEvent.velocityY : 0;
var directionX = prevEvent ? prevEvent.directionX : 1;
var directionY = prevEvent ? prevEvent.directionY : 1;
// If offset is 0, it inherits the direction of the previous event.
if (offsetX > 0) {
directionX = 1;
} else if (offsetX < 0) {
directionX = -1;
}
if (offsetY > 0) {
directionY = 1;
} else if (offsetY < 0) {
directionY = -1;
}
if (!latestInterval || deltaTime >= VELOCITY_INTERVAL) {
if (latestInterval) {
_a = [(deltaX - latestInterval.deltaX) / deltaTime, (deltaY - latestInterval.deltaY) / deltaTime], velocityX = _a[0], velocityY = _a[1];
}
this._latestInterval = {
timestamp: timeStamp,
deltaX: deltaX,
deltaY: deltaY
};
}
return {
srcEvent: event,
scale: scale,
angle: angle,
center: center,
deltaX: deltaX,
deltaY: deltaY,
offsetX: offsetX,
offsetY: offsetY,
directionX: directionX,
directionY: directionY,
velocityX: velocityX,
velocityY: velocityY,
preventSystemEvent: true
};
};
__proto._getDistance = function (start, end) {
var x = end.clientX - start.clientX;
var y = end.clientY - start.clientY;
return Math.sqrt(x * x + y * y);
};
__proto._getButton = function (event) {
var buttonCodeMap = {
1: MOUSE_LEFT,
2: MOUSE_RIGHT,
4: MOUSE_MIDDLE
};
var button = this._isTouchEvent(event) ? MOUSE_LEFT : buttonCodeMap[event.buttons];
return button ? button : null;
};
__proto._isTouchEvent = function (event) {
return event.type && event.type.indexOf("touch") > -1;
};
__proto._isValidButton = function (button, inputButton) {
return inputButton.indexOf(button) > -1;
};
__proto._isValidEvent = function (event, inputKey, inputButton) {
return (!inputKey || isValidKey(event, inputKey)) && (!inputButton || this._isValidButton(this._getButton(event), inputButton));
};
__proto._preventMouseButton = function (event, button) {
if (button === MOUSE_RIGHT) {
win.addEventListener("contextmenu", this._stopContextMenu);
} else if (button === MOUSE_MIDDLE) {
event.preventDefault();
}
};
return EventInput;
}();
var MouseEventInput = /*#__PURE__*/function (_super) {
__extends(MouseEventInput, _super);
function MouseEventInput() {
var _this = _super !== null && _super.apply(this, arguments) || this;
_this.start = ["mousedown"];
_this.move = ["mousemove"];
_this.end = ["mouseup"];
return _this;
}
var __proto = MouseEventInput.prototype;
__proto.onEventStart = function (event, inputKey, inputButton) {
var button = this._getButton(event);
if (!this._isValidEvent(event, inputKey, inputButton)) {
return null;
}
this._preventMouseButton(event, button);
return this.extendEvent(event);
};
__proto.onEventMove = function (event, inputKey, inputButton) {
if (!this._isValidEvent(event, inputKey, inputButton)) {
return null;
}
return this.extendEvent(event);
};
__proto.onEventEnd = function () {
return;
};
__proto.onRelease = function () {
this.prevEvent = null;
return;
};
__proto.getTouches = function (event, inputButton) {
if (inputButton) {
return this._isValidButton(MOUSE_BUTTON_CODE_MAP[event.which], inputButton) && this.end.indexOf(event.type) === -1 ? 1 : 0;
}
return 0;
};
__proto._getScale = function () {
return 1;
};
__proto._getCenter = function (event) {
return {
x: event.clientX,
y: event.clientY
};
};
__proto._getMovement = function (event) {
var prev = this.prevEvent.srcEvent;
return {
x: event.clientX - prev.clientX,
y: event.clientY - prev.clientY
};
};
return MouseEventInput;
}(EventInput);
var TouchEventInput = /*#__PURE__*/function (_super) {
__extends(TouchEventInput, _super);
function TouchEventInput() {
var _this = _super !== null && _super.apply(this, arguments) || this;
_this.start = ["touchstart"];
_this.move = ["touchmove"];
_this.end = ["touchend", "touchcancel"];
return _this;
}
var __proto = TouchEventInput.prototype;
__proto.onEventStart = function (event, inputKey) {
this._baseTouches = event.touches;
if (!this._isValidEvent(event, inputKey)) {
return null;
}
return this.extendEvent(event);
};
__proto.onEventMove = function (event, inputKey) {
if (!this._isValidEvent(event, inputKey)) {
return null;
}
return this.extendEvent(event);
};
__proto.onEventEnd = function (event) {
this._baseTouches = event.touches;
return;
};
__proto.onRelease = function () {
this.prevEvent = null;
this._baseTouches = null;
return;
};
__proto.getTouches = function (event) {
return event.touches.length;
};
__proto._getScale = function (event) {
if (event.touches.length !== 2 || this._baseTouches.length < 2) {
return null; // TODO: consider calculating non-pinch gesture scale
}
return this._getDistance(event.touches[0], event.touches[1]) / this._getDistance(this._baseTouches[0], this._baseTouches[1]);
};
__proto._getCenter = function (event) {
return {
x: event.touches[0].clientX,
y: event.touches[0].clientY
};
};
__proto._getMovement = function (event) {
var prev = this.prevEvent.srcEvent;
if (event.touches[0].identifier !== prev.touches[0].identifier) {
return {
x: 0,
y: 0
};
}
return {
x: event.touches[0].clientX - prev.touches[0].clientX,
y: event.touches[0].clientY - prev.touches[0].clientY
};
};
return TouchEventInput;
}(EventInput);
var PointerEventInput = /*#__PURE__*/function (_super) {
__extends(PointerEventInput, _super);
function PointerEventInput() {
var _this = _super !== null && _super.apply(this, arguments) || this;
_this.start = SUPPORT_POINTER ? ["pointerdown"] : ["MSPointerDown"];
_this.move = SUPPORT_POINTER ? ["pointermove"] : ["MSPointerMove"];
_this.end = SUPPORT_POINTER ? ["pointerup", "pointercancel"] : ["MSPointerUp", "MSPointerCancel"];
// store first, recent inputs for each event id
_this._firstInputs = [];
_this._recentInputs = [];
return _this;
}
var __proto = PointerEventInput.prototype;
__proto.onEventStart = function (event, inputKey, inputButton) {
var button = this._getButton(event);
if (!this._isValidEvent(event, inputKey, inputButton)) {
return null;
}
this._preventMouseButton(event, button);
this._updatePointerEvent(event);
return this.extendEvent(event);
};
__proto.onEventMove = function (event, inputKey, inputButton) {
if (!this._isValidEvent(event, inputKey, inputButton)) {
return null;
}
this._updatePointerEvent(event);
return this.extendEvent(event);
};
__proto.onEventEnd = function (event) {
this._removePointerEvent(event);
};
__proto.onRelease = function () {
this.prevEvent = null;
this._firstInputs = [];
this._recentInputs = [];
return;
};
__proto.getTouches = function () {
return this._recentInputs.length;
};
__proto._getScale = function () {
if (this._recentInputs.length !== 2) {
return null; // TODO: consider calculating non-pinch gesture scale
}
return this._getDistance(this._recentInputs[0], this._recentInputs[1]) / this._getDistance(this._firstInputs[0], this._firstInputs[1]);
};
__proto._getCenter = function (event) {
return {
x: event.clientX,
y: event.clientY
};
};
__proto._getMovement = function (event) {
var prev = this.prevEvent.srcEvent;
if (event.pointerId !== prev.pointerId) {
return {
x: 0,
y: 0
};
}
return {
x: event.clientX - prev.clientX,
y: event.clientY - prev.clientY
};
};
__proto._updatePointerEvent = function (event) {
var _this = this;
var addFlag = false;
this._recentInputs.forEach(function (e, i) {
if (e.pointerId === event.pointerId) {
addFlag = true;
_this._recentInputs[i] = event;
}
});
if (!addFlag) {
this._firstInputs.push(event);
this._recentInputs.push(event);
}
};
__proto._removePointerEvent = function (event) {
this._firstInputs = this._firstInputs.filter(function (x) {
return x.pointerId !== event.pointerId;
});
this._recentInputs = this._recentInputs.filter(function (x) {
return x.pointerId !== event.pointerId;
});
};
return PointerEventInput;
}(EventInput);
var TouchMouseEventInput = /*#__PURE__*/function (_super) {
__extends(TouchMouseEventInput, _super);
function TouchMouseEventInput() {
var _this = _super !== null && _super.apply(this, arguments) || this;
_this.start = ["mousedown", "touchstart"];
_this.move = ["mousemove", "touchmove"];
_this.end = ["mouseup", "touchend", "touchcancel"];
return _this;
}
var __proto = TouchMouseEventInput.prototype;
__proto.onEventStart = function (event, inputKey, inputButton) {
var button = this._getButton(event);
if (this._isTouchEvent(event)) {
this._baseTouches = event.touches;
}
if (!this._isValidEvent(event, inputKey, inputButton)) {
return null;
}
this._preventMouseButton(event, button);
return this.extendEvent(event);
};
__proto.onEventMove = function (event, inputKey, inputButton) {
if (!this._isValidEvent(event, inputKey, inputButton)) {
return null;
}
return this.extendEvent(event);
};
__proto.onEventEnd = function (event) {
if (this._isTouchEvent(event)) {
this._baseTouches = event.touches;
}
return;
};
__proto.onRelease = function () {
this.prevEvent = null;
this._baseTouches = null;
return;
};
__proto.getTouches = function (event, inputButton) {
if (this._isTouchEvent(event)) {
return event.touches.length;
} else {
return this._isValidButton(MOUSE_BUTTON_CODE_MAP[event.which], inputButton) && this.end.indexOf(event.type) === -1 ? 1 : 0;
}
};
__proto._getScale = function (event) {
if (this._isTouchEvent(event)) {
if (event.touches.length !== 2 || this._baseTouches.length < 2) {
return 1; // TODO: consider calculating non-pinch gesture scale
}
return this._getDistance(event.touches[0], event.touches[1]) / this._getDistance(this._baseTouches[0], this._baseTouches[1]);
}
return this.prevEvent.scale;
};
__proto._getCenter = function (event) {
if (this._isTouchEvent(event)) {
return {
x: event.touches[0].clientX,
y: event.touches[0].clientY
};
}
return {
x: event.clientX,
y: event.clientY
};
};
__proto._getMovement = function (event) {
var _this = this;
var prev = this.prevEvent.srcEvent;
var _a = [event, prev].map(function (e) {
if (_this._isTouchEvent(e)) {
return {
id: e.touches[0].identifier,
x: e.touches[0].clientX,
y: e.touches[0].clientY
};
}
return {
id: null,
x: e.clientX,
y: e.clientY
};
}),
nextSpot = _a[0],
prevSpot = _a[1];
return nextSpot.id === prevSpot.id ? {
x: nextSpot.x - prevSpot.x,
y: nextSpot.y - prevSpot.y
} : {
x: 0,
y: 0
};
};
return TouchMouseEventInput;
}(EventInput);
var toAxis = function (source, offset) {
return offset.reduce(function (acc, v, i) {
if (source[i]) {
acc[source[i]] = v;
}
return acc;
}, {});
};
var convertInputType = function (inputType) {
if (inputType === void 0) {
inputType = [];
}
var hasTouch = false;
var hasMouse = false;
var hasPointer = false;
inputType.forEach(function (v) {
switch (v) {
case "mouse":
hasMouse = true;
break;
case "touch":
hasTouch = SUPPORT_TOUCH;
break;
case "pointer":
hasPointer = SUPPORT_POINTER_EVENTS;
// no default
}
});
if (hasPointer) {
return new PointerEventInput();
} else if (hasTouch && hasMouse) {
return new TouchMouseEventInput();
} else if (hasTouch) {
return new TouchEventInput();
} else if (hasMouse) {
return new MouseEventInput();
}
return null;
};
function getAddEventOptions(eventName) {
// The passive default value of the touch event is true.
// If not a touch event, return false to support ie11
return eventName.indexOf("touch") > -1 ? {
passive: false
} : false;
}
var InputObserver = /*#__PURE__*/function () {
function InputObserver(_a) {
var options = _a.options,
interruptManager = _a.interruptManager,
eventManager = _a.eventManager,
axisManager = _a.axisManager,
animationManager = _a.animationManager;
this._isOutside = false;
this._moveDistance = null;
this._isStopped = false;
this.options = options;
this._interruptManager = interruptManager;
this._eventManager = eventManager;
this._axisManager = axisManager;
this._animationManager = animationManager;
}
var __proto = InputObserver.prototype;
__proto.get = function (input) {
return this._axisManager.get(input.axes);
};
__proto.hold = function (input, event) {
if (this._interruptManager.isInterrupted() || !input.axes.length) {
return;
}
var changeOption = {
input: input,
event: event
};
this._isStopped = false;
this._interruptManager.setInterrupt(true);
this._animationManager.stopAnimation(changeOption);
++this._eventManager.holdingCount;
if (!this._moveDistance) {
this._eventManager.hold(this._axisManager.get(), changeOption);
}
this._isOutside = this._axisManager.isOutside(input.axes);
this._moveDistance = this._axisManager.get(input.axes);
};
__proto.change = function (input, event, offset, useAnimation) {
if (this._isStopped || !this._interruptManager.isInterrupting() || this._axisManager.every(offset, function (v) {
return v === 0;
})) {
return;
}
var nativeEvent = event.srcEvent ? event.srcEvent : event;
if (nativeEvent.__childrenAxesAlreadyChanged) {
return;
}
var depaPos = this._moveDistance || this._axisManager.get(input.axes);
var destPos;
// for outside logic
destPos = map(depaPos, function (v, k) {
return v + (offset[k] || 0);
});
if (this._moveDistance) {
this._moveDistance = this._axisManager.map(destPos, function (v, _a) {
var circular = _a.circular,
range = _a.range;
return circular && (circular[0] || circular[1]) ? getCirculatedPos(v, range, circular) : v;
});
}
// from outside to inside
if (this._isOutside && this._axisManager.every(depaPos, function (v, opt) {
return !isOutside(v, opt.range);
})) {
this._isOutside = false;
}
depaPos = this._atOutside(depaPos);
destPos = this._atOutside(destPos);
if (!this.options.nested || !this._isEndofAxis(offset, depaPos, destPos)) {
nativeEvent.__childrenAxesAlreadyChanged = true;
}
var changeOption = {
input: input,
event: event
};
if (useAnimation) {
var duration = this._animationManager.getDuration(destPos, depaPos);
this._animationManager.animateTo(destPos, duration, changeOption);
} else {
var isCanceled = !this._eventManager.triggerChange(destPos, depaPos, changeOption, true);
if (isCanceled) {
this._isStopped = true;
this._moveDistance = null;
this._animationManager.finish(false);
}
}
};
__proto.release = function (input, event, velocity, inputDuration) {
if (this._isStopped || !this._interruptManager.isInterrupting() || !this._moveDistance) {
return;
}
var nativeEvent = event.srcEvent ? event.srcEvent : event;
if (nativeEvent.__childrenAxesAlreadyReleased) {
velocity = velocity.map(function () {
return 0;
});
}
var pos = this._axisManager.get(input.axes);
var depaPos = this._axisManager.get();
var displacement = this._animationManager.getDisplacement(velocity);
var offset = toAxis(input.axes, displacement);
var destPos = this._axisManager.get(this._axisManager.map(offset, function (v, opt, k) {
if (opt.circular && (opt.circular[0] || opt.circular[1])) {
return pos[k] + v;
} else {
return getInsidePosition(pos[k] + v, opt.range, opt.circular, opt.bounce);
}
}));
nativeEvent.__childrenAxesAlreadyReleased = true;
var duration = this._animationManager.getDuration(destPos, pos, inputDuration);
if (duration === 0) {
destPos = __assign({}, depaPos);
}
// prepare params
var param = {
depaPos: depaPos,
destPos: destPos,
duration: duration,
delta: this._axisManager.getDelta(depaPos, destPos),
inputEvent: event,
input: input,
isTrusted: true
};
--this._eventManager.holdingCount;
this._eventManager.triggerRelease(param);
if (this._eventManager.holdingCount === 0) {
this._moveDistance = null;
}
// to contol
var userWish = this._animationManager.getUserControl(param);
var isEqual = equal(userWish.destPos, depaPos);
var changeOption = {
input: i