You can not select more than 25 topics
			Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
		
		
		
		
		
			
		
			
				
					
					
						
							188 lines
						
					
					
						
							4.3 KiB
						
					
					
				
			
		
		
		
			
			
			
				
					
				
				
					
				
			
		
		
	
	
							188 lines
						
					
					
						
							4.3 KiB
						
					
					
				
								<!-- Licensed under a BSD license. See license.html for license -->
							 | 
						|
								<!DOCTYPE html>
							 | 
						|
								<html>
							 | 
						|
								  <head>
							 | 
						|
								    <meta charset="utf-8">
							 | 
						|
								    <meta name="viewport" content="width=device-width, initial-scale=1.0, user-scalable=yes">
							 | 
						|
								    <title>Three.js - Offscreen Canvas</title>
							 | 
						|
								    <style>
							 | 
						|
								    html, body {
							 | 
						|
								        height: 100%;
							 | 
						|
								        margin: 0;
							 | 
						|
								    }
							 | 
						|
								    #c {
							 | 
						|
								        width: 100%;
							 | 
						|
								        height: 100%;
							 | 
						|
								        display: block;
							 | 
						|
								    }
							 | 
						|
								    #c:focus {
							 | 
						|
								      outline: none;
							 | 
						|
								    }
							 | 
						|
								    </style>
							 | 
						|
								  </head>
							 | 
						|
								  <body>
							 | 
						|
								    <canvas id="c" tabindex="1"></canvas>
							 | 
						|
								  </body>
							 | 
						|
								<script type="module">
							 | 
						|
								import {init} from './shared-orbitcontrols.js';
							 | 
						|
								
							 | 
						|
								const mouseEventHandler = makeSendPropertiesHandler([
							 | 
						|
								  'ctrlKey',
							 | 
						|
								  'metaKey',
							 | 
						|
								  'shiftKey',
							 | 
						|
								  'button',
							 | 
						|
								  'pointerType',
							 | 
						|
								  'clientX',
							 | 
						|
								  'clientY',
							 | 
						|
								  'pageX',
							 | 
						|
								  'pageY',
							 | 
						|
								]);
							 | 
						|
								const wheelEventHandlerImpl = makeSendPropertiesHandler([
							 | 
						|
								  'deltaX',
							 | 
						|
								  'deltaY',
							 | 
						|
								]);
							 | 
						|
								const keydownEventHandler = makeSendPropertiesHandler([
							 | 
						|
								  'ctrlKey',
							 | 
						|
								  'metaKey',
							 | 
						|
								  'shiftKey',
							 | 
						|
								  'keyCode',
							 | 
						|
								]);
							 | 
						|
								
							 | 
						|
								function wheelEventHandler(event, sendFn) {
							 | 
						|
								  event.preventDefault();
							 | 
						|
								  wheelEventHandlerImpl(event, sendFn);
							 | 
						|
								}
							 | 
						|
								
							 | 
						|
								function preventDefaultHandler(event) {
							 | 
						|
								  event.preventDefault();
							 | 
						|
								}
							 | 
						|
								
							 | 
						|
								function copyProperties(src, properties, dst) {
							 | 
						|
								  for (const name of properties) {
							 | 
						|
								      dst[name] = src[name];
							 | 
						|
								  }
							 | 
						|
								}
							 | 
						|
								
							 | 
						|
								function makeSendPropertiesHandler(properties) {
							 | 
						|
								  return function sendProperties(event, sendFn) {
							 | 
						|
								    const data = {type: event.type};
							 | 
						|
								    copyProperties(event, properties, data);
							 | 
						|
								    sendFn(data);
							 | 
						|
								  };
							 | 
						|
								}
							 | 
						|
								
							 | 
						|
								function touchEventHandler(event, sendFn) {
							 | 
						|
								  const touches = [];
							 | 
						|
								  const data = {type: event.type, touches};
							 | 
						|
								  for (let i = 0; i < event.touches.length; ++i) {
							 | 
						|
								    const touch = event.touches[i];
							 | 
						|
								    touches.push({
							 | 
						|
								      pageX: touch.pageX,
							 | 
						|
								      pageY: touch.pageY,
							 | 
						|
								    });
							 | 
						|
								  }
							 | 
						|
								  sendFn(data);
							 | 
						|
								}
							 | 
						|
								
							 | 
						|
								// The four arrow keys
							 | 
						|
								const orbitKeys = {
							 | 
						|
								  '37': true,  // left
							 | 
						|
								  '38': true,  // up
							 | 
						|
								  '39': true,  // right
							 | 
						|
								  '40': true,  // down
							 | 
						|
								};
							 | 
						|
								function filteredKeydownEventHandler(event, sendFn) {
							 | 
						|
								  const {keyCode} = event;
							 | 
						|
								  if (orbitKeys[keyCode]) {
							 | 
						|
								    event.preventDefault();
							 | 
						|
								    keydownEventHandler(event, sendFn);
							 | 
						|
								  }
							 | 
						|
								}
							 | 
						|
								
							 | 
						|
								let nextProxyId = 0;
							 | 
						|
								class ElementProxy {
							 | 
						|
								  constructor(element, worker, eventHandlers) {
							 | 
						|
								    this.id = nextProxyId++;
							 | 
						|
								    this.worker = worker;
							 | 
						|
								    const sendEvent = (data) => {
							 | 
						|
								      this.worker.postMessage({
							 | 
						|
								        type: 'event',
							 | 
						|
								        id: this.id,
							 | 
						|
								        data,
							 | 
						|
								      });
							 | 
						|
								    };
							 | 
						|
								
							 | 
						|
								    // register an id
							 | 
						|
								    worker.postMessage({
							 | 
						|
								      type: 'makeProxy',
							 | 
						|
								      id: this.id,
							 | 
						|
								    });
							 | 
						|
								    sendSize();
							 | 
						|
								    for (const [eventName, handler] of Object.entries(eventHandlers)) {
							 | 
						|
								      element.addEventListener(eventName, function(event) {
							 | 
						|
								        handler(event, sendEvent);
							 | 
						|
								      });
							 | 
						|
								    }
							 | 
						|
								
							 | 
						|
								    function sendSize() {
							 | 
						|
								      const rect = element.getBoundingClientRect();
							 | 
						|
								      sendEvent({
							 | 
						|
								        type: 'size',
							 | 
						|
								        left: rect.left,
							 | 
						|
								        top: rect.top,
							 | 
						|
								        width: element.clientWidth,
							 | 
						|
								        height: element.clientHeight,
							 | 
						|
								      });
							 | 
						|
								    }
							 | 
						|
								
							 | 
						|
								    // really need to use ResizeObserver
							 | 
						|
								    window.addEventListener('resize', sendSize);
							 | 
						|
								  }
							 | 
						|
								}
							 | 
						|
								
							 | 
						|
								function startWorker(canvas) {
							 | 
						|
								  canvas.focus();
							 | 
						|
								  const offscreen = canvas.transferControlToOffscreen();
							 | 
						|
								  const worker = new Worker('offscreencanvas-worker-orbitcontrols.js', {type: 'module'});
							 | 
						|
								
							 | 
						|
								  const eventHandlers = {
							 | 
						|
								    contextmenu: preventDefaultHandler,
							 | 
						|
								    mousedown: mouseEventHandler,
							 | 
						|
								    mousemove: mouseEventHandler,
							 | 
						|
								    mouseup: mouseEventHandler,
							 | 
						|
								    pointerdown: mouseEventHandler,
							 | 
						|
								    pointermove: mouseEventHandler,
							 | 
						|
								    pointerup: mouseEventHandler,
							 | 
						|
								    touchstart: touchEventHandler,
							 | 
						|
								    touchmove: touchEventHandler,
							 | 
						|
								    touchend: touchEventHandler,
							 | 
						|
								    wheel: wheelEventHandler,
							 | 
						|
								    keydown: filteredKeydownEventHandler,
							 | 
						|
								  };
							 | 
						|
								  const proxy = new ElementProxy(canvas, worker, eventHandlers);
							 | 
						|
								  worker.postMessage({
							 | 
						|
								    type: 'start',
							 | 
						|
								    canvas: offscreen,
							 | 
						|
								    canvasId: proxy.id,
							 | 
						|
								  }, [offscreen]);
							 | 
						|
								  console.log('using OffscreenCanvas');  /* eslint-disable-line no-console */
							 | 
						|
								}
							 | 
						|
								
							 | 
						|
								function startMainPage(canvas) {
							 | 
						|
								  init({canvas, inputElement: canvas});
							 | 
						|
								  console.log('using regular canvas');  /* eslint-disable-line no-console */
							 | 
						|
								}
							 | 
						|
								
							 | 
						|
								function main() {  /* eslint consistent-return: 0 */
							 | 
						|
								  const canvas = document.querySelector('#c');
							 | 
						|
								  if (canvas.transferControlToOffscreen) {
							 | 
						|
								    startWorker(canvas);
							 | 
						|
								  } else {
							 | 
						|
								    startMainPage(canvas);
							 | 
						|
								  }
							 | 
						|
								}
							 | 
						|
								
							 | 
						|
								main();
							 | 
						|
								</script>
							 | 
						|
								</html>
							 | 
						|
								
							 | 
						|
								
							 |