@@ -50,6 +50,48 @@ module.exports = function draw(gd) {
5050 } ;
5151
5252
53+ // Images must be converted to dataURL's for exporting.
54+ function setImage ( d ) {
55+
56+ var thisImage = d3 . select ( this ) ;
57+
58+ var imagePromise = new Promise ( function ( resolve ) {
59+
60+ var img = new Image ( ) ;
61+
62+ // If not set, a `tainted canvas` error is thrown
63+ img . setAttribute ( 'crossOrigin' , 'anonymous' ) ;
64+ img . onerror = errorHandler ;
65+ img . onload = function ( ) {
66+
67+ var canvas = document . createElement ( 'canvas' ) ;
68+ canvas . width = this . width ;
69+ canvas . height = this . height ;
70+
71+ var ctx = canvas . getContext ( '2d' ) ;
72+ ctx . drawImage ( this , 0 , 0 ) ;
73+
74+ var dataURL = canvas . toDataURL ( 'image/png' ) ;
75+
76+ thisImage . attr ( 'xlink:href' , dataURL ) ;
77+ } ;
78+
79+
80+ thisImage . on ( 'error' , errorHandler ) ;
81+ thisImage . on ( 'load' , resolve ) ;
82+
83+ img . src = d . source ;
84+
85+ function errorHandler ( ) {
86+ thisImage . remove ( ) ;
87+ resolve ( ) ;
88+ }
89+ } ) ;
90+
91+ gd . _promises . push ( imagePromise ) ;
92+ }
93+
94+
5395 function applyAttributes ( d ) {
5496
5597 var thisImage = d3 . select ( this ) ;
@@ -59,8 +101,6 @@ module.exports = function draw(gd) {
59101 yref = Axes . getFromId ( gd , d . yref ) ;
60102
61103 var size = fullLayout . _size ,
62- width = xref ? Math . abs ( xref . l2p ( d . width ) - xref . l2p ( 0 ) ) : d . width * size . w ,
63- height = yref ? Math . abs ( yref . l2p ( d . height ) - yref . l2p ( 0 ) ) : d . width * size . h ;
64104 width = xref ? Math . abs ( xref . l2p ( d . sizex ) - xref . l2p ( 0 ) ) : d . sizex * size . w ,
65105 height = yref ? Math . abs ( yref . l2p ( d . sizey ) - yref . l2p ( 0 ) ) : d . sizey * size . h ;
66106
@@ -96,22 +136,6 @@ module.exports = function draw(gd) {
96136 } ) ;
97137
98138
99- // Images load async so we must add the promise to the list
100- var imagePromise = new Promise ( function ( resolve ) {
101-
102- thisImage . on ( 'load' , resolve ) ;
103- thisImage . on ( 'error' , function ( ) {
104- thisImage . remove ( ) ;
105- console . log ( 'Image with source ' + d . source + ' could not be loaded.' ) ;
106- resolve ( ) ;
107- } ) ;
108-
109- thisImage . attr ( 'href' , d . source ) ;
110- } ) ;
111-
112- gd . _promises . push ( imagePromise ) ;
113-
114-
115139 // Set proper clipping on images
116140 var xId = xref ? xref . _id : '' ,
117141 yId = yref ? yref . _id : '' ,
@@ -121,16 +145,22 @@ module.exports = function draw(gd) {
121145 }
122146
123147
148+ // Required for updating images
149+ function keyFunction ( d ) {
150+ return d . source ;
151+ }
152+
153+
124154 var imagesBelow = fullLayout . _imageLowerLayer . selectAll ( 'image' )
125- . data ( imageDataBelow ) ,
155+ . data ( imageDataBelow , keyFunction ) ,
126156 imagesSubplot = fullLayout . _imageSubplotLayer . selectAll ( 'image' )
127- . data ( imageDataSubplot ) ,
157+ . data ( imageDataSubplot , keyFunction ) ,
128158 imagesAbove = fullLayout . _imageUpperLayer . selectAll ( 'image' )
129- . data ( imageDataAbove ) ;
159+ . data ( imageDataAbove , keyFunction ) ;
130160
131- imagesBelow . enter ( ) . append ( 'image' ) ;
132- imagesSubplot . enter ( ) . append ( 'image' ) ;
133- imagesAbove . enter ( ) . append ( 'image' ) ;
161+ imagesBelow . enter ( ) . append ( 'image' ) . each ( setImage ) ;
162+ imagesSubplot . enter ( ) . append ( 'image' ) . each ( setImage ) ;
163+ imagesAbove . enter ( ) . append ( 'image' ) . each ( setImage ) ;
134164
135165 imagesBelow . exit ( ) . remove ( ) ;
136166 imagesSubplot . exit ( ) . remove ( ) ;
0 commit comments