description |
---|
Bitmap & vector image container |
Skia Canvas's
Image
object is a stripped-down version of the standard Image used in browser environments. Since the Canvas API ignores most of its properties, only the relevant ones have been recreated here.
Content | Loading | Event Handlers |
---|---|---|
src | complete | onload / onerror |
width / height | decode() | on() / off() / once() |
Before an image file can be drawn to the canvas a number of behind-the-scenes steps have to take place: its data has to be loaded, potentially from a remote system, its format needs to be determined, and its data must be decompressed. As a result, newly created Image objects are not ready for use; instead you must asynchronously wait for them to complete their loading & decoding process before making use of them.
The traditional way to do this is to set up an event listener waiting for the load
event. You can do this either by assigning a callback function to the image's onload
property, or by using the on() or once() methods to set up the listener by name. Once the event handler has been set up, you can then kick off the load process by setting a src
value for the image:
let img = new Image()
img.onload = function(theImage){
// for non-arrow functions, the image object is also passed as `this`
ctx.drawImage(this, 100, 100)
}
img.src = 'https://skia-canvas.org/icon.png'
Or, equivalently:
img.on("load", (theImage) => {
// arrow functions can use the image reference passed as an argument
ctx.drawImage(theImage, 100, 100)
})
If you're setting up an Image within an asynchronous function, you can avoid some of this ‘callback hell’ by using the await
keyword in combination with the Image's decode() method. It returns a Promise which resolves only once the load process is complete and the image is ready for use, making it convenient for pausing execution before drawing the image:
let img = new Image()
img.src = 'https://skia-canvas.org/icon.png'
await img.decode()
ctx.drawImage(img, 100, 100)
To cut down on this repetitive boilerplate, you can also use the loadImage() utility function which wraps both image creation and loading, allowing for even more concise initialization. For instance, the previous example could be rewritten as:
let img = await loadImage('https://skia-canvas.org/icon.png')
ctx.drawImage(img, 100, 100)
Setting the src
property will kick off the loading process. While the browser version of this property requires a string containing a URL, here the src
can be any of the following:
- an HTTP URL to asynchronously retrieve the image from
- an absolute or relative path pointing to a file on the local system
- a Data URL with the image data base64-encoded into the string (or url-encoded in the case of SVG images)
- a Buffer containing the pre-loaded bytes of a supported image file format
The images you load can be from a variety of formats:
- Bitmap:
png
,jpeg
, orwebp
- Vector:
svg
(but notpdf
, sadly)
In the browser these are writable properties that can control the display size of the image within the HTML page. But the context's drawImage
method ignores them in favor of the image's intrinsic size. As a result, Skia Canvas doesn't let you overwrite the width
and height
properties (since it would have no effect anyway) and provides them as read-only values derived from the image data.
:::info[Note]
When loading an image from an SVG file, the intrinsic size may not be defined since the root <svg>
element is not required to have a defined width
and height
. In these cases, the Image will be set to a fixed height of 150
and its width will be scaled to a value that matches the aspect ratio of the SVG's viewbox
size.
:::
A boolean that is true
once the src
data has been fetched and parsed. It does not necessarily mean and the Image is ready to be drawn since the data retrieved may not have been a valid image. In addition your should confirm that the width
and height
are non-zero to be sure that loading was successful.
For compatibility with browser conventions, event handlers can be set up by assigning functions to the Image's .onload
and .onerror
properties. For a more modern-feeling approach, try using .on("load", …)
and .on("error", …)
instead
The .onload
function will be passed a reference to the Image as its argument, and the this
of its function context will also refer to the same Image object (presuming it is not defined as an arrow function).
The .onerror
function will be called with a reference to the Error that occurred as its sole argument.
img.decode()
Since image loading frequently occurs asynchronously, it can be convenient to use the await
keyword to pause execution of your function until the Image is ready to be worked with:
async function main(){
let img = new Image()
img.src = 'http://example.com/a-very-large-file.jpg'
await img.decode()
// …then do something with `img` now that it's ready
}
The browser version of this method returns a Promise that resolves to undefined
once decoding is complete, but for convenience the Skia Canvas version resolves to a reference to the Image object itself:
let img = new Image()
img.src = 'http://example.com/a-very-large-file.jpg'
img.decode().then(({width, height}) =>
console.log(`dimensions: ${width}×${height}`)
)
on(eventType, handlerFunction)
off(eventType, handlerFunction)
once(eventType, handlerFunction)
The Image object is an Event Emitter subclass and supports all the standard methods for adding and removing event listeners. The event handlers you create will be able to reference the target image through their this
variable.
The events emitted by the Image object both relate to image-loading and can be listened for using the on()
and once()
methods.
Emitted once data has been retrieved and successfully decoded into one of the supported image file formats. The image will be passed to your callback as the first argument.
Emitted if loading was unsuccessful for any reason. An Error object with details is passed to your callback as the first argument.
loadImage(src)
The loadImage
utility function is included to avoid the fiddly, callback-heavy verbosity of the normal Image-loading dance. It combines image creation, loading, and decoding and gives you a single call to await
before making use of an image:
import {loadImage} from 'skia-canvas'
let img = await loadImage('https://skia-canvas.org/icon.png')
Note that you are not limited to web URLs when calling loadImage
, but can include any of the path, URL, or buffer types listed above for the src property.