Skip to content

Commit

Permalink
fix: do not cache devicePixelRatio (#3844)
Browse files Browse the repository at this point in the history
* fix: do not cache devicePixelRatio
* feat: add `devicePixelRatio` change listener

---------

Co-authored-by: Dominik Moritz <domoritz@gmail.com>
  • Loading branch information
lsh and domoritz committed Dec 19, 2023
1 parent 9f08746 commit ae698ee
Show file tree
Hide file tree
Showing 5 changed files with 32 additions and 4 deletions.
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();
}
}

0 comments on commit ae698ee

Please sign in to comment.