initSpriteTooltip = () => {
const font = "9pt Tahoma",
canvas = document.createElement("canvas"),
ctx = canvas.getContext("2d");
ctx.font = font;
const maxWidth = Math.ceil(calcWidth()),
tm = ctx.measureText("Z"),
fontHeight = tm.fontBoundingBoxAscent + tm.fontBoundingBoxDescent;
canvas.width = maxWidth;
canvas.height = fontHeight * 2 + 10;
const texture = new THREE.CanvasTexture(canvas);
const material = new THREE.SpriteMaterial({ map: texture });
const sprite = new THREE.Sprite(material);
sprite.center.set(0, 1);
sprite.scale.set(maxWidth, canvas.height, 1);
sceneOrtho.add(sprite);
const tooltip = {
sprite,
attach: function () {},
update: function (target) {
drawTooltip(target);
sprite.position.set(mouse.screen.x -width / 2, -mouse.screen.y + height / 2, 1);
},
clear: function () {
ctx.clearRect(0, 0, canvas.width, canvas.height);
},
dispose: function () {
sceneOrtho.remove(this.sprite);
sprite.geometry.dispose();
sprite.material.map.dispose();
sprite.material.dispose();
}
}
return tooltip;
function calcWidth() {
let maxWidth = 0;
getNodesAt(0)[0].descendants().forEach(node => {
const w = ctx.measureText(getNodeFullName(node)).width;
if (w > maxWidth) maxWidth = w;
});
return maxWidth;
}
function drawTooltip(target) {
ctx.font = font;
const texts = [getNodeFullName(target.info), format(target.info.value)],
w = Math.max(...texts.map(d => ctx.measureText(d).width)),
dims = { w: w + 10, h: fontHeight * texts.length + 10 };
ctx.clearRect(0, 0, dims.w, dims.h);
ctx.fillStyle = "rgba(255, 255, 255, 0.75)";
ctx.fillRect(0, 0, dims.w, dims.h);
ctx.fillStyle = "black";
ctx.lineWidth = 0.5;
ctx.beginPath();
ctx.rect(0, 0, dims.w, dims.h);
ctx.stroke();
texts.forEach((t, i) => ctx.fillText(t, 5, fontHeight * i + fontHeight));
texture.needsUpdate = true;
}
}