body{
overflow: hidden;
margin: 0;
}
<script async src="https://ga.jspm.io/npm:es-module-shims@1.6.3/dist/es-module-shims.js" crossorigin="anonymous"></script>
<script type="importmap">
{
"imports": {
"three": "https://unpkg.com/three@0.153.0/build/three.module.js",
"three/addons/": "https://unpkg.com/three@0.153.0/examples/jsm/"
}
}
</script>
<script type="module">
import * as THREE from "three";
console.clear();
let scene = new THREE.Scene();
scene.background = new THREE.Color(0xffffff);
let frustumSize = 10;
let aspect = innerWidth / innerHeight;
let camera = new THREE.OrthographicCamera(frustumSize * aspect / - 2, frustumSize * aspect / 2, frustumSize / 2, frustumSize / - 2, 1, 100);
camera.position.set(0, 0, 10);
camera.lookAt(scene.position);
let renderer = new THREE.WebGLRenderer({
antialias: true
});
renderer.setSize(innerWidth, innerHeight);
document.body.appendChild(renderer.domElement);
window.addEventListener("resize", (event) => {
camera.aspect = innerWidth / innerHeight;
camera.updateProjectionMatrix();
renderer.setSize(innerWidth, innerHeight);
});
let pts = [
new THREE.Vector2(-3, 3),
new THREE.Vector2(-3, -2),
new THREE.Vector2(2, -3),
new THREE.Vector2(3, 3.5)
];
for(let i = 0; i < pts.length; i++){
let p1 = pts[i];
setPoint(p1);
if (i == pts.length - 1) continue;
let p2 = pts[i+1];
setLine(p1, p2);
let midP = new THREE.Vector3().lerpVectors(p1, p2, 0.5);
let shift = new THREE.Vector2().subVectors(p2, p1).normalize();
let angle = shift.angle();
let swapX = shift.x;
let swapY = shift.y;
shift.set(-swapY, swapX).negate().setLength(0.5);
let distance = p1.distanceTo(p2);
setMarker(midP, shift, angle, distance);
}
function setPoint(pos){
let g = new THREE.RingGeometry(0.5, 1, 32);
let m = new THREE.MeshBasicMaterial({color: "teal"});
let o = new THREE.Mesh(g, m);
o.scale.setScalar(0.1);
o.position.set(pos.x, pos.y, 0.01);
scene.add(o);
}
function setLine(pos1, pos2){
let g = new THREE.BufferGeometry().setFromPoints([pos1, pos2]);
let m = new THREE.LineBasicMaterial({color: "maroon"});
let l = new THREE.Line(g, m);
scene.add(l);
}
function setMarker(pos, shift, angle, distance){
let g = new THREE.PlaneGeometry(4, 1);
let m = new THREE.MeshBasicMaterial({
color: "black",
transparent: true,
map: getDistanceTexture(distance)
});
let o = new THREE.Mesh(g, m);
o.position.set(pos.x + shift.x, pos.y + shift.y, 0);
o.rotation.z = angle;
o.scale.setScalar(1);
scene.add(o);
}
function getDistanceTexture(value){
let text = value.toFixed(1) + "m";
let c = document.createElement("canvas");
c.width = 64 * 4;
c.height = 64;
let ctx = c.getContext("2d");
ctx.textAlign = "center";
ctx.textBaseline = "middle";
ctx.font = "60px Arial";
ctx.fillStyle = "white";
ctx.fillText(text, 64 * 2, 64 / 2);
let ct = new THREE.CanvasTexture(c);
return ct;
}
renderer.setAnimationLoop((_) => {
renderer.render(scene, camera);
});
</script>