<!-- 

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)


External CSS

This Pen doesn't use any external CSS resources.

External JavaScript

  1. https://cdn.rawgit.com/mrdoob/three.js/master/build/three.js
  2. https://cdn.rawgit.com/mrdoob/three.js/master/examples/js/controls/OrbitControls.js
  3. https://cdn.rawgit.com/wearekuva/oui/master/dist/oui.js