Jump to content
Search Community

Tweening value with large number of decimals

Kyeno test
Moderator Tag

Recommended Posts

Hey!

I recently switched from Tween.JS to GSAP, and I'm trying to tween a number with potentially large number of decimal places. I wrote a small library that finds-on-screen and auto-tweens those numbers, so I do not have a *predefined* number of decimals - but as they're cryptocurrency prices, those can be 4, 6, 8 or 9 - usually.

I noticed that both TweenMax and TweenLite do only 4 decimals, which is quite weird. Looking around the web (and this forum) I cannot find a solution/parameter/switch how to alter this behavior. Any advice?

 

import gsap from 'gsap';
import { TweenLite, Expo } from 'gsap/all';
gsap.registerPlugin(Expo);

export default class TweenEmAll {
  
	// ..cut
    objTween = undefined;
    objTweenProgress = { value: 0.000001 }; // experiment with pre-defined 6 decimals

	// ..cut
    tween() {

      	// ..cut
      
        // launch new tween
        this.objTween = TweenLite.to(this.objTweenProgress, this.duration, {

            value: this.target,
            ease: Expo.easeOut,
            //decimals: 6,		// experiment
            //autoRound: false,	// experiment
            onUpdate: this.onTweenUpdate.bind(this)
        });
    }
    onTweenUpdate() {

        // reconstruct value nicely
        let value = this.objTweenProgress.value.toFixed(6);	// experiment

        // update appropriate element
        if(this.isInput) this.elmContainer.val(value);
        else this.elmContainer.html(value);
    }
}

 

Link to comment
Share on other sites

It's actually a very intentional thing that we round in that way and I actually can't remember anyone requesting more than 4 decimal places, but it is entirely possible with a simple [custom] plugin: 

See the Pen 3f6f2d2624421d678c02a1a882c73aff?editors=0010 by GreenSock (@GreenSock) on CodePen

 

Here's the "precise" plugin: 

gsap.registerPlugin({
	name: "precise",
	init(target, vars, tween, index, targets) {
		let data = this,
			p, value;
		data.t = target;
		for (p in vars) {
			value = vars[p];
			typeof(value) === "function" && (value = value.call(tween, index, target, targets));
			data.pt = {n: data.pt, p: p, s: target[p], c: value - target[p]};
			data._props.push(p);
		}
	},
	render(ratio, data) {
		let pt = data.pt;
		while (pt) {
			data.t[pt.p] = pt.s + pt.c * ratio;
			pt = pt.n;
		}
	}
});

you'd just register it once like that and then use it like: 

let obj = { value: 0.000001 };

gsap.to(obj, {
  duration: 3,
  precise: {
    value: 0.00009,
  },
  onUpdate: () => console.log(obj.value)
});

There are several reasons we apply rounding by default: 

  1. It conserves memory and can improve speed. It's just wasteful to have a bunch of decimal places pushed into strings for CSS values that'd never make any visual difference whatsoever. Like opacity: 0.005014 will look no different than opacity: 0.005. And when you've got values in a complex string like <path> data (hundreds of numbers), when each one has 10 decimal places instead of 4, it leads to strings that are WAY longer and the browser must parse it all. Again, wasteful. 
  2. It helps avoid scientific notation values that can creep in which can break rendering, like if you set certain values to 1e-12, for example. In other words, when the decimal values are sufficiently small and get cast to strings, the browser uses scientific notation and it breaks stuff. 
  3. It helps avoid rounding issues with binary number systems. For example, 1 % 0.4 results in 0.19999999999999996 instead of 0.2. That's just the nature of how binary systems work and has nothing to do with GSAP, but this rounding strategy helps avoid it. 

 

Does that clear things up? 

  • Like 4
Link to comment
Share on other sites

Hey, thanks a lot! And I totally understand what you're doing there - not blaming whatsoever, just pointed out my *strange* use case and the fact I couldn't find any real solution around. I don't know GSAP Engine good enough just yet to be able to provide such plugins as you did. :)
Thank you again! Going back to GSAPing!

  • Like 1
Link to comment
Share on other sites

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now
  • Recently Browsing   0 members

    • No registered users viewing this page.
×
×
  • Create New...