| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247 |
- type DragCallback = (dx: number, dy: number) => void
- type ZoomCallback = (scale: number, focusX: number, focusY: number) => void
- type TapCallback = (dx: number, dy: number) => void
- export interface Callbacks {
- drag?: DragCallback,
- zoom?: ZoomCallback,
- tap?: TapCallback,
- }
- interface MyTouch {
- identifier: number,
- lastX: number,
- lastY: number,
- dx: number,
- dy: number,
- }
- interface ScaleTracker {
- focusX: number,
- focusY: number,
- distance: number,
- }
- export class TouchTracker {
- touches: Array<MyTouch> = []
- callbacks: Callbacks;
- el: HTMLElement;
- scaleTracker?: ScaleTracker
- distance = 0
- constructor(el: HTMLElement, callbacks: Callbacks) {
- this.callbacks = callbacks;
- this.el = el;
- }
- private removeTouch(identifier: number) {
- let index = this.touches.findIndex(t => t.identifier == identifier)
- if (index >= 0) {
- this.touches.splice(index, 1)
- }
- }
- private getTouch(identifier: number): MyTouch | null {
- let index = this.touches.findIndex(t => t.identifier == identifier)
- if (index >= 0) return this.touches[index]
- else return null
- }
- private getX(touch: Touch) {
- //return touch.pageX - this.el.offsetLeft
- return touch.pageX
- }
- private getY(touch: Touch) {
- //return touch.pageY - this.el.offsetTop
- return touch.pageY
- }
- start(list: TouchList) {
- for (var i = 0; i < list.length; i++) {
- let touch = list[i];
- this.removeTouch(touch.identifier);
- this.touches.push({
- lastX: this.getX(touch),
- lastY: this.getY(touch),
- dx: 0,
- dy: 0,
- identifier: touch.identifier
- })
- }
- if (this.touches.length == 1) {
- this.distance = 0;
- }
- this.updateFocus();
- }
- updateFocus() {
- if (this.touches.length < 2) {
- this.scaleTracker = undefined;
- return
- }
- let t1 = this.touches[0];
- let t2 = this.touches[1];
- let focusX = (t1.lastX + t2.lastX) / 2;
- let focusY = (t1.lastY + t2.lastY) / 2;
- let distance = Math.sqrt(Math.pow(t2.lastX - t1.lastX, 2) + Math.pow(t2.lastY - t1.lastY, 2));
- this.scaleTracker = { focusX, focusY, distance }
- }
- end(list: TouchList) {
- console.log('end')
- for (var i = 0; i < list.length; i++) {
- this.removeTouch(list[i].identifier);
- }
- this.updateFocus();
- if (this.touches.length <= 0 && this.distance == 0) {
- let touch = list[0];
- let el = touch.target as HTMLElement
- //console.log('kkkkkk', el.offsetLeft, el.offsetTop)
- //this.callbacks?.tap?.(touch.clientX - el.offsetLeft, touch.clientY - el.offsetTop)
- this.callbacks?.tap?.(touch.clientX , touch.clientY)
- }
- }
- move(list: TouchList) {
- for (var i = 0; i < list.length; i++) {
- let touch = list[i];
- let mytouch = this.getTouch(touch.identifier);
- if (mytouch == null) continue;
- mytouch.dx = this.getX(touch) - mytouch.lastX
- mytouch.dy = this.getY(touch) - mytouch.lastY
- mytouch.lastX = this.getX(touch)
- mytouch.lastY = this.getY(touch)
- if (this.scaleTracker) {
- let t1 = this.touches[0];
- let t2 = this.touches[1];
- let focusX = (t1.lastX + t2.lastX) / 2;
- let focusY = (t1.lastY + t2.lastY) / 2;
- let distance = Math.sqrt(Math.pow(t2.lastX - t1.lastX, 2) + Math.pow(t2.lastY - t1.lastY, 2));
- let dx = focusX - this.scaleTracker.focusX;
- let dy = focusY - this.scaleTracker.focusY;
- let scale = distance / this.scaleTracker.distance;
- console.log(`dx=${dx}, dy=${dy}, scale=${scale}, distance=${distance}`);
- this.callbacks.drag?.(dx, dy);
- this.callbacks.zoom?.(scale, focusX, focusY);
- this.scaleTracker.focusX = focusX;
- this.scaleTracker.focusY = focusY;
- this.scaleTracker.distance = distance;
- this.distance += Math.abs(dx) + Math.abs(dy)
- } else {
- //if(mytouch.dx > 0 || mytouch.dy >0) {
- this.callbacks.drag?.(mytouch.dx, mytouch.dy)
- // }
- this.distance += Math.abs(mytouch.dx) + Math.abs(mytouch.dy)
- }
- }
- }
- }
- export class Gesture {
- constructor(el: HTMLElement, callbacks: Callbacks) {
- var dx, dy;
- var isDown = false;
- var lastX: number = 0;
- var lastY: number = 0;
- var distance = 0;
- el.addEventListener('mousedown', e => {
- isDown = true;
- lastX = e.clientX;
- lastY = e.clientY;
- distance = 0;
- })
- document.addEventListener('mouseup', e => {
- isDown = false;
- if (distance == 0 && e.target == el) {
- callbacks.tap?.(e.offsetX, e.offsetY)
- }
- })
- document.addEventListener('mousemove', e => {
- if (isDown) {
- e.preventDefault()
- dx = e.clientX - lastX;
- dy = e.clientY - lastY;
- lastX = e.clientX;
- lastY = e.clientY;
- distance += Math.abs(dx) + Math.abs(dy)
- callbacks?.drag?.(dx, dy);
- }
- })
- el.addEventListener('wheel', e => {
- e.preventDefault()
- let scale = e.deltaY * -0.01 + 1;
- callbacks.zoom?.(scale, e.offsetX, e.offsetY)
- })
- el.addEventListener('click', e => {
- e.preventDefault()
- //callbacks.tap?.(e.offsetX, e.offsetY)
- })
- const tracker = new TouchTracker(el, callbacks);
- el.addEventListener('touchstart', e => {
- e.preventDefault();
- tracker.start(e.changedTouches);
- })
- el.addEventListener('touchmove', e => {
- tracker.move(e.changedTouches)
- })
- el.addEventListener('touchend', e => {
- tracker.end(e.changedTouches)
- })
- el.addEventListener('touchcancel', e => {
- tracker.end(e.changedTouches)
- })
- }
- }
|