diff --git a/site/examples/graphics/webimage/setimage/setimage.js b/site/examples/graphics/webimage/setimage/setimage.js
new file mode 100644
index 00000000..f0fc37d8
--- /dev/null
+++ b/site/examples/graphics/webimage/setimage/setimage.js
@@ -0,0 +1,6 @@
+var img = new WebImage('https://codehs.com/uploads/056e56f7b32cdc9ed21c681c31166108');
+img.setAnchor({ vertical: 0.5, horizontal: 0.5 });
+img.setPosition(getWidth() / 2, getHeight() / 2);
+add(img);
+
+img.setImage('https://codehs.com/uploads/1e38851d76e7691d923a3d3f3f7eae1d');
diff --git a/site/examples/graphics/webimage/setimage/setimage.md b/site/examples/graphics/webimage/setimage/setimage.md
new file mode 100644
index 00000000..94fcdfef
--- /dev/null
+++ b/site/examples/graphics/webimage/setimage/setimage.md
@@ -0,0 +1,9 @@
+---
+title: WebImage - setImage
+layout: example
+code: setimage.js
+width: 500
+height: 500
+---
+
+You can replace the image content of a `WebImage` using `setImage()`
diff --git a/site/examples/index.html b/site/examples/index.html
index 78298af4..02eb2be0 100644
--- a/site/examples/index.html
+++ b/site/examples/index.html
@@ -175,6 +175,9 @@
WebImage
Manipulating ImageData
+
+ setImage
+
Rotation
diff --git a/src/graphics/webimage.js b/src/graphics/webimage.js
index deaa3508..2b4918a1 100644
--- a/src/graphics/webimage.js
+++ b/src/graphics/webimage.js
@@ -72,9 +72,14 @@ class WebImage extends Thing {
this._hiddenCanvas = document.createElement('canvas');
this._hiddenCanvas.width = 1;
this._hiddenCanvas.height = 1;
-
+ if (this.image) {
+ // if this WebImage had an existing image, it may have an unresolved onload callback.
+ // dont allow original callback to resolve, since it might attempt to load pixel data
+ // from a potentially empty canvas.
+ this.image.onload = null;
+ }
this.image = new Image();
- this.image.crossOrigin = true;
+ this.image.crossOrigin = 'anonymous';
this.image.src = filename;
this.filename = filename;
this.width = null;
diff --git a/test/webimage.test.js b/test/webimage.test.js
index 8fd521e8..35b0404a 100644
--- a/test/webimage.test.js
+++ b/test/webimage.test.js
@@ -182,6 +182,32 @@ describe('WebImage', () => {
expect(topLeftPixel).toEqual([0, 0, 255, 255]);
});
});
+ describe('setImage', () => {
+ it('Allows replacing the image of the WebImage', () => {
+ const g = new Graphics({ shouldUpdate: false });
+ const img = new WebImage('www.codehs.com/doesnt-matter.gif');
+ img.setImage(RGBURL);
+ g.add(img);
+ img.loaded(() => {
+ g.redraw();
+ expect(g.getPixel(0, 0)).toEqual([255, 0, 0, 255]);
+ });
+ });
+ it('Cancels the original onload of the image', () => {
+ const g = new Graphics({ shouldUpdate: false });
+ const img = new WebImage('www.codehs.com/doesnt-matter.gif');
+ const firstLoadedSpy = jasmine.createSpy();
+ // we have to inspect here to get the actual onload event
+ img.image.onload = firstLoadedSpy;
+ img.setImage(RGBURL);
+ g.add(img);
+ img.loaded(() => {
+ g.redraw();
+ expect(g.getPixel(0, 0)).toEqual([255, 0, 0, 255]);
+ expect(firstLoadedSpy).not.toHaveBeenCalled();
+ });
+ });
+ });
describe('setRed/Blue/Green/Alpha', () => {
it('Updates the underlying data', () => {
const img = new WebImage(RGBURL);