How to smoothly animate drawing of a line

I have about 40 curved lines and all of them have from 30 to 200 points. I draw all of them equally using BufferGeometry and setDrawRange() but it is smooth only for line with >200 points. I've tried TWEEN.js but it in this case it wasn't good idea. Is there any other option to make it happen?

In Unreal Engine 4 this problem can be resolved by setting opacity in masked material and update it every tick (and we have drawing effect).

I would like to hear from you if you have any ideas how can I try to do it.

Best regards.

Answers:

Answer

You can smoothly animate the drawing of a line -- even if the line consists of only a few points -- by using LineDashedMaterial.

The trick is to render only one dash, and increment the length of the dash in the animation loop.

// geometry
var geometry = new THREE.BufferGeometry();

// attributes
numPoints = points.length;
var positions = new Float32Array( numPoints * 3 ); // 3 vertices per point
var colors = new Float32Array( numPoints * 3 ); // 3 channels per point
var lineDistances = new Float32Array( numPoints * 1 ); // 1 value per point

geometry.addAttribute( 'position', new THREE.BufferAttribute( positions, 3 ) );
geometry.addAttribute( 'color', new THREE.BufferAttribute( colors, 3 ) );
geometry.addAttribute( 'lineDistance', new THREE.BufferAttribute( lineDistances, 1 ) );

// populate
var color = new THREE.Color();

for ( var i = 0, index = 0, l = numPoints; i < l; i ++, index += 3 ) {

    positions[ index ] = points[ i ].x;
    positions[ index + 1 ] = points[ i ].y;
    positions[ index + 2 ] = points[ i ].z;

    color.setHSL( i / l, 1.0, 0.5 );

    colors[ index ] = color.r;
    colors[ index + 1 ] = color.g;
    colors[ index + 2 ] = color.b;

    if ( i > 0 ) {

        lineDistances[ i ] = lineDistances[ i - 1 ] + points[ i - 1 ].distanceTo( points[ i ] );

    }

}

lineLength = lineDistances[ numPoints - 1 ];

// material
var material = new THREE.LineDashedMaterial( {

    vertexColors: THREE.VertexColors,
    dashSize: 1, // to be updated in the render loop
    gapSize: 1e10 // a big number, so only one dash is rendered

} );

// line
line = new THREE.Line( geometry, material );
scene.add( line );

Then, in the animation loop:

fraction = ( fraction + 0.001 ) % 1; // fraction in [ 0, 1 ]

line.material.dashSize = fraction * lineLength;

fiddle: http://jsfiddle.net/156yxd3L/

Note: You can compute the line distances any way you want. For example, you could normalize the distances by the total length, so the distance to the last point is 1. You would then vary dashSize from 0 to 1.


Compare this approach with this alternate method.

three.js r.84

Answer

You can draw Lines with LineSegments: https://threejs.org/docs/api/objects/LineSegments.html and the other way: https://threejs.org/docs/api/objects/Line.html

Maybe a change gives better results.

Tags

Recent Questions

Top Questions

Home Tags Terms of Service Privacy Policy DMCA Contact Us

©2020 All rights reserved.