javascript - establecer color de fondo para guardar el gráfico del canvas
Estoy usando ChartJS y guardándolos localmente, convirtiendo la imagen del gráfico en canvas a un blob de datos y luego guardándolo. Pero tengo problemas para establecer el color de fondo de cualquier gráfico en canvas que esté guardando, solo puedo guardar el gráfico sin color de fondo, lo cual confunde al usuario.
Lo que he intentado hasta ahora fue:
- Cambiar el tipo de image/png a image/jpg
- Crea un documento con un estilo y agréguelo como hijo a mi document.createElement que va a tener la imagen
- dar estilo a mi 'link' que sea igual al document.createElement de arriba
Pero sin éxito, la imagen se descarga correctamente sin fondo.
Estaba buscando y encontré algún tema:
crear un lienzo con imagen de fondo y guardar
guardar lienzo con imagen de fondo
pero, al final de todo el trabajo, no pude encontrar la solución para mí.
Mi tabla en HTML es:
<canvas id="divName"></canvas>
la función de TypeScript para guardar la imagen, creando un nuevo blob con bytearray y el tipo de la imagen es: (ese código tiene todos los intentos de agregar color de fondo)
saveimg(divName){
let canvas:any;
let style = document.createElement('style');
style.type = 'text/css';
style.innerHTML = '.cssClass { background-color: "aquamarine"; }';
if(this.deviceValue != null) {
canvas = document.getElementById(this.deviceValue);
}
else {
canvas = document.getElementById(divName);
}
//SOLUTION that works BY Caleb Miller ***********
fillCanvasBackground(canvas, 'white');
function fillCanvasBackground(canvasc, color)
{
const context = canvasc.getContext('2d');
context.save();
context.globalCompositeOperation = 'destination-over';
context.fillStyle = color;
context.fillRect(0, 0, canvasc.width, canvasc.height);
context.restore();
}
// end***********************
let dataURL = canvas.toDataURL();
let datablob = dataURL.substring(dataURL.indexOf(",") + 1);
let byteCharacters = atob(datablob);
let byteNumbers = new Array(byteCharacters.length);
for (let i = 0; i < byteCharacters.length; i++) {
byteNumbers[i] = byteCharacters.charCodeAt(i);
}
let byteArray = new Uint8Array(byteNumbers);
let blob = new Blob([byteArray], {"type": "image/jpg"});
if(navigator.msSaveBlob){
let filename = this.chartTitle + ' - ' + this.entityName;
navigator.msSaveBlob(blob, filename);
} else {
let filename =this.chartTitle + ' - ' + this.entityName;
let link = document.createElement("a");
link.onload = function() {
canvas.drawImage(0,0);
};
document.getElementsByTagName('a')[0].appendChild(style);
link.href = URL.createObjectURL(blob);
link.setAttribute('visibility','hidden');
link.download = filename;
link.style.backgroundColor = "lightblue repeat-x center";
document.body.appendChild(link).style.background = "lightblue repeat-x center";
link.click();
document.body.removeChild(link);
}
this.deviceValue = null;
}
Imágenes para expresar el problema:
en el sitio la imagen es:
cuando lo descargue
¿Es posible añadir color de fondo a una imagen de lienzo?
Respuesta #1
Como descubriste, canvas.toDataURL() no captura ningún estilo visual aplicado mediante CSS. Solo captura los datos de píxeles sin procesar del mapa de bits que respalda la instancia del canvas. Esto es por diseño.
Para usar un color de fondo personalizado, necesitas dibujarlo directamente en el lienzo. Aquí hay un ejemplo de una función que llena el fondo de un lienzo dado con un color determinado. Mis comentarios en línea deberían explicar cómo funciona.
function fillCanvasBackgroundWithColor(canvas, color) {
// Get the 2D drawing context from the provided canvas.
const context = canvas.getContext('2d');
// We're going to modify the context state, so it's
// good practice to save the current state first.
context.save();
// Normally when you draw on a canvas, the new drawing
// covers up any previous drawing it overlaps. This is
// because the default `globalCompositeOperation` is
// 'source-over'. By changing this to 'destination-over',
// our new drawing goes behind the existing drawing. This
// is desirable so we can fill the background, while leaving
// the chart and any other existing drawing intact.
// Learn more about `globalCompositeOperation` here:
// https://developer.mozilla.org/en-US/docs/Web/API/CanvasRenderingContext2D/globalCompositeOperation
context.globalCompositeOperation = 'destination-over';
// Fill in the background. We do this by drawing a rectangle
// filling the entire canvas, using the provided color.
context.fillStyle = color;
context.fillRect(0, 0, canvas.width, canvas.height);
// Restore the original context state from `context.save()`
context.restore();
}
Para usar la función, llámala antes de tu código de guardado, dándole el lienzo del gráfico y un color. Debería verse algo así:
const canvas = document.getElementById('yourCanvasId');
fillCanvasBackgroundWithColor(canvas, 'aquamarine');
// ...the rest of your save code
La imagen guardada debería tener un color de fondo.
