threejs-offscreencanvas-w-picking.html 3.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122
  1. <!-- Licensed under a BSD license. See license.html for license -->
  2. <!DOCTYPE html>
  3. <html>
  4. <head>
  5. <meta charset="utf-8">
  6. <meta name="viewport" content="width=device-width, initial-scale=1.0, user-scalable=yes">
  7. <title>Three.js - OffscreenCanvas Picking</title>
  8. <style>
  9. body {
  10. margin: 0;
  11. }
  12. #c {
  13. width: 100vw;
  14. height: 100vh;
  15. display: block;
  16. }
  17. </style>
  18. </head>
  19. <body>
  20. <canvas id="c"></canvas>
  21. </body>
  22. <script type="module">
  23. import {state, init, pickPosition} from './shared-picking.js';
  24. let sendMouse;
  25. function startWorker(canvas) {
  26. const offscreen = canvas.transferControlToOffscreen();
  27. const worker = new Worker('offscreencanvas-worker-picking.js', {type: 'module'});
  28. worker.postMessage({type: 'init', canvas: offscreen}, [offscreen]);
  29. sendMouse = (x, y) => {
  30. worker.postMessage({
  31. type: 'mouse',
  32. x,
  33. y,
  34. });
  35. };
  36. function sendSize() {
  37. worker.postMessage({
  38. type: 'size',
  39. width: canvas.clientWidth,
  40. height: canvas.clientHeight,
  41. });
  42. }
  43. window.addEventListener('resize', sendSize);
  44. sendSize();
  45. console.log('using OffscreenCanvas'); /* eslint-disable-line no-console */
  46. }
  47. function startMainPage(canvas) {
  48. init({canvas});
  49. sendMouse = (x, y) => {
  50. pickPosition.x = x;
  51. pickPosition.y = y;
  52. };
  53. function sendSize() {
  54. state.width = canvas.clientWidth;
  55. state.height = canvas.clientHeight;
  56. }
  57. window.addEventListener('resize', sendSize);
  58. sendSize();
  59. console.log('using regular canvas'); /* eslint-disable-line no-console */
  60. }
  61. function main() { /* eslint consistent-return: 0 */
  62. const canvas = document.querySelector('#c');
  63. if (canvas.transferControlToOffscreen) {
  64. startWorker(canvas);
  65. } else {
  66. startMainPage(canvas);
  67. }
  68. function getCanvasRelativePosition(event) {
  69. const rect = canvas.getBoundingClientRect();
  70. return {
  71. x: (event.clientX - rect.left) * canvas.width / rect.width,
  72. y: (event.clientY - rect.top ) * canvas.height / rect.height,
  73. };
  74. }
  75. function setPickPosition(event) {
  76. const pos = getCanvasRelativePosition(event);
  77. sendMouse(
  78. (pos.x / canvas.width ) * 2 - 1,
  79. (pos.y / canvas.height) * -2 + 1); // note we flip Y
  80. }
  81. function clearPickPosition() {
  82. // unlike the mouse which always has a position
  83. // if the user stops touching the screen we want
  84. // to stop picking. For now we just pick a value
  85. // unlikely to pick something
  86. sendMouse(-100000, -100000);
  87. }
  88. window.addEventListener('mousemove', setPickPosition);
  89. window.addEventListener('mouseout', clearPickPosition);
  90. window.addEventListener('mouseleave', clearPickPosition);
  91. window.addEventListener('touchstart', (event) => {
  92. // prevent the window from scrolling
  93. event.preventDefault();
  94. setPickPosition(event.touches[0]);
  95. }, {passive: false});
  96. window.addEventListener('touchmove', (event) => {
  97. setPickPosition(event.touches[0]);
  98. });
  99. window.addEventListener('touchend', clearPickPosition);
  100. }
  101. main();
  102. </script>
  103. </html>