html!!!save
This commit is contained in:
parent
4f22196d68
commit
107ebd7a1d
@ -1,74 +1,107 @@
|
||||
/**
|
||||
* HTML转图片工具
|
||||
* 基于 html2canvas 实现,兼容低版本 Safari/微信
|
||||
* 基于 html-to-image 将DOM元素转换为图片
|
||||
*/
|
||||
|
||||
import html2canvas from 'html2canvas';
|
||||
import { toCanvas } from 'html-to-image'
|
||||
|
||||
/**
|
||||
* 将DOM元素转换为图片
|
||||
* @param {string|HTMLElement} selector - DOM选择器或元素
|
||||
* @param {Object} options - 配置选项
|
||||
* @param {number} [options.width] - 自定义宽度(会应用到元素上)
|
||||
* @param {number} [options.height] - 自定义高度(会应用到元素上)
|
||||
* @param {number} [options.canvasWidth] - 输出画布宽度
|
||||
* @param {number} [options.canvasHeight] - 输出画布高度
|
||||
* @param {number} [options.pixelRatio] - 像素比例,默认2
|
||||
* @param {boolean} [options.useCORS] - 是否允许跨域,默认true
|
||||
* @param {string} [options.format] - 图片格式,'png'或'jpeg',默认'png'
|
||||
* @param {number} [options.quality] - 图片质量,0-1,仅jpeg有效,默认1.0
|
||||
* @returns {Promise<string>} - 返回base64图片数据URL
|
||||
*/
|
||||
export async function toDataURL(selector, options = {}) {
|
||||
const {
|
||||
width,
|
||||
height,
|
||||
canvasWidth,
|
||||
canvasHeight,
|
||||
pixelRatio = 2,
|
||||
useCORS = true,
|
||||
format = 'png',
|
||||
quality = 1.0
|
||||
} = options;
|
||||
} = options
|
||||
|
||||
const element = typeof selector === 'string' ? document.querySelector(selector) : selector;
|
||||
if (!element) throw new Error('Element not found');
|
||||
const element = typeof selector === 'string' ? document.querySelector(selector) : selector
|
||||
if (!element) {
|
||||
throw new Error('Element not found')
|
||||
}
|
||||
|
||||
const canvas = await html2canvas(element, {
|
||||
scale: pixelRatio,
|
||||
useCORS: true,
|
||||
allowTaint: false,
|
||||
backgroundColor: '#ffffff',
|
||||
dpi: window.devicePixelRatio * pixelRatio,
|
||||
logging: false
|
||||
});
|
||||
const canvasEl = await toCanvas(element, {
|
||||
width,
|
||||
height,
|
||||
canvasWidth,
|
||||
canvasHeight,
|
||||
pixelRatio,
|
||||
cors: useCORS,
|
||||
backgroundColor: '#ffffff'
|
||||
})
|
||||
|
||||
const mimeType = format === 'jpeg' ? 'image/jpeg' : 'image/png';
|
||||
return canvas.toDataURL(mimeType, quality);
|
||||
const mimeType = format === 'jpeg' ? 'image/jpeg' : 'image/png'
|
||||
return canvasEl.toDataURL(mimeType, quality)
|
||||
}
|
||||
|
||||
/**
|
||||
* 将DOM元素转换为图片并下载
|
||||
* @param {string|HTMLElement} selector - DOM选择器或元素
|
||||
* @param {string} [filename] - 下载文件名,不含扩展名
|
||||
* @param {Object} options - 配置选项,同toDataURL
|
||||
*/
|
||||
export async function toImageDownload(selector, filename = 'download', options = {}) {
|
||||
const dataUrl = await toDataURL(selector, options);
|
||||
const link = document.createElement('a');
|
||||
link.download = filename + '.png';
|
||||
link.href = dataUrl;
|
||||
document.body.appendChild(link);
|
||||
link.click();
|
||||
document.body.removeChild(link);
|
||||
const dataUrl = await toDataURL(selector, options)
|
||||
|
||||
const link = document.createElement('a')
|
||||
link.download = filename + '.png'
|
||||
link.href = dataUrl
|
||||
document.body.appendChild(link)
|
||||
link.click()
|
||||
document.body.removeChild(link)
|
||||
}
|
||||
|
||||
/**
|
||||
* 转为 Blob
|
||||
* 将DOM元素转换为Blob
|
||||
* @param {string|HTMLElement} selector - DOM选择器或元素
|
||||
* @param {Object} options - 配置选项,同toDataURL
|
||||
* @returns {Promise<Blob>}
|
||||
*/
|
||||
export function toBlob(selector, options = {}) {
|
||||
return new Promise(async (resolve, reject) => {
|
||||
try {
|
||||
const dataUrl = await toDataURL(selector, options);
|
||||
const arr = dataUrl.split(',');
|
||||
const mime = arr[0].match(/:(.*?);/)[1];
|
||||
const bstr = atob(arr[1]);
|
||||
const u8arr = new Uint8Array(bstr.length);
|
||||
for (let i = 0; i < bstr.length; i++) {
|
||||
u8arr[i] = bstr.charCodeAt(i);
|
||||
export async function toBlob(selector, options = {}) {
|
||||
const dataUrl = await toDataURL(selector, options)
|
||||
|
||||
const arr = dataUrl.split(',')
|
||||
const mime = arr[0].match(/:(.*?);/)[1]
|
||||
const bstr = atob(arr[1])
|
||||
let n = bstr.length
|
||||
const u8arr = new Uint8Array(n)
|
||||
while (n--) {
|
||||
u8arr[n] = bstr.charCodeAt(n)
|
||||
}
|
||||
resolve(new Blob([u8arr], { type: mime }));
|
||||
} catch (e) {
|
||||
reject(e);
|
||||
}
|
||||
});
|
||||
return new Blob([u8arr], { type: mime })
|
||||
}
|
||||
|
||||
export default { toDataURL, toImageDownload, toBlob };
|
||||
/**
|
||||
* 通过 dataURL 直接下载图片
|
||||
*/
|
||||
export function downloadByDataURL(dataUrl, filename = 'download') {
|
||||
const link = document.createElement('a')
|
||||
link.download = filename + '.png'
|
||||
link.href = dataUrl
|
||||
document.body.appendChild(link)
|
||||
link.click()
|
||||
document.body.removeChild(link)
|
||||
}
|
||||
|
||||
export default {
|
||||
toDataURL,
|
||||
toImageDownload,
|
||||
toBlob,
|
||||
downloadByDataURL
|
||||
}
|
||||
@ -11,7 +11,7 @@
|
||||
<img src="/img/paycode.jpg" alt="" style="width: 100%; display: block;" class="bg-img" @load="onBgLoad">
|
||||
<div class="user-info">
|
||||
<div class="info">
|
||||
<img :src="$file(shopimg)" alt="" style="border-radius: 50%;">
|
||||
<img :src="$file(shopimg)" alt="">
|
||||
</div>
|
||||
<div class="name">
|
||||
<span>{{ shopname?.length > 8 ? shopname.slice(0, 8) + '...' : shopname }}</span>
|
||||
@ -33,7 +33,7 @@
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import { toDataURL } from '@/utils/html2image'
|
||||
import { toDataURL, downloadByDataURL } from '@/utils/html2image'
|
||||
|
||||
export default {
|
||||
name: 'PayCode',
|
||||
@ -94,38 +94,21 @@ export default {
|
||||
|
||||
async handleSave() {
|
||||
if (this.loading) return
|
||||
// 如果已生成图片,直接下载
|
||||
if (this.generatedImage) {
|
||||
this.downloadByBlob(this.generatedImage, `收款码_${this.shopname}.png`)
|
||||
this.$showSuccessToast('保存成功')
|
||||
return
|
||||
}
|
||||
// 否则生成图片
|
||||
try {
|
||||
this.loading = true
|
||||
if (!this.generatedImage) {
|
||||
await this.generateImage()
|
||||
}
|
||||
if (this.generatedImage) {
|
||||
this.downloadByBlob(this.generatedImage, `收款码_${this.shopname}.png`)
|
||||
downloadByDataURL(this.generatedImage, `收款码_${this.shopname}`)
|
||||
this.$showSuccessToast('保存成功')
|
||||
}
|
||||
},
|
||||
|
||||
downloadByBlob(dataUrl, filename) {
|
||||
const arr = dataUrl.split(',')
|
||||
const mime = arr[0].match(/:(.*?);/)[1]
|
||||
const bstr = atob(arr[1])
|
||||
let n = bstr.length
|
||||
const u8arr = new Uint8Array(n)
|
||||
while (n--) {
|
||||
u8arr[n] = bstr.charCodeAt(n)
|
||||
} catch (e) {
|
||||
console.error('保存失败:', e)
|
||||
this.$showFailToast('保存失败')
|
||||
} finally {
|
||||
this.loading = false
|
||||
}
|
||||
const blob = new Blob([u8arr], { type: mime })
|
||||
const url = URL.createObjectURL(blob)
|
||||
const link = document.createElement('a')
|
||||
link.download = filename
|
||||
link.href = url
|
||||
document.body.appendChild(link)
|
||||
link.click()
|
||||
document.body.removeChild(link)
|
||||
URL.revokeObjectURL(url)
|
||||
},
|
||||
},
|
||||
}
|
||||
@ -171,7 +154,7 @@ export default {
|
||||
img {
|
||||
width: 6.4vw;
|
||||
height: 6.4vw;
|
||||
border-radius: 50%;
|
||||
// border-radius: 50%;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@ -167,7 +167,7 @@ export default {
|
||||
color: #3a0a05;
|
||||
position: absolute;
|
||||
left: 20.27vw;
|
||||
bottom: 34vw;
|
||||
bottom: 32.4vw;
|
||||
}
|
||||
|
||||
.icon {
|
||||
@ -175,7 +175,7 @@ export default {
|
||||
width: 10.67vw;
|
||||
height: 10.67vw;
|
||||
left: 20.27vw;
|
||||
bottom: 42vw;
|
||||
bottom: 43vw;
|
||||
border-radius: 50%;
|
||||
}
|
||||
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user