tab-counter-plus
tab-counter-plus copied to clipboard
Flicker when updating icon
When using SVG icons, and a new tab is opened, there is often a flicker lasting a few frames where the old icon blinks out but the new icon is not drawn yet.
i.e. it goes something like [24] -> [ ] -> [25]
This doesn't happen as often when closing tabs, because (I think) the icon is cached and therefore Firefox just swaps out the bitmap rather than re-rendering the SVG. But if you open a lot of tabs and close them one-by-one the flicker does eventually return though.
Maybe there is some way to explicitly draw/cache the icon for +1 / -1 in the background so the flicker can be avoided? Obviously it would still flicker if you closed 10 tabs at once but in that case FF UI is slow enough anyway that it doesn't matter.
The problem is that the SVG won't be rendered unless I display it in an active tab. And if I display the next number in order to cache it, there will still be some flickering. If there are multiple windows, and one is minimized or the current one is maximized, I could render the SVG in the hidden window. But maybe Firefox has some optimization and won't render it.
There's the background web page the addon runs in, maybe inserting a SVG there will render it.
Another idea would be rendering to canvas and using toDataUrl, PNG is probably faster.
Well, background doesn't work. I'll try canvas next.
Canvas doesn't help either, but it does seem a little easier to use than the SVG:
function canvasDataIcon(text) {
let canvas = document.createElement("canvas");
let scale = window.devicePixelRatio;
let size = 16 * scale;
canvas.width = 16 * scale;
canvas.height = 16 * scale;
let canvas_context = canvas.getContext('2d');
canvas_context.scale(scale, scale);
canvas_context.clearRect(0,0,16,16);
canvas_context.fillStyle = prefs.bgColorEnabled ? prefs.bgColor : "transparent";
canvas_context.fillRect(0,0,16,16);
canvas_context.textBaseline = 'middle';
canvas_context.textAlign = "center";
let l = text.length;
canvas_context.font = `${14-l}px 'Segoe UI', 'DejaVu Sans', sans-serif`;
canvas_context.fillStyle = prefs.colorEnabled ? prefs.color : "transparent";
canvas_context.fillText(text, 8-1/scale, 8+1/scale, 16);
return canvas_context.getImageData(0,0,16*scale,16*scale);
}
I guess the flicker is really due to the indirection of using CSS variables for the image data, it has to load 6-7 data urls.
I couldn't find a Mozilla bug on file, but you filed https://bugzilla.mozilla.org/show_bug.cgi?id=1475877, which is close enough.
Ideally passing ImageData would pass-by-reference, so we could just use the canvas API to draw straight to the icon...
Firefox uses CSS variables so that it's easy to update the icon when the DPI changes. And in fact this is why I prefer SVG than canvas, I don't have to care about the size of the icon because it will be scaled as necessarily without becoming blurry.
Yeah, the only workable approach is to get the icons cached properly. The existing WebExtension caching code is borked, so maybe a decently powerful API for specifying a set of icons to all be cached w/ Firefox's internal cache could be approved...