手动绘制仿qq截屏效果

        因我司业务需要,现在在electron端需要开发仿qq截屏功能,(其实window端已经实现,具体实现方案可以看前面一篇文章~),现在需要手动使用canvas做一个仿qq截图功能的截屏效果,不说了,直接入正题。。。。

        其中有部分效果参考了其他博客文章 https://www.cnblogs.com/ygtq-island/p/7676564.html,(部分算法实在是写起来麻烦,于是就把人家的源码拿过来用啦~嘿嘿)先看一个效果图

其中马赛克和箭头的部分实现起来是花费了挺多时间的,首先是截取全屏,通过调用electron的api截取全屏图片数据:


然后在当前屏幕里面创建遮罩层区域,根据在鼠标点击遮罩层事件开始划分截图的矩形并生成同样大小的canvas画布,根据矩形的起始坐标和宽高可以算出画布在全屏截图中的位置,并通过canvas的drawImage属性将图片画到canvas中去,并同时在画布下创建按钮区域,接下来就是开始做各种编辑操作了编辑

本次案例中一共使用了两块画布,也就是说生成了2个canvas,先生成canvas01,这个是基本的canvas,最后获取截图数据就是通过它来获取的,文字编辑功能和马赛克功能目前是在此canvas01上完成

文字编辑功能:

createTextEvent(target) { // 绘制文字事件

    this.btnFn(target).then(() => {

      let that = this;

      let textX, textY;

      let nowColor = '#FF0F00'

      that.canvasResult.onmousedown = function(ev) {

        let input_dx = ev.clientX

        let input_dy = ev.clientY

        textX = input_dx

        textY = input_dy-15

        $("body").append(`

         

           

           

           

         

        `)

        sendDom()

      }

      that.canvasResult.onmouseup = function(ev) {

        that.canvasResult.onmousedown = null

      }

      let sendDom = function() {

        $('.text-color-choose ul li').click(function() {

          nowColor = $(this).attr('colors')

          console.log(nowColor)

          $(this).addClass('on').siblings().removeClass('on')

          $('.font-group .draw-text').css({color: nowColor})

        })

        $('.font-group .draw-text-move').mousedown(function(ev) {

          ev.stopPropagation()

          let dx = ev.clientX - that.canvasResult.offsetLeft

          let dy = ev.clientY - that.canvasResult.offsetTop

          let input_dx = $('.font-group').offset().left

          let input_dy = $('.font-group').offset().top

          document.onmousemove = function(ev) {

            let mx = ev.clientX - dx - that.canvasResult.offsetLeft

            let my = ev.clientY - dy - that.canvasResult.offsetTop

            textX = input_dx+mx

            textY = input_dy+my

            $('.font-group').css({left: input_dx+mx+'px', top: input_dy+my+'px'})

          }

          document.onmouseup = function(ev) {

            document.onmousemove = null

            document.onmouseup = null

          }

        })


        $('.font-group .draw-text-define').click(function(ev) {

          let input_test = $('.font-group .draw-text').val()

          that.ctx.strokeStyle=nowColor;

          that.ctx.font="18px Arial";

          console.log(textX)

          console.log(textY)

          that.ctx.strokeText(input_test, textX - that.canvasResult.offsetLeft, textY - that.canvasResult.offsetTop+15);

          let fontGroup = document.getElementsByClassName('font-group')[0]

          if (!fontGroup) return

          document.getElementsByTagName('body')[0].removeChild(fontGroup)

        })

      }

    })

  }

在canvas中生成一个文字编辑区块,也可以自行选择颜色,最终获取到input中的val,通过ctx.strokeText绘制到canvas中;

马赛克功能:

this.btnFn(target).then(() => {

      let that = this

      var lastImgArr = []; //修改缓存

      canvasResult.onmousedown = function(ev) {

        var modifyImgData = that.ctx.getImageData(0, 0, that.canvasResult.width, that.canvasResult.height);

        lastImgArr.push(modifyImgData); //每次下笔前先保存

        var ev=ev || window.event;

        var dx = ev.clientX-canvasResult.offsetLeft;

        var dy = ev.clientY-canvasResult.offsetTop;

        drawLine(that.Img,dx,dy, that.ctx, that.canvasResult, that.quan, that.num);

        document.onmousemove = function(ev) {

          var ev = ev || window.event;

          var mx = ev.clientX - that.canvasResult.offsetLeft;

          var my = ev.clientY - that.canvasResult.offsetTop;

          if (

            Math.pow(dx - mx, 2) + Math.pow(dy - my, 2) >=

            Math.pow(that.quan * that.num, 2)

          ) {

            //(quan*马赛克个数*2)的平方

            drawLine(that.Img, mx, my, that.ctx, that.canvasResult, that.quan, that.num);

            dx = mx;

            dy = my;

          }

        };

        document.onmouseup = function() {

          document.onmousemove = null;

          document.onmouseup = null;

        };

      }

    })

function drawLine(obj, dx, dy, context, canvas, quan, num) {

  //原始图像

  var originalImgData = context.getImageData(

    0,

    0,

    canvas.width,

    canvas.height

  );

  var originalPxData = originalImgData.data;

  //用于循环修改

  var modifyImgData = context.getImageData(

    0,

    0,

    canvas.width,

    canvas.height

  );

  var modifyPxData = modifyImgData.data;

  for (

    var i = dx - quan * num;

    i < dx + quan * num;

    i = i + 2 * quan + 1

  ) {

    for (

      var j = dy - quan * num;

      j < dy + quan * num;

      j = j + 2 * quan + 1

    ) {

      //中心点(dx,dy)

      // if(Math.pow(i-dx,2)+Math.pow(j-dy,2) <= Math.pow(quan*num/2,2)){

      if (

        !(

          (i == dx - quan * num && j == dy - quan * num) ||

          (i == dx - quan * num &&

            j == dy - quan * num + 2 * quan + 1) ||

          (i == dx - quan * num &&

            j == dy - quan * num + 4 * quan + 2) ||

          (i == dx - quan * num &&

            j == dy - quan * num + 12 * quan + 6) ||

          (i == dx - quan * num &&

            j == dy - quan * num + 14 * quan + 7) ||

          (i == dx - quan * num &&

            j == dy - quan * num + 16 * quan + 8) ||

          (i == dx - quan * num + 16 * quan + 8 &&

            j == dy - quan * num) ||

          (i == dx - quan * num + 16 * quan + 8 &&

            j == dy - quan * num + 2 * quan + 1) ||

          (i == dx - quan * num + 16 * quan + 8 &&

            j == dy - quan * num + 4 * quan + 2) ||

          (i == dx - quan * num + 16 * quan + 8 &&

            j == dy - quan * num + 12 * quan + 6) ||

          (i == dx - quan * num + 16 * quan + 8 &&

            j == dy - quan * num + 14 * quan + 7) ||

          (i == dx - quan * num + 16 * quan + 8 &&

            j == dy - quan * num + 16 * quan + 8) ||

          (i == dx - quan * num + 2 * quan + 1 &&

            j == dy - quan * num) ||

          (i == dx - quan * num + 4 * quan + 2 &&

            j == dy - quan * num) ||

          (i == dx - quan * num + 12 * quan + 6 &&

            j == dy - quan * num) ||

          (i == dx - quan * num + 14 * quan + 7 &&

            j == dy - quan * num) ||

          (i == dx - quan * num + 2 * quan + 1 &&

            j == dy - quan * num + 16 * quan + 8) ||

          (i == dx - quan * num + 4 * quan + 2 &&

            j == dy - quan * num + 16 * quan + 8) ||

          (i == dx - quan * num + 12 * quan + 6 &&

            j == dy - quan * num + 16 * quan + 8) ||

          (i == dx - quan * num + 14 * quan + 7 &&

            j == dy - quan * num + 16 * quan + 8)

        )

      ) {

        var sumR = 0;

        var sumG = 0;

        var sumB = 0;

        //找他周围的元素

        for (var x = -quan; x <= quan; x++) {

          for (var y = -quan; y <= quan; y++) {

            var xx = i + x;

            var yy = j + y;

            var pp = yy * canvas.width + xx; //周围的元素。

            sumR += originalPxData[pp * 4 + 0];

            sumG += originalPxData[pp * 4 + 1];

            sumB += originalPxData[pp * 4 + 2];

          }

        }

        var totlal = (2 * quan + 1) * (2 * quan + 1);

        var avgR = sumR / totlal;

        var avgG = sumG / totlal;

        var avgB = sumB / totlal;

        for (var x = -quan; x <= quan; x++) {

          for (var y = -quan; y <= quan; y++) {

            var xx = i + x;

            var yy = j + y;

            var pp = yy * canvas.width + xx; //周围的元素。

            modifyPxData[pp * 4 + 0] = avgR;

            modifyPxData[pp * 4 + 1] = avgG;

            modifyPxData[pp * 4 + 2] = avgB;

          }

        }

      }

    }

  }

  context.putImageData(

    modifyImgData,

    0,

    0,

    0,

    0,

    canvas.width,

    canvas.height

  );

}

其中绘制马赛克的算法借助了drawLine,是从其他途径获取的,主要实现方式看代码即可;

绘制箭头,矩形方法参考了文章(https://www.cnblogs.com/ygtq-island/p/7676564.html)中使用的Ypaint.js,在需要绘制箭头矩形等功能时新创建一块矩形区域并生成canvas02,将绘制成功的canvas02通过toDataURL("image/png")方法获取到图片数据,在通过drawImage方法渲染到canvas01中即可

源代码地址:https://download.csdn.net/download/lbn2676043895/11275821

你可能感兴趣的:(手动绘制仿qq截屏效果)