Provides a Mesh-based replacement for THREE.Line
from
Three.js, allowing line thicknesses of any size
(THREE.Line
is limited to 1 pixel width), and other features.
Note This is forked from
three.meshline
, as that project has been dormant. The version of this starts at 2.0 because it modernizes the code base in ways that make it a breaking change, and removes deprecated features.
Instead of using GL_LINE, it uses a strip of triangles billboarded. Some examples:
Play: play with the different mesh line options |
Graph: example of using `MeshLine` to plot graphs |
Spinner: example of dynamic `MeshLine` with texture |
SVG: example of `MeshLine` rendering SVG Paths |
Shape: example of `MeshLine` created from an OBJ file |
Birds: example of `MeshLine.advance()` by @caramelcode (Jared Sprague) and @mwcz (Michael Clayton) |
- Include script
- Create an array of 3D coordinates
- Create a
MeshLineGeometry
and assign the points - Create a
MeshLineMaterial
to style the line points - Create a
MeshLine
rendering object given theMeshLineGeometry
andMeshLineMaterial
First install @lume/three-meshline
:
npm i @lume/three-meshline
Add the importmap to your HTML if you are using native JavaScript modules (if you have a build step handling your modules, you'd skip this):
<script src="/node_modules/@lume/three-meshline/importmap.js"></script>
If your browser doesn't support importmaps natively yet, you can load an importmap polyfill then embed the importmap manually in your HTML like so:
<script defer src="https://ga.jspm.io/npm:[email protected]/dist/es-module-shims.js"></script>
<script src="/node_modules/@lume/three-meshline/importmap.js"></script>
Finally import APIs into your JavaScript code:
import {MeshLine, MeshLineGeometry, MeshLineMaterial} from '@lume/three-meshline'
First, create the list of numbers that will define the 3D points for the line.
const points = []
for (let j = 0; j < Math.PI; j += (2 * Math.PI) / 100) {
points.push(Math.cos(j), Math.sin(j), 0)
}
Once you have that, you can create a new MeshLineGeometry
, and call
.setPoints()
passing the list of points.
const geometry = new MeshLineGeometry()
geometry.setPoints(points)
Note: .setPoints
accepts a second parameter, which is a function to define the
width in each point along the line. By default that value is 1, making the line
width 1 * lineWidth in the material.
// p is a decimal percentage of the number of points
// ie. point 200 of 250 points, p = 0.8
geometry.setPoints(points, p => 2) // makes width 2 * lineWidth
geometry.setPoints(points, p => 1 - p) // makes width taper from the beginning
geometry.setPoints(points, p => 1 - (1 - p)) // makes width taper from the end
geometry.setPoints(points, p => 2 + Math.sin(50 * p)) // makes width sinusoidal
A MeshLine
needs a MeshLineMaterial
:
const material = new MeshLineMaterial(options)
By default it's a white material with line width 1 unit.
MeshLineMaterial
accepts options
to control the appereance of the MeshLine
:
resolution
-THREE.Vector2
specifying the canvas size (REQUIRED) (default:new Vector2(1, 1)
)map
- aTHREE.Texture
to paint along the line (requiresuseMap
set to true) (default:null
)useMap
- tells the material to usemap
(false
- solid color,true
use texture) (defaultfalse
)alphaMap
- aTHREE.Texture
to use as alpha along the line (requiresuseAlphaMap
set to true) (default: 'null')useAlphaMap
- tells the material to usealphaMap
(false
- no alpha,true
alpha from texture) (default:false
)repeat
-THREE.Vector2
to define the texture tiling (applies tomap
andalphaMap
) (default:new Vector2(1, 1)
)color
-THREE.Color
to paint the line width, or tint the texture with (default:new Color('white')
)opacity
- alpha value from0
to1
(requirestransparent
set totrue
) (default:1
)alphaTest
- cutoff value from0
to1
(default:0
)dashArray
- the length and space between dashes. (0
- no dash) (default:0
)dashOffset
- defines the location where the dash will begin. Ideal to animate the line. (default:0
)dashRatio
- defines the ratio between that is visible or not (0
- more visible,1
- more invisible) (default:0.5
)useDash
- whether to use dashes or not. SettingdashArray
to a non-zero value automatically sets this totrue
. (false
- no dashes,true
- dashes) (default:
true
)
- dashes) (default:
sizeAttenuation
- makes the line width constant regardless distance (1 unit is 1px on screen) (false
- attenuate,true
- don't attenuate) (default:true
)lineWidth
- width of the line (ifsizeAttenuation
istrue
, the value is in world units; othwerwise it is in screen pixels) (default:1
)visibility
- A number from0
to1
denoting the portion of the line that is visible, starting from the end (0.5
means half of the line is visible,0
means the whole line is invisible) (default:1
)
If you're rendering transparent lines or using a texture with alpha map, you may
consider setting depthTest
to false
, transparent
to true
and blending
to an appropriate blending mode, or use alphaTest
.
Finally, we create a mesh and add it to the scene:
const line = new MeshLine(geometry, material)
scene.add(line)
Note that MeshLine
extends from THREE.Mesh
and adds raycast support:
const raycaster = new THREE.Raycaster()
// Use raycaster as usual:
raycaster.intersectObject(line)
MeshLine
can be used declaritively. This is how it would look like in
react-three-fiber. You can try it
live
here.
import {extend, Canvas} from 'react-three-fiber'
import {MeshLine, MeshLineMaterial, MeshLineRaycast} from '@lume/three-meshline'
extend({MeshLine, MeshLineGeometry, MeshLineMaterial})
function Line({points, width, color}) {
return (
<Canvas>
<meshLine>
<meshLineGeometry attach="geometry" points={points} />
<meshLineMaterial
attach="material"
transparent
depthTest={false}
lineWidth={width}
color={color}
dashArray={0.05}
dashRatio={0.95}
/>
</meshLine>
</Canvas>
)
}
Dynamic line widths can be set along each point using the widthCallback
prop.
<meshLineGeometry attach="geometry" points={points} widthCallback={pointWidth => pointWidth * Math.random()} />
- Better miters
- Faster setPoints() method
- Size attenuation when using OrthographicCamera
- Support for vertex colors (
geometry.vertexColors
) - global script for people still using global script tags for a global THREE variable
Tested successfully on
- Chrome OSX, Windows, Android
- Firefox OSX, Windows, Anroid
- Safari OSX, iOS
MIT licensed