Published
Edited
Oct 7, 2020
1 star
Insert cell
Insert cell
Insert cell
{
const renderer = new THREE.WebGLRenderer({antialias: true});
const controls = new THREE.OrbitControls(camera, renderer.domElement);
invalidation.then(() => renderer.dispose());
renderer.setSize(width, height);
renderer.setPixelRatio(devicePixelRatio);
let fraction = 0;
const up = new THREE.Vector3( 0, 1, 0 );
while (true) {
paths.forEach(d => {
const axis = new THREE.Vector3( );
const newPosition = d.points.getPoint(fraction);
const tangent = d.points.getTangent(fraction);
d.arrow.position.copy(newPosition);
axis.crossVectors( up, tangent ).normalize();
const radians = Math.acos( up.dot( tangent ) );
d.arrow.quaternion.setFromAxisAngle( axis, radians );
});
renderer.render(scene, camera);
fraction +=0.001;
if (fraction > 1) {
fraction = 0;
}
yield renderer.domElement;
}
}
Insert cell
scene = {
const scene = new THREE.Scene();
scene.background = new THREE.Color(0xffffff);

paths.forEach(d => {
scene.add(d.line);
scene.add(d.arrow);
});
const axesHelper = new THREE.AxesHelper( 0.5 );
axesHelper.translateX(1);
scene.add( axesHelper );
const ambientLight = new THREE.AmbientLight(0x0c0c0c, 12);
scene.add(ambientLight);

const spotLight = new THREE.SpotLight(0xffffff);
spotLight.position.set(-0, 30, 30);
spotLight.castShadow = true;
spotLight.intensity = 0.6;
scene.add(spotLight);
return scene;
}
Insert cell
paths = {
const material = new THREE.LineBasicMaterial({
color: 0x9132a8
});
const arrowMaterial = new THREE.MeshPhongMaterial({color: 0x9977ff});
const pathsArray = [];
for(let i=0; i < numberArrows; i++){
const pointsPath = getPointsPath();
const points =pointsPath.curves.reduce((p, d)=> [...p, ...d.getPoints(20)], []);
const geometry = new THREE.BufferGeometry().setFromPoints( points );
pathsArray.push({line: new THREE.Line( geometry, material), points: pointsPath, arrow: new THREE.Mesh(arrow, arrowMaterial)});
}

return pathsArray;
}
Insert cell
getPointsPath = () => {
const pointsPath = new THREE.CurvePath();
const p1 = new THREE.Vector3( d3.randomUniform(-1, 1)(), d3.randomUniform(-1, 1)(),d3.randomUniform(-1, 1)() );
const p2 = new THREE.Vector3( d3.randomUniform(-1, 1)(), d3.randomUniform(-1, 1)(), d3.randomUniform(-1, 1)() );
const p3 = new THREE.Vector3( d3.randomUniform(-1, 1)(), d3.randomUniform(-1, 1)(), d3.randomUniform(-1, 1)() );
const p4 = new THREE.Vector3( d3.randomUniform(-1, 1)(), d3.randomUniform(-1, 1)(), d3.randomUniform(-1, 1)() );
const firstLine = new THREE.LineCurve3(p1, p2);
const secondLine = new THREE.LineCurve3(p2, p3);
const thirdLine = new THREE.LineCurve3(p3, p4);

pointsPath.add(firstLine);
pointsPath.add(secondLine);
pointsPath.add(thirdLine);

return pointsPath;
}
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell

Purpose-built for displays of data

Observable is your go-to platform for exploring data and creating expressive data visualizations. Use reactive JavaScript notebooks for prototyping and a collaborative canvas for visual data exploration and dashboard creation.
Learn more