Export canvas settings

This example shows how you can use the exportToBlob() function to create an image with all the shapes on the canvas in it and then download it. The easiest way to download an image is to use the download attribute of a link element.

import { useState } from 'react'
import { Box, exportToBlob, Tldraw, TLImageExportOptions, TLUiComponents, useEditor } from 'tldraw'
import 'tldraw/tldraw.css'

const components: TLUiComponents = {
	SharePanel: ExportCanvasButton,
}

export default function ExportCanvasImageExample() {
	return (
		<div className="tldraw__editor">
			<Tldraw components={components} />
		</div>
	)
}

function ExportCanvasButton() {
	const editor = useEditor()

	// [1]
	const [opts, setOpts] = useState<TLImageExportOptions>({
		scale: 1,
		background: false,
		padding: editor.options.defaultSvgPadding,
	})

	// [2]
	const [box, setBox] = useState({ x: 0, y: 0, w: 0, h: 0 })

	return (
		<div
			style={{
				pointerEvents: 'all',
				border: '1px solid black',
				borderRadius: 5,
				padding: 12,
				position: 'absolute',
				display: 'flex',
				flexDirection: 'column',
				right: 164,
				top: 8,
			}}
		>
			<div
				style={{
					display: 'grid',
					gridTemplateColumns: '1fr auto',
					gridAutoFlow: 'row',
					rowGap: 4,
					columnGap: 16,
				}}
			>
				<Control
					type="checkbox"
					name="background"
					checked={opts.background}
					onChange={(e) => {
						setOpts({ ...opts, background: e.target.checked })
					}}
				/>
				<Control
					type="checkbox"
					name="darkmode"
					checked={opts.darkMode}
					onChange={(e) => {
						setOpts({ ...opts, darkMode: e.target.checked })
					}}
				/>
				<Control
					type="number"
					name="padding"
					value={opts.padding}
					onChange={(e) => {
						setOpts({ ...opts, padding: Math.ceil(Number(e.target.value)) })
					}}
				/>
				<Control
					type="number"
					name="scale"
					value={opts.scale}
					onChange={(e) => {
						setOpts({ ...opts, scale: Math.ceil(Number(e.target.value)) })
					}}
				/>
				<p style={{ gridColumn: '1 / span 2' }}>Box</p>
				{['x', 'y', 'w', 'h'].map((key) => (
					<div key={key} style={{ display: 'flex', gap: 4 }}>
						<Control
							type="number"
							name={key}
							value={box[key as keyof typeof box]}
							onChange={(event) => {
								setBox({
									...box,
									[key]: Math.ceil(Number(event.target.value)),
								})
							}}
						/>
					</div>
				))}
			</div>
			<button
				style={{ pointerEvents: 'all', marginTop: 16 }}
				onClick={async () => {
					const shapeIds = editor.getCurrentPageShapeIds()
					if (shapeIds.size === 0) return alert('No shapes on the canvas')

					const blob = await exportToBlob({
						editor,
						ids: [...shapeIds],
						format: 'png',
						opts: {
							...opts,
							// If we have numbers for all of the box values, we can use them as bounds
							bounds: Object.values(box).every((b) => Number.isNaN(b))
								? new Box(box.x, box.y, box.y, box.x)
								: undefined,
						},
					})

					const link = document.createElement('a')
					link.href = window.URL.createObjectURL(blob)
					link.download = 'every-shape-on-the-canvas.jpg'
					link.click()
				}}
			>
				Export canvas as image
			</button>
		</div>
	)
}

const Control = ({
	name,
	type,
	value,
	checked,
	onChange,
}: {
	name: string
	type?: React.HTMLInputTypeAttribute
	value?: string | number | readonly string[]
	checked?: boolean
	onChange?: React.ChangeEventHandler<HTMLInputElement>
}) => {
	return (
		<>
			<label htmlFor={`opt-${name}`} style={{ flexGrow: 2 }}>
				{name}
			</label>
			<input
				id={`opt-${name}`}
				name={name}
				type={type}
				style={{ maxWidth: 64, justifySelf: 'flex-end' }}
				value={value ?? ''}
				checked={!!checked}
				onChange={onChange}
			/>
		</>
	)
}

/* 
This example shows how you can use the image export settings in tldraw when generating an image.

1.
These are our defaults, though the rest of export / copy features use the user preferences,
e.g. editor.user.getIsDarkMode() for whether the user has enabled dark mode or not. But if
you're calling the image functions yourself, you can provide whatever options you wish.

2.
The bounding box is an optional argument that you can use to export a specific part of the canvas
or selection.
*/
Is this page helpful?
Prev
Export canvas as image
Next
External content sources