A lot of online games use animations of HTML elements as a core gameplay mechanics. For example, a solitaire game may have a DIV element or an IMG element for every card on the gameboard. Players drag and drop these cards across the board, and the game often shows animations that last a few seconds. An example of such animation is dealing cards, i.e. distributing them from the deck to their proper places on the gameboard at the beginning of the game. This is usually done 1) without user interaction, upon entering the website, and then 2) after user interaction, upon finishing one game and starting another.
These animations are longer than 500 ms, and so (as I understand) the elements, which finish their movement after that time, count towards CLS regardless of whether the user initiated the animation or not. Moreover, the card-dealing animation that greets the user on the website is entirely counted towards CLS. This might be solved by forcing the user to interact with the website before the initial animation, but it is a bad UX, as this is an extra unnecessary and potentially annoying click for the user. There is a lot to write about it, but for now, I’ll just state that showing a (not user-initiated) greeting animation is the best UX practice in this context and it is employed by the most popular games (also those using canvas).
The websites with games based on HTML elements are quite popular, and include Solitaire, Mahjong, Minesweeper etc. Some are at the top spots in the Google search results and have hundreds of thousands of users every month. I suspect that other, non-game-related sites may also employ useful movement animations of HTML elements which are appreciated by the users. Hence, I’ll ask in general:
Do I understand correctly that such animations of HTML elements, despite being expected by the user, are misclassified by contemporary CLS measures as unexpected?
Is the intention of the designers of the CLS measures to penalize this type of website behavior? I am especially asking in terms of SEO as I suspect CLS may be used as a factor by some ranking algorithms.
It's hard to say exactly what's causing your issue without knowing how you've implemented your animations, but if you are animating or transitioning using the CSS transform property, then it shouldn't contribute to CLS because it doesn't trigger a re-layout of the page.
In general, this is a best practice for smooth animations, so I'd recommend it even if your CLS was fine.
See more details here: https://web.dev/optimize-cls/#animations
Related
I have a javascript canvas game with pixi.js that requires a player to press a certain combination of buttons to complete a level. They basically have to press the button that matches a certain color.
It turns out that players are writing bots in python to do this task and they are getting the maxium score each time. The game is already live and users enjoy playing it so I can't really change anything gameplay wise.
So I thought about a few possible solutions but I have some concerns
Captcha between each level
Check the speed of the input
Check how consistent the input is
The captcha will hurt user experience, and there are tons of video's how to bypass it. 2 and 3 will fail after the creators of the bots understand what is happening. So I am really stuck on what I could do.
I would consider a random grace period before allowing the buttons to be clicked. this may stump some bots, but is circumventable.
Besides that, I would profile the timing of the clicks/interactions. Every time next level is requested, compare to the profile, and if they are consistently the same introduce a randomized button id, button shape (circle, oval, square, etc.), button placement (swap buttons) to avoid easy scripting. Also the font and the actual text could be varied.
I would also change the input element to <input type="image"> since it will give you the exact coordinates (if possible - I'm not familiar with pixi.js) and this will aid in the profiling.
You could also implement some sort of mouse position tracker, but people on touchscreens will not produce data for this. You could supplement with additional check if the user input is touch, but a bot would easily be able to circumvent it.
EDIT
I don't know if some library to detect other JavaScript imports and thereby detecting potential bots would be applicable. Might be one avenue to consider.
Doing something like this: Check whether user has a Chrome extension installed to verify that you are running in a browser and not in a python environment could be another avenue. It would mean that you restrict your users to certain browsers, and as a lot of other code, could be circumvented. Cost/benefit should be kept in mind here.
If everything is being run though the actual browser with some sort of headless interface it is not going to be useful at all.
EDIT 2
A quick googling of python automate browser game brings up a tutorial of how to automate browser games with python. based on a cursory glance, making your buttons move around and changing font would be effective, and even resizing the playing area "randomly" (even if you have a full screen function) may be a viable defense. Again, following the tutorial and trying to automate it using that, and seeing how to block it would be a good exercise.
You could also consider asking some students for help. This could be a good project idea for many computer studies courses that offer project based courses. It could also be a student job type deal - if you want to ensure that you get a result and a "report".
I think your approach is valid. It seems a bit excessive to add Capcha between each level, perhaps add it before the game starts.
It might be a good idea to check interval between individual clicks, and define some threshold when you can safely assume that it was a bot who clicked the button.
Another approach you could take is to make it more complicated to look up the correct buttons. Approaches like randomizing the element IDs, not rendering the label inside the buttons but as separate elements (I assume it is a game with some fixed window size and you don't care about mobile that much).
I am not familiar with Pixi.js, but that could be an approach to consider.
----------------------- Edit -----------------------
What if you run your game in an iframe ?
I'm creating an online psychology experiment in JavaScript with the goal of studying people's ability to recognize images quickly (this RSVP, Rapid Serial Visual Presentation, paradigm is a common approach in psychophysics for isolating the feedforward, pre-attentive stages of visual processing). I aim to show a sequence of images for brief durations (e.g. 30 ms, 50 ms, 70 ms, etc.). For valid results, it's important to get the presentation times as precise as possible. Usually, this is done in a lab with specialized software or equipment, but this setup isn't an option for me. I recognize that some slop is an inevitable side effect of doing this experiment in a browser, but I'm hoping to (A) minimize it as much as possible, and (B) quantify, to the extent that I can, the amount of imprecision that actually occurred.
Right now, I'm preloading images, and am using setTimeout() to control stimulus duration. I'm assuming that experiment participants will use a variety of monitors (so refresh rates may differ) and browsers.
By eye, the timings of the images with my current approach seem to be wrong, and, in particular, highly variable. This is consistent with things I've read saying that variability for brief presentation times can be high.
Are there tools available to control timing more precisely in JavaScript? Additionally, are there tools that can measure/estimate the time an image was actually shown on screen? Finally, are there other options I should look at, e.g. compiling the sequence of images into a video, gif, etc.?
setTimeout does not specify when an action should take place. It only states that an action should take place once the timer has expired; but there's no way to guarantee when exactly the event will take place (https://developer.mozilla.org/en-US/docs/Web/API/WindowOrWorkerGlobalScope/setTimeout).
When working on (psychological) expiriments, and when you have no control over the participant's environment, I would argue (apart from not entertaing such an uncontrolled environment in such cases) for claiming the whole tab the user is using (effectively blocking any interaction while the image is shown) or, as you already mention yourself, using an animated gif or sequence of images.
Or you can monitor and store the time the image was actually shown to your participant (using checking when the image comes into the viewport), and compare that timestamp with the participant's interaction. That would perhaps give the most valid results, as it will eliminate the inpredictability of setTimeout.
Long stay made short, marketing wnats our entire sitemap (5000 pages) in one menu. After 1 year of fighting them on this, there is no winning and we must implement.
We are currently evaluating technologies that will help us make this decision.
Some menu items will have recursive nested levels 5 items deep(insane I know).
The data is driven from JSON because our sitemap is stored in XML in an archaic CMS (Ektron).
I am considering React but there may be no answer. We are looking for a JavaScript library that will help us achieve this and improve performance. Currently our menu alone takes 4 seconds to load for a desktop computer with a half decent Internet connection.
Question; Is using React for this a good idea? If not, are there any other options for us to consider.
Many thanks.
Take a look at React Infinite
When a long list of DOM elements are placed in a scrollable container,
all of them are kept in the DOM even when they are out the user's
view. This is highly inefficient, especially in cases when scrolling
lists can be tens or hundreds of thousands of items long. React
Infinite solves this by rendering only DOM nodes that the user is able
to see or might soon see. Other DOM nodes are clustered and rendered
as a single blank node.
How can I control the rendering loop frame rate in KineticJS? The docs for Kinetic.Animation show a frame rate being passed to the render callback, and Kinetic.Tween seems to have no frame rate logic, but I don't see anyway to force, say, a 30fps when 60fps is possible.
Loads of context for the curious follows, but the question is that simple. If anyone reads on, other advice is welcome. If you already know the answer, don't waste your time reading on!
I'm developing a music app that combines some DOM-based GUI controls (current iteration using jQuery Mobile) and Canvas-based GUI controls (using KineticJS). The latter involve some animation. Because the animated elements are triggered by music playback, I'm using Kinetic.Tween to avoid the complexity of remembering how long a given note has been playing (which Kinetic.Animation would require doing).
This approach works great at 60fps in Chrome (on a fast machine) but is just slow enough on iOS 6.1 Safari (iPad 2) that manipulating controls while animations are happening gets a little janky. I'm not using WebGL (unless KineticJS or Chrome does this by default for canvas?), and that's not an option when I package for native UIWebView.
As I'm getting beyond prototype into wanting to make more committed tech decisions, I see the following options, in order of perceived goodness:
Figure out how to cap the frame rate. Because my animations heavily use alpha fades but do not involve motion, I believe I could get away with 20-30fps and look fine. Could also scale this up on faster devices.
Don't respond immediately to touch inputs, but add them to a queue which I poll at a constant interval and only use the freshest for things like touchmove. This has no impact on my non-interactive animated elements, but tackles the problem from the other direction, trying to reduce the load of user interaction. This would require making Kinetic controls static and manually tracking touch coordinates (not terrible effort if it actually helped).
Rewrite DOM-based GUI to canvas-based (KineticJS); rewrite WebAudio-based engine to HTML5 audio; leverage CocoonJS or Ejecta for GPU-acceleration. This means having to hand-code stuff like file choosers and nav menus and such (bad). Losing WebAudio is pretty serious as it eliminates features like DSP effects and very fine-grained, low-latency timing (which is working just fine on an iPad 2).
Rewrite the app to separate DOM based GUI and WebAudio from Canvas-based elements, leverage CocoonJS. I'm not sure if/how well this works out, but the fact that CocoonJS passes JavaScript code as strings between the 2 components makes me very skittish about how solid this idea is. It's probably doable, but best case I'm very tied to CocoonJS moving forwards. I don't like architecting this way, but maybe it's not as bad as it sounds?
Make animations less juicy. This is least good not because of its design impact but because, as it is, I'm only animating ~20 simple shapes at any time in my central view component, however they include transparency and span an area ~1000x300. Other components like sliders are similarly bare-bones. In other words, it's not very juicy right now.
Overcome severe allergy to Objective-C; forget about the browser, Android, and that other mobile OS. Have a fast app that performs natively and has shiny Apple-approved widgets. My biggest problem with this approach is not wanting to be stuck in Objective-C reality for years, skillset-wise. I just don't like it.
Buy an iPad 3 or later. Since I already am pretending Android doesn't exist (I don't have any devices to test), why not pretend no one still has iPad 2? I think this is passing the buck -- if I can get acceptable performance on iPad 2, I will feel confident about the app's performance as I add more features.
I may be overlooking options or otherwise naive about how to tackle this. Some would say what I'm trying to build is just silly. But it's working pretty well just not ready for prime time on the iPad 2.
Yes, you can control the Kinetic.Animation framerate
The Kinetic.Animation sends in a frame object which has a frame.time property.
That .time is a running timer that you can use to throttle your animation speed.
Here's an example that throttles the Kinetic.Animation: http://jsfiddle.net/m1erickson/Hn3cC/
var lastTime;
var frameDelay=1000;
var loop = new Kinetic.Animation(function(frame) {
var time = frame.time
if(!lastTime){lastTime=time;}
var elapsed = time-lastTime;
if(elapsed>=frameDelay){
// frameDelay has expired, so animate stuff now
// set lastTime for the next loop
lastTime=time;
}
}, layer);
loop.start();
Working from #markE's suggestions, I tried a few things and found a solution. It's ultimately not rocket science, but sharing what I figured out:
First, tried the hack of doubling Tween durations and targets, using a timer to stop them at 50%. This kinda sorta worked but was hard to get to look good and was pretty error prone in coding bogus targets like negative opacity or height or whatnot.
Second, having read the source to Tween and looked at docs again for Animation, decided I could locally use Animation instances instead of Tween instances, and allow the closure scope to hang onto the relevant note properties. Eventually got this working smoothly and finally realized a big Duh! which is that throttling the frame rate of several independently animating things does not in any way throttle the overall frame rate.
Lastly, decided to give my component a render() method that calls itself in a loop with requestAnimationFrame, exits immediately if called before my clamp time, and inside render() I update all objects in the Kinetic canvas and call layer.drawScene(). Because there is now only one animation, this drops frame rate to whatever I need and the app is fast on iPad 2 (looks exactly the same to my eyes too).
So Kinetic is still helping for its higher level canvas API, and so far my other control widgets are still easy code using Kinetic to handle user input and dragging, now performing much better as the big beast component is not eating up the CPU.
The short answer to my original question is that no, you can't lock the overall frame rate for very complex animations, but as Mark said, you can for anything that fits in a single Animation instance.
Note that I could have still used Animation without giving it a layer or explicitly calling any draw() methods, but since I'd still have to write all the logic to determine individual element's current visual state, there was no gain to doing this. What would be very useful would be if Tween could accept a parameter to not automatically render. This would simplify code like mine, as I could shorthand the animation on individual objects but still choose when to actually do the heavy lifting of rendering everything. Seeing how much this whole exercise gained in performance on the iPad 2, might be worth adding this option to the framework.
I'm trying to learn how to program a (virtual) Trading Card Game game (similar to Magic the Gathering) in Javascript. I've read a little about MVC architecture and controllers, but it's all over my head (I don't have any formal CS education) and I'm wondering if anyone has any good links or tips about how I might learn more about code architecture at a beginner's level.
Would each "card" be represented as an object, and all the logic of the cards' rules be wrapped inside one large game engine function, or many small functions that are connected to each other?
Here's an example question:
Imagine there's a card which says, "When this card comes into play, draw a card." How should I architect the game to prepare for this situation, and how is it triggered (most efficiently)? Does the card trigger the game engine, or does the game engine parse each card that's played?
Here's another example:
Imagine there's a card which says, "All your cards cost 1 less to play." and it stays in play permanently. How does the game understand that it needs to alter its rules in this case? Is this a function which listens for card to be played and interrupts the cost? As each turn resolves, where is this rule stored? Are there variables which store the base rules of the game (global card cost modifier: 0; your card cost modifier: 0) and other variables which store those new rules which cards introduce (your card cost modifier: -1), or are these variables dynamically created by the game engine as cards alter the rules (your elf cost modifier: -2)? And how do the rules know to change when a card has been destroyed, thus removing the card's rule modification?
Is what I need a primer on listeners and events? (I don't really know anything about them, but I've seen references to them from time to time.) Could you point me in the direction of a good resource?
To be clear, I'm not trying to make a long-winded request for folks to manually Google for me; I'm blindly fumbling in the dark and asking if someone would point me to the right words or phrases to search. Thank you!
There is a very nice blog about recreating a similar card game: Hearthstone from Blizzard. Allthough it is written in C# and uses Unity as a view layer, you get a pretty good understanding of how one goes about creating a suitable architecture for such a game. A fair warning though, recreating Magic the Gathering in Javascript can prove incredibly complicated and mess with your head a lot (I have first hand experience).
Blog: http://theliquidfire.com/2017/08/21/make-a-ccg-intro/
You need to go a level deeper here and think about the "game" itself. The game you're describing will actually be built around a "state machine" which is a core CS concept you should dive into and understand before you start building.
The rules of your game are going to be a state machine and the events (cards) triggered (by being played) during your game can modify those rules. You'll want some kind of interpreter to "read" the card and to modify either the rules or the game state. And then you'll need something to iterate the game through turns and phases, reading the state and taking appropriate action.
You'll also want to learn about stacks. If your game lets players interrupt each other you'll need a way to keep track of which event should happen first because events will want to be able to affect, block, redirect other events. A stack will help you keep track of that ordering.