Bachelorarbeit/packages/modelviewer.dev/examples/ux-pan.html

141 lines
5.0 KiB
HTML

<!DOCTYPE html>
<html lang="en">
<head>
<title>&lt;model-viewer&gt;</title>
<meta charset="utf-8">
<meta name="description" content="&lt;model-viewer&gt;">
<meta name="viewport" content="width=device-width, initial-scale=1">
<link type="text/css" href="../styles/ux-test.css" rel="stylesheet" />
<link rel="shortcut icon" type="image/png" href="../assets/favicon.png"/>
<script type='module' src='https://modelviewer.dev/node_modules/@google/model-viewer/dist/model-viewer.min.js'></script>
</head>
<body>
<h1>Product details</h1>
<model-viewer
src='../assets/ShopifyModels/Chair.glb'
poster='../assets/ShopifyModels/Chair.png'
camera-controls
shadow-intensity='1'
interaction-prompt='none'
touch-action='none'
style='background-color: #F7F7F7;'
oncontextmenu="return false;">
</model-viewer>
<p>It's ideal for placement in a cozy living room seating group, a bedroom, rec room, or den.
This attractive recliner has a sturdy frame covered with an easy-to-maintain pleather.
This piece gives you a suitable place for relaxation.</p>
<script type="module">
const modelViewer = document.querySelector('model-viewer');
const tapDistance = 2;
let panning = false;
let panX, panY;
let startX, startY;
let lastX, lastY;
let metersPerPixel;
const startPan = () => {
const orbit = modelViewer.getCameraOrbit();
const {theta, phi, radius} = orbit;
const psi = theta - modelViewer.turntableRotation;
metersPerPixel = 0.75 * radius / modelViewer.getBoundingClientRect().height;
panX = [-Math.cos(psi), 0, Math.sin(psi)];
panY = [
-Math.cos(phi) * Math.sin(psi),
Math.sin(phi),
-Math.cos(phi) * Math.cos(psi)
];
modelViewer.interactionPrompt = 'none';
};
const movePan = (thisX, thisY) => {
const dx = (thisX - lastX) * metersPerPixel;
const dy = (thisY - lastY) * metersPerPixel;
lastX = thisX;
lastY = thisY;
const target = modelViewer.getCameraTarget();
target.x += dx * panX[0] + dy * panY[0];
target.y += dx * panX[1] + dy * panY[1];
target.z += dx * panX[2] + dy * panY[2];
modelViewer.cameraTarget = `${target.x}m ${target.y}m ${target.z}m`;
// This pauses turntable rotation
modelViewer.dispatchEvent(new CustomEvent(
'camera-change', {detail: {source: 'user-interaction'}}));
};
const recenter = (pointer) => {
panning = false;
if (Math.abs(pointer.clientX - startX) > tapDistance ||
Math.abs(pointer.clientY - startY) > tapDistance)
return;
const hit = modelViewer.positionAndNormalFromPoint(pointer.clientX, pointer.clientY);
modelViewer.cameraTarget =
hit == null ? 'auto auto auto' : hit.position.toString();
};
modelViewer.addEventListener('mousedown', (event) => {
startX = event.clientX;
startY = event.clientY;
panning = event.button === 2 || event.ctrlKey || event.metaKey ||
event.shiftKey;
if (!panning)
return;
lastX = startX;
lastY = startY;
startPan();
event.stopPropagation();
}, true);
modelViewer.addEventListener('touchstart', (event) => {
const {targetTouches, touches} = event;
startX = targetTouches[0].clientX;
startY = targetTouches[0].clientY;
panning = targetTouches.length === 2 && targetTouches.length === touches.length;
if (!panning)
return;
lastX = 0.5 * (targetTouches[0].clientX + targetTouches[1].clientX);
lastY = 0.5 * (targetTouches[0].clientY + targetTouches[1].clientY);
startPan();
}, true);
self.addEventListener('mousemove', (event) => {
if (!panning)
return;
movePan(event.clientX, event.clientY);
event.stopPropagation();
}, true);
modelViewer.addEventListener('touchmove', (event) => {
if (!panning || event.targetTouches.length !== 2)
return;
const {targetTouches} = event;
const thisX = 0.5 * (targetTouches[0].clientX + targetTouches[1].clientX);
const thisY = 0.5 * (targetTouches[0].clientY + targetTouches[1].clientY);
movePan(thisX, thisY);
}, true);
self.addEventListener('mouseup', (event) => {
recenter(event);
}, true);
modelViewer.addEventListener('touchend', (event) => {
if (event.targetTouches.length === 0) {
recenter(event.changedTouches[0]);
if (event.cancelable) {
event.preventDefault();
}
}
}, true);
</script>
</body>
</html>