UNPKG

105 kBJavaScriptView Raw
1/*
2Copyright (c) 2015 NAVER Corp.
3name: @egjs/axes
4license: MIT
5author: NAVER Corp.
6repository: https://github.com/naver/egjs-axes
7version: 2.8.0
8*/
9(function (global, factory) {
10 typeof exports === 'object' && typeof module !== 'undefined' ? module.exports = factory(require('@egjs/hammerjs'), require('@egjs/agent'), require('@egjs/component')) :
11 typeof define === 'function' && define.amd ? define(['@egjs/hammerjs', '@egjs/agent', '@egjs/component'], factory) :
12 (global.eg = global.eg || {}, global.eg.Axes = factory(global.Hammer,global.eg.agent,global.eg.Component));
13}(this, (function (hammerjs,getAgent,Component) { 'use strict';
14
15 /*! *****************************************************************************
16 Copyright (c) Microsoft Corporation. All rights reserved.
17 Licensed under the Apache License, Version 2.0 (the "License"); you may not use
18 this file except in compliance with the License. You may obtain a copy of the
19 License at http://www.apache.org/licenses/LICENSE-2.0
20
21 THIS CODE IS PROVIDED ON AN *AS IS* BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
22 KIND, EITHER EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION ANY IMPLIED
23 WARRANTIES OR CONDITIONS OF TITLE, FITNESS FOR A PARTICULAR PURPOSE,
24 MERCHANTABLITY OR NON-INFRINGEMENT.
25
26 See the Apache Version 2.0 License for specific language governing permissions
27 and limitations under the License.
28 ***************************************************************************** */
29
30 /* global Reflect, Promise */
31 var extendStatics = function (d, b) {
32 extendStatics = Object.setPrototypeOf || {
33 __proto__: []
34 } instanceof Array && function (d, b) {
35 d.__proto__ = b;
36 } || function (d, b) {
37 for (var p in b) if (b.hasOwnProperty(p)) d[p] = b[p];
38 };
39
40 return extendStatics(d, b);
41 };
42
43 function __extends(d, b) {
44 extendStatics(d, b);
45
46 function __() {
47 this.constructor = d;
48 }
49
50 d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __());
51 }
52 var __assign = function () {
53 __assign = Object.assign || function __assign(t) {
54 for (var s, i = 1, n = arguments.length; i < n; i++) {
55 s = arguments[i];
56
57 for (var p in s) if (Object.prototype.hasOwnProperty.call(s, p)) t[p] = s[p];
58 }
59
60 return t;
61 };
62
63 return __assign.apply(this, arguments);
64 };
65
66 function getInsidePosition(destPos, range, circular, bounce) {
67 var toDestPos = destPos;
68 var targetRange = [circular[0] ? range[0] : bounce ? range[0] - bounce[0] : range[0], circular[1] ? range[1] : bounce ? range[1] + bounce[1] : range[1]];
69 toDestPos = Math.max(targetRange[0], toDestPos);
70 toDestPos = Math.min(targetRange[1], toDestPos);
71 return toDestPos;
72 } // determine outside
73
74 function isOutside(pos, range) {
75 return pos < range[0] || pos > range[1];
76 }
77 function getDuration(distance, deceleration) {
78 var duration = Math.sqrt(distance / deceleration * 2); // when duration is under 100, then value is zero
79
80 return duration < 100 ? 0 : duration;
81 }
82 function isCircularable(destPos, range, circular) {
83 return circular[1] && destPos > range[1] || circular[0] && destPos < range[0];
84 }
85 function getCirculatedPos(pos, range, circular) {
86 var toPos = pos;
87 var min = range[0];
88 var max = range[1];
89 var length = max - min;
90
91 if (circular[1] && pos > max) {
92 // right
93 toPos = (toPos - max) % length + min;
94 }
95
96 if (circular[0] && pos < min) {
97 // left
98 toPos = (toPos - min) % length + max;
99 }
100
101 return toPos;
102 }
103
104 /* eslint-disable no-new-func, no-nested-ternary */
105 var win;
106
107 if (typeof window === "undefined") {
108 // window is undefined in node.js
109 win = {
110 navigator: {
111 userAgent: ""
112 }
113 };
114 } else {
115 win = window;
116 }
117
118 function toArray(nodes) {
119 // const el = Array.prototype.slice.call(nodes);
120 // for IE8
121 var el = [];
122
123 for (var i = 0, len = nodes.length; i < len; i++) {
124 el.push(nodes[i]);
125 }
126
127 return el;
128 }
129 function $(param, multi) {
130 if (multi === void 0) {
131 multi = false;
132 }
133
134 var el;
135
136 if (typeof param === "string") {
137 // String (HTML, Selector)
138 // check if string is HTML tag format
139 var match = param.match(/^<([a-z]+)\s*([^>]*)>/); // creating element
140
141 if (match) {
142 // HTML
143 var dummy = document.createElement("div");
144 dummy.innerHTML = param;
145 el = toArray(dummy.childNodes);
146 } else {
147 // Selector
148 el = toArray(document.querySelectorAll(param));
149 }
150
151 if (!multi) {
152 el = el.length >= 1 ? el[0] : undefined;
153 }
154 } else if (param === win) {
155 // window
156 el = param;
157 } else if (param.nodeName && (param.nodeType === 1 || param.nodeType === 9)) {
158 // HTMLElement, Document
159 el = param;
160 } else if ("jQuery" in win && param instanceof jQuery || param.constructor.prototype.jquery) {
161 // jQuery
162 el = multi ? param.toArray() : param.get(0);
163 } else if (Array.isArray(param)) {
164 el = param.map(function (v) {
165 return $(v);
166 });
167
168 if (!multi) {
169 el = el.length >= 1 ? el[0] : undefined;
170 }
171 }
172
173 return el;
174 }
175 var raf = win.requestAnimationFrame || win.webkitRequestAnimationFrame;
176 var caf = win.cancelAnimationFrame || win.webkitCancelAnimationFrame;
177
178 if (raf && !caf) {
179 var keyInfo_1 = {};
180 var oldraf_1 = raf;
181
182 raf = function (callback) {
183 function wrapCallback(timestamp) {
184 if (keyInfo_1[key]) {
185 callback(timestamp);
186 }
187 }
188
189 var key = oldraf_1(wrapCallback);
190 keyInfo_1[key] = true;
191 return key;
192 };
193
194 caf = function (key) {
195 delete keyInfo_1[key];
196 };
197 } else if (!(raf && caf)) {
198 raf = function (callback) {
199 return win.setTimeout(function () {
200 callback(win.performance && win.performance.now && win.performance.now() || new Date().getTime());
201 }, 16);
202 };
203
204 caf = win.clearTimeout;
205 }
206 /**
207 * A polyfill for the window.requestAnimationFrame() method.
208 * @see https://developer.mozilla.org/en-US/docs/Web/API/window/requestAnimationFrame
209 * @private
210 */
211
212
213 function requestAnimationFrame(fp) {
214 return raf(fp);
215 }
216 /**
217 * A polyfill for the window.cancelAnimationFrame() method. It cancels an animation executed through a call to the requestAnimationFrame() method.
218 * @param {Number} key − The ID value returned through a call to the requestAnimationFrame() method. <ko>requestAnimationFrame() 메서드가 반환한 아이디 값</ko>
219 * @see https://developer.mozilla.org/en-US/docs/Web/API/Window/cancelAnimationFrame
220 * @private
221 */
222
223 function cancelAnimationFrame(key) {
224 caf(key);
225 }
226 function map(obj, callback) {
227 var tranformed = {};
228
229 for (var k in obj) {
230 k && (tranformed[k] = callback(obj[k], k));
231 }
232
233 return tranformed;
234 }
235 function filter(obj, callback) {
236 var filtered = {};
237
238 for (var k in obj) {
239 k && callback(obj[k], k) && (filtered[k] = obj[k]);
240 }
241
242 return filtered;
243 }
244 function every(obj, callback) {
245 for (var k in obj) {
246 if (k && !callback(obj[k], k)) {
247 return false;
248 }
249 }
250
251 return true;
252 }
253 function equal(target, base) {
254 return every(target, function (v, k) {
255 return v === base[k];
256 });
257 }
258 var roundNumFunc = {};
259 function roundNumber(num, roundUnit) {
260 // Cache for performance
261 if (!roundNumFunc[roundUnit]) {
262 roundNumFunc[roundUnit] = getRoundFunc(roundUnit);
263 }
264
265 return roundNumFunc[roundUnit](num);
266 }
267 function roundNumbers(num, roundUnit) {
268 if (!num || !roundUnit) {
269 return num;
270 }
271
272 var isNumber = typeof roundUnit === "number";
273 return map(num, function (value, key) {
274 return roundNumber(value, isNumber ? roundUnit : roundUnit[key]);
275 });
276 }
277 function getDecimalPlace(val) {
278 if (!isFinite(val)) {
279 return 0;
280 }
281
282 var v = val + "";
283
284 if (v.indexOf("e") >= 0) {
285 // Exponential Format
286 // 1e-10, 1e-12
287 var p = 0;
288 var e = 1;
289
290 while (Math.round(val * e) / e !== val) {
291 e *= 10;
292 p++;
293 }
294
295 return p;
296 } // In general, following has performance benefit.
297 // https://jsperf.com/precision-calculation
298
299
300 return v.indexOf(".") >= 0 ? v.length - v.indexOf(".") - 1 : 0;
301 }
302 function inversePow(n) {
303 // replace Math.pow(10, -n) to solve floating point issue.
304 // eg. Math.pow(10, -4) => 0.00009999999999999999
305 return 1 / Math.pow(10, n);
306 }
307 function getRoundFunc(v) {
308 var p = v < 1 ? Math.pow(10, getDecimalPlace(v)) : 1;
309 return function (n) {
310 if (v === 0) {
311 return 0;
312 }
313
314 return Math.round(Math.round(n / v) * v * p) / p;
315 };
316 }
317
318 function minMax(value, min, max) {
319 return Math.max(Math.min(value, max), min);
320 }
321
322 var AnimationManager =
323 /*#__PURE__*/
324 function () {
325 function AnimationManager(_a) {
326 var options = _a.options,
327 itm = _a.itm,
328 em = _a.em,
329 axm = _a.axm;
330 this.options = options;
331 this.itm = itm;
332 this.em = em;
333 this.axm = axm;
334 this.animationEnd = this.animationEnd.bind(this);
335 }
336
337 var __proto = AnimationManager.prototype;
338
339 __proto.getDuration = function (depaPos, destPos, wishDuration) {
340 var _this = this;
341
342 var duration;
343
344 if (typeof wishDuration !== "undefined") {
345 duration = wishDuration;
346 } else {
347 var durations_1 = map(destPos, function (v, k) {
348 return getDuration(Math.abs(v - depaPos[k]), _this.options.deceleration);
349 });
350 duration = Object.keys(durations_1).reduce(function (max, v) {
351 return Math.max(max, durations_1[v]);
352 }, -Infinity);
353 }
354
355 return minMax(duration, this.options.minimumDuration, this.options.maximumDuration);
356 };
357
358 __proto.createAnimationParam = function (pos, duration, option) {
359 var depaPos = this.axm.get();
360 var destPos = pos;
361 var inputEvent = option && option.event || null;
362 return {
363 depaPos: depaPos,
364 destPos: destPos,
365 duration: minMax(duration, this.options.minimumDuration, this.options.maximumDuration),
366 delta: this.axm.getDelta(depaPos, destPos),
367 inputEvent: inputEvent,
368 input: option && option.input || null,
369 isTrusted: !!inputEvent,
370 done: this.animationEnd
371 };
372 };
373
374 __proto.grab = function (axes, option) {
375 if (this._animateParam && axes.length) {
376 var orgPos_1 = this.axm.get(axes);
377 var pos = this.axm.map(orgPos_1, function (v, opt) {
378 return getCirculatedPos(v, opt.range, opt.circular);
379 });
380
381 if (!every(pos, function (v, k) {
382 return orgPos_1[k] === v;
383 })) {
384 this.em.triggerChange(pos, false, orgPos_1, option, !!option);
385 }
386
387 this._animateParam = null;
388 this._raf && cancelAnimationFrame(this._raf);
389 this._raf = null;
390 this.em.triggerAnimationEnd(!!(option && option.event));
391 }
392 };
393
394 __proto.getEventInfo = function () {
395 if (this._animateParam && this._animateParam.input && this._animateParam.inputEvent) {
396 return {
397 input: this._animateParam.input,
398 event: this._animateParam.inputEvent
399 };
400 } else {
401 return null;
402 }
403 };
404
405 __proto.restore = function (option) {
406 var pos = this.axm.get();
407 var destPos = this.axm.map(pos, function (v, opt) {
408 return Math.min(opt.range[1], Math.max(opt.range[0], v));
409 });
410 this.animateTo(destPos, this.getDuration(pos, destPos), option);
411 };
412
413 __proto.animationEnd = function () {
414 var beforeParam = this.getEventInfo();
415 this._animateParam = null; // for Circular
416
417 var circularTargets = this.axm.filter(this.axm.get(), function (v, opt) {
418 return isCircularable(v, opt.range, opt.circular);
419 });
420 Object.keys(circularTargets).length > 0 && this.setTo(this.axm.map(circularTargets, function (v, opt) {
421 return getCirculatedPos(v, opt.range, opt.circular);
422 }));
423 this.itm.setInterrupt(false);
424 this.em.triggerAnimationEnd(!!beforeParam);
425
426 if (this.axm.isOutside()) {
427 this.restore(beforeParam);
428 } else {
429 this.finish(!!beforeParam);
430 }
431 };
432
433 __proto.finish = function (isTrusted) {
434 this._animateParam = null;
435 this.itm.setInterrupt(false);
436 this.em.triggerFinish(isTrusted);
437 };
438
439 __proto.animateLoop = function (param, complete) {
440 if (param.duration) {
441 this._animateParam = __assign({}, param);
442 var info_1 = this._animateParam;
443 var self_1 = this;
444 var destPos_1 = info_1.destPos;
445 var prevPos_1 = info_1.depaPos;
446 var prevEasingPer_1 = 0;
447 var directions_1 = map(prevPos_1, function (value, key) {
448 return value <= destPos_1[key] ? 1 : -1;
449 });
450 var originalIntendedPos_1 = map(destPos_1, function (v) {
451 return v;
452 });
453 var prevTime_1 = new Date().getTime();
454 info_1.startTime = prevTime_1;
455
456 (function loop() {
457 self_1._raf = null;
458 var currentTime = new Date().getTime();
459 var ratio = (currentTime - info_1.startTime) / param.duration;
460 var easingPer = self_1.easing(ratio);
461 var toPos = self_1.axm.map(prevPos_1, function (pos, options, key) {
462 var nextPos = ratio >= 1 ? destPos_1[key] : pos + info_1.delta[key] * (easingPer - prevEasingPer_1); // Subtract distance from distance already moved.
463 // Recalculate the remaining distance.
464 // Fix the bouncing phenomenon by changing the range.
465
466 var circulatedPos = getCirculatedPos(nextPos, options.range, options.circular);
467
468 if (nextPos !== circulatedPos) {
469 // circular
470 var rangeOffset = directions_1[key] * (options.range[1] - options.range[0]);
471 destPos_1[key] -= rangeOffset;
472 prevPos_1[key] -= rangeOffset;
473 }
474
475 return circulatedPos;
476 });
477 var isCanceled = !self_1.em.triggerChange(toPos, false, prevPos_1);
478 prevPos_1 = toPos;
479 prevTime_1 = currentTime;
480 prevEasingPer_1 = easingPer;
481
482 if (easingPer >= 1) {
483 destPos_1 = self_1.getFinalPos(destPos_1, originalIntendedPos_1);
484
485 if (!equal(destPos_1, self_1.axm.get(Object.keys(destPos_1)))) {
486 self_1.em.triggerChange(destPos_1, true, prevPos_1);
487 }
488
489 complete();
490 return;
491 } else if (isCanceled) {
492 self_1.finish(false);
493 } else {
494 // animationEnd
495 self_1._raf = requestAnimationFrame(loop);
496 }
497 })();
498 } else {
499 this.em.triggerChange(param.destPos, true);
500 complete();
501 }
502 };
503 /**
504 * Get estimated final value.
505 *
506 * If destPos is within the 'error range' of the original intended position, the initial intended position is returned.
507 * - eg. original intended pos: 100, destPos: 100.0000000004 ==> return 100;
508 * If dest Pos is outside the 'range of error' compared to the originally intended pos, it is returned rounded based on the originally intended pos.
509 * - eg. original intended pos: 100.123 destPos: 50.12345 => return 50.123
510 *
511 * @param originalIntendedPos
512 * @param destPos
513 */
514
515
516 __proto.getFinalPos = function (destPos, originalIntendedPos) {
517 var _this = this; // compare destPos and originalIntendedPos
518
519
520 var ERROR_LIMIT = 0.000001;
521 var finalPos = map(destPos, function (value, key) {
522 if (value >= originalIntendedPos[key] - ERROR_LIMIT && value <= originalIntendedPos[key] + ERROR_LIMIT) {
523 // In error range, return original intended
524 return originalIntendedPos[key];
525 } else {
526 // Out of error range, return rounded pos.
527 var roundUnit = _this.getRoundUnit(value, key);
528
529 var result = roundNumber(value, roundUnit);
530 return result;
531 }
532 });
533 return finalPos;
534 };
535
536 __proto.getRoundUnit = function (val, key) {
537 var roundUnit = this.options.round; // manual mode
538
539 var minRoundUnit = null; // auto mode
540 // auto mode
541
542 if (!roundUnit) {
543 // Get minimum round unit
544 var options = this.axm.getAxisOptions(key);
545 minRoundUnit = inversePow(Math.max(getDecimalPlace(options.range[0]), getDecimalPlace(options.range[1]), getDecimalPlace(val)));
546 }
547
548 return minRoundUnit || roundUnit;
549 };
550
551 __proto.getUserControll = function (param) {
552 var userWish = param.setTo();
553 userWish.destPos = this.axm.get(userWish.destPos);
554 userWish.duration = minMax(userWish.duration, this.options.minimumDuration, this.options.maximumDuration);
555 return userWish;
556 };
557
558 __proto.animateTo = function (destPos, duration, option) {
559 var _this = this;
560
561 var param = this.createAnimationParam(destPos, duration, option);
562
563 var depaPos = __assign({}, param.depaPos);
564
565 var retTrigger = this.em.triggerAnimationStart(param); // to control
566
567 var userWish = this.getUserControll(param); // You can't stop the 'animationStart' event when 'circular' is true.
568
569 if (!retTrigger && this.axm.every(userWish.destPos, function (v, opt) {
570 return isCircularable(v, opt.range, opt.circular);
571 })) {
572 console.warn("You can't stop the 'animation' event when 'circular' is true.");
573 }
574
575 if (retTrigger && !equal(userWish.destPos, depaPos)) {
576 var inputEvent = option && option.event || null;
577 this.animateLoop({
578 depaPos: depaPos,
579 destPos: userWish.destPos,
580 duration: userWish.duration,
581 delta: this.axm.getDelta(depaPos, userWish.destPos),
582 isTrusted: !!inputEvent,
583 inputEvent: inputEvent,
584 input: option && option.input || null
585 }, function () {
586 return _this.animationEnd();
587 });
588 }
589 };
590
591 __proto.easing = function (p) {
592 return p > 1 ? 1 : this.options.easing(p);
593 };
594
595 __proto.setTo = function (pos, duration) {
596 if (duration === void 0) {
597 duration = 0;
598 }
599
600 var axes = Object.keys(pos);
601 this.grab(axes);
602 var orgPos = this.axm.get(axes);
603
604 if (equal(pos, orgPos)) {
605 return this;
606 }
607
608 this.itm.setInterrupt(true);
609 var movedPos = filter(pos, function (v, k) {
610 return orgPos[k] !== v;
611 });
612
613 if (!Object.keys(movedPos).length) {
614 return this;
615 }
616
617 movedPos = this.axm.map(movedPos, function (v, opt) {
618 var range = opt.range,
619 circular = opt.circular;
620
621 if (circular && (circular[0] || circular[1])) {
622 return v;
623 } else {
624 return getInsidePosition(v, range, circular);
625 }
626 });
627
628 if (equal(movedPos, orgPos)) {
629 return this;
630 }
631
632 if (duration > 0) {
633 this.animateTo(movedPos, duration);
634 } else {
635 this.em.triggerChange(movedPos);
636 this.finish(false);
637 }
638
639 return this;
640 };
641
642 __proto.setBy = function (pos, duration) {
643 if (duration === void 0) {
644 duration = 0;
645 }
646
647 return this.setTo(map(this.axm.get(Object.keys(pos)), function (v, k) {
648 return v + pos[k];
649 }), duration);
650 };
651
652 return AnimationManager;
653 }();
654
655 var EventManager =
656 /*#__PURE__*/
657 function () {
658 function EventManager(axes) {
659 this.axes = axes;
660 }
661 /**
662 * This event is fired when a user holds an element on the screen of the device.
663 * @ko 사용자가 기기의 화면에 손을 대고 있을 때 발생하는 이벤트
664 * @name eg.Axes#hold
665 * @event
666 * @type {object}
667 * @property {Object.<string, number>} pos coordinate <ko>좌표 정보</ko>
668 * @property {Object} input The instance of inputType where the event occurred<ko>이벤트가 발생한 inputType 인스턴스</ko>
669 * @property {Object} inputEvent The event object received from inputType <ko>inputType으로 부터 받은 이벤트 객체</ko>
670 * @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>
671 *
672 * @example
673 * const axes = new eg.Axes({
674 * "x": {
675 * range: [0, 100]
676 * },
677 * "zoom": {
678 * range: [50, 30]
679 * }
680 * }).on("hold", function(event) {
681 * // event.pos
682 * // event.input
683 * // event.inputEvent
684 * // isTrusted
685 * });
686 */
687
688
689 var __proto = EventManager.prototype;
690
691 __proto.triggerHold = function (pos, option) {
692 var roundPos = this.getRoundPos(pos).roundPos;
693 this.axes.trigger("hold", {
694 pos: roundPos,
695 input: option.input || null,
696 inputEvent: option.event || null,
697 isTrusted: true
698 });
699 };
700 /**
701 * Specifies the coordinates to move after the 'change' event. It works when the holding value of the change event is true.
702 * @ko 'change' 이벤트 이후 이동할 좌표를 지정한다. change이벤트의 holding 값이 true일 경우에 동작한다
703 * @name set
704 * @function
705 * @param {Object.<string, number>} pos The coordinate to move to <ko>이동할 좌표</ko>
706 * @example
707 * const axes = new eg.Axes({
708 * "x": {
709 * range: [0, 100]
710 * },
711 * "zoom": {
712 * range: [50, 30]
713 * }
714 * }).on("change", function(event) {
715 * event.holding && event.set({x: 10});
716 * });
717 */
718
719 /** Specifies the animation coordinates to move after the 'release' or 'animationStart' events.
720 * @ko 'release' 또는 'animationStart' 이벤트 이후 이동할 좌표를 지정한다.
721 * @name setTo
722 * @function
723 * @param {Object.<string, number>} pos The coordinate to move to <ko>이동할 좌표</ko>
724 * @param {Number} [duration] Duration of the animation (unit: ms) <ko>애니메이션 진행 시간(단위: ms)</ko>
725 * @example
726 * const axes = new eg.Axes({
727 * "x": {
728 * range: [0, 100]
729 * },
730 * "zoom": {
731 * range: [50, 30]
732 * }
733 * }).on("animationStart", function(event) {
734 * event.setTo({x: 10}, 2000);
735 * });
736 */
737
738 /**
739 * This event is fired when a user release an element on the screen of the device.
740 * @ko 사용자가 기기의 화면에서 손을 뗐을 때 발생하는 이벤트
741 * @name eg.Axes#release
742 * @event
743 * @type {object}
744 * @property {Object.<string, number>} depaPos The coordinates when releasing an element<ko>손을 뗐을 때의 좌표 </ko>
745 * @property {Object.<string, number>} destPos The coordinates to move to after releasing an element<ko>손을 뗀 뒤에 이동할 좌표</ko>
746 * @property {Object.<string, number>} delta The movement variation of coordinate <ko>좌표의 변화량</ko>
747 * @property {Object} inputEvent The event object received from inputType <ko>inputType으로 부터 받은 이벤트 객체</ko>
748 * @property {Object} input The instance of inputType where the event occurred<ko>이벤트가 발생한 inputType 인스턴스</ko>
749 * @property {setTo} setTo Specifies the animation coordinates to move after the event <ko>이벤트 이후 이동할 애니메이션 좌표를 지정한다</ko>
750 * @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>
751 *
752 * @example
753 * const axes = new eg.Axes({
754 * "x": {
755 * range: [0, 100]
756 * },
757 * "zoom": {
758 * range: [50, 30]
759 * }
760 * }).on("release", function(event) {
761 * // event.depaPos
762 * // event.destPos
763 * // event.delta
764 * // event.input
765 * // event.inputEvent
766 * // event.setTo
767 * // event.isTrusted
768 *
769 * // if you want to change the animation coordinates to move after the 'release' event.
770 * event.setTo({x: 10}, 2000);
771 * });
772 */
773
774
775 __proto.triggerRelease = function (param) {
776 var _a = this.getRoundPos(param.destPos, param.depaPos),
777 roundPos = _a.roundPos,
778 roundDepa = _a.roundDepa;
779
780 param.destPos = roundPos;
781 param.depaPos = roundDepa;
782 param.setTo = this.createUserControll(param.destPos, param.duration);
783 this.axes.trigger("release", param);
784 };
785 /**
786 * This event is fired when coordinate changes.
787 * @ko 좌표가 변경됐을 때 발생하는 이벤트
788 * @name eg.Axes#change
789 * @event
790 * @type {object}
791 * @property {Object.<string, number>} pos The coordinate <ko>좌표</ko>
792 * @property {Object.<string, number>} delta The movement variation of coordinate <ko>좌표의 변화량</ko>
793 * @property {Boolean} holding Indicates whether a user holds an element on the screen of the device.<ko>사용자가 기기의 화면을 누르고 있는지 여부</ko>
794 * @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>
795 * @property {Object} inputEvent The event object received from inputType. If the value is changed by animation, it returns 'null'.<ko>inputType으로 부터 받은 이벤트 객체. 애니메이션에 의해 값이 변경될 경우에는 'null'을 반환한다.</ko>
796 * @property {set} set Specifies the coordinates to move after the event. It works when the holding value is true <ko>이벤트 이후 이동할 좌표를 지정한다. holding 값이 true일 경우에 동작한다.</ko>
797 * @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>
798 *
799 * @example
800 * const axes = new eg.Axes({
801 * "x": {
802 * range: [0, 100]
803 * },
804 * "zoom": {
805 * range: [50, 30]
806 * }
807 * }).on("change", function(event) {
808 * // event.pos
809 * // event.delta
810 * // event.input
811 * // event.inputEvent
812 * // event.holding
813 * // event.set
814 * // event.isTrusted
815 *
816 * // if you want to change the coordinates to move after the 'change' event.
817 * // it works when the holding value of the change event is true.
818 * event.holding && event.set({x: 10});
819 * });
820 */
821
822
823 __proto.triggerChange = function (pos, isAccurate, depaPos, option, holding) {
824 if (holding === void 0) {
825 holding = false;
826 }
827
828 var am = this.am;
829 var axm = am.axm;
830 var eventInfo = am.getEventInfo();
831
832 var _a = this.getRoundPos(pos, depaPos),
833 roundPos = _a.roundPos,
834 roundDepa = _a.roundDepa;
835
836 var moveTo = axm.moveTo(roundPos, roundDepa);
837 var inputEvent = option && option.event || eventInfo && eventInfo.event || null;
838 var param = {
839 pos: moveTo.pos,
840 delta: moveTo.delta,
841 holding: holding,
842 inputEvent: inputEvent,
843 isTrusted: !!inputEvent,
844 input: option && option.input || eventInfo && eventInfo.input || null,
845 set: inputEvent ? this.createUserControll(moveTo.pos) : function () {}
846 };
847 var result = this.axes.trigger("change", param);
848 inputEvent && axm.set(param.set()["destPos"]);
849 return result;
850 };
851 /**
852 * This event is fired when animation starts.
853 * @ko 에니메이션이 시작할 때 발생한다.
854 * @name eg.Axes#animationStart
855 * @event
856 * @type {object}
857 * @property {Object.<string, number>} depaPos The coordinates when animation starts<ko>애니메이션이 시작 되었을 때의 좌표 </ko>
858 * @property {Object.<string, number>} destPos The coordinates to move to. If you change this value, you can run the animation<ko>이동할 좌표. 이값을 변경하여 애니메이션을 동작시킬수 있다</ko>
859 * @property {Object.<string, number>} delta The movement variation of coordinate <ko>좌표의 변화량</ko>
860 * @property {Number} duration Duration of the animation (unit: ms). If you change this value, you can control the animation duration time.<ko>애니메이션 진행 시간(단위: ms). 이값을 변경하여 애니메이션의 이동시간을 조절할 수 있다.</ko>
861 * @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>
862 * @property {Object} inputEvent The event object received from inputType <ko>inputType으로 부터 받은 이벤트 객체</ko>
863 * @property {setTo} setTo Specifies the animation coordinates to move after the event <ko>이벤트 이후 이동할 애니메이션 좌표를 지정한다</ko>
864 * @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>
865 *
866 * @example
867 * const axes = new eg.Axes({
868 * "x": {
869 * range: [0, 100]
870 * },
871 * "zoom": {
872 * range: [50, 30]
873 * }
874 * }).on("release", function(event) {
875 * // event.depaPos
876 * // event.destPos
877 * // event.delta
878 * // event.input
879 * // event.inputEvent
880 * // event.setTo
881 * // event.isTrusted
882 *
883 * // if you want to change the animation coordinates to move after the 'animationStart' event.
884 * event.setTo({x: 10}, 2000);
885 * });
886 */
887
888
889 __proto.triggerAnimationStart = function (param) {
890 var _a = this.getRoundPos(param.destPos, param.depaPos),
891 roundPos = _a.roundPos,
892 roundDepa = _a.roundDepa;
893
894 param.destPos = roundPos;
895 param.depaPos = roundDepa;
896 param.setTo = this.createUserControll(param.destPos, param.duration);
897 return this.axes.trigger("animationStart", param);
898 };
899 /**
900 * This event is fired when animation ends.
901 * @ko 에니메이션이 끝났을 때 발생한다.
902 * @name eg.Axes#animationEnd
903 * @event
904 * @type {object}
905 * @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>
906 *
907 * @example
908 * const axes = new eg.Axes({
909 * "x": {
910 * range: [0, 100]
911 * },
912 * "zoom": {
913 * range: [50, 30]
914 * }
915 * }).on("animationEnd", function(event) {
916 * // event.isTrusted
917 * });
918 */
919
920
921 __proto.triggerAnimationEnd = function (isTrusted) {
922 if (isTrusted === void 0) {
923 isTrusted = false;
924 }
925
926 this.axes.trigger("animationEnd", {
927 isTrusted: isTrusted
928 });
929 };
930 /**
931 * This event is fired when all actions have been completed.
932 * @ko 에니메이션이 끝났을 때 발생한다.
933 * @name eg.Axes#finish
934 * @event
935 * @type {object}
936 * @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>
937 *
938 * @example
939 * const axes = new eg.Axes({
940 * "x": {
941 * range: [0, 100]
942 * },
943 * "zoom": {
944 * range: [50, 30]
945 * }
946 * }).on("finish", function(event) {
947 * // event.isTrusted
948 * });
949 */
950
951
952 __proto.triggerFinish = function (isTrusted) {
953 if (isTrusted === void 0) {
954 isTrusted = false;
955 }
956
957 this.axes.trigger("finish", {
958 isTrusted: isTrusted
959 });
960 };
961
962 __proto.createUserControll = function (pos, duration) {
963 if (duration === void 0) {
964 duration = 0;
965 } // to controll
966
967
968 var userControl = {
969 destPos: __assign({}, pos),
970 duration: duration
971 };
972 return function (toPos, userDuration) {
973 toPos && (userControl.destPos = __assign({}, toPos));
974 userDuration !== undefined && (userControl.duration = userDuration);
975 return userControl;
976 };
977 };
978
979 __proto.setAnimationManager = function (am) {
980 this.am = am;
981 };
982
983 __proto.destroy = function () {
984 this.axes.off();
985 };
986
987 __proto.getRoundPos = function (pos, depaPos) {
988 // round value if round exist
989 var roundUnit = this.axes.options.round; // if (round == null) {
990 // return {pos, depaPos}; // undefined, undefined
991 // }
992
993 return {
994 roundPos: roundNumbers(pos, roundUnit),
995 roundDepa: roundNumbers(depaPos, roundUnit)
996 };
997 };
998
999 return EventManager;
1000 }();
1001
1002 var InterruptManager =
1003 /*#__PURE__*/
1004 function () {
1005 function InterruptManager(options) {
1006 this.options = options;
1007 this._prevented = false; // check whether the animation event was prevented
1008 }
1009
1010 var __proto = InterruptManager.prototype;
1011
1012 __proto.isInterrupting = function () {
1013 // when interruptable is 'true', return value is always 'true'.
1014 return this.options.interruptable || this._prevented;
1015 };
1016
1017 __proto.isInterrupted = function () {
1018 return !this.options.interruptable && this._prevented;
1019 };
1020
1021 __proto.setInterrupt = function (prevented) {
1022 !this.options.interruptable && (this._prevented = prevented);
1023 };
1024
1025 return InterruptManager;
1026 }();
1027
1028 var AxisManager =
1029 /*#__PURE__*/
1030 function () {
1031 function AxisManager(axis, options) {
1032 var _this = this;
1033
1034 this.axis = axis;
1035 this.options = options;
1036
1037 this._complementOptions();
1038
1039 this._pos = Object.keys(this.axis).reduce(function (acc, v) {
1040 acc[v] = _this.axis[v].range[0];
1041 return acc;
1042 }, {});
1043 }
1044 /**
1045 * set up 'css' expression
1046 * @private
1047 */
1048
1049
1050 var __proto = AxisManager.prototype;
1051
1052 __proto._complementOptions = function () {
1053 var _this = this;
1054
1055 Object.keys(this.axis).forEach(function (axis) {
1056 _this.axis[axis] = __assign({
1057 range: [0, 100],
1058 bounce: [0, 0],
1059 circular: [false, false]
1060 }, _this.axis[axis]);
1061 ["bounce", "circular"].forEach(function (v) {
1062 var axisOption = _this.axis;
1063 var key = axisOption[axis][v];
1064
1065 if (/string|number|boolean/.test(typeof key)) {
1066 axisOption[axis][v] = [key, key];
1067 }
1068 });
1069 });
1070 };
1071
1072 __proto.getDelta = function (depaPos, destPos) {
1073 var fullDepaPos = this.get(depaPos);
1074 return map(this.get(destPos), function (v, k) {
1075 return v - fullDepaPos[k];
1076 });
1077 };
1078
1079 __proto.get = function (axes) {
1080 var _this = this;
1081
1082 if (axes && Array.isArray(axes)) {
1083 return axes.reduce(function (acc, v) {
1084 if (v && v in _this._pos) {
1085 acc[v] = _this._pos[v];
1086 }
1087
1088 return acc;
1089 }, {});
1090 } else {
1091 return __assign(__assign({}, this._pos), axes || {});
1092 }
1093 };
1094
1095 __proto.moveTo = function (pos, depaPos) {
1096 if (depaPos === void 0) {
1097 depaPos = this._pos;
1098 }
1099
1100 var delta = map(this._pos, function (v, key) {
1101 return key in pos && key in depaPos ? pos[key] - depaPos[key] : 0;
1102 });
1103 this.set(this.map(pos, function (v, opt) {
1104 return opt ? getCirculatedPos(v, opt.range, opt.circular) : 0;
1105 }));
1106 return {
1107 pos: __assign({}, this._pos),
1108 delta: delta
1109 };
1110 };
1111
1112 __proto.set = function (pos) {
1113 for (var k in pos) {
1114 if (k && k in this._pos) {
1115 this._pos[k] = pos[k];
1116 }
1117 }
1118 };
1119
1120 __proto.every = function (pos, callback) {
1121 var axisOptions = this.axis;
1122 return every(pos, function (value, key) {
1123 return callback(value, axisOptions[key], key);
1124 });
1125 };
1126
1127 __proto.filter = function (pos, callback) {
1128 var axisOptions = this.axis;
1129 return filter(pos, function (value, key) {
1130 return callback(value, axisOptions[key], key);
1131 });
1132 };
1133
1134 __proto.map = function (pos, callback) {
1135 var axisOptions = this.axis;
1136 return map(pos, function (value, key) {
1137 return callback(value, axisOptions[key], key);
1138 });
1139 };
1140
1141 __proto.isOutside = function (axes) {
1142 return !this.every(axes ? this.get(axes) : this._pos, function (v, opt) {
1143 return !isOutside(v, opt.range);
1144 });
1145 };
1146
1147 __proto.getAxisOptions = function (key) {
1148 return this.axis[key];
1149 };
1150
1151 return AxisManager;
1152 }();
1153
1154 var InputObserver =
1155 /*#__PURE__*/
1156 function () {
1157 function InputObserver(_a) {
1158 var options = _a.options,
1159 itm = _a.itm,
1160 em = _a.em,
1161 axm = _a.axm,
1162 am = _a.am;
1163 this.isOutside = false;
1164 this.moveDistance = null;
1165 this.isStopped = false;
1166 this.options = options;
1167 this.itm = itm;
1168 this.em = em;
1169 this.axm = axm;
1170 this.am = am;
1171 } // when move pointer is held in outside
1172
1173
1174 var __proto = InputObserver.prototype;
1175
1176 __proto.atOutside = function (pos) {
1177 var _this = this;
1178
1179 if (this.isOutside) {
1180 return this.axm.map(pos, function (v, opt) {
1181 var tn = opt.range[0] - opt.bounce[0];
1182 var tx = opt.range[1] + opt.bounce[1];
1183 return v > tx ? tx : v < tn ? tn : v;
1184 });
1185 } else {
1186 // when start pointer is held in inside
1187 // get a initialization slope value to prevent smooth animation.
1188 var initSlope_1 = this.am.easing(0.00001) / 0.00001;
1189 return this.axm.map(pos, function (v, opt) {
1190 var min = opt.range[0];
1191 var max = opt.range[1];
1192 var out = opt.bounce;
1193 var circular = opt.circular;
1194
1195 if (circular && (circular[0] || circular[1])) {
1196 return v;
1197 } else if (v < min) {
1198 // left
1199 return min - _this.am.easing((min - v) / (out[0] * initSlope_1)) * out[0];
1200 } else if (v > max) {
1201 // right
1202 return max + _this.am.easing((v - max) / (out[1] * initSlope_1)) * out[1];
1203 }
1204
1205 return v;
1206 });
1207 }
1208 };
1209
1210 __proto.get = function (input) {
1211 return this.axm.get(input.axes);
1212 };
1213
1214 __proto.hold = function (input, event) {
1215 if (this.itm.isInterrupted() || !input.axes.length) {
1216 return;
1217 }
1218
1219 var changeOption = {
1220 input: input,
1221 event: event
1222 };
1223 this.isStopped = false;
1224 this.itm.setInterrupt(true);
1225 this.am.grab(input.axes, changeOption);
1226 !this.moveDistance && this.em.triggerHold(this.axm.get(), changeOption);
1227 this.isOutside = this.axm.isOutside(input.axes);
1228 this.moveDistance = this.axm.get(input.axes);
1229 };
1230
1231 __proto.change = function (input, event, offset) {
1232 if (this.isStopped || !this.itm.isInterrupting() || this.axm.every(offset, function (v) {
1233 return v === 0;
1234 })) {
1235 return;
1236 }
1237
1238 var depaPos = this.moveDistance || this.axm.get(input.axes);
1239 var destPos; // for outside logic
1240
1241 destPos = map(depaPos, function (v, k) {
1242 return v + (offset[k] || 0);
1243 });
1244 this.moveDistance && (this.moveDistance = destPos); // from outside to inside
1245
1246 if (this.isOutside && this.axm.every(depaPos, function (v, opt) {
1247 return !isOutside(v, opt.range);
1248 })) {
1249 this.isOutside = false;
1250 }
1251
1252 depaPos = this.atOutside(depaPos);
1253 destPos = this.atOutside(destPos);
1254 var isCanceled = !this.em.triggerChange(destPos, false, depaPos, {
1255 input: input,
1256 event: event
1257 }, true);
1258
1259 if (isCanceled) {
1260 this.isStopped = true;
1261 this.moveDistance = null;
1262 this.am.finish(false);
1263 }
1264 };
1265
1266 __proto.release = function (input, event, offset, inputDuration) {
1267 if (this.isStopped || !this.itm.isInterrupting() || !this.moveDistance) {
1268 return;
1269 }
1270
1271 var pos = this.axm.get(input.axes);
1272 var depaPos = this.axm.get();
1273 var destPos = this.axm.get(this.axm.map(offset, function (v, opt, k) {
1274 if (opt.circular && (opt.circular[0] || opt.circular[1])) {
1275 return pos[k] + v;
1276 } else {
1277 return getInsidePosition(pos[k] + v, opt.range, opt.circular, opt.bounce);
1278 }
1279 }));
1280 var duration = this.am.getDuration(destPos, pos, inputDuration);
1281
1282 if (duration === 0) {
1283 destPos = __assign({}, depaPos);
1284 } // prepare params
1285
1286
1287 var param = {
1288 depaPos: depaPos,
1289 destPos: destPos,
1290 duration: duration,
1291 delta: this.axm.getDelta(depaPos, destPos),
1292 inputEvent: event,
1293 input: input,
1294 isTrusted: true
1295 };
1296 this.em.triggerRelease(param);
1297 this.moveDistance = null; // to contol
1298
1299 var userWish = this.am.getUserControll(param);
1300 var isEqual = equal(userWish.destPos, depaPos);
1301 var changeOption = {
1302 input: input,
1303 event: event
1304 };
1305
1306 if (isEqual || userWish.duration === 0) {
1307 !isEqual && this.em.triggerChange(userWish.destPos, false, depaPos, changeOption, true);
1308 this.itm.setInterrupt(false);
1309
1310 if (this.axm.isOutside()) {
1311 this.am.restore(changeOption);
1312 } else {
1313 this.em.triggerFinish(true);
1314 }
1315 } else {
1316 this.am.animateTo(userWish.destPos, userWish.duration, changeOption);
1317 }
1318 };
1319
1320 return InputObserver;
1321 }();
1322
1323 // export const DIRECTION_NONE = 1;
1324 var IOS_EDGE_THRESHOLD = 30;
1325 var IS_IOS_SAFARI = "ontouchstart" in win && getAgent().browser.name === "safari";
1326 var TRANSFORM = function () {
1327 if (typeof document === "undefined") {
1328 return "";
1329 }
1330
1331 var bodyStyle = (document.head || document.getElementsByTagName("head")[0]).style;
1332 var target = ["transform", "webkitTransform", "msTransform", "mozTransform"];
1333
1334 for (var i = 0, len = target.length; i < len; i++) {
1335 if (target[i] in bodyStyle) {
1336 return target[i];
1337 }
1338 }
1339
1340 return "";
1341 }();
1342
1343 /**
1344 * @typedef {Object} AxisOption The Axis information. The key of the axis specifies the name to use as the logical virtual coordinate system.
1345 * @ko 축 정보. 축의 키는 논리적인 가상 좌표계로 사용할 이름을 지정한다.
1346 * @property {Number[]} [range] The coordinate of range <ko>좌표 범위</ko>
1347 * @property {Number} [range.0=0] The coordinate of the minimum <ko>최소 좌표</ko>
1348 * @property {Number} [range.1=0] The coordinate of the maximum <ko>최대 좌표</ko>
1349 * @property {Number[]} [bounce] The size of bouncing area. The coordinates can exceed the coordinate area as much as the bouncing area based on user action. If the coordinates does not exceed the bouncing area when an element is dragged, the coordinates where bouncing effects are applied are retuned back into the coordinate area<ko>바운스 영역의 크기. 사용자의 동작에 따라 좌표가 좌표 영역을 넘어 바운스 영역의 크기만큼 더 이동할 수 있다. 사용자가 끌어다 놓는 동작을 했을 때 좌표가 바운스 영역에 있으면, 바운스 효과가 적용된 좌표가 다시 좌표 영역 안으로 들어온다</ko>
1350 * @property {Number} [bounce.0=0] The size of coordinate of the minimum area <ko>최소 좌표 바운스 영역의 크기</ko>
1351 * @property {Number} [bounce.1=0] The size of coordinate of the maximum area <ko>최대 좌표 바운스 영역의 크기</ko>
1352 * @property {Boolean[]} [circular] Indicates whether a circular element is available. If it is set to "true" and an element is dragged outside the coordinate area, the element will appear on the other side.<ko>순환 여부. 'true'로 설정한 방향의 좌표 영역 밖으로 엘리먼트가 이동하면 반대 방향에서 엘리먼트가 나타난다</ko>
1353 * @property {Boolean} [circular.0=false] Indicates whether to circulate to the coordinate of the minimum <ko>최소 좌표 방향의 순환 여부</ko>
1354 * @property {Boolean} [circular.1=false] Indicates whether to circulate to the coordinate of the maximum <ko>최대 좌표 방향의 순환 여부</ko>
1355 **/
1356
1357 /**
1358 * @typedef {Object} AxesOption The option object of the eg.Axes module
1359 * @ko eg.Axes 모듈의 옵션 객체
1360 * @property {Function} [easing=easing.easeOutCubic] The easing function to apply to an animation <ko>애니메이션에 적용할 easing 함수</ko>
1361 * @property {Number} [maximumDuration=Infinity] Maximum duration of the animation <ko>가속도에 의해 애니메이션이 동작할 때의 최대 좌표 이동 시간</ko>
1362 * @property {Number} [minimumDuration=0] Minimum duration of the animation <ko>가속도에 의해 애니메이션이 동작할 때의 최소 좌표 이동 시간</ko>
1363 * @property {Number} [deceleration=0.0006] Deceleration of the animation where acceleration is manually enabled by user. A higher value indicates shorter running time. <ko>사용자의 동작으로 가속도가 적용된 애니메이션의 감속도. 값이 높을수록 애니메이션 실행 시간이 짧아진다</ko>
1364 * @property {Boolean} [interruptable=true] Indicates whether an animation is interruptible.<br>- true: It can be paused or stopped by user action or the API.<br>- false: It cannot be paused or stopped by user action or the API while it is running.<ko>진행 중인 애니메이션 중지 가능 여부.<br>- true: 사용자의 동작이나 API로 애니메이션을 중지할 수 있다.<br>- false: 애니메이션이 진행 중일 때는 사용자의 동작이나 API가 적용되지 않는다</ko>
1365 * @property {Number} [round = null] Rounding unit. For example, 0.1 rounds to 0.1 decimal point(6.1234 => 6.1), 5 rounds to 5 (93 => 95) <br>[Details](https://github.com/naver/egjs-axes/wiki/round-option)<ko>반올림 단위. 예를 들어 0.1 은 소숫점 0.1 까지 반올림(6.1234 => 6.1), 5 는 5 단위로 반올림(93 => 95).<br>[상세내용](https://github.com/naver/egjs-axes/wiki/round-option)</ko>
1366 **/
1367
1368 /**
1369 * @class eg.Axes
1370 * @classdesc 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.
1371 * @ko 터치 입력 장치나 마우스와 같은 다양한 입력 장치를 통해 전달 받은 사용자의 동작을 논리적인 가상 좌표로 변경하는 모듈이다. 사용자 동작에 반응하는 UI를 손쉽게 만들수 있다.
1372 * @extends eg.Component
1373 *
1374 * @param {Object.<string, AxisOption>} axis Axis information managed by eg.Axes. The key of the axis specifies the name to use as the logical virtual coordinate system. <ko>eg.Axes가 관리하는 축 정보. 축의 키는 논리적인 가상 좌표계로 사용할 이름을 지정한다.</ko>
1375 * @param {AxesOption} [options] The option object of the eg.Axes module<ko>eg.Axes 모듈의 옵션 객체</ko>
1376 * @param {Object.<string, number>} [startPos] The coordinates to be moved when creating an instance. not triggering change event.<ko>인스턴스 생성시 이동할 좌표, change 이벤트는 발생하지 않음.</ko>
1377 *
1378 * @support {"ie": "10+", "ch" : "latest", "ff" : "latest", "sf" : "latest", "edge" : "latest", "ios" : "7+", "an" : "2.3+ (except 3.x)"}
1379 * @example
1380 *
1381 * // 1. Initialize eg.Axes
1382 * const axes = new eg.Axes({
1383 * something1: {
1384 * range: [0, 150],
1385 * bounce: 50
1386 * },
1387 * something2: {
1388 * range: [0, 200],
1389 * bounce: 100
1390 * },
1391 * somethingN: {
1392 * range: [1, 10],
1393 * }
1394 * }, {
1395 * deceleration : 0.0024
1396 * });
1397 *
1398 * // 2. attach event handler
1399 * axes.on({
1400 * "hold" : function(evt) {
1401 * },
1402 * "release" : function(evt) {
1403 * },
1404 * "animationStart" : function(evt) {
1405 * },
1406 * "animationEnd" : function(evt) {
1407 * },
1408 * "change" : function(evt) {
1409 * }
1410 * });
1411 *
1412 * // 3. Initialize inputTypes
1413 * const panInputArea = new eg.Axes.PanInput("#area", {
1414 * scale: [0.5, 1]
1415 * });
1416 * const panInputHmove = new eg.Axes.PanInput("#hmove");
1417 * const panInputVmove = new eg.Axes.PanInput("#vmove");
1418 * const pinchInputArea = new eg.Axes.PinchInput("#area", {
1419 * scale: 1.5
1420 * });
1421 *
1422 * // 4. Connect eg.Axes and InputTypes
1423 * // [PanInput] When the mouse or touchscreen is down and moved.
1424 * // Connect the 'something2' axis to the mouse or touchscreen x position and
1425 * // connect the 'somethingN' axis to the mouse or touchscreen y position.
1426 * axes.connect(["something2", "somethingN"], panInputArea); // or axes.connect("something2 somethingN", panInputArea);
1427 *
1428 * // Connect only one 'something1' axis to the mouse or touchscreen x position.
1429 * axes.connect(["something1"], panInputHmove); // or axes.connect("something1", panInputHmove);
1430 *
1431 * // Connect only one 'something2' axis to the mouse or touchscreen y position.
1432 * axes.connect(["", "something2"], panInputVmove); // or axes.connect(" something2", panInputVmove);
1433 *
1434 * // [PinchInput] Connect 'something2' axis when two pointers are moving toward (zoom-in) or away from each other (zoom-out).
1435 * axes.connect("something2", pinchInputArea);
1436 */
1437
1438 var Axes =
1439 /*#__PURE__*/
1440 function (_super) {
1441 __extends(Axes, _super);
1442
1443 function Axes(axis, options, startPos) {
1444 if (axis === void 0) {
1445 axis = {};
1446 }
1447
1448 if (options === void 0) {
1449 options = {};
1450 }
1451
1452 var _this = _super.call(this) || this;
1453
1454 _this.axis = axis;
1455 _this._inputs = [];
1456 _this.options = __assign({
1457 easing: function easeOutCubic(x) {
1458 return 1 - Math.pow(1 - x, 3);
1459 },
1460 interruptable: true,
1461 maximumDuration: Infinity,
1462 minimumDuration: 0,
1463 deceleration: 0.0006,
1464 round: null
1465 }, options);
1466 _this.itm = new InterruptManager(_this.options);
1467 _this.axm = new AxisManager(_this.axis, _this.options);
1468 _this.em = new EventManager(_this);
1469 _this.am = new AnimationManager(_this);
1470 _this.io = new InputObserver(_this);
1471
1472 _this.em.setAnimationManager(_this.am);
1473
1474 startPos && _this.em.triggerChange(startPos);
1475 return _this;
1476 }
1477 /**
1478 * Connect the axis of eg.Axes to the inputType.
1479 * @ko eg.Axes의 축과 inputType을 연결한다
1480 * @method eg.Axes#connect
1481 * @param {(String[]|String)} axes The name of the axis to associate with inputType <ko>inputType과 연결할 축의 이름</ko>
1482 * @param {Object} inputType The inputType instance to associate with the axis of eg.Axes <ko>eg.Axes의 축과 연결할 inputType 인스턴스<ko>
1483 * @return {eg.Axes} An instance of a module itself <ko>모듈 자신의 인스턴스</ko>
1484 * @example
1485 * const axes = new eg.Axes({
1486 * "x": {
1487 * range: [0, 100]
1488 * },
1489 * "xOther": {
1490 * range: [-100, 100]
1491 * }
1492 * });
1493 *
1494 * axes.connect("x", new eg.Axes.PanInput("#area1"))
1495 * .connect("x xOther", new eg.Axes.PanInput("#area2"))
1496 * .connect(" xOther", new eg.Axes.PanInput("#area3"))
1497 * .connect(["x"], new eg.Axes.PanInput("#area4"))
1498 * .connect(["xOther", "x"], new eg.Axes.PanInput("#area5"))
1499 * .connect(["", "xOther"], new eg.Axes.PanInput("#area6"));
1500 */
1501
1502
1503 var __proto = Axes.prototype;
1504
1505 __proto.connect = function (axes, inputType) {
1506 var mapped;
1507
1508 if (typeof axes === "string") {
1509 mapped = axes.split(" ");
1510 } else {
1511 mapped = axes.concat();
1512 } // check same instance
1513
1514
1515 if (~this._inputs.indexOf(inputType)) {
1516 this.disconnect(inputType);
1517 } // check same element in hammer type for share
1518
1519
1520 if ("hammer" in inputType) {
1521 var targets = this._inputs.filter(function (v) {
1522 return v.hammer && v.element === inputType.element;
1523 });
1524
1525 if (targets.length) {
1526 inputType.hammer = targets[0].hammer;
1527 }
1528 }
1529
1530 inputType.mapAxes(mapped);
1531 inputType.connect(this.io);
1532
1533 this._inputs.push(inputType);
1534
1535 return this;
1536 };
1537 /**
1538 * Disconnect the axis of eg.Axes from the inputType.
1539 * @ko eg.Axes의 축과 inputType의 연결을 끊는다.
1540 * @method eg.Axes#disconnect
1541 * @param {Object} [inputType] An inputType instance associated with the axis of eg.Axes <ko>eg.Axes의 축과 연결한 inputType 인스턴스<ko>
1542 * @return {eg.Axes} An instance of a module itself <ko>모듈 자신의 인스턴스</ko>
1543 * @example
1544 * const axes = new eg.Axes({
1545 * "x": {
1546 * range: [0, 100]
1547 * },
1548 * "xOther": {
1549 * range: [-100, 100]
1550 * }
1551 * });
1552 *
1553 * const input1 = new eg.Axes.PanInput("#area1");
1554 * const input2 = new eg.Axes.PanInput("#area2");
1555 * const input3 = new eg.Axes.PanInput("#area3");
1556 *
1557 * axes.connect("x", input1);
1558 * .connect("x xOther", input2)
1559 * .connect(["xOther", "x"], input3);
1560 *
1561 * axes.disconnect(input1); // disconnects input1
1562 * axes.disconnect(); // disconnects all of them
1563 */
1564
1565
1566 __proto.disconnect = function (inputType) {
1567 if (inputType) {
1568 var index = this._inputs.indexOf(inputType);
1569
1570 if (index >= 0) {
1571 this._inputs[index].disconnect();
1572
1573 this._inputs.splice(index, 1);
1574 }
1575 } else {
1576 this._inputs.forEach(function (v) {
1577 return v.disconnect();
1578 });
1579
1580 this._inputs = [];
1581 }
1582
1583 return this;
1584 };
1585 /**
1586 * Returns the current position of the coordinates.
1587 * @ko 좌표의 현재 위치를 반환한다
1588 * @method eg.Axes#get
1589 * @param {Object} [axes] The names of the axis <ko>축 이름들</ko>
1590 * @return {Object.<string, number>} Axis coordinate information <ko>축 좌표 정보</ko>
1591 * @example
1592 * const axes = new eg.Axes({
1593 * "x": {
1594 * range: [0, 100]
1595 * },
1596 * "xOther": {
1597 * range: [-100, 100]
1598 * },
1599 * "zoom": {
1600 * range: [50, 30]
1601 * }
1602 * });
1603 *
1604 * axes.get(); // {"x": 0, "xOther": -100, "zoom": 50}
1605 * axes.get(["x", "zoom"]); // {"x": 0, "zoom": 50}
1606 */
1607
1608
1609 __proto.get = function (axes) {
1610 return this.axm.get(axes);
1611 };
1612 /**
1613 * Moves an axis to specific coordinates.
1614 * @ko 좌표를 이동한다.
1615 * @method eg.Axes#setTo
1616 * @param {Object.<string, number>} pos The coordinate to move to <ko>이동할 좌표</ko>
1617 * @param {Number} [duration=0] Duration of the animation (unit: ms) <ko>애니메이션 진행 시간(단위: ms)</ko>
1618 * @return {eg.Axes} An instance of a module itself <ko>모듈 자신의 인스턴스</ko>
1619 * @example
1620 * const axes = new eg.Axes({
1621 * "x": {
1622 * range: [0, 100]
1623 * },
1624 * "xOther": {
1625 * range: [-100, 100]
1626 * },
1627 * "zoom": {
1628 * range: [50, 30]
1629 * }
1630 * });
1631 *
1632 * axes.setTo({"x": 30, "zoom": 60});
1633 * axes.get(); // {"x": 30, "xOther": -100, "zoom": 60}
1634 *
1635 * axes.setTo({"x": 100, "xOther": 60}, 1000); // animatation
1636 *
1637 * // after 1000 ms
1638 * axes.get(); // {"x": 100, "xOther": 60, "zoom": 60}
1639 */
1640
1641
1642 __proto.setTo = function (pos, duration) {
1643 if (duration === void 0) {
1644 duration = 0;
1645 }
1646
1647 this.am.setTo(pos, duration);
1648 return this;
1649 };
1650 /**
1651 * Moves an axis from the current coordinates to specific coordinates.
1652 * @ko 현재 좌표를 기준으로 좌표를 이동한다.
1653 * @method eg.Axes#setBy
1654 * @param {Object.<string, number>} pos The coordinate to move to <ko>이동할 좌표</ko>
1655 * @param {Number} [duration=0] Duration of the animation (unit: ms) <ko>애니메이션 진행 시간(단위: ms)</ko>
1656 * @return {eg.Axes} An instance of a module itself <ko>모듈 자신의 인스턴스</ko>
1657 * @example
1658 * const axes = new eg.Axes({
1659 * "x": {
1660 * range: [0, 100]
1661 * },
1662 * "xOther": {
1663 * range: [-100, 100]
1664 * },
1665 * "zoom": {
1666 * range: [50, 30]
1667 * }
1668 * });
1669 *
1670 * axes.setBy({"x": 30, "zoom": 10});
1671 * axes.get(); // {"x": 30, "xOther": -100, "zoom": 60}
1672 *
1673 * axes.setBy({"x": 70, "xOther": 60}, 1000); // animatation
1674 *
1675 * // after 1000 ms
1676 * axes.get(); // {"x": 100, "xOther": -40, "zoom": 60}
1677 */
1678
1679
1680 __proto.setBy = function (pos, duration) {
1681 if (duration === void 0) {
1682 duration = 0;
1683 }
1684
1685 this.am.setBy(pos, duration);
1686 return this;
1687 };
1688 /**
1689 * Returns whether there is a coordinate in the bounce area of ​​the target axis.
1690 * @ko 대상 축 중 bounce영역에 좌표가 존재하는지를 반환한다
1691 * @method eg.Axes#isBounceArea
1692 * @param {Object} [axes] The names of the axis <ko>축 이름들</ko>
1693 * @return {Boolen} Whether the bounce area exists. <ko>bounce 영역 존재 여부</ko>
1694 * @example
1695 * const axes = new eg.Axes({
1696 * "x": {
1697 * range: [0, 100]
1698 * },
1699 * "xOther": {
1700 * range: [-100, 100]
1701 * },
1702 * "zoom": {
1703 * range: [50, 30]
1704 * }
1705 * });
1706 *
1707 * axes.isBounceArea(["x"]);
1708 * axes.isBounceArea(["x", "zoom"]);
1709 * axes.isBounceArea();
1710 */
1711
1712
1713 __proto.isBounceArea = function (axes) {
1714 return this.axm.isOutside(axes);
1715 };
1716 /**
1717 * Destroys properties, and events used in a module and disconnect all connections to inputTypes.
1718 * @ko 모듈에 사용한 속성, 이벤트를 해제한다. 모든 inputType과의 연결을 끊는다.
1719 * @method eg.Axes#destroy
1720 */
1721
1722
1723 __proto.destroy = function () {
1724 this.disconnect();
1725 this.em.destroy();
1726 };
1727 /**
1728 * Version info string
1729 * @ko 버전정보 문자열
1730 * @name VERSION
1731 * @static
1732 * @type {String}
1733 * @example
1734 * eg.Axes.VERSION; // ex) 3.3.3
1735 * @memberof eg.Axes
1736 */
1737
1738
1739 Axes.VERSION = "2.8.0";
1740 /**
1741 * @name eg.Axes.TRANSFORM
1742 * @desc Returns the transform attribute with CSS vendor prefixes.
1743 * @ko CSS vendor prefixes를 붙인 transform 속성을 반환한다.
1744 *
1745 * @constant
1746 * @type {String}
1747 * @example
1748 * eg.Axes.TRANSFORM; // "transform" or "webkitTransform"
1749 */
1750
1751 Axes.TRANSFORM = TRANSFORM;
1752 /**
1753 * @name eg.Axes.DIRECTION_NONE
1754 * @constant
1755 * @type {Number}
1756 */
1757
1758 Axes.DIRECTION_NONE = hammerjs.DIRECTION_NONE;
1759 /**
1760 * @name eg.Axes.DIRECTION_LEFT
1761 * @constant
1762 * @type {Number}
1763 */
1764
1765 Axes.DIRECTION_LEFT = hammerjs.DIRECTION_LEFT;
1766 /**
1767 * @name eg.Axes.DIRECTION_RIGHT
1768 * @constant
1769 * @type {Number}
1770 */
1771
1772 Axes.DIRECTION_RIGHT = hammerjs.DIRECTION_RIGHT;
1773 /**
1774 * @name eg.Axes.DIRECTION_UP
1775 * @constant
1776 * @type {Number}
1777 */
1778
1779 Axes.DIRECTION_UP = hammerjs.DIRECTION_UP;
1780 /**
1781 * @name eg.Axes.DIRECTION_DOWN
1782 * @constant
1783 * @type {Number}
1784 */
1785
1786 Axes.DIRECTION_DOWN = hammerjs.DIRECTION_DOWN;
1787 /**
1788 * @name eg.Axes.DIRECTION_HORIZONTAL
1789 * @constant
1790 * @type {Number}
1791 */
1792
1793 Axes.DIRECTION_HORIZONTAL = hammerjs.DIRECTION_HORIZONTAL;
1794 /**
1795 * @name eg.Axes.DIRECTION_VERTICAL
1796 * @constant
1797 * @type {Number}
1798 */
1799
1800 Axes.DIRECTION_VERTICAL = hammerjs.DIRECTION_VERTICAL;
1801 /**
1802 * @name eg.Axes.DIRECTION_ALL
1803 * @constant
1804 * @type {Number}
1805 */
1806
1807 Axes.DIRECTION_ALL = hammerjs.DIRECTION_ALL;
1808 return Axes;
1809 }(Component);
1810
1811 var SUPPORT_POINTER_EVENTS = "PointerEvent" in win || "MSPointerEvent" in win;
1812 var SUPPORT_TOUCH = ("ontouchstart" in win);
1813 var UNIQUEKEY = "_EGJS_AXES_INPUTTYPE_";
1814 function toAxis(source, offset) {
1815 return offset.reduce(function (acc, v, i) {
1816 if (source[i]) {
1817 acc[source[i]] = v;
1818 }
1819
1820 return acc;
1821 }, {});
1822 }
1823 function createHammer(element, options) {
1824 try {
1825 // create Hammer
1826 return new hammerjs.Manager(element, __assign({}, options));
1827 } catch (e) {
1828 return null;
1829 }
1830 }
1831 function convertInputType(inputType) {
1832 if (inputType === void 0) {
1833 inputType = [];
1834 }
1835
1836 var hasTouch = false;
1837 var hasMouse = false;
1838 var hasPointer = false;
1839 inputType.forEach(function (v) {
1840 switch (v) {
1841 case "mouse":
1842 hasMouse = true;
1843 break;
1844
1845 case "touch":
1846 hasTouch = SUPPORT_TOUCH;
1847 break;
1848
1849 case "pointer":
1850 hasPointer = SUPPORT_POINTER_EVENTS;
1851 // no default
1852 }
1853 });
1854
1855 if (hasPointer) {
1856 return hammerjs.PointerEventInput;
1857 } else if (hasTouch && hasMouse) {
1858 return hammerjs.TouchMouseInput;
1859 } else if (hasTouch) {
1860 return hammerjs.TouchInput;
1861 } else if (hasMouse) {
1862 return hammerjs.MouseInput;
1863 }
1864
1865 return null;
1866 }
1867
1868 function getDirectionByAngle(angle, thresholdAngle) {
1869 if (thresholdAngle < 0 || thresholdAngle > 90) {
1870 return hammerjs.DIRECTION_NONE;
1871 }
1872
1873 var toAngle = Math.abs(angle);
1874 return toAngle > thresholdAngle && toAngle < 180 - thresholdAngle ? hammerjs.DIRECTION_VERTICAL : hammerjs.DIRECTION_HORIZONTAL;
1875 }
1876 function getNextOffset(speeds, deceleration) {
1877 var normalSpeed = Math.sqrt(speeds[0] * speeds[0] + speeds[1] * speeds[1]);
1878 var duration = Math.abs(normalSpeed / -deceleration);
1879 return [speeds[0] / 2 * duration, speeds[1] / 2 * duration];
1880 }
1881 function useDirection(checkType, direction, userDirection) {
1882 if (userDirection) {
1883 return !!(direction === hammerjs.DIRECTION_ALL || direction & checkType && userDirection & checkType);
1884 } else {
1885 return !!(direction & checkType);
1886 }
1887 }
1888 /**
1889 * @typedef {Object} PanInputOption The option object of the eg.Axes.PanInput module.
1890 * @ko eg.Axes.PanInput 모듈의 옵션 객체
1891 * @property {String[]} [inputType=["touch","mouse", "pointer"]] Types of input devices.<br>- touch: Touch screen<br>- mouse: Mouse <ko>입력 장치 종류.<br>- touch: 터치 입력 장치<br>- mouse: 마우스</ko>
1892 * @property {Number[]} [scale] Coordinate scale that a user can move<ko>사용자의 동작으로 이동하는 좌표의 배율</ko>
1893 * @property {Number} [scale.0=1] horizontal axis scale <ko>수평축 배율</ko>
1894 * @property {Number} [scale.1=1] vertical axis scale <ko>수직축 배율</ko>
1895 * @property {Number} [thresholdAngle=45] The threshold value that determines whether user action is horizontal or vertical (0~90) <ko>사용자의 동작이 가로 방향인지 세로 방향인지 판단하는 기준 각도(0~90)</ko>
1896 * @property {Number} [threshold=0] Minimal pan distance required before recognizing <ko>사용자의 Pan 동작을 인식하기 위해산 최소한의 거리</ko>
1897 * @property {Number} [iOSEdgeSwipeThreshold=30] Area (px) that can go to the next page when swiping the right edge in iOS safari <ko>iOS Safari에서 오른쪽 엣지를 스와이프 하는 경우 다음 페이지로 넘어갈 수 있는 영역(px)</ko>
1898 * @property {Object} [hammerManagerOptions={cssProps: {userSelect: "none",touchSelect: "none",touchCallout: "none",userDrag: "none"}] Options of Hammer.Manager <ko>Hammer.Manager의 옵션</ko>
1899 **/
1900
1901 /**
1902 * @class eg.Axes.PanInput
1903 * @classdesc A module that passes the amount of change to eg.Axes when the mouse or touchscreen is down and moved. use less than two axes.
1904 * @ko 마우스나 터치 스크린을 누르고 움직일때의 변화량을 eg.Axes에 전달하는 모듈. 두개 이하의 축을 사용한다.
1905 *
1906 * @example
1907 * const pan = new eg.Axes.PanInput("#area", {
1908 * inputType: ["touch"],
1909 * scale: [1, 1.3],
1910 * });
1911 *
1912 * // Connect the 'something2' axis to the mouse or touchscreen x position when the mouse or touchscreen is down and moved.
1913 * // Connect the 'somethingN' axis to the mouse or touchscreen y position when the mouse or touchscreen is down and moved.
1914 * axes.connect(["something2", "somethingN"], pan); // or axes.connect("something2 somethingN", pan);
1915 *
1916 * // Connect only one 'something1' axis to the mouse or touchscreen x position when the mouse or touchscreen is down and moved.
1917 * axes.connect(["something1"], pan); // or axes.connect("something1", pan);
1918 *
1919 * // Connect only one 'something2' axis to the mouse or touchscreen y position when the mouse or touchscreen is down and moved.
1920 * axes.connect(["", "something2"], pan); // or axes.connect(" something2", pan);
1921 *
1922 * @param {HTMLElement|String|jQuery} element An element to use the eg.Axes.PanInput module <ko>eg.Axes.PanInput 모듈을 사용할 엘리먼트</ko>
1923 * @param {PanInputOption} [options] The option object of the eg.Axes.PanInput module<ko>eg.Axes.PanInput 모듈의 옵션 객체</ko>
1924 */
1925
1926 var PanInput =
1927 /*#__PURE__*/
1928 function () {
1929 function PanInput(el, options) {
1930 this.axes = [];
1931 this.hammer = null;
1932 this.element = null;
1933 this.panRecognizer = null;
1934 this.isRightEdge = false;
1935 this.rightEdgeTimer = 0;
1936 this.panFlag = false;
1937 /**
1938 * Hammer helps you add support for touch gestures to your page
1939 *
1940 * @external Hammer
1941 * @see {@link http://hammerjs.github.io|Hammer.JS}
1942 * @see {@link http://hammerjs.github.io/jsdoc/Hammer.html|Hammer.JS API documents}
1943 * @see Hammer.JS applies specific CSS properties by {@link http://hammerjs.github.io/jsdoc/Hammer.defaults.cssProps.html|default} when creating an instance. The eg.Axes module removes all default CSS properties provided by Hammer.JS
1944 */
1945
1946 if (typeof hammerjs.Manager === "undefined") {
1947 throw new Error("The Hammerjs must be loaded before eg.Axes.PanInput.\nhttp://hammerjs.github.io/");
1948 }
1949
1950 this.element = $(el);
1951 this.options = __assign({
1952 inputType: ["touch", "mouse", "pointer"],
1953 scale: [1, 1],
1954 thresholdAngle: 45,
1955 threshold: 0,
1956 iOSEdgeSwipeThreshold: IOS_EDGE_THRESHOLD,
1957 releaseOnScroll: false,
1958 hammerManagerOptions: {
1959 // css properties were removed due to usablility issue
1960 // http://hammerjs.github.io/jsdoc/Hammer.defaults.cssProps.html
1961 cssProps: {
1962 userSelect: "none",
1963 touchSelect: "none",
1964 touchCallout: "none",
1965 userDrag: "none"
1966 }
1967 }
1968 }, options);
1969 this.onHammerInput = this.onHammerInput.bind(this);
1970 this.onPanmove = this.onPanmove.bind(this);
1971 this.onPanend = this.onPanend.bind(this);
1972 }
1973
1974 var __proto = PanInput.prototype;
1975
1976 __proto.mapAxes = function (axes) {
1977 var useHorizontal = !!axes[0];
1978 var useVertical = !!axes[1];
1979
1980 if (useHorizontal && useVertical) {
1981 this._direction = hammerjs.DIRECTION_ALL;
1982 } else if (useHorizontal) {
1983 this._direction = hammerjs.DIRECTION_HORIZONTAL;
1984 } else if (useVertical) {
1985 this._direction = hammerjs.DIRECTION_VERTICAL;
1986 } else {
1987 this._direction = hammerjs.DIRECTION_NONE;
1988 }
1989
1990 this.axes = axes;
1991 };
1992
1993 __proto.connect = function (observer) {
1994 var hammerOption = {
1995 direction: this._direction,
1996 threshold: this.options.threshold
1997 };
1998
1999 if (this.hammer) {
2000 // for sharing hammer instance.
2001 // hammer remove previous PanRecognizer.
2002 this.removeRecognizer();
2003 this.dettachEvent();
2004 } else {
2005 var keyValue = this.element[UNIQUEKEY];
2006
2007 if (!keyValue) {
2008 keyValue = String(Math.round(Math.random() * new Date().getTime()));
2009 }
2010
2011 var inputClass = convertInputType(this.options.inputType);
2012
2013 if (!inputClass) {
2014 throw new Error("Wrong inputType parameter!");
2015 }
2016
2017 this.hammer = createHammer(this.element, __assign({
2018 inputClass: inputClass
2019 }, this.options.hammerManagerOptions));
2020 this.element[UNIQUEKEY] = keyValue;
2021 }
2022
2023 this.panRecognizer = new hammerjs.Pan(hammerOption);
2024 this.hammer.add(this.panRecognizer);
2025 this.attachEvent(observer);
2026 return this;
2027 };
2028
2029 __proto.disconnect = function () {
2030 this.removeRecognizer();
2031
2032 if (this.hammer) {
2033 this.dettachEvent();
2034 }
2035
2036 this._direction = hammerjs.DIRECTION_NONE;
2037 return this;
2038 };
2039 /**
2040 * Destroys elements, properties, and events used in a module.
2041 * @ko 모듈에 사용한 엘리먼트와 속성, 이벤트를 해제한다.
2042 * @method eg.Axes.PanInput#destroy
2043 */
2044
2045
2046 __proto.destroy = function () {
2047 this.disconnect();
2048
2049 if (this.hammer && this.hammer.recognizers.length === 0) {
2050 this.hammer.destroy();
2051 }
2052
2053 delete this.element[UNIQUEKEY];
2054 this.element = null;
2055 this.hammer = null;
2056 };
2057 /**
2058 * Enables input devices
2059 * @ko 입력 장치를 사용할 수 있게 한다
2060 * @method eg.Axes.PanInput#enable
2061 * @return {eg.Axes.PanInput} An instance of a module itself <ko>모듈 자신의 인스턴스</ko>
2062 */
2063
2064
2065 __proto.enable = function () {
2066 this.hammer && (this.hammer.get("pan").options.enable = true);
2067 return this;
2068 };
2069 /**
2070 * Disables input devices
2071 * @ko 입력 장치를 사용할 수 없게 한다.
2072 * @method eg.Axes.PanInput#disable
2073 * @return {eg.Axes.PanInput} An instance of a module itself <ko>모듈 자신의 인스턴스</ko>
2074 */
2075
2076
2077 __proto.disable = function () {
2078 this.hammer && (this.hammer.get("pan").options.enable = false);
2079 return this;
2080 };
2081 /**
2082 * Returns whether to use an input device
2083 * @ko 입력 장치를 사용 여부를 반환한다.
2084 * @method eg.Axes.PanInput#isEnable
2085 * @return {Boolean} Whether to use an input device <ko>입력장치 사용여부</ko>
2086 */
2087
2088
2089 __proto.isEnable = function () {
2090 return !!(this.hammer && this.hammer.get("pan").options.enable);
2091 };
2092
2093 __proto.removeRecognizer = function () {
2094 if (this.hammer && this.panRecognizer) {
2095 this.hammer.remove(this.panRecognizer);
2096 this.panRecognizer = null;
2097 }
2098 };
2099
2100 __proto.onHammerInput = function (event) {
2101 if (this.isEnable()) {
2102 if (event.isFirst) {
2103 this.panFlag = false;
2104
2105 if (event.srcEvent.cancelable !== false) {
2106 var edgeThreshold = this.options.iOSEdgeSwipeThreshold;
2107 this.observer.hold(this, event);
2108 this.isRightEdge = IS_IOS_SAFARI && event.center.x > window.innerWidth - edgeThreshold;
2109 this.panFlag = true;
2110 }
2111 } else if (event.isFinal) {
2112 this.onPanend(event);
2113 }
2114 }
2115 };
2116
2117 __proto.onPanmove = function (event) {
2118 var _this = this;
2119
2120 if (!this.panFlag) {
2121 return;
2122 }
2123
2124 var _a = this.options,
2125 iOSEdgeSwipeThreshold = _a.iOSEdgeSwipeThreshold,
2126 releaseOnScroll = _a.releaseOnScroll;
2127 var userDirection = getDirectionByAngle(event.angle, this.options.thresholdAngle); // not support offset properties in Hammerjs - start
2128
2129 var prevInput = this.hammer.session.prevInput;
2130
2131 if (releaseOnScroll && !event.srcEvent.cancelable) {
2132 this.onPanend(__assign(__assign({}, event), {
2133 velocityX: 0,
2134 velocityY: 0,
2135 offsetX: 0,
2136 offsetY: 0
2137 }));
2138 return;
2139 }
2140
2141 if (prevInput && IS_IOS_SAFARI) {
2142 var swipeLeftToRight = event.center.x < 0;
2143
2144 if (swipeLeftToRight) {
2145 // iOS swipe left => right
2146 this.onPanend(__assign(__assign({}, prevInput), {
2147 velocityX: 0,
2148 velocityY: 0,
2149 offsetX: 0,
2150 offsetY: 0
2151 }));
2152 return;
2153 } else if (this.isRightEdge) {
2154 clearTimeout(this.rightEdgeTimer); // - is right to left
2155
2156 var swipeRightToLeft = event.deltaX < -iOSEdgeSwipeThreshold;
2157
2158 if (swipeRightToLeft) {
2159 this.isRightEdge = false;
2160 } else {
2161 // iOS swipe right => left
2162 this.rightEdgeTimer = window.setTimeout(function () {
2163 _this.onPanend(__assign(__assign({}, prevInput), {
2164 velocityX: 0,
2165 velocityY: 0,
2166 offsetX: 0,
2167 offsetY: 0
2168 }));
2169 }, 100);
2170 }
2171 }
2172 }
2173 /* eslint-disable no-param-reassign */
2174
2175
2176 if (prevInput) {
2177 event.offsetX = event.deltaX - prevInput.deltaX;
2178 event.offsetY = event.deltaY - prevInput.deltaY;
2179 } else {
2180 event.offsetX = 0;
2181 event.offsetY = 0;
2182 }
2183
2184 var offset = this.getOffset([event.offsetX, event.offsetY], [useDirection(hammerjs.DIRECTION_HORIZONTAL, this._direction, userDirection), useDirection(hammerjs.DIRECTION_VERTICAL, this._direction, userDirection)]);
2185 var prevent = offset.some(function (v) {
2186 return v !== 0;
2187 });
2188
2189 if (prevent) {
2190 var srcEvent = event.srcEvent;
2191
2192 if (srcEvent.cancelable !== false) {
2193 srcEvent.preventDefault();
2194 }
2195
2196 srcEvent.stopPropagation();
2197 }
2198
2199 event.preventSystemEvent = prevent;
2200 prevent && this.observer.change(this, event, toAxis(this.axes, offset));
2201 };
2202
2203 __proto.onPanend = function (event) {
2204 if (!this.panFlag) {
2205 return;
2206 }
2207
2208 clearTimeout(this.rightEdgeTimer);
2209 this.panFlag = false;
2210 var offset = this.getOffset([Math.abs(event.velocityX) * (event.deltaX < 0 ? -1 : 1), Math.abs(event.velocityY) * (event.deltaY < 0 ? -1 : 1)], [useDirection(hammerjs.DIRECTION_HORIZONTAL, this._direction), useDirection(hammerjs.DIRECTION_VERTICAL, this._direction)]);
2211 offset = getNextOffset(offset, this.observer.options.deceleration);
2212 this.observer.release(this, event, toAxis(this.axes, offset));
2213 };
2214
2215 __proto.attachEvent = function (observer) {
2216 this.observer = observer;
2217 this.hammer.on("hammer.input", this.onHammerInput).on("panstart panmove", this.onPanmove);
2218 };
2219
2220 __proto.dettachEvent = function () {
2221 this.hammer.off("hammer.input", this.onHammerInput).off("panstart panmove", this.onPanmove);
2222 this.observer = null;
2223 };
2224
2225 __proto.getOffset = function (properties, direction) {
2226 var offset = [0, 0];
2227 var scale = this.options.scale;
2228
2229 if (direction[0]) {
2230 offset[0] = properties[0] * scale[0];
2231 }
2232
2233 if (direction[1]) {
2234 offset[1] = properties[1] * scale[1];
2235 }
2236
2237 return offset;
2238 };
2239
2240 return PanInput;
2241 }();
2242
2243 /**
2244 * @class eg.Axes.RotatePanInput
2245 * @classdesc A module that passes the angle moved by touch to Axes and uses one axis of rotation.<br>[Details](https://github.com/naver/egjs-axes/wiki/RotatePanInput)
2246 * @ko 터치에 의해 움직인 각도를 Axes 에 전달하며 1개의 회전축만 사용한다.<br>[상세내용](https://github.com/naver/egjs-axes/wiki/RotatePanInput-%7C-%ED%95%9C%EA%B5%AD%EC%96%B4)
2247 *
2248 * @example
2249 * const input = new eg.Axes.RotatePanInput("#area");
2250 *
2251 * var axes = new eg.Axes({
2252 * // property name('angle') could be anything you want (eg. x, y, z...)
2253 * angle: {
2254 * range: [-180, 180] // from -180deg to 180deg
2255 * }
2256 * });
2257 *
2258 * axes.connect("angle", input)
2259 *
2260 * @param {HTMLElement|String|jQuery} element An element to use the eg.Axes.RotatePanInput module <ko>eg.Axes.RotatePanInput 모듈을 사용할 엘리먼트</ko>
2261 * @param {PanInputOption} [options] The option object of the eg.Axes.PanInput module<ko>eg.Axes.PanInput 모듈의 옵션 객체</ko>
2262 * @extends eg.Axes.PanInput
2263 */
2264
2265 var RotatePanInput =
2266 /*#__PURE__*/
2267 function (_super) {
2268 __extends(RotatePanInput, _super);
2269
2270 function RotatePanInput(el, options) {
2271 var _this = _super.call(this, el, options) || this;
2272
2273 _this.prevQuadrant = null;
2274 _this.lastDiff = 0;
2275 return _this;
2276 }
2277
2278 var __proto = RotatePanInput.prototype;
2279
2280 __proto.mapAxes = function (axes) {
2281 this._direction = Axes.DIRECTION_ALL;
2282 this.axes = axes;
2283 };
2284
2285 __proto.onHammerInput = function (event) {
2286 if (this.isEnable()) {
2287 if (event.isFirst) {
2288 this.observer.hold(this, event);
2289 this.onPanstart(event);
2290 } else if (event.isFinal) {
2291 this.onPanend(event);
2292 }
2293 }
2294 };
2295
2296 __proto.onPanstart = function (event) {
2297 var rect = this.element.getBoundingClientRect();
2298 /**
2299 * Responsive
2300 */
2301 // TODO: how to do if element is ellipse not circle.
2302
2303 this.coefficientForDistanceToAngle = 360 / (rect.width * Math.PI); // from 2*pi*r * x / 360
2304 // TODO: provide a way to set origin like https://developer.mozilla.org/en-US/docs/Web/CSS/transform-origin
2305
2306 this.rotateOrigin = [rect.left + (rect.width - 1) / 2, rect.top + (rect.height - 1) / 2]; // init angle.
2307
2308 this.prevAngle = null;
2309 this.triggerChange(event);
2310 };
2311
2312 __proto.onPanmove = function (event) {
2313 this.triggerChange(event);
2314 };
2315
2316 __proto.onPanend = function (event) {
2317 this.triggerChange(event);
2318 this.triggerAnimation(event);
2319 };
2320
2321 __proto.triggerChange = function (event) {
2322 var angle = this.getAngle(event.center.x, event.center.y);
2323 var quadrant = this.getQuadrant(event.center.x, event.center.y);
2324 var diff = this.getDifference(this.prevAngle, angle, this.prevQuadrant, quadrant);
2325 this.prevAngle = angle;
2326 this.prevQuadrant = quadrant;
2327
2328 if (diff === 0) {
2329 return;
2330 }
2331
2332 this.lastDiff = diff;
2333 this.observer.change(this, event, toAxis(this.axes, [-diff])); // minus for clockwise
2334 };
2335
2336 __proto.triggerAnimation = function (event) {
2337 var vx = event.velocityX;
2338 var vy = event.velocityY;
2339 var velocity = Math.sqrt(vx * vx + vy * vy) * (this.lastDiff > 0 ? -1 : 1); // clockwise
2340
2341 var duration = Math.abs(velocity / -this.observer.options.deceleration);
2342 var distance = velocity / 2 * duration;
2343 this.observer.release(this, event, toAxis(this.axes, [distance * this.coefficientForDistanceToAngle]));
2344 };
2345
2346 __proto.getDifference = function (prevAngle, angle, prevQuadrant, quadrant) {
2347 var diff;
2348
2349 if (prevAngle === null) {
2350 diff = 0;
2351 } else if (prevQuadrant === 1 && quadrant === 4) {
2352 diff = -prevAngle - (360 - angle);
2353 } else if (prevQuadrant === 4 && quadrant === 1) {
2354 diff = 360 - prevAngle + angle;
2355 } else {
2356 diff = angle - prevAngle;
2357 }
2358
2359 return diff;
2360 };
2361
2362 __proto.getPosFromOrigin = function (posX, posY) {
2363 return {
2364 x: posX - this.rotateOrigin[0],
2365 y: this.rotateOrigin[1] - posY
2366 };
2367 };
2368
2369 __proto.getAngle = function (posX, posY) {
2370 var _a = this.getPosFromOrigin(posX, posY),
2371 x = _a.x,
2372 y = _a.y;
2373
2374 var angle = Math.atan2(y, x) * 180 / Math.PI; // console.log(angle, x, y);
2375
2376 return angle < 0 ? 360 + angle : angle;
2377 };
2378 /**
2379 * Quadrant
2380 * y(+)
2381 * |
2382 * 2 | 1
2383 * --------------->x(+)
2384 * 3 | 4
2385 * |
2386 */
2387
2388
2389 __proto.getQuadrant = function (posX, posY) {
2390 var _a = this.getPosFromOrigin(posX, posY),
2391 x = _a.x,
2392 y = _a.y;
2393
2394 var q = 0;
2395
2396 if (x >= 0 && y >= 0) {
2397 q = 1;
2398 } else if (x < 0 && y >= 0) {
2399 q = 2;
2400 } else if (x < 0 && y < 0) {
2401 q = 3;
2402 } else if (x >= 0 && y < 0) {
2403 q = 4;
2404 }
2405
2406 return q;
2407 };
2408
2409 return RotatePanInput;
2410 }(PanInput);
2411
2412 /**
2413 * @typedef {Object} PinchInputOption The option object of the eg.Axes.PinchInput module
2414 * @ko eg.Axes.PinchInput 모듈의 옵션 객체
2415 * @property {Number} [scale=1] Coordinate scale that a user can move<ko>사용자의 동작으로 이동하는 좌표의 배율</ko>
2416 * @property {Number} [threshold=0] Minimal scale before recognizing <ko>사용자의 Pinch 동작을 인식하기 위해산 최소한의 배율</ko>
2417 * @property {Object} [hammerManagerOptions={cssProps: {userSelect: "none",touchSelect: "none",touchCallout: "none",userDrag: "none"}] Options of Hammer.Manager <ko>Hammer.Manager의 옵션</ko>
2418 **/
2419
2420 /**
2421 * @class eg.Axes.PinchInput
2422 * @classdesc A module that passes the amount of change to eg.Axes when two pointers are moving toward (zoom-in) or away from each other (zoom-out). use one axis.
2423 * @ko 2개의 pointer를 이용하여 zoom-in하거나 zoom-out 하는 동작의 변화량을 eg.Axes에 전달하는 모듈. 한 개 의 축을 사용한다.
2424 * @example
2425 * const pinch = new eg.Axes.PinchInput("#area", {
2426 * scale: 1
2427 * });
2428 *
2429 * // Connect 'something' axis when two pointers are moving toward (zoom-in) or away from each other (zoom-out).
2430 * axes.connect("something", pinch);
2431 *
2432 * @param {HTMLElement|String|jQuery} element An element to use the eg.Axes.PinchInput module <ko>eg.Axes.PinchInput 모듈을 사용할 엘리먼트</ko>
2433 * @param {PinchInputOption} [options] The option object of the eg.Axes.PinchInput module<ko>eg.Axes.PinchInput 모듈의 옵션 객체</ko>
2434 */
2435
2436 var PinchInput =
2437 /*#__PURE__*/
2438 function () {
2439 function PinchInput(el, options) {
2440 this.axes = [];
2441 this.hammer = null;
2442 this.element = null;
2443 this._base = null;
2444 this._prev = null;
2445 this.pinchRecognizer = null;
2446 /**
2447 * Hammer helps you add support for touch gestures to your page
2448 *
2449 * @external Hammer
2450 * @see {@link http://hammerjs.github.io|Hammer.JS}
2451 * @see {@link http://hammerjs.github.io/jsdoc/Hammer.html|Hammer.JS API documents}
2452 * @see Hammer.JS applies specific CSS properties by {@link http://hammerjs.github.io/jsdoc/Hammer.defaults.cssProps.html|default} when creating an instance. The eg.Axes module removes all default CSS properties provided by Hammer.JS
2453 */
2454
2455 if (typeof hammerjs.Manager === "undefined") {
2456 throw new Error("The Hammerjs must be loaded before eg.Axes.PinchInput.\nhttp://hammerjs.github.io/");
2457 }
2458
2459 this.element = $(el);
2460 this.options = __assign({
2461 scale: 1,
2462 threshold: 0,
2463 inputType: ["touch", "pointer"],
2464 hammerManagerOptions: {
2465 // css properties were removed due to usablility issue
2466 // http://hammerjs.github.io/jsdoc/Hammer.defaults.cssProps.html
2467 cssProps: {
2468 userSelect: "none",
2469 touchSelect: "none",
2470 touchCallout: "none",
2471 userDrag: "none"
2472 }
2473 }
2474 }, options);
2475 this.onPinchStart = this.onPinchStart.bind(this);
2476 this.onPinchMove = this.onPinchMove.bind(this);
2477 this.onPinchEnd = this.onPinchEnd.bind(this);
2478 }
2479
2480 var __proto = PinchInput.prototype;
2481
2482 __proto.mapAxes = function (axes) {
2483 this.axes = axes;
2484 };
2485
2486 __proto.connect = function (observer) {
2487 var hammerOption = {
2488 threshold: this.options.threshold
2489 };
2490
2491 if (this.hammer) {
2492 // for sharing hammer instance.
2493 // hammer remove previous PinchRecognizer.
2494 this.removeRecognizer();
2495 this.dettachEvent();
2496 } else {
2497 var keyValue = this.element[UNIQUEKEY];
2498
2499 if (!keyValue) {
2500 keyValue = String(Math.round(Math.random() * new Date().getTime()));
2501 }
2502
2503 var inputClass = convertInputType(this.options.inputType);
2504
2505 if (!inputClass) {
2506 throw new Error("Wrong inputType parameter!");
2507 }
2508
2509 this.hammer = createHammer(this.element, __assign({
2510 inputClass: inputClass
2511 }, this.options.hammerManagerOptions));
2512 this.element[UNIQUEKEY] = keyValue;
2513 }
2514
2515 this.pinchRecognizer = new hammerjs.Pinch(hammerOption);
2516 this.hammer.add(this.pinchRecognizer);
2517 this.attachEvent(observer);
2518 return this;
2519 };
2520
2521 __proto.disconnect = function () {
2522 this.removeRecognizer();
2523
2524 if (this.hammer) {
2525 this.hammer.remove(this.pinchRecognizer);
2526 this.pinchRecognizer = null;
2527 this.dettachEvent();
2528 }
2529
2530 return this;
2531 };
2532 /**
2533 * Destroys elements, properties, and events used in a module.
2534 * @ko 모듈에 사용한 엘리먼트와 속성, 이벤트를 해제한다.
2535 * @method eg.Axes.PinchInput#destroy
2536 */
2537
2538
2539 __proto.destroy = function () {
2540 this.disconnect();
2541
2542 if (this.hammer && this.hammer.recognizers.length === 0) {
2543 this.hammer.destroy();
2544 }
2545
2546 delete this.element[UNIQUEKEY];
2547 this.element = null;
2548 this.hammer = null;
2549 };
2550
2551 __proto.removeRecognizer = function () {
2552 if (this.hammer && this.pinchRecognizer) {
2553 this.hammer.remove(this.pinchRecognizer);
2554 this.pinchRecognizer = null;
2555 }
2556 };
2557
2558 __proto.onPinchStart = function (event) {
2559 this._base = this.observer.get(this)[this.axes[0]];
2560 var offset = this.getOffset(event.scale);
2561 this.observer.hold(this, event);
2562 this.observer.change(this, event, toAxis(this.axes, [offset]));
2563 this._prev = event.scale;
2564 };
2565
2566 __proto.onPinchMove = function (event) {
2567 var offset = this.getOffset(event.scale, this._prev);
2568 this.observer.change(this, event, toAxis(this.axes, [offset]));
2569 this._prev = event.scale;
2570 };
2571
2572 __proto.onPinchEnd = function (event) {
2573 var offset = this.getOffset(event.scale, this._prev);
2574 this.observer.change(this, event, toAxis(this.axes, [offset]));
2575 this.observer.release(this, event, toAxis(this.axes, [0]), 0);
2576 this._base = null;
2577 this._prev = null;
2578 };
2579
2580 __proto.getOffset = function (pinchScale, prev) {
2581 if (prev === void 0) {
2582 prev = 1;
2583 }
2584
2585 return this._base * (pinchScale - prev) * this.options.scale;
2586 };
2587
2588 __proto.attachEvent = function (observer) {
2589 this.observer = observer;
2590 this.hammer.on("pinchstart", this.onPinchStart).on("pinchmove", this.onPinchMove).on("pinchend", this.onPinchEnd);
2591 };
2592
2593 __proto.dettachEvent = function () {
2594 this.hammer.off("pinchstart", this.onPinchStart).off("pinchmove", this.onPinchMove).off("pinchend", this.onPinchEnd);
2595 this.observer = null;
2596 this._prev = null;
2597 };
2598 /**
2599 * Enables input devices
2600 * @ko 입력 장치를 사용할 수 있게 한다
2601 * @method eg.Axes.PinchInput#enable
2602 * @return {eg.Axes.PinchInput} An instance of a module itself <ko>모듈 자신의 인스턴스</ko>
2603 */
2604
2605
2606 __proto.enable = function () {
2607 this.hammer && (this.hammer.get("pinch").options.enable = true);
2608 return this;
2609 };
2610 /**
2611 * Disables input devices
2612 * @ko 입력 장치를 사용할 수 없게 한다.
2613 * @method eg.Axes.PinchInput#disable
2614 * @return {eg.Axes.PinchInput} An instance of a module itself <ko>모듈 자신의 인스턴스</ko>
2615 */
2616
2617
2618 __proto.disable = function () {
2619 this.hammer && (this.hammer.get("pinch").options.enable = false);
2620 return this;
2621 };
2622 /**
2623 * Returns whether to use an input device
2624 * @ko 입력 장치를 사용 여부를 반환한다.
2625 * @method eg.Axes.PinchInput#isEnable
2626 * @return {Boolean} Whether to use an input device <ko>입력장치 사용여부</ko>
2627 */
2628
2629
2630 __proto.isEnable = function () {
2631 return !!(this.hammer && this.hammer.get("pinch").options.enable);
2632 };
2633
2634 return PinchInput;
2635 }();
2636
2637 /**
2638 * @typedef {Object} WheelInputOption The option object of the eg.Axes.WheelInput module
2639 * @ko eg.Axes.WheelInput 모듈의 옵션 객체
2640 * @property {Number} [scale=1] Coordinate scale that a user can move<ko>사용자의 동작으로 이동하는 좌표의 배율</ko>
2641 **/
2642
2643 /**
2644 * @class eg.Axes.WheelInput
2645 * @classdesc A module that passes the amount of change to eg.Axes when the mouse wheel is moved. use one axis.
2646 * @ko 마우스 휠이 움직일때의 변화량을 eg.Axes에 전달하는 모듈. 한 개 의 축을 사용한다.
2647 *
2648 * @example
2649 * const wheel = new eg.Axes.WheelInput("#area", {
2650 * scale: 1
2651 * });
2652 *
2653 * // Connect 'something' axis when the mousewheel is moved.
2654 * axes.connect("something", wheel);
2655 *
2656 * @param {HTMLElement|String|jQuery} element An element to use the eg.Axes.WheelInput module <ko>eg.Axes.WheelInput 모듈을 사용할 엘리먼트</ko>
2657 * @param {WheelInputOption} [options] The option object of the eg.Axes.WheelInput module<ko>eg.Axes.WheelInput 모듈의 옵션 객체</ko>
2658 */
2659
2660 var WheelInput =
2661 /*#__PURE__*/
2662 function () {
2663 function WheelInput(el, options) {
2664 this.axes = [];
2665 this.element = null;
2666 this._isEnabled = false;
2667 this._isHolded = false;
2668 this._timer = null;
2669 this.element = $(el);
2670 this.options = __assign({
2671 scale: 1,
2672 useNormalized: true
2673 }, options);
2674 this.onWheel = this.onWheel.bind(this);
2675 }
2676
2677 var __proto = WheelInput.prototype;
2678
2679 __proto.mapAxes = function (axes) {
2680 this.axes = axes;
2681 };
2682
2683 __proto.connect = function (observer) {
2684 this.dettachEvent();
2685 this.attachEvent(observer);
2686 return this;
2687 };
2688
2689 __proto.disconnect = function () {
2690 this.dettachEvent();
2691 return this;
2692 };
2693 /**
2694 * Destroys elements, properties, and events used in a module.
2695 * @ko 모듈에 사용한 엘리먼트와 속성, 이벤트를 해제한다.
2696 * @method eg.Axes.WheelInput#destroy
2697 */
2698
2699
2700 __proto.destroy = function () {
2701 this.disconnect();
2702 this.element = null;
2703 };
2704
2705 __proto.onWheel = function (event) {
2706 var _this = this;
2707
2708 if (!this._isEnabled) {
2709 return;
2710 }
2711
2712 event.preventDefault();
2713
2714 if (event.deltaY === 0) {
2715 return;
2716 }
2717
2718 if (!this._isHolded) {
2719 this.observer.hold(this, event);
2720 this._isHolded = true;
2721 }
2722
2723 var offset = (event.deltaY > 0 ? -1 : 1) * this.options.scale * (this.options.useNormalized ? 1 : Math.abs(event.deltaY));
2724 this.observer.change(this, event, toAxis(this.axes, [offset]));
2725 clearTimeout(this._timer);
2726 this._timer = setTimeout(function () {
2727 if (_this._isHolded) {
2728 _this._isHolded = false;
2729
2730 _this.observer.release(_this, event, toAxis(_this.axes, [0]));
2731 }
2732 }, 50);
2733 };
2734
2735 __proto.attachEvent = function (observer) {
2736 this.observer = observer;
2737 this.element.addEventListener("wheel", this.onWheel);
2738 this._isEnabled = true;
2739 };
2740
2741 __proto.dettachEvent = function () {
2742 this.element.removeEventListener("wheel", this.onWheel);
2743 this._isEnabled = false;
2744 this.observer = null;
2745
2746 if (this._timer) {
2747 clearTimeout(this._timer);
2748 this._timer = null;
2749 }
2750 };
2751 /**
2752 * Enables input devices
2753 * @ko 입력 장치를 사용할 수 있게 한다
2754 * @method eg.Axes.WheelInput#enable
2755 * @return {eg.Axes.WheelInput} An instance of a module itself <ko>모듈 자신의 인스턴스</ko>
2756 */
2757
2758
2759 __proto.enable = function () {
2760 this._isEnabled = true;
2761 return this;
2762 };
2763 /**
2764 * Disables input devices
2765 * @ko 입력 장치를 사용할 수 없게 한다.
2766 * @method eg.Axes.WheelInput#disable
2767 * @return {eg.Axes.WheelInput} An instance of a module itself <ko>모듈 자신의 인스턴스</ko>
2768 */
2769
2770
2771 __proto.disable = function () {
2772 this._isEnabled = false;
2773 return this;
2774 };
2775 /**
2776 * Returns whether to use an input device
2777 * @ko 입력 장치를 사용 여부를 반환한다.
2778 * @method eg.Axes.WheelInput#isEnable
2779 * @return {Boolean} Whether to use an input device <ko>입력장치 사용여부</ko>
2780 */
2781
2782
2783 __proto.isEnable = function () {
2784 return this._isEnabled;
2785 };
2786
2787 return WheelInput;
2788 }();
2789
2790 var KEY_LEFT_ARROW = 37;
2791 var KEY_A = 65;
2792 var KEY_UP_ARROW = 38;
2793 var KEY_W = 87;
2794 var KEY_RIGHT_ARROW = 39;
2795 var KEY_D = 68;
2796 var KEY_DOWN_ARROW = 40;
2797 var KEY_S = 83;
2798 var DIRECTION_REVERSE = -1;
2799 var DIRECTION_FORWARD = 1;
2800 var DIRECTION_HORIZONTAL = -1;
2801 var DIRECTION_VERTICAL = 1;
2802 var DELAY = 80;
2803 /**
2804 * @typedef {Object} MoveKeyInputOption The option object of the eg.Axes.MoveKeyInput module
2805 * @ko eg.Axes.MoveKeyInput 모듈의 옵션 객체
2806 * @property {Array<Number>} [scale] Coordinate scale that a user can move<ko>사용자의 동작으로 이동하는 좌표의 배율</ko>
2807 * @property {Number} [scale[0]=1] Coordinate scale for the first axis<ko>첫번째 축의 배율</ko>
2808 * @property {Number} [scale[1]=1] Coordinate scale for the decond axis<ko>두번째 축의 배율</ko>
2809 **/
2810
2811 /**
2812 * @class eg.Axes.MoveKeyInput
2813 * @classdesc A module that passes the amount of change to eg.Axes when the move key stroke is occured. use two axis.
2814 * @ko 이동키 입력이 발생했을 때의 변화량을 eg.Axes에 전달하는 모듈. 두 개 의 축을 사용한다.
2815 *
2816 * @example
2817 * const moveKey = new eg.Axes.MoveKeyInput("#area", {
2818 * scale: [1, 1]
2819 * });
2820 *
2821 * // Connect 'x', 'y' axes when the moveKey is pressed.
2822 * axes.connect(["x", "y"], moveKey);
2823 *
2824 * @param {HTMLElement|String|jQuery} element An element to use the eg.Axes.MoveKeyInput module <ko>eg.Axes.MoveKeyInput 모듈을 사용할 엘리먼트</ko>
2825 * @param {MoveKeyInputOption} [options] The option object of the eg.Axes.MoveKeyInput module<ko>eg.Axes.MoveKeyInput 모듈의 옵션 객체</ko>
2826 */
2827
2828 var MoveKeyInput =
2829 /*#__PURE__*/
2830 function () {
2831 function MoveKeyInput(el, options) {
2832 this.axes = [];
2833 this.element = null;
2834 this._isEnabled = false;
2835 this._isHolded = false;
2836 this._timer = null;
2837 this.element = $(el);
2838 this.options = __assign({
2839 scale: [1, 1]
2840 }, options);
2841 this.onKeydown = this.onKeydown.bind(this);
2842 this.onKeyup = this.onKeyup.bind(this);
2843 }
2844
2845 var __proto = MoveKeyInput.prototype;
2846
2847 __proto.mapAxes = function (axes) {
2848 this.axes = axes;
2849 };
2850
2851 __proto.connect = function (observer) {
2852 this.dettachEvent(); // add tabindex="0" to the container for making it focusable
2853
2854 if (this.element.getAttribute("tabindex") !== "0") {
2855 this.element.setAttribute("tabindex", "0");
2856 }
2857
2858 this.attachEvent(observer);
2859 return this;
2860 };
2861
2862 __proto.disconnect = function () {
2863 this.dettachEvent();
2864 return this;
2865 };
2866 /**
2867 * Destroys elements, properties, and events used in a module.
2868 * @ko 모듈에 사용한 엘리먼트와 속성, 이벤트를 해제한다.
2869 * @method eg.Axes.MoveKeyInput#destroy
2870 */
2871
2872
2873 __proto.destroy = function () {
2874 this.disconnect();
2875 this.element = null;
2876 };
2877
2878 __proto.onKeydown = function (e) {
2879 if (!this._isEnabled) {
2880 return;
2881 }
2882
2883 var isMoveKey = true;
2884 var direction = DIRECTION_FORWARD;
2885 var move = DIRECTION_HORIZONTAL;
2886
2887 switch (e.keyCode) {
2888 case KEY_LEFT_ARROW:
2889 case KEY_A:
2890 direction = DIRECTION_REVERSE;
2891 break;
2892
2893 case KEY_RIGHT_ARROW:
2894 case KEY_D:
2895 break;
2896
2897 case KEY_DOWN_ARROW:
2898 case KEY_S:
2899 direction = DIRECTION_REVERSE;
2900 move = DIRECTION_VERTICAL;
2901 break;
2902
2903 case KEY_UP_ARROW:
2904 case KEY_W:
2905 move = DIRECTION_VERTICAL;
2906 break;
2907
2908 default:
2909 isMoveKey = false;
2910 }
2911
2912 if (move === DIRECTION_HORIZONTAL && !this.axes[0] || move === DIRECTION_VERTICAL && !this.axes[1]) {
2913 isMoveKey = false;
2914 }
2915
2916 if (!isMoveKey) {
2917 return;
2918 }
2919
2920 var offsets = move === DIRECTION_HORIZONTAL ? [+this.options.scale[0] * direction, 0] : [0, +this.options.scale[1] * direction];
2921
2922 if (!this._isHolded) {
2923 this.observer.hold(this, event);
2924 this._isHolded = true;
2925 }
2926
2927 clearTimeout(this._timer);
2928 this.observer.change(this, event, toAxis(this.axes, offsets));
2929 };
2930
2931 __proto.onKeyup = function (e) {
2932 var _this = this;
2933
2934 if (!this._isHolded) {
2935 return;
2936 }
2937
2938 clearTimeout(this._timer);
2939 this._timer = setTimeout(function () {
2940 _this.observer.release(_this, e, toAxis(_this.axes, [0, 0]));
2941
2942 _this._isHolded = false;
2943 }, DELAY);
2944 };
2945
2946 __proto.attachEvent = function (observer) {
2947 this.observer = observer;
2948 this.element.addEventListener("keydown", this.onKeydown, false);
2949 this.element.addEventListener("keypress", this.onKeydown, false);
2950 this.element.addEventListener("keyup", this.onKeyup, false);
2951 this._isEnabled = true;
2952 };
2953
2954 __proto.dettachEvent = function () {
2955 this.element.removeEventListener("keydown", this.onKeydown, false);
2956 this.element.removeEventListener("keypress", this.onKeydown, false);
2957 this.element.removeEventListener("keyup", this.onKeyup, false);
2958 this._isEnabled = false;
2959 this.observer = null;
2960 };
2961 /**
2962 * Enables input devices
2963 * @ko 입력 장치를 사용할 수 있게 한다
2964 * @method eg.Axes.MoveKeyInput#enable
2965 * @return {eg.Axes.MoveKeyInput} An instance of a module itself <ko>모듈 자신의 인스턴스</ko>
2966 */
2967
2968
2969 __proto.enable = function () {
2970 this._isEnabled = true;
2971 return this;
2972 };
2973 /**
2974 * Disables input devices
2975 * @ko 입력 장치를 사용할 수 없게 한다.
2976 * @method eg.Axes.MoveKeyInput#disable
2977 * @return {eg.Axes.MoveKeyInput} An instance of a module itself <ko>모듈 자신의 인스턴스</ko>
2978 */
2979
2980
2981 __proto.disable = function () {
2982 this._isEnabled = false;
2983 return this;
2984 };
2985 /**
2986 * Returns whether to use an input device
2987 * @ko 입력 장치를 사용 여부를 반환한다.
2988 * @method eg.Axes.MoveKeyInput#isEnable
2989 * @return {Boolean} Whether to use an input device <ko>입력장치 사용여부</ko>
2990 */
2991
2992
2993 __proto.isEnable = function () {
2994 return this._isEnabled;
2995 };
2996
2997 return MoveKeyInput;
2998 }();
2999
3000 Axes.PanInput = PanInput;
3001 Axes.RotatePanInput = RotatePanInput;
3002 Axes.PinchInput = PinchInput;
3003 Axes.WheelInput = WheelInput;
3004 Axes.MoveKeyInput = MoveKeyInput;
3005
3006 return Axes;
3007
3008})));
3009//# sourceMappingURL=axes.js.map