leaflet使用domtoimage插件与h5 canvas实现截图功能并下载

canvas参考:https://blog.csdn.net/u012468376/article/details/73350998?ops_request_misc=%257B%2522request%255Fid%2522%253A%2522163642386816780261954825%2522%252C%2522scm%2522%253A%252220140713.130102334..%2522%257D&request_id=163642386816780261954825&biz_id=0&utm_medium=distribute.pc_search_result.none-task-blog-2~all~top_positive~default-1-73350998.first_rank_v2_pc_rank_v29&utm_term=canvas&spm=1018.2226.3001.4187

domtoimage参考文档:

domToImage 中文文档

实现思路:

简单版:(单个图不叠加不使用canvas)

dom-to-image 是一个JS类库,它可以将任意DOM节点转换成 SVG/PNG/JPEG 格式的图像。所以我们将想要截图区域的全部节点(给整个大节点加个ref='mynode',通过this.$refs.mynode取到节点)放进参数,会得到一个带有 dataUrls 的 promise。然后生成一个 Blob 格式的 PNG 图片,并下载它

代码如下:

 function jietu(){
  
     const node = this.$refs.map.$el     //获取截图区域的节点,map是我的节点的ref的名称
     domtoimage.toBlob(node)             //生成一个 Blob 格式的 PNG 图片,并下载它
     .then(function (blob) {
        window.saveAs(blob, 'my-node.png');
    });
}

进阶版:使用canvas实现截图(单层)

   

 function jietu(){
  
     const node = this.$refs.map.$el     //获取截图区域的节点,map是我的节点的ref的名称
     domtoimage.toPng(node)
        .then(dataUrl => {
            var img = new Image();   // 创建一个<img>元素
            img.src = dataUrl; // 设置图片源地址
           
             img.onload = () => {
                 const baseCanvas = document.createElement('canvas')
                 const baseContext = baseCanvas.getContext('2d')
                 baseCanvas.width = img.width
                 baseCanvas.height = img.height
                 baseContext.drawImage(img, 0, 0, img.width, img.height)
                //下载图片
                 baseCanvas.toBlob(function(blob) {
                 aveAs(blob, 'screen.png')
      })
                             }
        })
}

复杂进阶版:(多层瓦片图层与窗格叠加)

需要使用canvas画布,将每层瓦片图层imagedata取出来然后放在画布上一层一层叠加混合,最终画布成一个图片,难点转化像素

  //截图leaflet地图
saveMap() {
      const node = this.$refs.map.$el
      domtoimage.toPng(node)
        .then(dataUrl => {
          this.mapHelp.toScreenImage(dataUrl)
        })
    },

mapHelp是我们封装的创建地图的类,类里方法toScreenImage如下:


  toScreenImage(dataUrl) {
    const canvas = this.airPortCollection.PixiMap.toScreenCanvas()
    const context = canvas.getContext('2d')
    const airdata = context.getImageData(0, 0, canvas.width, canvas.height)

    const canvas_draw = this.pixiLayer.toScreenCanvas()
    const context_draw = canvas_draw.getContext('2d')
    const draw_data = context_draw.getImageData(
      0,
      0,
      canvas_draw.width,
      canvas_draw.height
    )

    var img = new Image()
    img.src = dataUrl
    img.onload = () => {
      const baseContext = this.baseCanvas.getContext('2d')
      this.baseCanvas.width = img.width
      this.baseCanvas.height = img.height
      baseContext.drawImage(img, 0, 0, img.width, img.height)
      const baseImage = baseContext.getImageData(
        0,
        0,
        canvas.width,
        canvas.height
      )
      const imageData = blendImage(baseImage, [airdata.data, draw_data.data])
      this.baseCanvas.width = canvas.width
      this.baseCanvas.height = canvas.height
      baseContext.putImageData(imageData, 0, 0)
      this.baseCanvas.toBlob(function(blob) {
        saveAs(blob, 'screen.png')
      })
    }
  }

这里我们又封装了canvas类方法blendImage(混合图片)与traverse(将原始像素转化成我想要的像素rgba)

export function traverse(imageData, pass) {
  const { width, height, data } = imageData
  for (let i = 0; i < width * height * 4; i += 4) {
    const [r, g, b, a] = pass({
      r: data[i],
      g: data[i + 1],
      b: data[i + 2],
      a: data[i + 3],
      index: i,
      width: width,
      height: height,
      x: (i / 4) % width,
      y: Math.floor(i / 4 / width)
    })

    data.set([r, g, b, a].map(v => Math.round(v)), i)
  }
  return imageData
}

export function blendImage(baseData, datas) {
  traverse(baseData, ({ r, g, b, a, index }) => {
    for (let l = datas.length - 1; l >= 0; l--) {
    //  debugger
      if (datas[l][index + 3] > 10) {
        return [datas[l][index], datas[l][index + 1], datas[l][index + 2], datas[l][index + 3]]
      }
    }

    return [r, g, b, a]
  })
  return baseData
}

  • 2
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值