draw-to-canvas.js (112 lines of code) (raw):
const htmlToCanvas = (selector, canvas, width, height, whenDone) => {
const node = document.querySelector(selector);
if (!node) {
console.warn('no element with selector `' + selector + '` was found');
if (whenDone) whenDone(canvas);
return;
}
const context = canvas.getContext('2d');
const data =
'<svg xmlns="http://www.w3.org/2000/svg" width="'+width+'px" height="'+height+'px">' +
'<foreignObject width="100%" height="100%">' +
'<div xmlns="http://www.w3.org/1999/xhtml">' +
node.innerHTML +
'</div>' +
'</foreignObject>' +
'</svg>';
const image = new Image();
// image.crossOrigin = 'Anonymous';
image.addEventListener('error', (err) => {
throw err;
});
image.setAttribute('crossOrigin', 'anonymous');
//const svg = new Blob([data], {type: 'image/svg+xml;charset=utf-8'});
const url = 'data:image/svg+xml;base64,' + btoa(data);
//const url = URL.createObjectURL(svg);
image.addEventListener('load', () => {
URL.revokeObjectURL(url);
context.drawImage(image, 0, 0);
if (whenDone) whenDone(canvas);
}, false);
image.src = url;
// document.body.appendChild(image);
// context.canvas.width = width;
// context.canvas.height = height;
}
const svgToCanvas = (selector, canvas, width, height, whenDone) => {
const svg = document.querySelector(selector);
if (!svg) {
console.warn('no element with selector `' + selector + '` was found');
if (whenDone) whenDone(canvas);
return;
}
const context = canvas.getContext('2d');
// get svg data
const xml = new XMLSerializer().serializeToString(svg);
const image = new Image();
image.setAttribute('crossOrigin', 'anonymous');
// make it base64
const svg64 = btoa(xml);
const b64Start = 'data:image/svg+xml;base64,';
// prepend a "header"
const image64 = b64Start + svg64;
// set it as the source of the img element
image.addEventListener('load', () => {
URL.revokeObjectURL(image64);
// draw the image onto the canvas
context.drawImage(image, 0, 0);
if (whenDone) whenDone(canvas);
}, false);
image.src = image64;
}
const imageToCanvas = (src, transform, canvas, x, y, width, height, whenDone) => {
const context = canvas.getContext('2d');
const image = new Image();
//image.style.cssText = document.defaultView.getComputedStyle(cloneFrom, '').cssText;
image.setAttribute('crossOrigin', 'anonymous');
image.addEventListener('error', (err) => {
throw err;
});
image.addEventListener('load', () => {
transform(image, context);
context.drawImage(image, 0, 0, width, height);
context.resetTransform();
if (whenDone) whenDone(canvas);
}, false);
image.src = src;
//document.body.appendChild(image);
}
const storedToCanvas = (selector, trgCanvas, whenDone) => {
const selectedNode = document.querySelector(selector);
if (!selectedNode) {
console.warn('no element with selector `' + selector + '` was found');
if (whenDone) whenDone(trgCanvas);
return;
}
const state = JSON.parse(selectedNode.getAttribute('data-stored'));
imageToCanvas(state.imagePath,
function(image, context) {
context.resetTransform();
context.translate(state.posX, state.posY);
context.scale(state.scale, state.scale);
context.translate(-(state.width / 2), -(state.height / 2));
context.globalCompositeOperation = state.blend;
image.width = state.width;
image.height = state.height;
},
trgCanvas, 0, 0, state.width, state.height,
whenDone
);
}
const canvasToCanvas = (selector, trgCanvas, whenDone) => {
const selectedNode = document.querySelector(selector);
if (!selectedNode) {
console.error('no element with selector `' + selector + '` was found');
return;
}
requestAnimationFrame(() => {
const srcCanvas = selectedNode;
trgCanvas.style.mixBlendMode = srcCanvas.style.mixBlendMode;
trgCanvas.style.opacity = srcCanvas.style.opacity;
const trgContext = trgCanvas.getContext('2d');
//trgContext.globalCompositeOperation = 'copy';
trgContext.resetTransform();
trgContext.globalCompositeOperation = srcCanvas.style.mixBlendMode || 'copy';
trgContext.globalAlpha = srcCanvas.style.opacity;
trgContext.drawImage(srcCanvas, 0, 0);
whenDone();
});
}
module.exports = {
html: htmlToCanvas,
image: imageToCanvas,
svg: svgToCanvas,
stored: storedToCanvas,
canvas: canvasToCanvas
};