Html:
<div class="record">
<!-- 如果没有生成过海报,则先拼接成海报样式展示 -->
<div v-show="!imageUrl || (imageUrl && !isImageLoaded)" class="poster-preview" id="poster-preview">
<!-- 内容自定义, 需要在海报各元素加载完成并使用base64格式进行生成海报 -->
<img crossOrigin='anonymous' @load="loadBackground" class="display-image" :src="recordBackgroundPng" />
<img crossOrigin='anonymous' class="record-detail-logo" @load="loadLogoPng" :src="logoPng" />
<div class="val other-val">{{targets[2].target}}</div>
</div>
<!-- 如果生成海报完毕,则显示图片,长按可保存 -->
<img v-show="isImageLoaded" @load="loadImage" class="record-image" :src="recordSrc" />
</div>
JS:
async created() {
this.convertImageToBase64();
this.$nextTick(() => {
setTimeout(() => {
this.generatImage();
}, 1000);
});
},
watch: {
imageUrl: {
handler() {
this.setImageSrc(this.imageUrl);
},
},
},
convertImageToBase64() {
UploadUtil.getBase64(RecordBackgroundPng)
.then((pngData) => {
this.recordBackgroundPng = pngData;
});
UploadUtil.getBase64(this.images.LogoPng)
.then((pngData) => { this.logoPng = pngData; });
},
generatImage() {
this.timer = setInterval(() => {
// 设置定时器,等图片加载完成才可以进行canvas绘制,否则有可能海报不完整
if (this.isLogoPngLoaded && this.isRecordTopPngLoaded) {
clearInterval(this.timer);
const div = document.getElementById('poster-preview');
html2canvas(div, {
useCORS: true,
allowTaint: true,
}).then(async (canvas) => {
const key = `image/poster${getFileNameUUID()}.png`;
const file = this.canvasToFile(canvas, key);
const img = [{ key, file, src: window.URL.createObjectURL(file) }];
try {
const imagesInfo = await uploadService.uploadFiles(img);
this.imageUrl = imagesInfo[0].fileUrl;
this.saveImageUrl();
} catch (error) {
console.log(error);
}
});
}
}, 1000);
},
async saveImageUrl() {
await api.saveImage({ imageUrl: this.imageUrl });
this.setImageSrc(this.imageUrl);
},
setImageSrc(url) {
if (!url) return;
UploadUtil.getBase64(url).then((res) => {
this.recordSrc = res;
this.$forceUpdate();
});
},
canvasToFile(canvas, fileName) {
const uricode = canvas.toDataURL('images/png', 1.0);
const blobs = UploadUtil.urlToBlob(uricode);
const file = UploadUtil.blobToFile(blobs, fileName);
return file;
},
Util:
import Compressor from 'compressorjs';
// 当使用uploader元素 比如<van-uploader /> 可以先压缩
function beforeRead(file) {
return new Promise((resolve) => {
// eslint-disable-next-line no-new
new Compressor(file, {
quality: 0.6,
convertSize: 2000000, // png超过2MB则转为jpeg
success: resolve,
error(err) {},
});
});
}
function urlToBlob(dataURL, specificContentType = null) {
const BASE64_MARKER = ';base64,';
if (dataURL.indexOf(BASE64_MARKER) === -1) {
const parts = dataURL.split(',');
const contentType = specificContentType || parts[0].split(':')[1];
const raw = decodeURIComponent(parts[1]);
return new Blob([raw], { type: contentType });
}
const parts = dataURL.split(BASE64_MARKER);
const contentType = specificContentType || parts[0].split(':')[1];
const raw = window.atob(parts[1]);
const rawLength = raw.length;
const uInt8Array = new Uint8Array(rawLength);
for (let i = 0; i < rawLength; i += 1) {
uInt8Array[i] = raw.charCodeAt(i);
}
return new Blob([uInt8Array], { type: contentType });
}
function blobToFile(theBlob, fileName) {
theBlob.lastModifiedDate = new Date();
theBlob.name = fileName;
return theBlob;
}
function getBase64(url) {
return new Promise((resolve, reject) => {
const image = new Image();
image.setAttribute('crossOrigin', 'anonymous');
image.onload = () => {
const canvas = document.createElement('canvas');
canvas.width = image.width;
canvas.height = image.height;
const context = canvas.getContext('2d');
context.drawImage(image, 0, 0, image.width, image.height);
const quality = 0.8;
const dataURL = canvas.toDataURL('image/png', quality);
resolve(dataURL);
};
image.src = `${url}?time=${new Date().valueOf()}`;
image.onerror = (error) => {
reject(new Error('Image stream is abnormal'));
};
});
}
export function getFileNameUUID() {
const s = [];
const hexDigits = '0123456789abcdef';
for (let i = 0; i < 36; i += 1) {
s[i] = hexDigits.substr(Math.floor(Math.random() * 0x10), 1);
}
const uuid = s.join('');
return uuid;
}
export default {
beforeRead,
urlToBlob,
blobToFile,
getBase64,
};