Skip to content

tweens.js

Video Lecture

Using tweens.js Using tweens.js

Description

Tweenjs is a JavaScript tweening engine.

A tween (from in-between) is a concept that allows you to change the values of the properties of an object smoothly. We can decide how long it should take, and if there should be a delay, and what to do each time the tween is updated, whether it should repeat and other things.

<>

Install Tween

npm install @tweenjs/tween.js --save-dev

It comes with its own type declarations, so it is unnecessary to install the types separately.

To import use,

import TWEEN from '@tweenjs/tween.js'

Lesson Script

./src/main.ts

  1
  2
  3
  4
  5
  6
  7
  8
  9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31
 32
 33
 34
 35
 36
 37
 38
 39
 40
 41
 42
 43
 44
 45
 46
 47
 48
 49
 50
 51
 52
 53
 54
 55
 56
 57
 58
 59
 60
 61
 62
 63
 64
 65
 66
 67
 68
 69
 70
 71
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
import './style.css'
import * as THREE from 'three'
import { OrbitControls } from 'three/addons/controls/OrbitControls.js'
import { GLTFLoader } from 'three/addons/loaders/GLTFLoader.js'
import { RGBELoader } from 'three/addons/loaders/RGBELoader.js'
import Stats from 'three/addons/libs/stats.module.js'
import TWEEN from '@tweenjs/tween.js'

const scene = new THREE.Scene()

const gridHelper = new THREE.GridHelper()
gridHelper.position.y = -1
scene.add(gridHelper)

await new RGBELoader().loadAsync('img/venice_sunset_1k.hdr').then((texture) => {
  texture.mapping = THREE.EquirectangularReflectionMapping
  scene.environment = texture
})

const camera = new THREE.PerspectiveCamera(75, window.innerWidth / window.innerHeight, 0.1, 100)
camera.position.set(0, 1, 4)

const renderer = new THREE.WebGLRenderer({ antialias: true })
renderer.toneMapping = THREE.ACESFilmicToneMapping
renderer.toneMappingExposure = 0.8
renderer.shadowMap.enabled = true
renderer.setSize(window.innerWidth, window.innerHeight)
document.body.appendChild(renderer.domElement)

window.addEventListener('resize', () => {
  camera.aspect = window.innerWidth / window.innerHeight
  camera.updateProjectionMatrix()
  renderer.setSize(window.innerWidth, window.innerHeight)
  //render() //this line is unnecessary if you are re-rendering within the animation loop
})

const controls = new OrbitControls(camera, renderer.domElement)
controls.enableDamping = true
//controls.addEventListener('change', render) //this line is unnecessary if you are re-rendering within the animation loop

let suzanne: THREE.Mesh, plane: THREE.Mesh

new GLTFLoader().load('models/suzanne_scene.glb', (gltf) => {
  suzanne = gltf.scene.getObjectByName('Suzanne') as THREE.Mesh
  suzanne.castShadow = true
  ;((suzanne.material as THREE.MeshStandardMaterial).map as THREE.Texture).colorSpace = THREE.LinearSRGBColorSpace

  plane = gltf.scene.getObjectByName('Plane') as THREE.Mesh
  plane.scale.set(50, 1, 50)
  ;(plane.material as THREE.MeshStandardMaterial).envMap = scene.environment // since three@163, we need to set `envMap` before changing `envMapIntensity` has any effect.
  ;(plane.material as THREE.MeshStandardMaterial).envMapIntensity = 0.05
  plane.receiveShadow = true

  const spotLight = gltf.scene.getObjectByName('Spot') as THREE.SpotLight
  spotLight.intensity /= 500
  spotLight.castShadow = true
  spotLight.target = suzanne

  scene.add(gltf.scene)

  //render()
})

const raycaster = new THREE.Raycaster()
const mouse = new THREE.Vector2()

renderer.domElement.addEventListener('dblclick', (e) => {
  mouse.set((e.clientX / renderer.domElement.clientWidth) * 2 - 1, -(e.clientY / renderer.domElement.clientHeight) * 2 + 1)

  raycaster.setFromCamera(mouse, camera)

  const intersects = raycaster.intersectObjects([suzanne, plane], false)

  if (intersects.length) {
    const p = intersects[0].point

    //controls.target.set(p.x, p.y, p.z)

    // //  Tweening controls.target
    // new TWEEN.Tween(controls.target)
    //   .to(
    //     {
    //       x: p.x,
    //       y: p.y,
    //       z: p.z
    //     },
    //     500
    //   )
    //   //.delay (1000)
    //   //.easing(TWEEN.Easing.Cubic.Out)
    //   //.onUpdate(() => render())
    //   .start()

    // // slding x,z
    // new TWEEN.Tween(suzanne.position)
    //   .to(
    //     {
    //       x: p.x,
    //       z: p.z
    //     },
    //     500
    //   )
    //   .start()

    // // going up
    // new TWEEN.Tween(suzanne.position)
    //   .to(
    //     {
    //       y: p.y + 3
    //     },
    //     250
    //   )
    //   //.easing(TWEEN.Easing.Cubic.Out)
    //   .start()
    // //.onComplete(() => {

    // // going down
    // new TWEEN.Tween(suzanne.position)
    //   .to(
    //     {
    //       y: p.y + 1
    //     },
    //     250
    //   )
    //   .delay(250)
    //   //.easing(TWEEN.Easing.Cubic.In)
    //   .start()
    // //})
  }
})

const stats = new Stats()
document.body.appendChild(stats.dom)

function animate() {
  requestAnimationFrame(animate)

  controls.update()

  TWEEN.update()

  render()

  stats.update()
}

function render() {
  renderer.render(scene, camera)
}

animate()

Tween Easing Options

TWEEN.Easing._equation_._direction_

TWEEN.Easing.*equation*.*direction*

tween.js GitHub

Comments