Skip to content

Commit e19f15d

Browse files
committed
Check browser support for pixelated image rendering.
1 parent ab756a1 commit e19f15d

File tree

1 file changed

+49
-2
lines changed

1 file changed

+49
-2
lines changed

src/traces/heatmap/plot.js

Lines changed: 49 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,50 @@ var LINE_SPACING = alignmentConstants.LINE_SPACING;
1818

1919
var labelClass = 'heatmap-label';
2020

21+
// Pixelated image rendering
22+
// The actual declaration is prepended with fallbacks for older browsers.
23+
// https://developer.mozilla.org/en-US/docs/Web/CSS/image-rendering
24+
// https://caniuse.com/?search=image-rendering
25+
var pixelatedImageCSS = [
26+
'image-rendering: optimizeSpeed',
27+
'image-rendering: -moz-crisp-edges',
28+
'image-rendering: -o-crisp-edges',
29+
'image-rendering: -webkit-optimize-contrast',
30+
'image-rendering: optimize-contrast',
31+
'image-rendering: crisp-edges',
32+
'image-rendering: pixelated'
33+
];
34+
35+
var _supportsPixelated = null;
36+
function supportsPixelatedImage() {
37+
if(_supportsPixelated !== null) { // only run the feature detection once
38+
return _supportsPixelated;
39+
}
40+
if(Lib.isIE()) {
41+
// `-ms-interpolation-mode` works only with <img> not with SVG <image>
42+
_supportsPixelated = false;
43+
} else {
44+
var declarations = Array.from(pixelatedImageCSS).reverse();
45+
var supports = window.CSS && window.CSS.supports || window.supportsCSS;
46+
if(typeof supports === 'function') {
47+
_supportsPixelated = declarations.some(function(d) {
48+
return supports.apply(null, d.split(': '));
49+
});
50+
} else {
51+
var image3 = Drawing.tester.append('image');
52+
var cStyles = window.getComputedStyle(image3.node());
53+
image3.attr('style', pixelatedImageCSS.join('; ') + ';');
54+
_supportsPixelated = declarations.some(function(d) {
55+
var value = d.split(': ')[1];
56+
return cStyles.imageRendering === value ||
57+
cStyles.imageRendering === value.toLowerCase();
58+
});
59+
image3.remove();
60+
}
61+
}
62+
return _supportsPixelated;
63+
}
64+
2165
function selectLabels(plotGroup) {
2266
return plotGroup.selectAll('g.' + labelClass);
2367
}
@@ -112,7 +156,7 @@ module.exports = function(gd, plotinfo, cdheatmaps, heatmapLayer) {
112156
var drawingMethod = 'default';
113157
if(zsmooth) {
114158
drawingMethod = zsmooth === 'best' ? 'smooth' : 'fast';
115-
} else if(trace._islinear && xGap === 0 && yGap === 0) {
159+
} else if(trace._islinear && xGap === 0 && yGap === 0 && supportsPixelatedImage()) {
116160
drawingMethod = 'fast';
117161
}
118162

@@ -358,10 +402,13 @@ module.exports = function(gd, plotinfo, cdheatmaps, heatmapLayer) {
358402
width: imageWidth,
359403
x: left,
360404
y: top,
361-
'image-rendering': drawingMethod === 'fast' && !zsmooth ? 'pixelated' : 'auto',
362405
'xlink:href': canvas.toDataURL('image/png')
363406
});
364407

408+
if(drawingMethod === 'fast' && !zsmooth) {
409+
image3.attr('style', pixelatedImageCSS.join('; ') + ';');
410+
}
411+
365412
removeLabels(plotGroup);
366413

367414
var texttemplate = trace.texttemplate;

0 commit comments

Comments
 (0)