-
Notifications
You must be signed in to change notification settings - Fork 27
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Immediate redraw #161
Comments
I'm not sure. It might be possible but I haven't had the need to support it. I'm not yet sure I fully understand the issue. When you print a page that contains a scatter plot, the issue is that the scatter plot is printed according to the canvas size prior to printing? If this is the case, I'm not sure I know a solution from the top of my head because regl-scatterplot automatically redraws every time the canvas resizes. That means, in case of printing, the resize event is either not fired or the printing page is finished before the next animation frame is available. Do you have an example of what the issue you're running into looks like?
Good catch! Always feel free to open a PR to fix such issues. I fixed the |
It doesn't fire. If I go to scatterplot demo, make window size small and press print, the result looks low quality and stretched. The solution would be to expose function that can redraw the canvas immediately. As a workaround I am capturing requestAnimationFrame calls from regl and trigger them myself and it works, but it's very ugly. |
I don't want to expose a new function that's should practically only be used in one edge case. I.e., immediate re-rendering for printing. Instead, it'd be better to if regl-scatterplot can capture the printing event internally and then do a forced re-rendering. As it sounds like you've basically solved that problem already (even if it's ugly) it'd be great if you could share your solution as a starting point for a fix. |
I doubt my workaround will be of any use to you. It consists of two parts, first I globally capture all requestAnimationFrame calls to expose new function that lets me trigger all requested animation frames: const origRequestAnimationFrame = window.requestAnimationFrame;
const origCancelAnimationFrame = window.cancelAnimationFrame;
const frameCallbacks = new Map<number, FrameRequestCallback>();
window.requestAnimationFrame = callback => {
const id = origRequestAnimationFrame(time => {
frameCallbacks.delete(id);
callback(time);
});
frameCallbacks.set(id, callback);
return id;
};
window.cancelAnimationFrame = id => {
origCancelAnimationFrame(id);
frameCallbacks.delete(id);
};
export function triggerAnimationFrame(time: number) {
const callbacks = [...frameCallbacks.values()]; // Map.values is an iterator, can cause infinite loops
for (const callback of callbacks) {
try {
callback(time);
} catch (error) {
console.error(error);
}
}
} Then since currently regl scatterplot renderer is either limited to the size of the window or to fixed framebuffer size(couldn't find any way to resize a custom renderer), I create a new renderer that is a proxy that exposes either default renderer or a renderer with fixed width and height of what I would expect on A3 @ 300 DPI, depending on whenever the browser is doing a printing pass or regular one. const printWidth = 4556;
const printHeight = 1646;
const defaultRenderer = createRenderer();
const printCanvas = document.createElement('canvas');
printCanvas.width = printWidth;
printCanvas.height = printHeight;
const printRenderer = createRenderer({ canvas: printCanvas });
const smartRenderer = new Proxy(defaultRenderer, {
get: (_target, property) =>
window.matchMedia('print')
? (printRenderer as any)[property]
: (defaultRenderer as any)[property],
set: (_target, property, value) =>
window.matchMedia('print')
? ((printRenderer as any)[property] = value)
: ((defaultRenderer as any)[property] = value),
}); And then I watch media changes and trigger rerender with some fixed resolution. const onPrint = (event: MediaQueryListEvent) => {
if (event.matches) {
const printPointScale = printHeight / canvas.height;
const defaultPointSize = regl.get('pointSize');
const printPointSize = Array.isArray(defaultPointSize)
? defaultPointSize.map(size => size * printPointScale)
: defaultPointSize * printPointScale;
regl.set({
width: printWidth,
height: printHeight,
aspectRatio: printWidth / printHeight,
pointSize: printPointSize,
});
regl.redraw();
triggerAnimationFrame(-1);
regl.set({ pointSize: defaultPointSize });
} else {
onResize();
}
};
const mediaQueryList = window.matchMedia('print');
mediaQueryList.addEventListener('change', onPrint);
You can just add a flag to redraw/draw function that would trigger rerender immediately instead of setting |
Hi. When I am using browser's printing function, the scatterplot does not redraw itself and instead just stretches last canvas content into the new one. It is possible to detect printing using
window.matchMedia
but callingredraw
function doesn't do anything since redraws are queued for next animation frames. It is also not possible to hold printing until the next frame, it happens immediately after related events get fired. It would be nice to be able to redraw scatterplot immediately to update it for printing specific size/aspectratio changes.Also
redraw
function is missing from documentation anddraw
can't be called with empty arguments according to typescript types, while being allowed according to documentation.The text was updated successfully, but these errors were encountered: