Skip to content
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

fix: do not cache devicePixelRatio #3844

Merged
merged 14 commits into from
Dec 19, 2023
1 change: 1 addition & 0 deletions docs/docs/api/view.md
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,7 @@ Constructor that creates a new View instance for the provided [Vega dataflow *ru
- *tooltip*: Handler function invoked to support tooltip display. See the [tooltip](#view_tooltip) method.
- *locale*: Locale definitions for string parsing and formatting of number and date values. The locale object should contain `number` and/or `time` properties with [locale definitions](../locale). If unspecified, the current default locale at the time of instantiation will be used for the View instance. <small>{% include tag ver="5.12" %}</small>
- *expr*: Alternate evaluator for Vega expressions. See the [interpreter](../../../usage/interpreter) usage documentation. <small>{% include tag ver="5.13" %}</small>
- *watchPixelRatio*: Boolean flag allowing an event listener to trigger a re-render when the pixel ratio of the page changes (such as via zooming or changing monitors).

The View constructor call is typically followed by a chain of method calls to setup the desired view configuration. After this chain, the [runAsync](#view_runAsync) method evaluates the underlying dataflow graph to update and render the visualization.

Expand Down
4 changes: 1 addition & 3 deletions packages/vega-scenegraph/src/util/canvas/resize.js
Original file line number Diff line number Diff line change
Expand Up @@ -2,14 +2,12 @@ function devicePixelRatio() {
return typeof window !== 'undefined' ? window.devicePixelRatio || 1 : 1;
}

var pixelRatio = devicePixelRatio();

export default function(canvas, width, height, origin, scaleFactor, opt) {
const inDOM = typeof HTMLElement !== 'undefined'
&& canvas instanceof HTMLElement
&& canvas.parentNode != null,
context = canvas.getContext('2d'),
ratio = inDOM ? pixelRatio : scaleFactor;
ratio = inDOM ? devicePixelRatio() : scaleFactor;

canvas.width = width * ratio;
canvas.height = height * ratio;
Expand Down
1 change: 1 addition & 0 deletions packages/vega-typings/types/runtime/index.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -65,6 +65,7 @@ export interface ViewOptions {
tooltip?: TooltipHandler;
locale?: LocaleFormatters;
expr?: any;
watchPixelRatio?: boolean;
}

export class View {
Expand Down
8 changes: 7 additions & 1 deletion packages/vega-view/src/View.js
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@ import {getState, setState} from './state';
import timer from './timer';
import defaultTooltip from './tooltip';
import trap from './trap';
import watchPixelRatio from './watchPixelRatio';

import {Dataflow, asyncCallback} from 'vega-dataflow';
import {locale} from 'vega-format';
Expand Down Expand Up @@ -113,6 +114,8 @@ export default function View(spec, options) {

// initialize DOM container(s) and renderer
if (options.container) view.initialize(options.container, options.bind);

if (options.watchPixelRatio) view._watchPixelRatio();
}

function lookupSignal(view, name) {
Expand Down Expand Up @@ -385,5 +388,8 @@ inherits(View, Dataflow, {

// -- SAVE / RESTORE STATE ----
getState,
setState
setState,

// RE-RENDER ON ZOOM
_watchPixelRatio: watchPixelRatio
});
22 changes: 22 additions & 0 deletions packages/vega-view/src/watchPixelRatio.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
export default function() {
// based on https://developer.mozilla.org/en-US/docs/Web/API/Window/devicePixelRatio#monitoring_screen_resolution_or_zoom_level_changes
if (this.renderer() === 'canvas' && this._renderer._canvas) {
let remove = null;
const updatePixelRatio = () => {
if (remove != null) {
remove();
}
const media = matchMedia(`(resolution: ${window.devicePixelRatio}dppx)`);
media.addEventListener('change', updatePixelRatio);
remove = () => {
media.removeEventListener('change', updatePixelRatio);
};

this._renderer._canvas.getContext('2d').pixelRatio = window.devicePixelRatio || 1;
this._redraw = true;
this._resize = 1;
this.resize().runAsync();
};
updatePixelRatio();
}
}