viewer/svgoverlay.js
import * as mat4 from "./glmatrix/mat4.js";
import * as vec3 from "./glmatrix/vec3.js";
let tmp = vec3.create();
/**
* A SVG overlay that is synced with the WebGL viewport for efficiently rendering
* two-dimensional elements such as text, that are not easily rendered using WebGL.
*
* @export
* @class SvgOverlay
*/
export class SvgOverlay {
constructor(domNode, camera) {
this.track = domNode;
this.camera = camera;
let svg = this.svg = this.create("svg", {id:"viewerOverlay"}, {
padding: 0,
margin: 0,
position: "absolute",
zIndex: 10000,
display: "block",
"pointer-events": "none"
});
document.body.appendChild(svg);
this.resize();
this.camera.listeners.push(this.update.bind(this));
this._orbitCenter = this.create("circle", {
visibility: "hidden",
r: 6,
fill: "white",
stroke: "black",
"fill-opacity": 0.4
});
window.addEventListener("resize", this.resize.bind(this), false);
}
update() {
if (this.camera.orbitting != this.lastOrbitting) {
this._orbitCenter.setAttribute("visibility", this.camera.orbitting ? "visible" : "hidden");
this.lastOrbitting = this.camera.orbitting
}
if (this.camera.orbitting) {
vec3.transformMat4(tmp, this.camera.center, this.camera.viewProjMatrix);
this._orbitCenter.setAttribute("cx", +tmp[0] * this.w + this.w);
this._orbitCenter.setAttribute("cy", -tmp[1] * this.h + this.h);
}
}
create(tag, attrs, style) {
let elem = document.createElementNS("http://www.w3.org/2000/svg", tag);
for (let [k, v] of Object.entries(attrs || {})) {
elem.setAttribute(k, v);
}
let s = elem.style;
for (let [k, v] of Object.entries(style || {})) {
s[k] = v;
}
if (this.svg) {
this.svg.appendChild(elem);
}
return elem;
}
resize() {
function getElementXY(e) {
var x = 0, y = 0;
while (e) {
x += (e.offsetLeft-e.scrollLeft);
y += (e.offsetTop-e.scrollTop);
e = e.offsetParent;
}
var bodyRect = document.body.getBoundingClientRect();
return {
x: (x - bodyRect.left),
y: (y - bodyRect.top)
};
}
let svgStyle = this.svg.style;
var xy = getElementXY(this.track);
svgStyle.left = xy.x + "px";
svgStyle.top = xy.y + "px";
svgStyle.width = (this.w = this.track.clientWidth) + "px";
svgStyle.height = (this.h = this.track.clientHeight) + "px";
this.svg.setAttribute("width", this.w);
this.svg.setAttribute("height", this.h);
this.svg.setAttribute("viewBox", "0 0 " + this.w + " " + this.h);
this.w /= 2.;
this.h /= 2.;
this.aspect = this.w / this.h;
}
}