Jump to content
GreenSock

Search In
  • More options...
Find results that contain...
Find results in...
Krix Ferenc

Tween 18000px wide image on canvas

Recommended Posts

Hi,

 

We created a small game, where we tween a very long image (18000px) on the canvas.

It has good performance on Chrome with a strong pc.

But the tween is vey laggy on standard laptop or Firefox / IE.

 

And I think this is relevant snippet:


function init() {
    canvas = document.getElementById("bg").getContext("2d");
    img = new Image();
    img.xpos = 0;
    img.ypos = 0;
    img.src = "img/bg.jpg";
    img.onload = function() {
        animate();
    }

    $('#trigger').click(function() {
        TweenMax.to(img, 60, {xpos:-17807, ypos:0, force3D:true, ease:Linear.easeNone});
        TweenMax.to($('#egg_container'), 60, {x:-17807, force3D:true, ease:Linear.easeNone});           
        TweenLite.ticker.addEventListener("tick", animate);
    });       
}

function animate() {
    canvas.drawImage(img, img.xpos, img.ypos);
}
init()

We do something wrong?

How can be the tween animation smooth on everywhere.

 

We have BusinessGreen plan, please help!

 

Best regards,

Ferenc Krix

 

 

 

See the Pen MyezpL by zabalint (@zabalint) on CodePen

Link to comment
Share on other sites

Hello Krix Ferenc, and Welcome to the GreenSock Forum!

 

Just keep in mind that animating an image that long or big can cause some jank (lost frames), especially on Mobile devices. But that has nothing to do with GSAP, and is just the nature of forcing the browser to animate such a large bitmap image.

 

But having said that.. Try adding a very slight rotation to your tween for Firefox to make it smooth:

rotation: 0.01

Like this in your tween:

TweenMax.to($('#egg_container'), 60, {x:-17807, rotation: 0.01, force3D:true, ease:Linear.easeNone});

You might want to only run your code after the window and DOM is ready. This way your animation will run when your image and code is fully loaded, which will help with the first delay stutter your seeing when clicking the start button.

 

Here you can see with the rotation: 0.01 and a DOM ready and window load event, it should be more smooth. It will also start smoother when clicking the start button due to waiting for the code and image to load before running your animation.

 

See the Pen KzMbjg by jonathan (@jonathan) on CodePen

 

And here is an example of using GSAP to animate a CSS background-image:

 

See the Pen YyMKMz by jonathan (@jonathan) on CodePen

 

Also i noticed you are using jQuery css() method to apply CSS properties. You should really watch out for adding or removing CSS properties outside of GSAP. You can use the GSAP set() method instead of the jQuery css() method. If you use the jQuery css() method you are changing CSS properties outside of GSAP so its best to just use GSAP for that.

 

GSAP set() method Docs:

 

http://greensock.com/docs/#/HTML5/GSAP/TweenMax/set/

 

Also keep in mind that force3D is part of the CSSPlugin, so it wont work in canvas on your 'img' variable, since that is a canvas object and force3D will only work on DOM and SVG elements that use CSS.

 

CSSPlugin Docs: http://greensock.com/docs/#/HTML5/GSAP/Plugins/CSSPlugin/

  • force3D
    As of 1.15.0, force3D defaults to "auto" mode which means transforms are automatically optimized for speed by using matrix3d() instead of matrix(), or translate3d() instead of translate(). This typically results in the browser putting that element onto its own compositor layer, making animation updates more efficient. In "auto" mode, GSAP will automatically switch back to 2D when the tween is done (if 3D isn't necessary) to free up more GPU memory. If you'd prefer to keep it in 3D mode, you can set force3D:true. Or, to stay in 2D mode whenever possible, set force3D:false. See http://css-tricks.com/myth-busting-css-animations-vs-javascript/ for more details about performance.

I hope this helps! :)

  • Like 5
Link to comment
Share on other sites

if you are using canvas, the force3D settings won't help.

 

Like Jonathan said, GSAP can't control how the browser renders things, it only animates numbers and applies them to properties. I'm certain your tweens are running super fast. I think it comes down to brute force pixel pushing of the browser. Your image at 18,000 x 600 is nearly 11 million pixels that you need to shift 60 times per second. I'm not sure what can be done to make that easier on under-powered hardware. 

  • Like 2
Link to comment
Share on other sites

Like Carl said, that image is huge. It's almost 1mb! You need to split it up into several different images and then tile them. That still might not be good enough. Changing the size of your image and then scaling it up might help. So would rendering it at lower FPS.

 

WebGL would be better. I like to use Pixi.js for that. Here's an example of a side scrolling game running full screen. You could get your example running that smooth with a little bit of work.

 

http://www.goodboydigital.com/runpixierun/

  • Like 2
Link to comment
Share on other sites

I would also definitely run your image through tinypng to optimize it, for low file size and keeping quality:

 

http://tinypng.com/

 

Also I would convert the image to a png-24. This way you get all your color ranges and then you can take advantage of saving your png image in tinypng to get an even smaller file size without losing quality due to png being lossless. A JPEG will lose quality after every save due to it being lossy format. But after converting your image from a JPEG and into to a PNG, and using tinypng, at least your file size will be smaller in the low kb's.

 

Along with all the other advice from Blake ;)

Link to comment
Share on other sites

Hi guys!

 

Thanks the lot of help!

 

@OSUblake:

What do you think, what is the best size if a cut to pieces this big image?

 

@Jonathan:

Do you sure that optimizing is good way?

I think client will need more performance to extract the compressed image.

 

@Carl 

Can I change the canvas render frequency?

 

 

Best regards,Feco

Link to comment
Share on other sites

That optimizing is a good way. That is due to the way images are, either lossless or lossy. Every little bit helps! So optimizing your image with tinypng to reduce the image size is a must to reduce the image as much as possible while keeping detail and quality :)

Link to comment
Share on other sites

For the record, compressing your images more won't have any effect on runtime memory or rendering performance - it would only affect loading time. The browser has to uncompress the image once it loads it, and it's the same number of pixels either way. 

  • Like 2
Link to comment
Share on other sites

For the size... there is no good answer other than that you need to test out different sizes yourself and see what works best.

 

To throttle the canvas, you could try something like this...

// Call animate function at 30fps
TweenMax.to({}, 1/30, { onRepeat: animate, repeat: -1 });
  • Like 1
Link to comment
Share on other sites

If you want all your animations to run at a lower frame rate like 30fps, it's as simple as:

TweenLite.ticker.fps(30);

You can set it to whatever value you want, of course. 

 

And you can add your own "tick" listeners to it if you want, like:

TweenLite.ticker.addEventListener("tick", yourFunction);

Blake's solution is a good one too. I just figured I'd chime in with a few other tid-bits in case they're useful.

  • Like 2
Link to comment
Share on other sites

To call function at 30fps you can use something like this :

 

function caller(fps,fn){
  var x = 0;
  this.call = function(){ x++; if(x % fps == 1 ){ fn() }; }
};

var nCaller = new caller( 30 , render ); // call function 30fps ( max to 60 )

TweenLite.ticker.addEventListener('tick',nCaller.call); // call function 60fps

function render(){
  console.log('render')
};
Link to comment
Share on other sites

I'll let you in on a little secret - you can just create your own ticker if you prefer, and have it run at whatever fps you want...

var ticker = new com.greensock.Ticker(30); //run at 30fps
ticker.addEventListener("tick", yourFunction);

:)

  • Like 3
Link to comment
Share on other sites

Oh.... Cool.... !  ^_^

There's always another secret !  :huh::mellow::huh:  :(:o:unsure::wacko::blink: ... <_<

  • Like 2
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.
×