Using tween.js to animate element margins

Hi there!

Ive a question about animating ui element margins with the tween.js library. The purpose is to change the aspect ratio of an Video Texture Entity, depending if the video file is landscape or portrait. I had the following function which works but changes the ratio instantly:

UiController.prototype.adjustMargins = function(isLandscape) {
    // Check if video entity is referenced
    if (!this.uiVideoEntity || !this.uiVideoEntity.element) {
        console.error('Video entity or element not found.');
        return;
    }
    // Check if video is landscape or portrait based on provided orientation
    if (isLandscape) { // Portrait
        this.uiVideoEntity.element.left = 0;
        this.uiVideoEntity.element.right = 0;
    } else { // Landscape
        this.uiVideoEntity.element.left = 400;
        this.uiVideoEntity.element.right = 400;
    }
};

But i thought it would be cool to using tween.js to animate the transition. But im not sure if its basically possible - i tried:

// Function to adjust margins based on video aspect ratio and orientation, with animation using Tween.js
UiController.prototype.adjustMargins = function(isLandscape) {
    // Check if video entity is referenced
    if (!this.uiVideoEntity || !this.uiVideoEntity.element) {
        console.error('Video entity or element not found.');
        return;
    }

    // Define target margins based on orientation
    var targetMargins = isLandscape ? { left: 0, right: 0 } : { left: 400, right: 400 };

    console.log(targetMargins);
   
    this.uiVideoEntity.tween(this.uiVideoEntity.element.margin)
        .to(targetMargins, this.duration)
        .start();
};

But nothing happens - also no error or warning. Does somebody may know how i can bring this to work? would be fantastic!

Thank you!

Hi @Question2u !

element.margin is a Vec4, so assigning left/right values wouldn’t change anything. Check out this information about Vec4:

You’ll see that the properties of the object are x, y, z, and w. I did something similar, but used anchors instead of margins. Beware, this code is a bit old:

Ui.prototype.onScreenClick = function() {
...
    this.screen.tween(this.screen.element.anchor)
        .to({y: 0.0, z: 1.0}, 3.0, pc.QuadraticInOut)
        .on('update', this.updateScreenDims, this)
        .on('complete', this.onScreenExpanded, this)
        .start();
...
};

Ui.prototype.updateScreenDims = function() {

    this.screen.element.anchor = this.screen.element.anchor;

};

I reassigned the value to itself on each frame so that the engine would recognize the image element as dirty.

I hope this is helpful.

Edited to add: Also, your tween function is missing an easing curve such as pc.Linear or pc.QuadraticOut in its .to() function. Check out the latest Tween documentation at the GitHub page here:

3 Likes