background

Today, the company has a new requirement, that is, the returned homework photos can be scribbled and corrected, and then uploaded to the server together with the corrected photos. This is a challenge for those of you who are not familiar with Canvas.

Demand analysis

  1. Can be corrected, is equivalent to a brush
  2. Can carry out the brush withdrawal function
  3. Can carry out all brush clearing function
  4. You can change the color of the brush

Technical implementation ideas

After hearing this requirement, my first reaction was to use Canvas, so I read the CANVAS API in W3School.

  1. To transfer the image to canvas, use the API: drawImage()
  2. Realization of brush
  • When the mouse is pressed (mousedown) record the start point startX, startY
  • When moving the mouse (mousemove), get the current mouse coordinate e. clientx, e. clienty. After getting the current coordinate, lineTo the left of the last coordinate axis to draw a horizontal line
  • The Mousemove function is cleared when the left mouse button is released (Mouseup)
  1. Clear: The original image is reset again using the drawImage() function
  2. Recall function: Every time you press the mouse, use getImageData() to get the current image record into the array, and then press recall to use putImageData() to put it on the canvas
  3. Brush Color: Change the strokeStyle pen color in mousemove

Code implementation

Move the mouse to draw a line of code

    let self = this;
    this.canvasNode = document.createElement('canvas');
    let styleString = this.utils.formatStyle(CANVAS_STYLE); // CANVAS_STYLE is the canvas style
    this.canvasNode.setAttribute('id'.'canvas');
    // Be sure to set width and height
    let ratio = this.imgNode.width / this.imgNode.height, height = this.imgNode.height, width = this.imgNode.width;
    let tempWidth , tempHeight;
    // Scale
    if(ratio >= window.innerWidth / window.innerHeight){
      if(width > window.innerWidth){
        tempWidth = window.innerWidth;
        tempHeight = height * window.innerWidth / width;
      } else{ tempWidth = width; tempHeight = height; }}else{
      if(height > window.innerHeight){
        tempWidth = width * window.innerHeight / width;
        tempHeight = window.innerHeight;
      }else{ tempWidth = width; tempHeight = height; }}this.canvasNode.height = tempHeight;
    this.canvasNode.width = tempWidth;
    styleString = Object.assign({'width': tempWidth, 'height': tempHeight}, CANVAS_STYLE);
    this.canvasNode.setAttribute('style', styleString);

    let ctx = this.canvasNode.getContext('2d'), startX = 0, startY = 0;
    let image = new Image() ;
    image.setAttribute("crossOrigin".'Anonymous')
    / / add a timestamp because it didn't set the cross-domain image domain https://www.jianshu.com/p/c3aa975923de
    image.src = this.imgNode.src + '? t=' + new Date().getTime(); 
    image.height = tempHeight;
    image.width = tempWidth;
    image.onload = function(){
      ctx.drawImage(image, 0.0, tempWidth, tempHeight);
    }
    // Mouse movement events
    let mousemoveFn = function(e) {
      ctx.beginPath();
      ctx.lineWidth = 3;
      ctx.strokeStyle = self.currentColor;
      if(startX == e.clientX - self.canvasNode.offsetLeft || startY ===  e.clientY - self.canvasNode.offsetTop  ) return
      ctx.moveTo(startX,startY);
      ctx.lineTo(e.clientX - self.canvasNode.offsetLeft , e.clientY - self.canvasNode.offsetTop );
      ctx.stroke();
      startX = e.clientX - self.canvasNode.offsetLeft;
      startY = e.clientY - self.canvasNode.offsetTop ; // 37 is the header height
    }
    // Mouse down event
    this.canvasNode.addEventListener("mousedown".function(e){
      startX = e.clientX - self.canvasNode.offsetLeft;
      startY = e.clientY - self.canvasNode.offsetTop ;

      // If recorded in mouseup, there is one more step to be taken when retracting
      let imageData = ctx.getImageData(0.0, self.canvasNode.width, self.canvasNode.height);
      self.imageDataArray.push(imageData); // This imageDataArray is used to record the strokes of the brush
      self.canvasNode.addEventListener("mousemove", mousemoveFn, false);
    },false);
    this.canvasNode.addEventListener('mouseup'.function(e){
      self.canvasNode.removeEventListener('mousemove', mousemoveFn);
    });
    this.bgNode.appendChild(this.canvasNode);
Copy the code

Problems encountered

  1. Because this domain name is only set to cross domain 192.168.6.*, so MY localhost domain name will report the cross domain problem (only for the cross domain 192.168.6.* was told by my colleague, otherwise I would still be stupid to check the problem).
  • Set vue. Congfig. Js file to host under dev
  1. After scaling, the size of the image changed after saving. The size of the base64 image output by toDataURL() method changed. Reason: When I draw the picture on canvas, I use the scaling algorithm of the above code to make the picture smaller, so the picture drawn on the canvas is also smaller…
  • Solution :(to be solved)

conclusion

  1. It was the first time that I got to know the function of combining canvas with pictures, which made me familiar with the API of Canvas
  2. Before you encounter new features, be sure to settle down and use what you know to think about possible solutions. When you find a breakthrough, you can do it
  3. When you encounter unfamiliar knowledge, you must read the API first. I was not good at this canvas before, but after I looked at the API several times, I was able to use it to do functions. What’s more, the examples I saw in W3School make me think that Canvas is really powerful