Skip to content

Commit 6fb171f

Browse files
committed
Refactor: pixelated image rendering
- move style and support function into `src/lib` - make heatmap and image trace use the same base
1 parent 1e9d6bd commit 6fb171f

File tree

4 files changed

+61
-64
lines changed

4 files changed

+61
-64
lines changed

src/lib/index.js

+56
Original file line numberDiff line numberDiff line change
@@ -1426,3 +1426,59 @@ lib.getPositionFromD3Event = function() {
14261426
];
14271427
}
14281428
};
1429+
1430+
// Pixelated image rendering
1431+
// The actual CSS declaration is prepended with fallbacks for older browsers.
1432+
// NB. IE's `-ms-interpolation-mode` works only with <img> not with SVG <image>
1433+
// https://developer.mozilla.org/en-US/docs/Web/CSS/image-rendering
1434+
// https://caniuse.com/?search=image-rendering
1435+
// http://phrogz.net/tmp/canvas_image_zoom.html
1436+
var PIXELATED_IMAGE_DECLARATIONS = [
1437+
['image-rendering', 'optimizeSpeed'],
1438+
['image-rendering', '-moz-crisp-edges'],
1439+
['image-rendering', '-o-crisp-edges'],
1440+
['image-rendering', '-webkit-optimize-contrast'],
1441+
['image-rendering', 'optimize-contrast'],
1442+
['image-rendering', 'crisp-edges'],
1443+
['image-rendering', 'pixelated']
1444+
];
1445+
1446+
lib.PIXELATED_IMAGE_STYLE = PIXELATED_IMAGE_DECLARATIONS.map(function(d) {
1447+
return d.join(': ') + '; ';
1448+
}).join('');
1449+
1450+
var _supportsPixelated = null;
1451+
1452+
/**
1453+
* Check browser support for pixelated image rendering
1454+
*
1455+
* @return {boolean}
1456+
*/
1457+
lib.supportsPixelatedImage = function() {
1458+
if(_supportsPixelated !== null) { // only run the feature detection once
1459+
return _supportsPixelated;
1460+
}
1461+
if(lib.isIE()) {
1462+
_supportsPixelated = false;
1463+
} else {
1464+
var declarations = Array.from(PIXELATED_IMAGE_DECLARATIONS).reverse();
1465+
var supports = window.CSS && window.CSS.supports || window.supportsCSS;
1466+
if(typeof supports === 'function') {
1467+
_supportsPixelated = declarations.some(function(d) {
1468+
return supports.apply(null, d);
1469+
});
1470+
} else {
1471+
var Drawing = require('../components/drawing');
1472+
var image3 = Drawing.tester.append('image');
1473+
var cStyles = window.getComputedStyle(image3.node());
1474+
image3.attr('style', lib.PIXELATED_IMAGE_STYLE);
1475+
_supportsPixelated = declarations.some(function(d) {
1476+
var value = d[1];
1477+
return cStyles.imageRendering === value ||
1478+
cStyles.imageRendering === value.toLowerCase();
1479+
});
1480+
image3.remove();
1481+
}
1482+
}
1483+
return _supportsPixelated;
1484+
};

src/traces/heatmap/plot.js

+2-46
Original file line numberDiff line numberDiff line change
@@ -18,50 +18,6 @@ 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-
6521
function selectLabels(plotGroup) {
6622
return plotGroup.selectAll('g.' + labelClass);
6723
}
@@ -156,7 +112,7 @@ module.exports = function(gd, plotinfo, cdheatmaps, heatmapLayer) {
156112
var drawingMethod = 'default';
157113
if(zsmooth) {
158114
drawingMethod = zsmooth === 'best' ? 'smooth' : 'fast';
159-
} else if(trace._islinear && xGap === 0 && yGap === 0 && supportsPixelatedImage()) {
115+
} else if(trace._islinear && xGap === 0 && yGap === 0 && Lib.supportsPixelatedImage()) {
160116
drawingMethod = 'fast';
161117
}
162118

@@ -406,7 +362,7 @@ module.exports = function(gd, plotinfo, cdheatmaps, heatmapLayer) {
406362
});
407363

408364
if(drawingMethod === 'fast' && !zsmooth) {
409-
image3.attr('style', pixelatedImageCSS.join('; ') + ';');
365+
image3.attr('style', Lib.PIXELATED_IMAGE_STYLE);
410366
}
411367

412368
removeLabels(plotGroup);

src/traces/image/constants.js

+1-14
Original file line numberDiff line numberDiff line change
@@ -47,18 +47,5 @@ module.exports = {
4747
},
4848
suffix: ['°', '%', '%', '']
4949
}
50-
},
51-
// For pixelated image rendering
52-
// http://phrogz.net/tmp/canvas_image_zoom.html
53-
// https://developer.mozilla.org/en-US/docs/Web/CSS/image-rendering
54-
pixelatedStyle: [
55-
'image-rendering: optimizeSpeed',
56-
'image-rendering: -moz-crisp-edges',
57-
'image-rendering: -o-crisp-edges',
58-
'image-rendering: -webkit-optimize-contrast',
59-
'image-rendering: optimize-contrast',
60-
'image-rendering: crisp-edges',
61-
'image-rendering: pixelated',
62-
''
63-
].join('; ')
50+
}
6451
};

src/traces/image/plot.js

+2-4
Original file line numberDiff line numberDiff line change
@@ -6,13 +6,11 @@ var strTranslate = Lib.strTranslate;
66
var xmlnsNamespaces = require('../../constants/xmlns_namespaces');
77
var constants = require('./constants');
88

9-
var unsupportedBrowsers = Lib.isIOS() || Lib.isSafari() || Lib.isIE();
10-
119
module.exports = function plot(gd, plotinfo, cdimage, imageLayer) {
1210
var xa = plotinfo.xaxis;
1311
var ya = plotinfo.yaxis;
1412

15-
var supportsPixelatedImage = !(unsupportedBrowsers || gd._context._exportedPlot);
13+
var supportsPixelatedImage = !gd._context._exportedPlot && Lib.supportsPixelatedImage();
1614

1715
Lib.makeTraceGroups(imageLayer, cdimage, 'im').each(function(cd) {
1816
var plotGroup = d3.select(this);
@@ -131,7 +129,7 @@ module.exports = function plot(gd, plotinfo, cdimage, imageLayer) {
131129

132130
image3.exit().remove();
133131

134-
var style = (trace.zsmooth === false) ? constants.pixelatedStyle : '';
132+
var style = (trace.zsmooth === false) ? Lib.PIXELATED_IMAGE_STYLE : '';
135133

136134
if(realImage) {
137135
var xRange = Lib.simpleMap(xa.range, xa.r2l);

0 commit comments

Comments
 (0)