设置背景颜色以保存画布图

时间:2018-04-30 16:18:20

标签: javascript typescript canvas chart.js

我使用ChartJS并在本地保存它们,将画布上的图表图像转换为数据blob,然后保存它。但是我在设置保存的任何画布图表的背景颜色时遇到问题,我只能保存没有背景颜色的图表,这会让用户感到困惑。

到目前为止我尝试的是:

  1. 将图像/ png的类型更改为image / jpg
  2. 创建一个带有样式的文档,并将其作为子项附加到我的文档中 document.createElement将有图像
  3. 为我的链接提供风格'等于document.createElement 上述
  4. 但没有成功,图像可以在没有背景的情况下下载。

    我正在搜索并找到一些主题:

    create a canvas with background image and save

    save canvas with background image

    但是,在所有工作结束时,我找不到适合我的解决方案。

    我的html图表是:

    <canvas id="divName"></canvas>
    

    用于保存图像的typescript函数,使用bytearray创建一个新的blob,图像的类型为:(该代码具有添加背景颜色的所有尝试)

    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;
        }
    

    表达问题的图片:

    on the site the image is:

    when i download it

    是否可以为画布图像添加背景颜色?

2 个答案:

答案 0 :(得分:2)

正如您所发现的,canvas.toDataURL()无法捕获通过CSS应用的任何视觉样式。它仅捕获支持画布实例的位图中的原始像素数据。这是设计的。

要使用自定义背景颜色,您需要将其直接绘制到画布上。下面是一个用给定颜色填充给定画布背景的函数示例。我的内联评论应该解释它是如何工作的。

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();
}

要使用此功能,请在保存代码之前调用它,为其提供图表画布和颜色。看起来应该是这样的:

const canvas = document.getElementById('yourCanvasId');
fillCanvasBackgroundWithColor(canvas, 'aquamarine');
// ...the rest of your save code

保存的图像应具有背景色。

答案 1 :(得分:1)

我要离开这里,因为我碰到了一个至少对我有用的更容易的替代解决方案。

当我使用chartCanvas.toDataURL("image/jpeg", 1.0);时,就像OP一样,我的色彩都被弄乱了。

仅切换到png对我有用。没有插件或额外的工作。只需更改为chartCanvas.toDataURL("image/png", 1.0);,就可以使dataUrl输出看起来完全像我的图表。