-
Notifications
You must be signed in to change notification settings - Fork 287
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
XCD-147 Implement an example of annotation touch create
- Loading branch information
1 parent
fb7f0ae
commit 1b6ba65
Showing
2 changed files
with
246 additions
and
0 deletions.
There are no files selected for viewing
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
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,245 @@ | ||
<!doctype html> | ||
<html> | ||
<head> | ||
<meta charset="utf-8"> | ||
<meta http-equiv="X-UA-Compatible" content="IE=edge,chrome=1"> | ||
<meta name="viewport" content="width=device-width, initial-scale=1"> | ||
<title>xeokit Example</title> | ||
<link href="../css/pageStyle.css" rel="stylesheet"/> | ||
<script src="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/5.13.0/js/all.min.js"></script> | ||
Check warning Code scanning / CodeQL Inclusion of functionality from an untrusted source Medium
Script loaded from content delivery network with no integrity check.
|
||
|
||
<style> | ||
|
||
.annotation-marker { | ||
color: #ffffff; | ||
line-height: 1.8; | ||
text-align: center; | ||
font-family: "monospace"; | ||
font-weight: bold; | ||
position: absolute; | ||
width: 25px; | ||
height: 25px; | ||
border-radius: 15px; | ||
border: 2px solid #ffffff; | ||
background: black; | ||
visibility: hidden; | ||
box-shadow: 5px 5px 15px 1px #000000; | ||
z-index: 0; | ||
} | ||
|
||
.annotation-label { | ||
position: absolute; | ||
max-width: 250px; | ||
min-height: 50px; | ||
padding: 8px; | ||
padding-left: 12px; | ||
padding-right: 12px; | ||
background: #ffffff; | ||
color: #000000; | ||
-webkit-border-radius: 3px; | ||
-moz-border-radius: 3px; | ||
border-radius: 8px; | ||
border: #ffffff solid 2px; | ||
box-shadow: 5px 5px 15px 1px #000000; | ||
z-index: 90000; | ||
} | ||
|
||
.annotation-label:after { | ||
content: ''; | ||
position: absolute; | ||
border-style: solid; | ||
border-width: 8px 12px 8px 0; | ||
border-color: transparent white; | ||
display: block; | ||
width: 0; | ||
z-index: 1; | ||
margin-top: -11px; | ||
left: -12px; | ||
top: 20px; | ||
} | ||
|
||
.annotation-label:before { | ||
content: ''; | ||
position: absolute; | ||
border-style: solid; | ||
border-width: 9px 13px 9px 0; | ||
border-color: transparent #ffffff; | ||
display: block; | ||
width: 0; | ||
z-index: 0; | ||
margin-top: -12px; | ||
left: -15px; | ||
top: 20px; | ||
} | ||
|
||
.annotation-title { | ||
font: normal 20px arial, serif; | ||
margin-bottom: 8px; | ||
} | ||
|
||
.annotation-desc { | ||
font: normal 14px arial, serif; | ||
} | ||
|
||
</style> | ||
</head> | ||
|
||
<body> | ||
<input type="checkbox" id="info-button"/> | ||
<label for="info-button" class="info-button"><i class="far fa-3x fa-question-circle"></i></label> | ||
<canvas id="myCanvas"></canvas> | ||
<div class="slideout-sidebar"> | ||
<img class="info-icon" src="../../assets/images/annotation_icon.png"/> | ||
<h1>AnnotationsPlugin</h1> | ||
<h2>Click or tap the model to create annotations</h2> | ||
<h3>Components Used</h3> | ||
<ul> | ||
<li> | ||
<a href="../../docs/class/src/viewer/Viewer.js~Viewer.html" | ||
target="_other">Viewer</a> | ||
</li> | ||
<li> | ||
<a href="../../docs/class/src/plugins/XKTLoaderPlugin/XKTLoaderPlugin.js~XKTLoaderPlugin.html" | ||
target="_other">XKTLoaderPlugin</a> | ||
</li> | ||
<li> | ||
<a href="../../docs/class/src/plugins/AnnotationsPlugin/AnnotationsPlugin.js~AnnotationsPlugin.html" | ||
target="_other">AnnotationsPlugin</a> | ||
</li> | ||
</ul> | ||
<h3>Resources</h3> | ||
<ul> | ||
<li> | ||
<a href="http://openifcmodel.cs.auckland.ac.nz/Model/Details/274" | ||
target="_other">Model source</a> | ||
</li> | ||
</ul> | ||
</div> | ||
</body> | ||
|
||
<script type="module"> | ||
|
||
//------------------------------------------------------------------------------------------------------------------ | ||
// Import the modules we need for this example | ||
//------------------------------------------------------------------------------------------------------------------ | ||
|
||
import { AnnotationsPlugin, PointerCircle, touchPointSelector, Viewer, XKTLoaderPlugin } from "../../dist/xeokit-sdk.min.es.js"; | ||
|
||
//------------------------------------------------------------------------------------------------------------------ | ||
// Create a Viewer and arrange the camera | ||
//------------------------------------------------------------------------------------------------------------------ | ||
|
||
const viewer = new Viewer({ | ||
canvasId: "myCanvas" | ||
}); | ||
|
||
viewer.camera.eye = [-3.93, 2.85, 27.01]; | ||
viewer.camera.look = [4.40, 3.72, 8.89]; | ||
viewer.camera.up = [-0.01, 0.99, 0.039]; | ||
|
||
//------------------------------------------------------------------------------------------------------------------ | ||
// Load a model | ||
//------------------------------------------------------------------------------------------------------------------ | ||
|
||
const xktLoader = new XKTLoaderPlugin(viewer); | ||
|
||
const sceneModel = xktLoader.load({ | ||
id: "myModel", | ||
src: "../../assets/models/xkt/v10/glTF-Embedded/Duplex_A_20110505.glTFEmbedded.xkt", | ||
edges: true | ||
}); | ||
|
||
//------------------------------------------------------------------------------------------------------------------ | ||
// Create an AnnotationsPlugin, with which we'll create annotations | ||
//------------------------------------------------------------------------------------------------------------------ | ||
|
||
const annotations = new AnnotationsPlugin(viewer, { | ||
|
||
markerHTML: "<div class='annotation-marker' style='background-color: {{markerBGColor}};'>{{glyph}}</div>", | ||
labelHTML: "<div class='annotation-label' style='background-color: {{labelBGColor}};'><div class='annotation-title'>{{title}}</div><div class='annotation-desc'>{{description}}</div></div>", | ||
|
||
values: { | ||
markerBGColor: "red", | ||
glyph: "X", | ||
title: "Untitled", | ||
description: "No description" | ||
}, | ||
|
||
// Amount to offset each Annotation from its Entity surface (0.3 is the default value). | ||
// This is useful when the Annotation is occludable, which is when it is hidden when occluded | ||
// by other objects. When occludable, there is potential for the Annotation#worldPos to become | ||
// visually embedded within the surface of its Entity when viewed from a distance. This happens | ||
// as a result of limited GPU accuracy GPU accuracy, especially when the near and far view-space clipping planes, | ||
// specified by Perspective#near and Perspective#far, or Ortho#near and Perspective#far, are far away from each other. | ||
// | ||
// Offsetting the Annotation may ensure that it does become visually embedded within its Entity. We may also | ||
// prevent this by keeping the distance between the view-space clipping planes to a minimum. In general, a good | ||
// default value for Perspective#far and Ortho#far is around ````2.000````. | ||
|
||
surfaceOffset: 0.1 | ||
}); | ||
|
||
//------------------------------------------------------------------------------------------------------------------ | ||
// Use the AnnotationsPlugin to create an annotation wherever we tap on an object | ||
//------------------------------------------------------------------------------------------------------------------ | ||
|
||
// This creates a function that will attach touch listeners to canvas, and handle tap events | ||
const setupTouchSelector = touchPointSelector( | ||
viewer, | ||
new PointerCircle(viewer), // needed to indicate tap duration to user | ||
(orig, dir) => { | ||
// find an intersection of a ray from the camera through the scene entities | ||
const pickResult = viewer.scene.pick({ | ||
origin: orig, | ||
direction: dir, | ||
pickSurface: true | ||
}); | ||
return pickResult && pickResult.worldPos; | ||
}); | ||
|
||
(function setupCreateAnnotation(id) { | ||
|
||
// This is a handler to add a single annotation | ||
|
||
// An annotation is created ... | ||
const annotation = annotations.createAnnotation({ | ||
id: "myAnnotation" + id, | ||
// occludable: true, | ||
markerShown: true, | ||
labelShown: true, | ||
values: { | ||
glyph: "A" + id, | ||
title: "My annotation " + id, | ||
description: "My description " + id | ||
}, | ||
}); | ||
|
||
const setAnnotationPos = worldPos => { | ||
if (worldPos) { | ||
annotation.worldPos = worldPos; | ||
} | ||
annotation.setMarkerShown(!! worldPos); | ||
annotation.setLabelShown(!! worldPos); | ||
}; | ||
|
||
setAnnotationPos(null); // initialy hide the annotation until the first user interaction | ||
|
||
// ... and touch events are handled through setupTouchSelector callbacks | ||
setupTouchSelector( | ||
() => setAnnotationPos(null), // onCancel continue the action | ||
(canvasPos, worldPos) => setAnnotationPos(worldPos), // onChange update annotation's position | ||
(canvasPos, worldPos) => { // onCommit | ||
if (worldPos) { // if the point selected by user was on top | ||
setAnnotationPos(worldPos); // of an attachable surface | ||
annotation.occludable = true; // then fix the annotation in place | ||
setupCreateAnnotation(id + 1); // and move on to next annotation | ||
} else { | ||
annotation.destroy(); // otherwise if the point was dragged by user | ||
setupCreateAnnotation(id); // outside attachable surfaces then start over | ||
} | ||
}); | ||
|
||
})(1); // first `id` to start with | ||
|
||
</script> | ||
</html> |
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