前端截图转base64转blob后上传

“Offer 驾到,掘友接招!我正在参与2022春招打卡活动,点击查看活动详情。”

项目中用到了html2canvas对图片区域进行截图,因为大都是图片是在几M,转成的base64自然就比原来的内存更大了,所以需要优化

1、截图

前端截图大都数用的是html2canavs,

这里存在的问题可能有

1.1. 图片跨域: 有可能是img未设置crossorigin属性 ;有可能是后台未允许图片跨域,有可能是缓存原因;

解决办法: 

  • img元素中设置crossorigin属性
  • 图片允许跨域,设置响应头Access-Control-Allow-Origin
  • 使用js方式请求图片资源, 需要避免使用缓存,设置url后加上时间戳,或者http头设置Cache-Control为no-cache

1.2. 在线图片无法截图获取:

  解决办法:

    克隆文档进行渲染时调用的回调函数,可用于修改将要渲染的内容而不影响原始源文档。

对于非base64的图片资源,转成base64后再进行下一步操作

1.3. 图片模糊

    通过自定义配置的画布配置选择项,将画布width,height设置后再设置style的width,height

canvas.width = w * 2;

canvas.height = h * 2;     

canvas.style.width = w + "px";     

canvas.style.height = h + "px";     

//然后将画布缩放,将图像放大两倍画到画布上     

context.scale(2,2);
复制代码

1.4. 图像偏移:因为margin的原因,导致生成图像位置有所偏移

var canvas = document.createElement("canvas");

// 获取元素相对于视窗的偏移量

var rect = dom.getBoundingClientRect(); 

var context = canvas.getContext("2d");

// 设置context位置, 值为相对于视窗的偏移量的负值, 实现图片复位

context.translate(-rect.left,-rect.top); // 实际偏移位置会根据实际效果有所不同
复制代码

请注意: 实际偏移位置会根据实际效果有所不同, 具体原因还未明白,我在项目中可能是因为绘图区域的位置原因,导致top还要向右偏移400才居中

截图的完整代码

const dom = document.getElementById('svg-container')

const rect = dom.getBoundingClientRect()

const can = document.createElement('canvas')

const w = 1940

const h = 1080

can.width = w * 2;

can.height = h * 2;     

can.style.width = w + "px";     

can.style.height = h + "px";         

//然后将画布缩放,将图像放大两倍画到画布上     

context.scale(2,2);

const context = can.getContext('2d')

context.translate(rect.left, rect.top

html2canvas(dom, {

  canvas: can,

scale: 2, 

  onclone (html) {

   const imageNodes = $(html).find('#imageBg')

   const promises = []

    imageNodes.each(function () {

       const element = $(this)

       const href = element.attr('href')

       if (href.startsWith('base64')) return

           const promise = new Promise((resolve, reject) => {

               const img = new Image()

                img.crossOrigin = 'anonymous'

                img.src = `${href}?time=${new Date().valueOf()}`

                img.onload = function () {

                 const canvas = document.createElement('canvas')

                  canvas.width = naturalWidth //图片原始宽高

                  canvas.height = naturalHeight // //图片原始宽高

                 const ctx = canvas.getContext('2d')

                  ctx.drawImage(img, 0, 0, naturalWidth, naturalHeight)

                 const base64 = canvas.toDataURL('image/png')

                  element.attr('href', base64)

                 resolve()

               }

                img.onerror = reject

             })

              promises.push(promise)

           })

           return Promise.all(promises)

         },

          backgroundColor: null

       }).then((canvas) => {

     })

复制代码

2、base64转blob

具体代码

const getBlob = function (can) {

           // 获取blob对象

           let data = can.toDataURL('image/png', 1)

            data = data.split(',')[1]

            data = window.atob(data)

           const ia = new Uint8Array(data.length)

           for (let i = 0; i < data.length; i++) {

              ia[i] = data.charCodeAt(i)

           }

           return new Blob([ia], {

              type: 'image/png'

           })

         }

         const blob = getBlob(canvas)

         // 生成和上传文件流

         const blobToFile = new window.File([blob], this.currentImage.fileName, {

            type: 'image/*'

         })
复制代码

这里除了转blob外,还可以转成文件流

//base64转blob
export function base64ToBlob(dataurl) {
    var arr = dataurl.split(','), mime = arr[0].match(/:(.*?);/)[1],
        bstr = atob(arr[1]), n = bstr.length, u8arr = new Uint8Array(n);
    while (n--) {
        u8arr[n] = bstr.charCodeAt(n);
    }
    return new Blob([u8arr], { type: mime });
}
复制代码

3、上传

采用axios表单提交


const uploadFileImg = function (blob) {

           const param = new FormData() // 创建form对象

            param.append('file', blob) // 通过append向form对象添加数据

            axios.post(url, param, {

              headers: { 'Content-Type': 'multipart/form-data' }

           }).then((res) => {

            

           }, () => {

              

           })

         }

复制代码

结论:

一般的截图要么是下载,要么就是在数据库中存base64,但是图片转base64也带来了内存问题和传输问题,所以本地选择上传后获取到服务器的图片资源地址

Supongo que te gusta

Origin juejin.im/post/7076717790912053256
Recomendado
Clasificación