Skip to content

Commit

Permalink
Plot outputs incorrectly sized inside scaled outputs (#4139)
Browse files Browse the repository at this point in the history
* Fix #4135: Plot outputs incorrectly sized inside scaled outputs

CSS zoom property affects el.getBoundingClientRect() but not
el.offsetWidth/Height. When reporting sizes of outputs from
client to server, we need to back out the CSS zoom because
those sizes are used as CSS width/height, which will be
affected by zoom.

(Note that something similar happens with CSS transforms but
we don't have a good way to deal with them)

* Squelch TS error

* `yarn build` (GitHub Actions)

* Add TODO

Co-authored-by: Garrick Aden-Buie <garrick@adenbuie.com>

* Rebuild JS

---------

Co-authored-by: jcheng5 <jcheng5@users.noreply.github.com>
Co-authored-by: Garrick Aden-Buie <garrick@adenbuie.com>
  • Loading branch information
3 people authored Dec 8, 2024
1 parent e5083f4 commit 5bf0701
Show file tree
Hide file tree
Showing 7 changed files with 39 additions and 11 deletions.
12 changes: 10 additions & 2 deletions inst/www/shared/shiny.js
Original file line number Diff line number Diff line change
Expand Up @@ -6873,6 +6873,14 @@
return 1;
}
}
function getBoundingClientSizeBeforeZoom(el) {
var rect = el.getBoundingClientRect();
var zoom = el.currentCSSZoom || 1;
return {
width: rect.width / zoom,
height: rect.height / zoom
};
}
function scopeExprToFunc(expr) {
var exprEscaped = expr.replace(/[\\"']/g, "\\$&").replace(/\u0000/g, "\\0").replace(/\n/g, "\\n").replace(/\r/g, "\\r").replace(/[\b]/g, "\\b");
var func;
Expand Down Expand Up @@ -25282,7 +25290,7 @@
};
doSendImageSize = function _doSendImageSize() {
(0, import_jquery39.default)(".shiny-image-output, .shiny-plot-output, .shiny-report-size").each(function() {
var id = getIdFromEl(this), rect = this.getBoundingClientRect();
var id = getIdFromEl(this), rect = getBoundingClientSizeBeforeZoom(this);
if (rect.width !== 0 || rect.height !== 0) {
inputs.setInput(".clientdata_output_" + id + "_width", rect.width);
inputs.setInput(".clientdata_output_" + id + "_height", rect.height);
Expand Down Expand Up @@ -25464,7 +25472,7 @@
};
initialValues = (0, _context3.t0)(_context3.t1, _context3.t2);
(0, import_jquery39.default)(".shiny-image-output, .shiny-plot-output, .shiny-report-size").each(function() {
var id = getIdFromEl(this), rect = this.getBoundingClientRect();
var id = getIdFromEl(this), rect = getBoundingClientSizeBeforeZoom(this);
if (rect.width !== 0 || rect.height !== 0) {
initialValues[".clientdata_output_" + id + "_width"] = rect.width;
initialValues[".clientdata_output_" + id + "_height"] = rect.height;
Expand Down
4 changes: 2 additions & 2 deletions inst/www/shared/shiny.js.map

Large diffs are not rendered by default.

2 changes: 1 addition & 1 deletion inst/www/shared/shiny.min.js

Large diffs are not rendered by default.

6 changes: 3 additions & 3 deletions inst/www/shared/shiny.min.js.map

Large diffs are not rendered by default.

5 changes: 3 additions & 2 deletions srcts/src/shiny/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@ import { debounce, Debouncer } from "../time";
import {
$escape,
compareVersion,
getBoundingClientSizeBeforeZoom,
getComputedLinkColor,
getStyle,
hasDefinedProperty,
Expand Down Expand Up @@ -289,7 +290,7 @@ class ShinyClass {
$(".shiny-image-output, .shiny-plot-output, .shiny-report-size").each(
function () {
const id = getIdFromEl(this),
rect = this.getBoundingClientRect();
rect = getBoundingClientSizeBeforeZoom(this);

if (rect.width !== 0 || rect.height !== 0) {
initialValues[".clientdata_output_" + id + "_width"] = rect.width;
Expand Down Expand Up @@ -425,7 +426,7 @@ class ShinyClass {
$(".shiny-image-output, .shiny-plot-output, .shiny-report-size").each(
function () {
const id = getIdFromEl(this),
rect = this.getBoundingClientRect();
rect = getBoundingClientSizeBeforeZoom(this);

if (rect.width !== 0 || rect.height !== 0) {
inputs.setInput(".clientdata_output_" + id + "_width", rect.width);
Expand Down
15 changes: 15 additions & 0 deletions srcts/src/utils/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -144,6 +144,20 @@ function pixelRatio(): number {
}
}

function getBoundingClientSizeBeforeZoom(el: HTMLElement): {
width: number;
height: number;
} {
const rect = el.getBoundingClientRect();
// Cast to any because currentCSSZoom isn't in the type def of HTMLElement
// TODO: typescript >= 5.5.2 added this property to the type definition
const zoom = (el as any).currentCSSZoom || 1;
return {
width: rect.width / zoom,
height: rect.height / zoom,
};
}

// Takes a string expression and returns a function that takes an argument.
//
// When the function is executed, it will evaluate that expression using
Expand Down Expand Up @@ -398,6 +412,7 @@ export {
formatDateUTC,
makeResizeFilter,
pixelRatio,
getBoundingClientSizeBeforeZoom,
scopeExprToFunc,
asArray,
mergeSort,
Expand Down
6 changes: 5 additions & 1 deletion srcts/types/src/utils/index.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,10 @@ declare function parseDate(dateString: string): Date;
declare function formatDateUTC(x: Date): string;
declare function makeResizeFilter(el: HTMLElement, func: (width: HTMLElement["offsetWidth"], height: HTMLElement["offsetHeight"]) => void): () => void;
declare function pixelRatio(): number;
declare function getBoundingClientSizeBeforeZoom(el: HTMLElement): {
width: number;
height: number;
};
declare function scopeExprToFunc(expr: string): (scope: unknown) => unknown;
declare function asArray<T>(value: T | T[] | null | undefined): T[];
declare function mergeSort<Item>(list: Item[], sortfunc: (a: Item, b: Item) => boolean | number): Item[];
Expand All @@ -26,4 +30,4 @@ declare function updateLabel(labelTxt: string | undefined, labelNode: JQuery<HTM
declare function getComputedLinkColor(el: HTMLElement): string;
declare function isBS3(): boolean;
declare function toLowerCase<T extends string>(str: T): Lowercase<T>;
export { escapeHTML, randomId, strToBool, getStyle, padZeros, roundSignif, parseDate, formatDateUTC, makeResizeFilter, pixelRatio, scopeExprToFunc, asArray, mergeSort, $escape, mapValues, isnan, _equal, equal, compareVersion, updateLabel, getComputedLinkColor, hasOwnProperty, hasDefinedProperty, isBS3, toLowerCase, };
export { escapeHTML, randomId, strToBool, getStyle, padZeros, roundSignif, parseDate, formatDateUTC, makeResizeFilter, pixelRatio, getBoundingClientSizeBeforeZoom, scopeExprToFunc, asArray, mergeSort, $escape, mapValues, isnan, _equal, equal, compareVersion, updateLabel, getComputedLinkColor, hasOwnProperty, hasDefinedProperty, isBS3, toLowerCase, };

0 comments on commit 5bf0701

Please sign in to comment.