I made a game where you can walk on a 2d grid world (Pokémon style) and currently you just hop from tile to tile instead of a nice walking animation in between.
I'm right now working on that walking animation, and it all works, except that the browser doesn't reflow/repaints fast enough.
If I closely zoom in on the sprite I can see the sprite moving and doing only half of the replaces he needs to do. This creates a lag feeling, which I obviously not want. So I googled today and learned about reflow and repaints and that the browsers stacks the animations until a certain time and then executes them in batches.
I want to avoid the stacking of animations so I searched on Google, and found a lot of hacks, which are not working for me, unfortunately...
I used hacks like requesting the offsetTop, hiding and showing the element, and some others which are easily to be found online. None of them worked.
I then learned here: http://dev.opera.com/articles/view/efficient-javascript/?page=3#reflow that the browser may reflow in the background, without making it visible. (probably why the hacks weren't working)
Do you have any way so I can make the browser visibly reflow?
Related
Call me crazy, but I'm working on a game using vanilla DOM and TypeScript. It's not action-heavy, but there are some animations going on, which are driven from JavaScript (too complex to do in CSS).
I'm already applying the common trick of translateZ(0) (called null transform hack or less accurately silver bullet) to pull animated elements into their own rendering layer, and I'm animating nothing besides compositor-only properties (transform and opacity). This works beautifully: during the game, everything feels buttery smooth, even on older mobile devices.
The problem is during the start of the game. At that moment, about 70 individually transformed and animated elements enter the page one by one over the space of a few seconds, by animating their opacity from 0 to nonzero. This is causing visible stutter during the animation.
My guess was that Chrome is being too clever here, and will only rasterize each element at the moment it first becomes visible. A quick check with the dev tools confirms this, as there's a lot of rasterization going on even during the animation:
I would prefer to rasterize all these elements once, before the animation starts, and only then trigger the animation. But how can I force rasterization of elements that aren't yet visible, without showing a flash of them to the user?
I'd be happy with a Chrome-only approach, but cross-browser would be even better.
When using scaling to change the size of an HTML element containing text, the text jitters during the animation, but only if being animated with JavaScript libraries.
The jittering is most visible when the animation is slower and the text is smaller. I can't seem to figure out what causes it or how to get rid of it.
This jittering does not occur during CSS animations or animations using the fairly new JavaScript Web Animations API. It also doesn't seem to occur in some browsers. (On my iPhone)
To easily compare the different methods of animating the scaling of an element and how they appear, I made a CodePen for convenience. Before checking it out, note these points:
All the animations are using some form or imitation of the CSS property transform: scale(num); for the animation and have the same easing and duration so they can be compared more easily.
Although the jittering appears on macOS too, it is almost impossible to see on Macs with retina screens because of the high resolution.
The results I got are a reflection of the appearance of the animations on a Windows 10 machine in Google Chrome 59, although for me Microsoft Edge also showed the same results.
So my question is this: How can I prevent the text from jittering or becoming blurry when animating a scale property with JavaScript? How can I make the text in my JavaScript scale animations appear just as smooth as they do when using CSS?
You may be wondering why I don't just use CSS. The answer is because I'm frustrated with how limited CSS animation is. I would like to use advanced easing functions beyond the capabilities of a simple bezier curve (like Robert Penner's bounce and elastic functions), and use different easings on hover when the mouse enters and exits the element. This s completely my own opinion, but so far the only painless way I've found to do this is with JavaScript libraries. Besides their functionality relating to easing, most seem to offer many other capabilities which make animating much more effortless. If you know of a better way to get all the functionality I need please let me know!
What you are encountering are differences in a browser's layerizing strategy. You'll find that all the examples appear smooth in Firefox. That's because Firefox detects when script is changing a property that can animated using layers and creates a layer in response.
Although all browsers create layers when needed for declarative animations (CSS animations, CSS transitions, Web Animations API animations, and even SVG SMIL animations in some cases) not all browsers do it for Javascript animations. So, for those browsers you need to try to trick the browser into creating a layer (or, you could just file a bug on the browser, since it really should do this for you!).
Until recently, using will-change: transform was the recommended approach to get a browser to create a layer. However, Chrome changed its rendering strategy and now will-change: transform can produce very blurry results with scale animations in Chrome. Some people have succeeded in tricking Chrome to layerize at a higher resolution initially and then scaling their element down before animating. This is really unfortunate to have to do this and I can only encourage you to petition Chrome to fix this.
Also, the examples using "with HA" are not accurate. The CSS animation in (1) will also use hardware acceleration in every browser I know of--there's no need to add perspective in. Unfortunately, there is a lot of misleading information in this area (e.g. some articles claim animations can run on the GPU but that's simply not true). At the risk of self promotion, you might find an article I wrote on this last year helpful.
I'm trying to build a homepage that has a lot of moving elements. I've checked other websites that have the same moving animations do the same technique e.g. move stuff on setInterval(). But I don't know if it would be ok, on my computer its running smoothly. But I don't know if it would cause any damage to other users specifically slow computers. I say this because when I opened the site on my phone it got hot real fast.
I made a fiddle where you can see what kind of simple movements are happening but how fast the functions are executing. The fiddle only shows 4 elements but the homepage has about 10 more elements moving.
So what would be good practices to follow when implementing these kinds of website animations?
setInterval would be fine if you target old browsers, but it's not meant for animation. Some browsers cap it to 4ms. Some won't slow down when the window is not focused, so it will eat up CPU cycles, and therefore power - not good when you're on a mobile device.
There's requestAnimationFrame, a timer that's optimized for animation. Animation slows down or halts when the window is not in focus, and it aims to draw at 60fps.
For minor, non-behavioral animation (style, rather than behavior), you can do CSS animations instead. One nice thing about CSS animations is that some of them, especially the ones that deal with 3D, are GPU accelerated, making them faster and smoother than your make-shift JS animations.
I am using text-shadow for all p and headline tags (2px white glow for better readability), everything works fine until page is scrolled and javascript changes absolute positioning on one element to fixed - which I want to stay visible.
Is there any way apart of changing style for opera to make it scrolled smoothly? overflow:auto is not working in this case...
Thanks
it's hard to say 100% without seeing the code, but I guess that the way you've styled this page makes Opera do a lot of reflowing and painting when it is scrolled, and the combination of styles will make this a very expensive operation. (It would be nice to see a jsfiddle or get a link to the actual page, this would also make it simpler to advice on possible workarounds).
There are various fixes you could try - like keeping the element you want on-screen styled with position:absolute and move it from JavaScript after scroll events, or simply avoid setting position:fixed in Opera and letting the element scroll away for better scroll performance.
However, I'd strongly recommend that you first report a bug to Opera. Why?
The reason and the genesis of the web is collaboration. It may not be obvious to (understandably) frustrated web developers struggling with browser bugs, but they have a responsibility for helping browser vendors improve when they find problems, thereby contributing to moving the web forward. A minority browser like Opera admittedly has less development and QA staff resources, but to some extent support from the user community and "normal" web developers makes up for this and makes it possible also for smaller players to develop in the Web ecosystem. I think that's one of the web's strengths and the real reason why no single corporation has been able to dominate it.
So please report your issues and problems :)
This is a problem with Opera, not any way you've written the code. Opera is a gigantic steaming pile of doo-doo with almost no market share, and you should use another browser.
That's basically all anyone could tell you here, unfortunately. I understand that everyone loves their browser of choice but some just don't handle these things well. Other examples: browser with a poor javascript engine rendering animations erratically and jerky, etc.
Im using JavaScript, the HTML5 canvas-element and WebGL to make a simple 3D-game in first person view for fun.
Ideally, I would like to control my movement by using the keyboard to move and the mouse to look around, like you usually do in FPS-games. As you probably understand, there are some limits to this in the browser, since the mouse cant be captured:
When using the onmousemove event, no further movement will be detected when the mouse pointer reaches the border of my screen (which means that I wont be able to run in a circle for example)
Seeing the mouse move across the screen is not the end of the world, but it is a little annoying
From what I know, it's impossible to hide the mouse as well as setting it's position in JavaScript. Hence, my question is this:
If we cant to those things, what can we do in order to get close to the desktop gaming experience when it comes to the mouse in the browser?
And I mean right now, using current APIs. Not "what could be changed in some standard to make life easier". Also, I realize that I could use the keyboard to look around, but then we're back in 1995 when Quake were actually played like that. And of course I know that it would be easier to write a desktop application or use Flash at least, but Im trying to push JavaScript's limits here.
Apart from those things, what are your suggestions? Any kind of reference, existing game, crazy idea, hack or even browser specific solution would be appreciated.
I have done some experiments with mousehiding for a game, as far as I recall it was only Opera that I didn't make behave, so I gave it the cross instead. One crucial point is that some browsers will display a completely invisible cursor image as a black box, but with just one almost invisible pixel it'll work. Feel free to take the mousehiding part and the cursor file. http://ebusiness.hopto.org/iimdtdt/
I have thought a bit about the look around part myself, for the up/down movement it is easy, since you will cap this anyway, and all you have to do is to make sure that the cap is in sync with the mouse movement cap. For the sideways part, I suggest that you try messing with the sensitivity, when the mouse nears the edge of the screen sensitivity should go up it the direction towards the screen edge, and down in the direction away from the screen edge. I haven't tried out this method, so I can't tell how well it will actually work, but it should help keep the mouse in the middle area even if the user spins around more one way than the other.
Good luck with the project, sounds exciting.
Your hopes and dreams are now possible with the new Pointer Lock API