关于model-viewer的两项技术咨询:获取模型点击位置坐标与实现用户自主动态添加标注
Hey there! Awesome that model-viewer aligns so well with your use case. Let's break down solutions for both your needs—adding dynamic annotations and capturing click coordinates on your 3D model.
Model-viewer makes it straightforward to add annotations on the fly using vanilla JavaScript. You can dynamically create <annotation> elements, configure their properties, and attach them directly to your <model-viewer> instance.
Here's a practical example that lets users input annotation details and place it (we'll tie this to click coordinates later, but this shows the core dynamic creation):
// Get your model-viewer element const modelViewer = document.querySelector('model-viewer'); // Function to add a dynamic annotation function addDynamicAnnotation(position, normal, annotationText) { // Create the annotation element const annotation = document.createElement('annotation'); // Configure required attributes annotation.slot = 'annotations'; annotation.dataset.position = position.join(' '); // Format: "x y z" annotation.dataset.normal = normal.join(' '); // Format: "x y z" // Add your annotation content (can be HTML too!) annotation.innerHTML = ` <div class="annotation-content"> <h3>Custom Annotation</h3> <p>${annotationText}</p> </div> `; // Attach the annotation to model-viewer modelViewer.appendChild(annotation); // Optional: Trigger a refresh to ensure the annotation renders modelViewer.requestUpdate(); } // Example usage (you can tie this to a user input form or click event) // addDynamicAnnotation([1, 0.5, 0], [0, 1, 0], "This is a dynamically added note!");
Key notes:
- The
data-positionattribute defines where the annotation anchors to the model (3D world coordinates). data-normalsets the direction the annotation faces (usually a unit vector pointing outward from the model surface).- You can style the annotation content with custom CSS to match your app's design.
To get the exact 3D coordinates where a user clicks the model, you'll use model-viewer's hitTest() method. This method checks if the click intersects the model and returns detailed intersection data.
Here's how to implement it:
const modelViewer = document.querySelector('model-viewer'); modelViewer.addEventListener('click', (event) => { // Get the mouse position relative to the model-viewer element const rect = modelViewer.getBoundingClientRect(); const x = event.clientX - rect.left; const y = event.clientY - rect.top; // Perform hit test to check if we clicked the model const hitResults = modelViewer.hitTest(x, y); if (hitResults.length > 0) { // Grab the first hit result (closest to the camera) const hit = hitResults[0]; // Extract 3D position coordinates const position = hit.position; // Returns a DOMPoint with x, y, z properties const normal = hit.normal; // Surface normal at the click point console.log(`Clicked position: (${position.x.toFixed(2)}, ${position.y.toFixed(2)}, ${position.z.toFixed(2)})`); console.log(`Surface normal: (${normal.x.toFixed(2)}, ${normal.y.toFixed(2)}, ${normal.z.toFixed(2)})`); // Bonus: Use these coordinates to add an annotation immediately! addDynamicAnnotation( [position.x, position.y, position.z], [normal.x, normal.y, normal.z], "User-added annotation here!" ); } else { console.log("Clicked outside the model"); } });
How this works:
- We calculate the click position relative to the model-viewer element (since
clientX/clientYare relative to the viewport). hitTest()returns an array of intersection results; if it's non-empty, we clicked the model.- The
positionproperty gives you the exact 3D world coordinates of the click, andnormaltells you the direction the model surface is facing at that point.
Combining both features gives you a complete workflow: users click the model to get coordinates, then you can either auto-add an annotation or let them input text before placing it.
内容的提问来源于stack exchange,提问作者Angad_Srivastav

