Skip to content

Commit 2dbef62

Browse files
committed
- added touch support
1 parent 7f72238 commit 2dbef62

3 files changed

Lines changed: 180 additions & 0 deletions

File tree

examples/ibds.html

Lines changed: 60 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -467,6 +467,11 @@ <h3>References</h3>
467467
this.canvas.addEventListener("mousemove", this.mouseMove.bind(this), false);
468468
this.canvas.addEventListener("mouseup", this.mouseUp.bind(this), false);
469469
this.canvas.addEventListener("wheel", this.wheel.bind(this), false);
470+
// register touch event listeners (mobile / tablet)
471+
// passive:false is required so we can call preventDefault() to suppress scrolling
472+
this.canvas.addEventListener("touchstart", this.touchStart.bind(this), { passive: false });
473+
this.canvas.addEventListener("touchmove", this.touchMove.bind(this), { passive: false });
474+
this.canvas.addEventListener("touchend", this.touchEnd.bind(this), { passive: false });
470475
}
471476

472477
// set simulation parameters from GUI and start mainLoop
@@ -642,6 +647,61 @@ <h3>References</h3>
642647
if (this.zoom < 1)
643648
this.zoom = 1;
644649
}
650+
651+
// Convert the first touch point to a plain {clientX, clientY} object
652+
// so it can be passed directly to the existing mouse handlers.
653+
getTouchClient(event)
654+
{
655+
const t = event.touches.length > 0 ? event.touches[0] : event.changedTouches[0];
656+
return { clientX: t.clientX, clientY: t.clientY };
657+
}
658+
659+
touchStart(event)
660+
{
661+
event.preventDefault();
662+
if (event.touches.length === 1)
663+
this.mouseDown({ which: 1, ...this.getTouchClient(event) });
664+
else if (event.touches.length === 2)
665+
this.lastPinchDist = this.getPinchDist(event);
666+
}
667+
668+
touchMove(event)
669+
{
670+
event.preventDefault();
671+
if (event.touches.length === 1)
672+
{
673+
this.lastPinchDist = null;
674+
this.mouseMove(this.getTouchClient(event));
675+
}
676+
else if (event.touches.length === 2)
677+
{
678+
// deselect any dragged particle while pinching
679+
this.selectedParticle = -1;
680+
const dist = this.getPinchDist(event);
681+
if (this.lastPinchDist !== null)
682+
{
683+
this.zoom += (dist - this.lastPinchDist) * 0.3;
684+
if (this.zoom < 1) this.zoom = 1;
685+
}
686+
this.lastPinchDist = dist;
687+
}
688+
}
689+
690+
touchEnd(event)
691+
{
692+
event.preventDefault();
693+
if (event.touches.length < 2)
694+
this.lastPinchDist = null;
695+
if (event.touches.length === 0)
696+
this.mouseUp(event);
697+
}
698+
699+
getPinchDist(event)
700+
{
701+
const dx = event.touches[0].clientX - event.touches[1].clientX;
702+
const dy = event.touches[0].clientY - event.touches[1].clientY;
703+
return Math.sqrt(dx*dx + dy*dy);
704+
}
645705
}
646706

647707
gui = new GUI();

examples/pbd.html

Lines changed: 60 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -360,6 +360,11 @@ <h3>References</h3>
360360
this.canvas.addEventListener("mousemove", this.mouseMove.bind(this), false);
361361
this.canvas.addEventListener("mouseup", this.mouseUp.bind(this), false);
362362
this.canvas.addEventListener("wheel", this.wheel.bind(this), false);
363+
// register touch event listeners (mobile / tablet)
364+
// passive:false is required so we can call preventDefault() to suppress scrolling
365+
this.canvas.addEventListener("touchstart", this.touchStart.bind(this), { passive: false });
366+
this.canvas.addEventListener("touchmove", this.touchMove.bind(this), { passive: false });
367+
this.canvas.addEventListener("touchend", this.touchEnd.bind(this), { passive: false });
363368
}
364369

365370
// set simulation parameters from GUI and start mainLoop
@@ -535,6 +540,61 @@ <h3>References</h3>
535540
if (this.zoom < 1)
536541
this.zoom = 1;
537542
}
543+
544+
// Convert the first touch point to a plain {clientX, clientY} object
545+
// so it can be passed directly to the existing mouse handlers.
546+
getTouchClient(event)
547+
{
548+
const t = event.touches.length > 0 ? event.touches[0] : event.changedTouches[0];
549+
return { clientX: t.clientX, clientY: t.clientY };
550+
}
551+
552+
touchStart(event)
553+
{
554+
event.preventDefault();
555+
if (event.touches.length === 1)
556+
this.mouseDown({ which: 1, ...this.getTouchClient(event) });
557+
else if (event.touches.length === 2)
558+
this.lastPinchDist = this.getPinchDist(event);
559+
}
560+
561+
touchMove(event)
562+
{
563+
event.preventDefault();
564+
if (event.touches.length === 1)
565+
{
566+
this.lastPinchDist = null;
567+
this.mouseMove(this.getTouchClient(event));
568+
}
569+
else if (event.touches.length === 2)
570+
{
571+
// deselect any dragged particle while pinching
572+
this.selectedParticle = -1;
573+
const dist = this.getPinchDist(event);
574+
if (this.lastPinchDist !== null)
575+
{
576+
this.zoom += (dist - this.lastPinchDist) * 0.3;
577+
if (this.zoom < 1) this.zoom = 1;
578+
}
579+
this.lastPinchDist = dist;
580+
}
581+
}
582+
583+
touchEnd(event)
584+
{
585+
event.preventDefault();
586+
if (event.touches.length < 2)
587+
this.lastPinchDist = null;
588+
if (event.touches.length === 0)
589+
this.mouseUp(event);
590+
}
591+
592+
getPinchDist(event)
593+
{
594+
const dx = event.touches[0].clientX - event.touches[1].clientX;
595+
const dy = event.touches[0].clientY - event.touches[1].clientY;
596+
return Math.sqrt(dx*dx + dy*dy);
597+
}
538598
}
539599

540600
gui = new GUI();

examples/xpbd.html

Lines changed: 60 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -385,6 +385,11 @@ <h3>References</h3>
385385
this.canvas.addEventListener("mousemove", this.mouseMove.bind(this), false);
386386
this.canvas.addEventListener("mouseup", this.mouseUp.bind(this), false);
387387
this.canvas.addEventListener("wheel", this.wheel.bind(this), false);
388+
// register touch event listeners (mobile / tablet)
389+
// passive:false is required so we can call preventDefault() to suppress scrolling
390+
this.canvas.addEventListener("touchstart", this.touchStart.bind(this), { passive: false });
391+
this.canvas.addEventListener("touchmove", this.touchMove.bind(this), { passive: false });
392+
this.canvas.addEventListener("touchend", this.touchEnd.bind(this), { passive: false });
388393
}
389394

390395
// set simulation parameters from GUI and start mainLoop
@@ -561,6 +566,61 @@ <h3>References</h3>
561566
if (this.zoom < 1)
562567
this.zoom = 1;
563568
}
569+
570+
// Convert the first touch point to a plain {clientX, clientY} object
571+
// so it can be passed directly to the existing mouse handlers.
572+
getTouchClient(event)
573+
{
574+
const t = event.touches.length > 0 ? event.touches[0] : event.changedTouches[0];
575+
return { clientX: t.clientX, clientY: t.clientY };
576+
}
577+
578+
touchStart(event)
579+
{
580+
event.preventDefault();
581+
if (event.touches.length === 1)
582+
this.mouseDown({ which: 1, ...this.getTouchClient(event) });
583+
else if (event.touches.length === 2)
584+
this.lastPinchDist = this.getPinchDist(event);
585+
}
586+
587+
touchMove(event)
588+
{
589+
event.preventDefault();
590+
if (event.touches.length === 1)
591+
{
592+
this.lastPinchDist = null;
593+
this.mouseMove(this.getTouchClient(event));
594+
}
595+
else if (event.touches.length === 2)
596+
{
597+
// deselect any dragged particle while pinching
598+
this.selectedParticle = -1;
599+
const dist = this.getPinchDist(event);
600+
if (this.lastPinchDist !== null)
601+
{
602+
this.zoom += (dist - this.lastPinchDist) * 0.3;
603+
if (this.zoom < 1) this.zoom = 1;
604+
}
605+
this.lastPinchDist = dist;
606+
}
607+
}
608+
609+
touchEnd(event)
610+
{
611+
event.preventDefault();
612+
if (event.touches.length < 2)
613+
this.lastPinchDist = null;
614+
if (event.touches.length === 0)
615+
this.mouseUp(event);
616+
}
617+
618+
getPinchDist(event)
619+
{
620+
const dx = event.touches[0].clientX - event.touches[1].clientX;
621+
const dy = event.touches[0].clientY - event.touches[1].clientY;
622+
return Math.sqrt(dx*dx + dy*dy);
623+
}
564624
}
565625

566626
gui = new GUI();

0 commit comments

Comments
 (0)