ami.js
Version:
<p align="center"> <img src="https://cloud.githubusercontent.com/assets/214063/23213764/78ade038-f90c-11e6-8208-4fcade5f3832.png" width="60%"> </p>
330 lines (258 loc) • 7.98 kB
JavaScript
import WidgetsBase from './widgets.base';
import WidgetsHandle from './widgets.handle';
import {Vector3} from 'three';
/**
* @module widgets/handle
*
*/
export default class WidgetsRuler extends WidgetsBase {
constructor(targetMesh, controls, camera, container) {
super(container);
this._targetMesh = targetMesh;
this._controls = controls;
this._camera = camera;
this._active = true;
this._lastEvent = null;
this._worldPosition = new Vector3();
if (this._targetMesh !== null) {
this._worldPosition = this._targetMesh.position;
}
// mesh stuff
this._material = null;
this._geometry = null;
this._mesh = null;
// dom stuff
this._line = null;
this._distance = null;
// add handles
this._handles = [];
// first handle
let firstHandle =
new WidgetsHandle(this._targetMesh, this._controls, this._camera, this._container);
firstHandle.worldPosition = this._worldPosition;
firstHandle.hovered = true;
this.add(firstHandle);
this._handles.push(firstHandle);
let secondHandle =
new WidgetsHandle(this._targetMesh, this._controls, this._camera, this._container);
secondHandle.worldPosition = this._worldPosition;
secondHandle.hovered = true;
// active and tracking might be redundant
secondHandle.active = true;
secondHandle.tracking = true;
this.add(secondHandle);
this._handles.push(secondHandle);
// Create ruler
this.create();
this.initOffsets();
this.onMove = this.onMove.bind(this);
this.onEndControl = this.onEndControl.bind(this);
this.addEventListeners();
}
addEventListeners() {
this._container.addEventListener('mousewheel', this.onMove);
this._container.addEventListener('DOMMouseScroll', this.onMove);
this._controls.addEventListener('end', this.onEndControl);
}
removeEventListeners() {
this._container.removeEventListener('mousewheel', this.onMove);
this._container.removeEventListener('DOMMouseScroll', this.onMove);
this._controls.removeEventListener('end', this.onEndControl);
}
onMove(evt) {
this._lastEvent = evt;
this._dragged = true;
this._handles[0].onMove(evt);
this._handles[1].onMove(evt);
this._hovered = this._handles[0].hovered || this._handles[1].hovered;
this.update();
}
onStart(evt) {
this._lastEvent = evt;
this._dragged = false;
this._handles[0].onStart(evt);
this._handles[1].onStart(evt);
this._active = this._handles[0].active || this._handles[1].active;
this.update();
}
onEnd(evt) {
this._lastEvent = evt;
// First Handle
this._handles[0].onEnd(evt);
// window.console.log(this);
// Second Handle
if (this._dragged || !this._handles[1].tracking) {
this._handles[1].tracking = false;
this._handles[1].onEnd(evt);
} else {
this._handles[1].tracking = false;
}
// State of ruler widget
this._active = this._handles[0].active || this._handles[1].active;
this.update();
}
onEndControl() {
if (!this._lastEvent) {
return;
}
window.requestAnimationFrame(() => {
this.onMove(this._lastEvent);
});
}
create() {
this.createMesh();
this.createDOM();
}
hideDOM() {
this._line.style.display = 'none';
this._distance.style.display = 'none';
for (let index in this._handles) {
this._handles[index].hideDOM();
}
}
showDOM() {
this._line.style.display = '';
this._distance.style.display = '';
for (let index in this._handles) {
this._handles[index].showDOM();
}
}
hideMesh() {
this.visible = false;
}
showMesh() {
this.visible = true;
}
show() {
this.showDOM();
this.showMesh();
}
hide() {
this.hideDOM();
this.hideMesh();
}
update() {
this.updateColor();
// update handles
this._handles[0].update();
this._handles[1].update();
// mesh stuff
this.updateMeshColor();
this.updateMeshPosition();
// DOM stuff
this.updateDOMColor();
this.updateDOMPosition();
}
createMesh() {
// geometry
this._geometry = new THREE.Geometry();
this._geometry.vertices.push(this._handles[0].worldPosition);
this._geometry.vertices.push(this._handles[1].worldPosition);
// material
this._material = new THREE.LineBasicMaterial();
this.updateMeshColor();
// mesh
this._mesh = new THREE.Line(this._geometry, this._material);
this._mesh.visible = true;
// add it!
this.add(this._mesh);
}
updateMeshColor() {
if (this._material) {
this._material.color.set(this._color);
}
}
updateMeshPosition() {
if (this._geometry) {
this._geometry.verticesNeedUpdate = true;
}
}
createDOM() {
// add line!
this._line = document.createElement('div');
this._line.setAttribute('id', this.uuid);
this._line.setAttribute('class', 'AMI Widget Ruler');
this._line.style.position = 'absolute';
this._line.style.transformOrigin = '0 100%';
this._line.style.marginTop = '-1px';
this._line.style.height = '2px';
this._line.style.width = '3px';
this._container.appendChild(this._line);
// add distance!
this._distance = document.createElement('div');
this._distance.setAttribute('class', 'widgets handle distance');
this._distance.style.border = '2px solid';
this._distance.style.backgroundColor = '#F9F9F9';
// this._distance.style.opacity = '0.5';
this._distance.style.color = '#353535';
this._distance.style.padding = '4px';
this._distance.style.position = 'absolute';
this._distance.style.transformOrigin = '0 100%';
this._distance.innerHTML = 'Hello, world!';
this._container.appendChild(this._distance);
this.updateDOMColor();
}
updateDOMPosition() {
// update rulers lines and text!
let x1 = this._handles[0].screenPosition.x;
let y1 = this._handles[0].screenPosition.y;
let x2 = this._handles[1].screenPosition.x;
let y2 = this._handles[1].screenPosition.y;
let x0 = x2;
let y0 = y2;
if (y1 >= y2) {
y0 = y2 - 30;
} else {
y0 = y2 + 30;
}
let length = Math.sqrt((x1-x2)*(x1-x2) + (y1-y2)*(y1-y2));
let angle = Math.atan2(y2 - y1, x2 - x1) * 180 / Math.PI;
let posY = y1 - this._container.offsetHeight;
// update line
let transform = `translate3D(${x1}px,${posY}px, 0)`;
transform += ` rotate(${angle}deg)`;
this._line.style.transform = transform;
this._line.style.width = length + 'px';
// update distance
let w0 = this._handles[0].worldPosition;
let w1 = this._handles[1].worldPosition;
this._distance.innerHTML =
`${
Math.sqrt(
(w0.x-w1.x)*(w0.x-w1.x) +
(w0.y-w1.y)*(w0.y-w1.y) +
(w0.z-w1.z)*(w0.z-w1.z)
).toFixed(2)} mm`;
let posY0 =
y0 - this._container.offsetHeight - this._distance.offsetHeight/2;
x0 -= this._distance.offsetWidth/2;
let transform2 =
`translate3D(${Math.round(x0)}px,${Math.round(posY0)}px, 0)`;
this._distance.style.transform = transform2;
}
updateDOMColor() {
this._line.style.backgroundColor = `${this._color}`;
this._distance.style.borderColor = `${this._color}`;
}
free() {
this._container.removeEventListener('mousewheel', this.onMove);
this._container.removeEventListener('DOMMouseScroll', this.onMove);
this._handles.forEach((h) => {
h.free();
});
this._handles = [];
this._container.removeChild(this._line);
this._container.removeChild(this._distance);
this.remove(this._mesh);
super.free();
}
get worldPosition() {
return this._worldPosition;
}
set worldPosition(worldPosition) {
this._worldPosition = worldPosition;
this._handles[0].worldPosition = this._worldPosition;
this._handles[1].worldPosition = this._worldPosition;
this.update();
}
}