<!--
So, this is basically the most compact form of three.js-boilerplate
I could come up with.
To write a demo, only a single function needs to be defined. This function will do all setup-work and return another function that
will be called for every animationFrame rendererd.
-->
body { margin: 0; overflow: hidden; background-color: black; }
canvas { width: 100vw; height: 100vh; }
function creatingLine() {
const line = createLine({
scene,
url: "https://raw.githubusercontent.com/ocio/r2r-client/master/public/assets/map/animated/line.png",
lineHeight: 0.2,
repeatFactor: 1
})
const fromX = 0
const fromZ = 0
const toX = 10
const toZ = 5
line.changePosition({ fromX, fromZ, toX, toZ })
// axes
const axesFrom = new THREE.AxesHelper(5)
axesFrom.position.set(fromX, 0, fromZ)
const axesTo = new THREE.AxesHelper(5)
axesTo.position.set(toX, 0, toZ)
scene.add(axesFrom)
scene.add(axesTo)
}
function createLine({ scene, url, repeatFactor, lineHeight, offsetX = 0.025, intervalMs=10 }) {
const textureLoader = new THREE.TextureLoader()
const texture = textureLoader.load(url)
const width = 1
const height = lineHeight
const geometry = new THREE.PlaneBufferGeometry(width, height)
const material = new THREE.MeshBasicMaterial({
color: 0xffffff,
map: texture,
transparent: true
})
const mesh = new THREE.Mesh(geometry, material)
texture.wrapS = texture.wrapT = THREE.RepeatWrapping
mesh.rotation.x = -Math.PI / 2
mesh.position.x = width / 2
const line = new THREE.Group()
line.add(mesh)
scene.add(line)
const tween = setInterval(() => {
texture.offset.x -= offsetX
}, intervalMs)
return {
changePosition: ({ fromX, fromZ, toX, toZ }) => {
const fromVector = new THREE.Vector2(fromX, fromZ)
const toVector = new THREE.Vector2(toX, toZ)
const distance = fromVector.distanceTo(toVector)
const scaleFactorX = distance / mesh.geometry.parameters.width
line.position.x = fromX
line.position.z = fromZ
line.scale.set(scaleFactorX, 1, 1)
texture.repeat.set(distance * repeatFactor, 1)
line.rotation.y = -Math.atan2(toZ - fromZ, toX - fromX)
},
destroy: () => {
clearInterval(tween)
scene.remove(line)
}
}
}
// NOT INTERESTING
const cameraPosition = 30
const scene = new THREE.Scene()
const renderer = new THREE.WebGLRenderer({ alpha: true, antialias: true })
const camera = new THREE.PerspectiveCamera(
20, // fov
window.innerWidth / window.innerHeight, // aspect
1, // near
999999 // far
)
camera.position.set(cameraPosition, cameraPosition, cameraPosition)
camera.lookAt(new THREE.Vector3(0, 0, 0))
renderer.setSize(window.innerWidth, window.innerHeight)
// geometry
scene.add(new THREE.GridHelper(50, 100, 0xaaaaaa, 0x999999))
creatingLine()
// lights
const dirLight = new THREE.DirectionalLight()
dirLight.position.set(1, 0.4, 0.2)
scene.add(dirLight, new THREE.AmbientLight(0x444444))
function animate(time) {
renderer.render(scene, camera)
requestAnimationFrame(animate)
}
animate()
document.body.appendChild(renderer.domElement)
This Pen doesn't use any external CSS resources.