Last active
April 7, 2024 21:42
-
-
Save superstes/0e8ec446715d993014cb3a92b975f8a8 to your computer and use it in GitHub Desktop.
ThreeJS - Let HTML-Element follow point (<model-viewer> annotation-like)
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
/* | |
NOTES: | |
basic source: https://codepen.io/lamb_1128/pen/xxQogxj | |
this functionality can be compared to the annotations seen at: https://modelviewer.dev/examples/annotations/index.html | |
but this has a very minimalistic approach | |
*/ | |
/* css | |
.annotation { | |
position: absolute; | |
# optional | |
background-color: #606060; | |
color: whitesmoke; | |
border-radius: 25%; | |
padding: 10px; | |
overflow: hidden; | |
opacity: 80%; | |
max-width: 10vw; | |
font-size: small; | |
} | |
*/ | |
/* html | |
... | |
<body> | |
<div id="annotation-anchor"></div><!-- there might be a cleaner approach --> | |
</body> | |
*/ | |
const ANNOTATION_ID = 'annotation1'; | |
const ANCHOR_ID = 'annotation-anchor'; | |
const ANNOTATION_CLS = 'annotation'; | |
_createAnnotation() { | |
let popup = document.createElement("div"); | |
popup.id = ANNOTATION_ID; | |
popup.classList.add(ANNOTATION_CLS); | |
popup.setAttribute("hidden", "hidden"); | |
popup.innerText = "Test Annotation"; | |
document.body.insertBefore(popup, document.getElementById(ANCHOR_ID)); | |
return popup; | |
} | |
updateAnnotation(camera, follow) { | |
let popup = document.getElementById(ANNOTATION_ID); | |
if (popup === null) { | |
popup = _createAnnotation(); | |
} | |
let target = new THREE.Vector3(); | |
target.copy(follow); | |
target.project(camera); | |
target.x = Math.round((0.57 + target.x / 2) * (window.innerWidth / window.devicePixelRatio)); | |
target.y = Math.round((0.57 - target.y / 2) * (window.innerHeight / window.devicePixelRatio)); | |
popup.style.top = `${target.y}px`; | |
popup.style.left = `${target.x}px`; | |
popup.removeAttribute("hidden"); | |
} | |
removeAnnotation() { | |
try { | |
document.getElementById(ANNOTATION_ID).remove(); | |
} catch { | |
// already deleted | |
} | |
} | |
const CAM_FOV = 60; | |
const aspect = 1920 / 1080; | |
const near = 1; | |
const far = 25000.0; | |
const camera = new THREE.PerspectiveCamera(CAM_FOV, aspect, near, far); | |
let pointToFollow = new THREE.Vector3(1, 1, 1); | |
// fov-check source: https://gist.github.com/superstes/4f11649ff089b45a29bc44f147c226c2 | |
... | |
if (inFrontOfCamera(camera.position, cameraDirection, pointToFollow)) { | |
updateAnnotation(camera); | |
} else { | |
removeAnnotation(); | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Using
window.innerWidth
andwindow.innerHeight
assuming the 3js canvas is filling the whole screen!Otherwise use the
width
/height
ofrenderer.domElement
(WebGL renderer instance)