【问题标题】:set background color to save canvas chart设置背景颜色以保存画布图表
【发布时间】:2019-10-31 22:45:13
【问题描述】:

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

到目前为止我尝试过的是:

  1. 将image/png的类型改为image/jpg
  2. 创建具有样式的文档并将其作为子项附加到我的 document.createElement 将有图像
  3. 为我的“链接”赋予与 document.createElement 相同的样式 以上

但是没有成功,图片是在没有背景的情况下正确下载的。

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

create a canvas with background image and save

save canvas with background image

但是,在所有工作结束时,无法为我找到解决方案。

我在 html 上的图表是:

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

用于保存图像的打字稿函数,使用 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

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

【问题讨论】:

    标签: javascript typescript canvas chart.js


    【解决方案1】:

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

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

    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
    

    保存的图片应该有背景色。

    【讨论】:

    • 谢谢你的朋友,这就是解决方案!我很接近......祝你有美好的一天!
    • 我只是拿了这段代码,把它放在一个注册到 afterRender 事件的插件中。这是一种享受。请参阅我的组合解决方案:stackoverflow.com/a/53946660/165164 谢谢。
    【解决方案2】:

    我把这个留在这里,因为我遇到了一个更简单的替代解决方案,至少对我有用。

    当我使用chartCanvas.toDataURL("image/jpeg", 1.0);时,我的颜色都像OP一样乱七八糟。

    只是切换到 png 对我有用。没有插件或额外的工作。只需更改为 chartCanvas.toDataURL("image/png", 1.0); 即可使 dataUrl 输出看起来与我的图表一模一样。

    【讨论】:

    • 感谢您的解决方案,我没有尝试将图像更改为 png,因为仅 jpeg 图像的要求。
    猜你喜欢
    • 1970-01-01
    • 2021-11-29
    • 2016-03-17
    • 2023-03-25
    • 1970-01-01
    • 2012-02-17
    • 2015-02-14
    • 2017-09-11
    相关资源
    最近更新 更多