For the recent UK Elections the folks The Guardian wanted to show big images along with their push notifications. Being bandwidth-aware they wanted a solution in which they could use a template image (which could then be cached) and then draw some stuff onto it. Only problem: Service Workers don’t have access to the Canvas API.
Enter PngPong, an basic image manipulation library, they’ve created:
PngPong is a very, very basic replacement for the Canvas API in environments that do not support it – primarily, service workers. Instead, it manually manipulates the bytes of a PNG file to copy the contents of another image, or draw basic shapes (currently only rectangles).
Their code to handle push notifications looked something like this:
self.addEventListener('push', (e) => {
e.waitUntil(
caches.match('/notification_template.png')
.then((res) => res.arrayBuffer())
.then((arrayBuffer) => {
addResultsToTemplate(arrayBuffer, e.data);
return blobToDataURL(new Blob([arrayBuffer]))
})
.then((imageURL) => {
return self.registration.showNotification("Title", {
image: imageURL
})
})
)
})
Inside addResultsToTemplate
they heavy lifting would be done by PngPong, drawing some small rectangles onto the template pictured below, yielding a push notification as pictured at the top of this post.
The template used
Example PngPong usage:
import {
PngPong,
PngPongShapeTransformer,
PngPongImageCopyTransformer
} from 'png-pong';
// Create new PngPong instance
const pngPong = new PngPong(imageArrayBuffer);
// Draw a 30px red square 10px from the top and 10px from the left
const shape = new PngPongShapeTransformer(pngPong);
shape.drawRect(10, 10, 30, 30, [255, 0, 0])
// Copy a 50x50 image 10px from the top left of the source image,
// and draw it 30px into our target image.
const toCopyFrom = new ArrayBuffer();
const imageCopy = new PngPongImageCopyTransformer(toCopyFrom, pngPong);
imageCopy.copy(10, 10, 50, 50, 30, 30);
// Run the transforms
pngPong.run();
PngPong (GitHub) →
PngPong Use Case: Generating Images in JavaScript Without Using the Canvas API →