“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也带来了内存问题和传输问题,所以本地选择上传后获取到服务器的图片资源地址
© 版权声明
文章版权归作者所有,未经允许请勿转载。
THE END