embiem / react-canvas-draw

React Component for drawing in canvas
https://embiem.github.io/react-canvas-draw/
MIT License
892 stars 315 forks source link

Question: How can i save canvas with the background image? #62

Closed Mwlm closed 4 years ago

Mwlm commented 4 years ago

I have a background image and would like to draw some lines on top of the image. I would like to save canvas with my background image.

embiem commented 4 years ago

Hey, sorry but this is currently not possible without extra code. I've tracked your request in #43, as other people have articulated their need to save the drawing to an image as well.

zemiacsik commented 4 years ago

If someone is still interested in this. I have just used @embiem advice in #43 with some stackoverflow and put canvases on top each other:

let baseCanvas = canvasRef.current.canvasContainer.children[3]; // canvas with background image let baseCanvasContex = rootCanvas.getContext('2d'); baseCanvasContex.drawImage(canvasRef.current.canvasContainer.children[1], 0, 0); // add drawing return baseCanvas.toDataURL(); // or whatever

canvasRef is CanvasDraw

jonra1993 commented 3 years ago

Hello, using @zemiacsik approach and combining some code from forums online I created this function. I hope It can help to someone in the future.

export const combineDrawing = (canvasRef) => {
    const width = canvasRef.current.props.canvasWidth;
    const height = canvasRef.current.props.canvasHeight;
    const background = canvasRef.current.canvasContainer.children[3]; 
    const drawing = canvasRef.current.canvasContainer.children[1]; 
    const canvas = document.createElement('canvas');
    canvas.width = width;
    canvas.height = height;

    // composite now
    canvas.getContext('2d').drawImage(background, 0, 0);
    canvas.getContext('2d').globalAlpha = 1.0; 
    canvas.getContext('2d').drawImage(drawing, 0, 0);

    const dataUri = canvas.toDataURL('image/jpeg', 1.0);
    const data = dataUri.split(',')[1];
    const mimeType = dataUri.split(';')[0].slice(5);

    const bytes = window.atob(data);
    const buf = new ArrayBuffer(bytes.length);
    const arr = new Uint8Array(buf);

    for (let i = 0; i < bytes.length; i++) {
        arr[i] = bytes.charCodeAt(i);
    }

    const blob = new Blob([arr], { type: mimeType });
    return { blob: blob, dataUri: dataUri };
}
export const saveImage = (blob, filename) => {
    const a = document.createElement('a');
    document.body.appendChild(a);
    a.style = 'display: none';

    const url = window.URL.createObjectURL(blob);
    a.href = url;
    a.download = filename;
    a.click();
    window.URL.revokeObjectURL(url);
}
const {blob, dataUri} = combineDrawing(canvasRef);
 saveImage(blob, 'test.jpg')
sasithahtl commented 3 years ago

Hello, using @zemiacsik approach and combining some code from forums online I created this function. I hope It can help to someone in the future.

export const combineDrawing = (canvasRef) => {
    const width = canvasRef.current.props.canvasWidth;
    const height = canvasRef.current.props.canvasHeight;
    const background = canvasRef.current.canvasContainer.children[3]; 
    const drawing = canvasRef.current.canvasContainer.children[1]; 
    const canvas = document.createElement('canvas');
    canvas.width = width;
    canvas.height = height;

    // composite now
    canvas.getContext('2d').drawImage(background, 0, 0);
    canvas.getContext('2d').globalAlpha = 1.0; 
    canvas.getContext('2d').drawImage(drawing, 0, 0);

    const dataUri = canvas.toDataURL('image/jpeg', 1.0);
    const data = dataUri.split(',')[1];
    const mimeType = dataUri.split(';')[0].slice(5);

    const bytes = window.atob(data);
    const buf = new ArrayBuffer(bytes.length);
    const arr = new Uint8Array(buf);

    for (let i = 0; i < bytes.length; i++) {
        arr[i] = bytes.charCodeAt(i);
    }

    const blob = new Blob([arr], { type: mimeType });
    return { blob: blob, dataUri: dataUri };
}
export const saveImage = (blob, filename) => {
    const a = document.createElement('a');
    document.body.appendChild(a);
    a.style = 'display: none';

    const url = window.URL.createObjectURL(blob);
    a.href = url;
    a.download = filename;
    a.click();
    window.URL.revokeObjectURL(url);
}
const {blob, dataUri} = combineDrawing(canvasRef);
 saveImage(blob, 'test.jpg')

used this to make the work

lablitt commented 2 years ago

Thanks for this function is really helpful, only change I had to make was change the background image index from 3 to 0, so its const background = canvasRef.current.canvasContainer.children[0];