# Tween Example

This article will focus on some common uses and interfaces in Cosos Creator Tween System.

## Construct Tween

Tween can be constructed either by the `tween` method or by using `new Tween<T>(target: T)`.

Note: 'tween' is a tool method provided by the engine and is not a member of 'Tween' class, please note the distinction. For this, please refer to the interface description: Tween Interface.

## Chain API

Most action-related interfaces return either `this` or a new `Tween` object, so it's easy to use chain calls to combine:

``````tween()
.target(this.node)
.to(1.0, { position: new Vec3(0, 10, 0) })
.by(1.0, { position: new Vec3(0, -10, 0) })
.delay(1.0)
.by(1.0, { position: new Vec3(0, -10, 0) })
.start()
``````

## Simple Example of 'to', 'by'

Here is a demonstration of how to use a `to` type of tween to bind the position information of a node and offset its position by 10 units along the Y-axis.

``````let tweenDuration : number = 1.0;                                    // Duration of tween
tween(this.node.position)
.to( tweenDuration, new Vec3(0, 10, 0), {                        // The interface 'to' represents the absolute value of the node
onUpdate : (target:Vec3, ratio:number)=>{                        // Implement ITweenOption's onUpdate callback to accept the current tweening progress
this.node.position = target;                                 // Assign the position of the node to the result calculated by the tween system
}
}).start();                                                          // Call the start method to enable tween
``````

## Binding Different Objects

There are more scenarios where `Node` is used as a binding target in development, and the code example is as follows.

``````let  quat : Quat = new Quat();
Quat.fromEuler(quat, 0, 90, 0);
tween(this.node)
.to(tweenDuration, {
position: new Vec3(0, 10, 0),                   // Bind position
scale: new Vec3(1.2, 3, 1),                     // Bind scale
rotation:quat }                                 // Bind rotation
)
.start();                                           // Call the start method to enable tween
``````

In fact the tween can be bound to any object, the code example is as follows:

``````class BindTarget{
color : Color
}

let sprite : Sprite = this.node.getComponent(Sprite) ;
let bindTarget : BindTarget = new BindTarget();
bindTarget.color = Color.BLACK;
tween(bindTarget)
.by( 1.0, { color: Color.RED }, {
onUpdate(tar:BindTarget){
sprite.color = tar.color;  // Set the sprite to the color inside the 'BindTarget'
}
})
.start()
``````

## Common Examples

### Multiple Actions

In general, a tween can consist of one or more actions, and `Tween` maintains a data structure consisting of multiple actions to manage all actions within the current tween.

The following code demonstrates moving the object's position 10 units along the Y-axis and then 10 units along the -Y-axis.

``````let tweenDuration : number = 1.0;
tween(this.node.position)
.to( tweenDuration, new Vec3(0, 10, 0), {
onUpdate : (target:Vec3, ratio:number)=>{
this.node.position = target;
}
})
.to( tweenDuration, new Vec3(0, -10, 0), {
onUpdate : (target:Vec3, ratio:number)=>{
this.node.position = target;
}
}) // At this point the number of actions in the tween is 2
``````

Multiple tweens can also be organized using the `union`, `squence`, and `parallel` interfaces. By creating some fixed tweens in advance and using `union`, `squence`, `parallel` to combine them, you can reduce the amount of code written.

### Union

The `union` method combines all current actions into one, with the following code example:

``````let tweenDuration : number = 1.0;
tween(this.node)
.to(tweenDuration, { position:new Vec3(0, 10, 0) })  // Here the node is the target of the tween
.to(tweenDuration, { position:new Vec3(0, -10, 0) }) // At this point the number of actions in the Tween is 2
.union()                                             // The above two tweens will be combined into one, and the number of actions in the Tween will be 1
.start();                                            // Call the start method to enable tween
``````

### Sequence

The `sequence` function will transform the incoming tween into a queue form and add it to the current tween, with the following code example:

``````let tweenDuration: number = 1.0;
let t1 = tween(this.node)
.to(tweenDuration, { position: new Vec3(0, 10, 0) })

let t2 = tween(this.node)
.to(tweenDuration, { position: new Vec3(0, -10, 0) })

tween(this.node).sequence(t1, t2).start(); // Add t1 and t2 tweens to the new tween queue
``````

### Parallel

The `parallel` function will convert the incoming tween into parallel form and add it to the current tween, with the following code example:

``````let tweenDuration: number = 1.0;
let t1 = tween(this.node)
.to(tweenDuration, { position: new Vec3(0, 10, 0) })

let t2 = tween(this.node)
.to(tweenDuration, { position: new Vec3(0, -10, 0) })

tween(this.node).parallel(t1, t2).start(); // Convert t1 and t2 to parallel tweens and add the current tween
``````

## Then

The `then` interface allows a new tween to be passed in and that tween integrated and added to the current tween's action, with the following code example.

``````let tweenAfter = tween(this.node)
.to(1.0, { position: new Vec3(0, -10, 0) })

tween(this.node)
.by(1.0, { position: new Vec3(0, 10, 0) })
.then(tweenAfter)
.start();
``````

## Delay

The `delay` interface adds a delay to the current action after it.

Note that in the following code example, different `delay` positions can cause completely different results.

• After a delay of 1 second, start the movement and perform it twice in a row：

``````  let tweenDuration: number = 1.0;
tween(this.node)
.delay(1.0)
.to(tweenDuration, { position: new Vec3(0, 10, 0) })
.to(tweenDuration, { position: new Vec3(0, -10, 0) })
.start()
``````
• After the first movement, there is a 1 second delay before the second movement is performed.

``````  let tweenDuration: number = 1.0;
tween(this.node)
.to(tweenDuration, { position: new Vec3(0, 10, 0) })
.delay(1.0)
.to(tweenDuration, { position: new Vec3(0, -10, 0) })
.start()
``````

### Repeat

The `repeat` interface can add a repeat count to the tween, if the `embedTween` parameter is empty, the last action of the current tween will be used as parameter.

This means that if the current tween consists of more than one tween, only the last one will be repeated, note the following example:

``````let tweenDuration: number = 1.0;
tween(this.node)
.to(tweenDuration, { position: new Vec3(0, 10, 0) })
.by(tweenDuration, { position: new Vec3(0, -10, 0) })
.repeat(3) // Note that the 'by' tween is repeated 3 times here
.start()
``````

If the second parameter `embedTween` is not empty, the embedded tween will be repeated, with the following code example:

``````let tweenDuration: number = 1.0;
let embedTween = tween(this.node)
.by(tweenDuration, { position: new Vec3(0, -10, 0) })

tween(this.node)
.to(tweenDuration, { position: new Vec3(0, 10, 0) })
.repeat(3, embedTween)  // Repeat the 'embedTween'
.start()
``````

The usage of `repeatForever` interface is similar to `repeat`, but it becomes permanently repeated.

The node-related methods only work if `target` is `Node`.

#### Visibility

The `show` and `hide` interfaces control the display and hiding of the bound nodes, in the following example the nodes are hidden and displayed after a 1 second delay.

``````tween(this.node)
.hide()
.delay(1.0)
.show()
.start();
``````

#### RemoveSelf

This method generates a delete node action that removes the incoming node from within the scene tree.

In the following example, the node will be removed from the scene after a delay of 1 second.

``````tween(this.node)
.delay(1.0)
.removeSelf()
.start()
``````

### Call

The `call` interface allows a callback action to be added to the tween, which is useful when dealing with certain asynchronous logic, as in the following example:

``````tween(this.node)
.to(1.0, { position: new Vec3(0, 10, 0)})
// This method will be called when the 'to' action is completed
.call( ()=>{
console.log("call");
})
.start()
``````

### Set

The properties of the target can be set via `set`. The following example will set the node at [0, 100, 0] after a delay of 1 second.

``````tween(this.node)
.delay(1.0)
.set({ position: new Vec3(0, 100, 0) })
.start();
``````

It is also possible to set several different properties at the same time, with the following code example:

``````tween(this.node)
// Set the position, scale and rotation of the node at the same time
.set({ position: new Vec3(0, 100, 0), scale: new Vec3(2, 2, 2), rotation: Quat.IDENTITY } )
.start();
``````

### Clone

The `clone` method copies the current tween to the target parameter. Note that the source tween and the current tween should be of the same type when copying, i.e. the `T` in `new Tween<T>(target: T)` needs to be of the same type. The code example is as follows.

``````let srcTween = tween(this.node).delay(1.0).by(1.0, { position: new Vec3(0, 10, 0) })
// Copy 'srcTween' to a node named Cone
srcTween.clone(find("Cone")).start();
``````

## Destruction

### Automatic Destruction

When the target of tween is `Node`, it will listen to its destruction event for automatic destruction of tween, and the call to `target` method will also update the listener automatically.

### Manual Destruction

Most tweens destroy themselves after the last action, but tweens that are not destroyed properly, such as `repeatForever`, will remain in memory after switching scenes. You need to call the destroy interface manually to destroy it.

To stop and destroy the tween, the following methods are available.

• member `stop` function to destroy the tween, with the following code example.

``````  let t = tween(this.node.position)
.to( 1.0, new Vec3(0, 10, 0), {
onUpdate : (target:Vec3, ratio:number)=>{
this.node.position = target;
}
})
t.stop();
``````
• Use the static functions `stopAll`, `stopAllByTag` and `stopAllByTarget` to destroy all or specific tweens, with the following code example.

``````  Tween.stopAll() // Destroy all tweens

Tween.stopAllByTag(0); // Destroy all tweens with 0 as the tag

Tween.stopAllByTarget(this.node); // Destroy all tweens on this node
``````

Note: Remember to stop the corresponding tweens when switching scenes.