代码之家  ›  专栏  ›  技术社区  ›  Flutterian

画布-保存为图像后在画布上绘制黑色线条的橡皮擦

  •  9
  • Flutterian  · 技术社区  · 8 年前

    在画布上画画非常好。甚至橡皮擦也工作得很好。问题是,当画布保存为图像时,它绘制的是黑线而不是橡皮擦。

    a、 源代码-

    erase(){
          this.ctx.globalCompositeOperation = 'destination-out';
        } 
    
    handleMove(ev){
    
      // let ctx = this.canvasElement.getContext('2d');
      let currentX = ev.touches[0].pageX - this.offsetX;
      let currentY = ev.touches[0].pageY - this.offsetY;
    
      this.ctx.beginPath();
      this.ctx.lineJoin = "round";
      this.ctx.moveTo(this.lastX, this.lastY);
      this.ctx.lineTo(currentX, currentY);
      this.ctx.closePath();
      this.ctx.strokeStyle = this.currentColour;
      this.ctx.lineWidth = this.brushSize;
      this.ctx.stroke();      
    
    
      this.undoList.push({
        x_start: currentX,
        y_start: currentY,
        x_end: this.lastX,
        y_end: this.lastY,
        color: this.currentColour,
        size: this.brushSize,
        mode: this.ctx.globalCompositeOperation
      });
    
      this.lastX = currentX;
      this.lastY = currentY;
    
    }
    

    enter image description here

    a、 代码-

    this.ctx.clearRect(0, 0, this.canvasElement.width, this.canvasElement.height);
        setTimeout(() => {
    
          // this.drawImg(this.newImg);
           for(let i=0; i<this.textAreasList.length; i++){
             let txt = this.textAreasList[i];
             this.ctx.font = this.textAreasList[i].bold + ' ' + this.textAreasList[i].italic + ' ' + this.textAreasList[i].fontSize + ' ' + 'Comic Sans MS';
             this.ctx.fillStyle = this.textAreasList[i].color;  
             if(this.textAreasList[i].left=="" || this.textAreasList[i].left==undefined) {
               this.textAreasList[i].left = 50;
             }
             if(this.textAreasList[i].top=="" || this.textAreasList[i].top==undefined) {
              this.textAreasList[i].top = 50;
            }
             this.ctx.fillText(this.textAreasList[i].value, this.textAreasList[i].left, this.textAreasList[i].top);
           }
    
           this.redrawCanvas(this.undoUseList);
           let imgPath = this.canvasElement.toDataURL('image/png');
           let message= "";
           this.base64ToGallery.base64ToGallery(imgPath).then(
             res => message = "Image saved to gallery!",
             err => message = "Something went wrong!!"
           );
           this.spinner.hide();
           let toast = this.toastCtrl.create({
             message: message,
             duration: 3000,
             position: 'bottom',
             cssClass: 'changeToast'
           });
           this.navCtrl.push(HomePage);
         }, 5000);
      }
    
    
    
    redrawCanvas(arr){
          // this.ctx.globalCompositeOperation = 'source-over';
          for(let i=0; i<arr.length; i++){
            for(let j=0; j< arr[i].length; j++){
              let ctx = this.canvasElement.getContext('2d');
              ctx.globalCompositeOperation = arr[i][j].mode;
              console.log('x start', arr[i][j].x_start);
              console.log('y start', arr[i][j].y_start);
              console.log('x end', arr[i][j].x_end);
              console.log('y end', arr[i][j].y_end);
              ctx.beginPath();
              ctx.lineJoin = "round";
              ctx.moveTo(arr[i][j].x_start, arr[i][j].y_start);
              ctx.lineTo(arr[i][j].x_end, arr[i][j].y_end);
              ctx.closePath();
              ctx.strokeStyle = arr[i][j].color;
              ctx.lineWidth = arr[i][j].size;
              ctx.stroke();
            }
    
          }
    
        }
    
    **b. Output -** 
    

    enter image description here

    我不明白为什么橡皮擦移动被替换为黑色,而保存画布作为图像。

    2 回复  |  直到 8 年前
        1
  •  4
  •   Victor Lia Fook    8 年前

    所以,你正在使用撤消列表重新绘制画布,对吧?然后使用toDataUrl()输出图像?

    this.undoList.push({
      x_start: currentX,
      y_start: currentY,
      x_end: this.lastX,
      y_end: this.lastY,
      color: this.currentColour, <== Is this an object?
      size: this.brushSize,
      mode: this.ctx.globalCompositeOperation
    });
    

    如果this.currentColour是一个对象,我猜属性在代码中的其他地方发生了变化,当您重新构建步骤时,您将得到黑色的样式,不确定它是否是默认样式。

    所以你可以试试这个

    this.undoList.push({
      x_start: currentX,
      y_start: currentY,
      x_end: this.lastX,
      y_end: this.lastY,
      color: {
        prop1: this.currentColour.prop1
        prop2: this.currentColour.prop2
        ...
      }
      size: this.brushSize,
      mode: this.ctx.globalCompositeOperation
    });
    

    你可以使它更华丽,但像这样你可以得到更好的推理。

        2
  •  2
  •   Flutterian    8 年前

    最后我解决了这个问题。我做了以下改变。

    redrawCanvas(arr){
          // this.ctx.globalCompositeOperation = 'source-over';
          for(let i=0; i<arr.length; i++){
            for(let j=0; j< arr[i].length; j++){
              let ctx = this.canvasElement.getContext('2d');
              // ctx.globalCompositeOperation = arr[i][j].mode;
    
              if(arr[i][j].mode== "destination-out"){
                // ctx.globalCompositeOperation = "destionation-out";
                // ctx.strokeStyle = "rgba(0,0,0,0.2)";
                let cImg = new Image();
                cImg.src = this.selectedImage;
                let pattern = ctx.createPattern(cImg, "no-repeat");
                ctx.strokeStyle = pattern;
              }else{
                ctx.strokeStyle = arr[i][j].color;
              }
              console.log('x start', arr[i][j].x_start);
              console.log('y start', arr[i][j].y_start);
              console.log('x end', arr[i][j].x_end);
              console.log('y end', arr[i][j].y_end);
              ctx.beginPath();
              ctx.lineJoin = "round";
              ctx.moveTo(arr[i][j].x_start, arr[i][j].y_start);
              ctx.lineTo(arr[i][j].x_end, arr[i][j].y_end);
              ctx.closePath();
              ctx.lineWidth = arr[i][j].size;
              ctx.stroke();
            }
    
          }
    
        }
    

    如您所见,我添加了一个检查,以检查它是画笔还是橡皮擦。我在检查橡皮擦是否 destination-out

    如果是橡皮擦,我正在创造新的形象,使 strokestyle .

    if(arr[i][j].mode== "destination-out"){
                // ctx.globalCompositeOperation = "destionation-out";
                // ctx.strokeStyle = "rgba(0,0,0,0.2)";
                let cImg = new Image();
                cImg.src = this.selectedImage;
                let pattern = ctx.createPattern(cImg, "no-repeat");
                ctx.strokeStyle = pattern;
              }else{
                ctx.strokeStyle = arr[i][j].color;
              }
    
    推荐文章