diff --git a/src/components/images/draw.js b/src/components/images/draw.js index 3fe1080fc32..603e46b059e 100644 --- a/src/components/images/draw.js +++ b/src/components/images/draw.js @@ -74,49 +74,54 @@ module.exports = function draw(gd) { function setImage(d) { var thisImage = d3.select(this); - if(this.img && this.img.src === d.source) { + if(this._imgSrc === d.source) { return; } thisImage.attr('xmlns', xmlnsNamespaces.svg); - var imagePromise = new Promise(function(resolve) { - var img = new Image(); - this.img = img; + if(d.source && d.source.slice(0, 5) === 'data:') { + thisImage.attr('xlink:href', d.source); + this._imgSrc = d.source; + } else { + var imagePromise = new Promise(function(resolve) { + var img = new Image(); + this.img = img; - // If not set, a `tainted canvas` error is thrown - img.setAttribute('crossOrigin', 'anonymous'); - img.onerror = errorHandler; - img.onload = function() { - var canvas = document.createElement('canvas'); - canvas.width = this.width; - canvas.height = this.height; + // If not set, a `tainted canvas` error is thrown + img.setAttribute('crossOrigin', 'anonymous'); + img.onerror = errorHandler; + img.onload = function() { + var canvas = document.createElement('canvas'); + canvas.width = this.width; + canvas.height = this.height; - var ctx = canvas.getContext('2d'); - ctx.drawImage(this, 0, 0); + var ctx = canvas.getContext('2d'); + ctx.drawImage(this, 0, 0); - var dataURL = canvas.toDataURL('image/png'); + var dataURL = canvas.toDataURL('image/png'); - thisImage.attr('xlink:href', dataURL); + thisImage.attr('xlink:href', dataURL); - // resolve promise in onload handler instead of on 'load' to support IE11 - // see https://github.com/plotly/plotly.js/issues/1685 - // for more details - resolve(); - }; + // resolve promise in onload handler instead of on 'load' to support IE11 + // see https://github.com/plotly/plotly.js/issues/1685 + // for more details + resolve(); + }; + thisImage.on('error', errorHandler); - thisImage.on('error', errorHandler); + img.src = d.source; + this._imgSrc = d.source; - img.src = d.source; - - function errorHandler() { - thisImage.remove(); - resolve(); - } - }.bind(this)); + function errorHandler() { + thisImage.remove(); + resolve(); + } + }.bind(this)); - gd._promises.push(imagePromise); + gd._promises.push(imagePromise); + } } function applyAttributes(d) { diff --git a/test/jasmine/tests/layout_images_test.js b/test/jasmine/tests/layout_images_test.js index ce1f47b9de6..0cdc86faa30 100644 --- a/test/jasmine/tests/layout_images_test.js +++ b/test/jasmine/tests/layout_images_test.js @@ -12,6 +12,10 @@ var mouseEvent = require('../assets/mouse_event'); var jsLogo = 'https://images.plot.ly/language-icons/api-home/js-logo.png'; var pythonLogo = 'https://images.plot.ly/language-icons/api-home/python-logo.png'; +// Single red pixel png generated with http://png-pixel.com/ +var dataUriImage = 'data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAEAAAABCAYAAAAfF' + + 'cSJAAAADUlEQVR42mP8z8DwHwAFBQIAX8jx0gAAAABJRU5ErkJggg=='; + describe('Layout images', function() { describe('supplyLayoutDefaults', function() { var layoutIn, @@ -290,6 +294,31 @@ describe('Layout images', function() { afterEach(destroyGraphDiv); + it('should only create canvas if url image', function(done) { + var originalCreateElement = document.createElement; + var newCanvasElement; + spyOn(document, 'createElement').and.callFake(function(elementType) { + var element = originalCreateElement.call(document, elementType); + if(elementType === 'canvas') { + newCanvasElement = element; + spyOn(newCanvasElement, 'toDataURL'); + } + return element; + }); + + Plotly.relayout(gd, 'images[0].source', dataUriImage) + .then(function() { + expect(newCanvasElement).toBeUndefined(); + }) + .then(function() { return Plotly.relayout(gd, 'images[0].source', jsLogo); }) + .then(function() { + expect(newCanvasElement).toBeDefined(); + expect(newCanvasElement.toDataURL).toHaveBeenCalledTimes(1); + }) + .catch(failTest) + .then(done); + }); + it('should update the image if changed', function(done) { var img = Plotly.d3.select('image'); var url = img.attr('xlink:href');