【问题标题】:HTML Canvas - passing a background image to Canvas while it's also passing base64 dataHTML Canvas - 将背景图像传递给 Canvas,同时它还传递 base64 数据
【发布时间】:2017-09-04 23:54:55
【问题描述】:

我目前正在尝试在 Laserfiche 表单中执行一些 Javascript 工作,这需要我将图像的 base64 数据保存在单独的文本区域中,并将该数据反馈到图像中以允许将画布变成我可以保存到系统中的图像。

问题是我试图有一个用户可以在其中绘制的背景图像(在这种情况下,他们可以在车辆上画一个圆圈来指示损坏的位置)。我正在使用sketch.js 来允许任务的绘图部分。

据我所知,背景 CSS 无法保存到画布中。很好,但是当我已经获取 base64 数据并将其传递回我的画布时,如何传递背景图像?

saveimage 类属于文本区域,imagefinish 属于它们在图像准备好时标记的复选框

html

<div class="demo" id="colors_demo">
  <div class="tools">
      <a href="#colors_sketch" data-tool="marker">Marker</a>         
      <a href="#colors_sketch" data-tool="eraser">Eraser</a>
      <a href="#colors_sketch" data-download="png" style="float: right; width: 100px;">Download</a>
  </div>
  <canvas id="colors_sketch" width="750" height="500" style="border:2px solid #000000 ; background: url(http://localhost/forms/img/vanImage.jpg"></canvas>
</div>
<input name="Field11" id="Field11-0" type="checkbox" value="isLocked" vo="e" data-parsley-class-handler="#Field11" data-parsley-errors-container="#Field11" data-parsley-multiple="Field11">
    <textarea id="Field13" name="Field13" aria-labelledby="Field13" class="cf-medium" rows="3" vo="e" data-parsley-id="28"></textarea>

Javascript

//submitted form
  if ($('[name=IsLocked]').val() == 'True') {
    var myCanvas = document.getElementById('colors_sketch');
    var ctx = myCanvas.getContext('2d');
    var img = new Image;
    img.onload = function() {
      ctx.drawImage(this, 0, 0, myCanvas.width, myCanvas.height);
    }
    img.src = $('.saveimage .cf-field').text();  
  }
  else {
  //fill form
  //$.getScript('http://localhost/Forms/js/sketch.js', function() {
     $.getScript('https://rawgit.com/intridea/sketch.js/gh-pages/lib/sketch.js', function() {
      //script is loaded and executed put your dependent JS here
      $.each(['#f00', '#ff0', '#0f0', '#0ff', '#00f', '#f0f', '#000', '#fff'], function() {
        $('#colors_demo .tools').append("<a href='#colors_sketch' data-color='" + this + "' style='width: 10px; background: " + this + ";'></a> ");
      });
      $.each([3, 5, 10, 15], function() {
        $('#colors_demo .tools').append("<a href='#colors_sketch' data-size='" + this + "' style='background: #ccc'>" + this + "</a> ");
      });
      //$('#colors_sketch').sketch();
      $('#colors_sketch').sketch({defaultColor: "#000"});
    });
    $('.imagefinish input').change(function(){
      if(this.checked) {
        var myCanvas = document.getElementById('colors_sketch');
        $('.saveimage textarea').val(myCanvas.toDataURL());
      }
    });
  }

我可以通过为我的图像路径添加一个变量来添加图像

 var image   = 'http://localhost/forms/img/vanImage.jpg'

我还将这两行添加到我的 onload 中,用于“myCanvas”的样式。我有一种感觉,这个解决方案只会起作用,因为 Laserfiches 表格软件的工作原理,但标记的答案也是正确的。

img.onload = function() {
      ctx.drawImage(this, 0, 0, myCanvas.width, myCanvas.height);
      myCanvas.style.backgroundRepeat = "no-repeat";
    myCanvas.style.backgroundImage = 'url('+image+')'
    }
    img.src = $('.saveimage .cf-field').text();  
  }

【问题讨论】:

    标签: javascript html canvas sketchjs


    【解决方案1】:

    在页面加载时加载背景图片,或者在适当的时间加载背景图片,当客户端准备好时,使用ctx.globalCompositeOperation = "destination-over";将背景绘制到用户内容后面的画布上

    创建一个图像来保持背景。

    const backgroundImage = new Image();
    backgroundImage.src = "http://localhost/forms/img/vanImage.jpg";
    

    您需要确保客户端点击就绪时图像已经加载,如果尚未加载,您可以设置回调,如果需要,将回调就绪函数。

    var backgroundLoadedCallback = null;
    backgroundImage.onload = function(){
         if( typeof backgroundLoadedCallback === "function"){
             backgroundLoadedCallback();
         }
    }
    

    然后创建画布-> textarea 函数

    function canvasToTextarea(){
    
        const myCanvas = document.getElementById('colors_sketch');
        const ctx = myCanvas.getContext("2d");
        ctx.globalCompositeOperation = "destination-over";  // make sure the background go under the drawn pixels
        // draw and fit background to the canvas
        ctx.drawImage(backgroundImage,0,0,ctx.canvas.width,ctx.canvas.height);
        // then convert to URL for textarea
        $('.saveimage textarea').val(myCanvas.toDataURL());
    
    }
    

    在检查函数中

    $('.imagefinish input').change(function(){
      if(this.checked) {
         if(backgroundImage.complete) { // image has loaded so all good
             canvasToTextarea(); // put canvas data URL to textarea
         } else { // background has not yet loaded (or could be an error you will have to deal with that as well
              // set the callback to the canvasToTextarea function
              backgroundLoadedCallback = canvasToTextarea;
              // when the background has loaded the canvas and background
              // will be moved to the textarea as a data URL
         } 
      }
    });
    

    或者修改sketch.js

    下面是来自 sketch.js 的 draw 函数(它非常老派)

    Sketch.prototype.redraw = function() {
      var sketch;
      this.el.width = this.canvas.width();
      this.context = this.el.getContext('2d');
      sketch = this;
      $.each(this.actions, function() {
        if (this.tool) {
          return $.sketch.tools[this.tool].draw.call(sketch, this);
        }
      });
      if (this.painting && this.action) {
        return $.sketch.tools[this.action.tool].draw.call(sketch, this.action);
      }
    };
    

    只需将其替换为以下内容。你不需要修改sketch.js文件,只需要覆盖redraw Prototype

    在您的代码中加载背景并设置新的重绘

    const backgroundImage = new Image();
    backgroundImage.src = "http://localhost/forms/img/vanImage.jpg";
    
    
    // replace Sketch.js redraw function
    Sketch.prototype.redraw = function(){
      var sketch;
      // dont need the next line use clear instead
      // this.el.width = this.canvas.width();
    
      const ctx = this.context = this.el.getContext('2d');
      // clear canvas
      this.context.clearRect(0, 0, ctx.canvas.width, ctx.canvas.height);
      // If backgroundimage complete draw it first
      if(backgroundImage && backgroundImage.complete){
          ctx.drawImage(backgroundImage,0,0,ctx.canvas.width,ctx.canvas.height);
      }
    
      // back to the original code. :P
      sketch = this;
      $.each(this.actions, function() {
        if (this.tool) {
          return $.sketch.tools[this.tool].draw.call(sketch, this);
        }
      });
      if (this.painting && this.action) {
        return $.sketch.tools[this.action.tool].draw.call(sketch, this.action);
      }
    }
    

    【讨论】:

    • 我能够找到一个超级解决方案,即拥有一个根本不用于保存的占位符背景 url,只是坐在 CSS 中。然后我为我的路径添加了一个变量,然后在图像绘制后加载。 myCanvas.style.backgroundRepeat = "无重复"; myCanvas.style.backgroundImage = 'url('+image+')' 。我的解决方案对我正在构建的软件相当具体,但你的也适用,所以我将其标记为答案并更新我的 OP。
    猜你喜欢
    • 1970-01-01
    • 2013-08-29
    • 2014-05-19
    • 1970-01-01
    • 2017-03-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多