本次开发主要实现前端截图上传,替换使用不太方便的图片上传文字上传
由于是从画板中截图,htmltopng之类的dom读取截图库就不可以使用
一开始考虑使用chrome extension实现截图,但实现起来效果不太理想(向js逻辑传递截图数据比较啰嗦,需要通过storage),且extension发布不方便还有浏览器限制与版本限制,考虑其他实现
后来经过调研发现getDisplayMedia可以获取屏幕视频流,可以把视频流打入video从中截取一屏内容读入canvas中实现截图
但这样截取的是整屏幕的内容,还需要做一个截屏中常用的拖拽截屏框,根据用户拖拽坐标计算出位置截取对应的图片即可
getDisplayMedia(options) {
// fill 不同版本的浏览器
if (navigator.mediaDevices && navigator.mediaDevices.getDisplayMedia) {
return navigator.mediaDevices.getDisplayMedia(options);
}
if (navigator.getDisplayMedia) {
return navigator.getDisplayMedia(options);
}
if (navigator.webkitGetDisplayMedia) {
return navigator.webkitGetDisplayMedia(options);
}
if (navigator.mozGetDisplayMedia) {
return navigator.mozGetDisplayMedia(options);
}
throw new Error("getDisplayMedia is not defined");
},
async takeScreenshotStream() {
// 计算屏幕实际长宽
const width = screen.width * (window.devicePixelRatio || 1);
const height = screen.height * (window.devicePixelRatio || 1);
const errors = [];
let stream;
const mediaStreamConstraints = {
audio: false,
video: {
width,
height,
frameRate: 1
}
};
// 获取视频流,注意浏览器适配
try {
stream = await this.getDisplayMedia(mediaStreamConstraints);
} catch (ex) {
errors.push(ex);
}
if (errors.length) {
console.debug(...errors);
if (!stream) {
throw errors[errors.length - 1];
}
}
return stream;
},
async takeScreenshotCanvas() {
const stream = await this.takeScreenshotStream();
const video = document.createElement("video");
const result = await new Promise((resolve, reject) => {
// 将获取的流输入video中,pause后将将内容读取金canvas中
video.onloadedmetadata = () => {
video.play();
video.pause();
const canvas = document.createElement("canvas");
canvas.width = video.videoWidth;
canvas.height = video.videoHeight;
const context = canvas.getContext("2d");
context.drawImage(video, 0, 0, video.videoWidth, video.videoHeight);
resolve(canvas);
};
video.srcObject = stream;
});
stream.getTracks().forEach(function(track) {
track.stop();
});
if (result == null) {
throw new Error("Cannot take canvas screenshot");
}
return result;
},
async capture() {
const pre = this.$refs.pre;
const context = pre.getContext("2d");
const createdCanvas = await this.takeScreenshotCanvas();
const height = this.endY - this.startY;
const width = this.endX - this.startX;
// 根据用户选取的内容坐标将对应部分截取出来
context.drawImage(
createdCanvas,
this.startX,
this.startY + this.gap,
width,
height,
0,
0,
32,
32
);
const data_url = pre.toDataURL();
// 把截取好的图片转为svg
const content = await this.transferToSvg(data_url);
document.getElementById("svg_holder").innerHTML = content;
this.tip = "截图完成,图片预览:";
this.svg_str = content;
this.base_64 = data_url;
this.captruing = false;
},
实现效果
截图的图片质量相对上传的图片质量较差,增加色数为32色,效果如下?
同时实现了一个小输入框
?
?
|