Skip to content

Instantly share code, notes, and snippets.

@AKosmachyov
Created October 28, 2020 12:44
Show Gist options
  • Save AKosmachyov/5e58b040b2fee0a9644c776a72f47e7b to your computer and use it in GitHub Desktop.
Save AKosmachyov/5e58b040b2fee0a9644c776a72f47e7b to your computer and use it in GitHub Desktop.
ThreeJS draw line with animation https://jsfiddle.net/AKosmachyov/cehn5Lsv/19/
import {
WebGLRenderer,
Scene,
PerspectiveCamera,
Vector3,
LineBasicMaterial,
Clock,
Group,
AnimationMixer,
BufferGeometry,
Line,
NumberKeyframeTrack,
AnimationClip
} from "https://threejs.org/build/three.module.js";
import { OrbitControls } from "https://threejs.org/examples/jsm/controls/OrbitControls.js";
var renderer, scene, camera, controls;
const clock = new Clock();
var mixer;
const points = [
[-0.36664525, -0.10947785, 0.046916813], [-0.36692896, -0.10949561, 0.045177102],
[-0.36692896, -0.10949561, 0.045177102], [-0.36740094, -0.109046996, 0.04425852],
[-0.36740094, -0.109046996, 0.04425852], [-0.36939454, -0.10644929, 0.039979294],
[-0.36939454, -0.10644929, 0.039979294], [-0.36924666, -0.10626322, 0.039851464],
[-0.36924666, -0.10626322, 0.039851464], [-0.36908317, -0.10625997, 0.039993413],
[-0.36908317, -0.10625997, 0.039993413], [-0.36884966, -0.10639346, 0.04018011],
[-0.36884966, -0.10639346, 0.04018011], [-0.36855415, -0.10663211, 0.04036987],
[-0.36855415, -0.10663211, 0.04036987], [-0.36821684, -0.10692939, 0.040591106],
[-0.36821684, -0.10692939, 0.040591106], [-0.36782336, -0.10731025, 0.040792957],
[-0.36782336, -0.10731025, 0.040792957], [-0.36739337, -0.10767262, 0.04081653],
[-0.36739337, -0.10767262, 0.04081653], [-0.36696225, -0.10808329, 0.04086826],
[-0.36696225, -0.10808329, 0.04086826], [-0.36651945, -0.10849321, 0.04093668],
[-0.36651945, -0.10849321, 0.04093668], [-0.3660869, -0.10886204, 0.041133083],
[-0.3660869, -0.10886204, 0.041133083], [-0.3656629, -0.109191254, 0.041313544],
[-0.3656629, -0.109191254, 0.041313544], [-0.36526364, -0.10944857, 0.041368306],
[-0.36526364, -0.10944857, 0.041368306], [-0.36505476, -0.109732196, 0.041054845],
[-0.36505476, -0.109732196, 0.041054845], [-0.36480078, -0.10983284, 0.041020878],
[-0.36480078, -0.10983284, 0.041020878], [-0.36448702, -0.109932125, 0.041197352],
[-0.36448702, -0.109932125, 0.041197352], [-0.36408502, -0.11012861, 0.041489124],
[-0.36408502, -0.11012861, 0.041489124], [-0.36359388, -0.1104442, 0.041919567],
[-0.36359388, -0.1104442, 0.041919567], [-0.36303306, -0.11085041, 0.042381927],
[-0.36303306, -0.11085041, 0.042381927], [-0.36243892, -0.11143258, 0.04276999],
[-0.36243892, -0.11143258, 0.04276999], [-0.3617374, -0.1120998, 0.0431685],
[-0.3617374, -0.1120998, 0.0431685], [-0.3609468, -0.1128708, 0.04357463],
[-0.3609468, -0.1128708, 0.04357463], [-0.3600725, -0.11373405, 0.04404799],
[-0.3600725, -0.11373405, 0.04404799], [-0.3591305, -0.11465132, 0.04459937],
[-0.3591305, -0.11465132, 0.04459937], [-0.3581447, -0.11558381, 0.045272343],
[-0.3581447, -0.11558381, 0.045272343], [-0.35691413, -0.116720095, 0.046141215],
[-0.35691413, -0.116720095, 0.046141215], [-0.35568836, -0.117887884, 0.04696259],
[-0.35568836, -0.117887884, 0.04696259], [-0.35441732, -0.11910939, 0.047765754],
[-0.35441732, -0.11910939, 0.047765754], [-0.35308284, -0.12038, 0.048583105],
[-0.35308284, -0.12038, 0.048583105], [-0.35167453, -0.1217152, 0.04943663],
[-0.35167453, -0.1217152, 0.04943663], [-0.3501896, -0.12310736, 0.050185166],
[-0.3501896, -0.12310736, 0.050185166], [-0.34849745, -0.124763414, 0.050675146],
[-0.34849745, -0.124763414, 0.050675146], [-0.34680438, -0.12634133, 0.051082835],
[-0.34680438, -0.12634133, 0.051082835], [-0.3450582, -0.1279286, 0.05150105],
[-0.3450582, -0.1279286, 0.05150105], [-0.34320015, -0.12958473, 0.051938303],
[-0.34320015, -0.12958473, 0.051938303], [-0.3412491, -0.13127428, 0.052369736],
[-0.3412491, -0.13127428, 0.052369736], [-0.33918387, -0.13304214, 0.052711822],
[-0.33918387, -0.13304214, 0.052711822], [-0.33687866, -0.1349298, 0.053158775],
[-0.33687866, -0.1349298, 0.053158775], [-0.3344907, -0.13701113, 0.05364669],
[-0.3344907, -0.13701113, 0.05364669], [-0.3319472, -0.13930501, 0.05420229],
[-0.3319472, -0.13930501, 0.05420229], [-0.3292506, -0.14179161, 0.054730386],
[-0.3292506, -0.14179161, 0.054730386], [-0.32643348, -0.14440367, 0.05533386],
[-0.32643348, -0.14440367, 0.05533386], [-0.32351935, -0.14707637, 0.05600246],
[-0.32351935, -0.14707637, 0.05600246], [-0.32068917, -0.14990018, 0.05667319],
[-0.32068917, -0.14990018, 0.05667319], [-0.31782606, -0.1524468, 0.057543837],
[-0.31782606, -0.1524468, 0.057543837], [-0.3149972, -0.15476, 0.058405243],
[-0.3149972, -0.15476, 0.058405243], [-0.31221414, -0.15690617, 0.05908837],
[-0.31221414, -0.15690617, 0.05908837], [-0.30952415, -0.15889138, 0.05936037]
]
init();
animate();
function init() {
// info
var info = document.createElement('div');
info.style.position = 'absolute';
info.style.top = '30px';
info.style.width = '100%';
info.style.textAlign = 'center';
info.style.color = '#fff';
info.style.fontWeight = 'bold';
info.style.backgroundColor = 'transparent';
info.style.zIndex = '1';
info.style.fontFamily = 'Monospace';
info.innerHTML = 'Drag mouse to rotate camera; scroll to zoom';
document.body.appendChild(info);
// renderer
renderer = new WebGLRenderer();
renderer.setSize(window.innerWidth, window.innerHeight);
document.body.appendChild(renderer.domElement);
// scene
scene = new Scene();
// camera
camera = new PerspectiveCamera(50, window.innerWidth / window.innerHeight, 0.01, 1000);
camera.position.set(-0.5774358006768022, -0.25063530420072944, 0.14832038190734845);
camera.quaternion.set(0.1561991821650019, -0.6007752371794557, 0.12114829834070436, 0.7745928089597173);
// controls
controls = new OrbitControls(camera, renderer.domElement);
controls.minDistance = 0.5;
controls.maxDistance = 2;
const linePoints = points.map(el => new Vector3(el[0], el[1], el[2]));
const { lineNode, animationClip } = createLineWithAnimation(linePoints);
scene.add(lineNode);
mixer = new AnimationMixer(lineNode);
const clipAction = mixer.clipAction(animationClip);
clipAction.play();
}
function createLineWithAnimation(points) {
const lineNode = new Group();
let fadeInDurationSec = 0.05
let delayBetweenLoopSec = 5.0
const animationDuration = points.length / 2 * fadeInDurationSec + delayBetweenLoopSec;
const keyFrames = [];
for (var i = 0; i < points.length; i += 2) {
const endSegmentIndex = i + 1;
const startOfSegment = points[i];
const endOfSegment = points[endSegmentIndex];
const lineSegmentName = "s" + i;
const lineSegmentNode = createLineNode(lineSegmentName, startOfSegment, endOfSegment);
lineNode.add(lineSegmentNode);
// Animation frame track
const beforeSegmentCount = i / 2;
const delay = beforeSegmentCount * fadeInDurationSec
const trackName = lineSegmentName + '.material.opacity';
const opacityKeyFrame = new NumberKeyframeTrack(trackName, [0, delay], [0, 1]);
keyFrames.push(opacityKeyFrame);
}
const animationClip = new AnimationClip('Line draw', animationDuration, keyFrames);
return {
lineNode,
animationClip
}
}
function createLineNode(name, start, end) {
const material = new LineBasicMaterial({ color: 'white', transparent: true });
const geometry = new BufferGeometry().setFromPoints([start, end]);
const line = new Line(geometry, material);
line.name = name;
return line;
}
function animate() {
requestAnimationFrame(animate);
render();
}
function render() {
var delta = clock.getDelta();
if (mixer) {
mixer.update(delta);
}
renderer.render(scene, camera);
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment