liang-z-screenshot
Version:
vue-web-screen-shot 修复 html2canvas 截图 图片空白
938 lines (901 loc) • 31.6 kB
text/typescript
import { onMounted, onUnmounted, Ref, nextTick } from "vue";
import { SetupContext } from "@vue/runtime-core";
import {
cutOutBoxBorder,
movePositionType,
zoomCutOutBoxReturnType,
drawCutOutBoxReturnType,
positionInfoType
} from "@/module/type/ComponentType";
import { drawMasking } from "@/module/split-methods/DrawMasking";
import html2canvas from "html2canvas";
import PlugInParameters from "@/module/main-entrance/PlugInParameters";
import { fixedData, nonNegativeData } from "@/module/common-methords/FixedData";
import { zoomCutOutBoxPosition } from "@/module/common-methords/ZoomCutOutBoxPosition";
import { saveBorderArrInfo } from "@/module/common-methords/SaveBorderArrInfo";
import { drawCutOutBox } from "@/module/split-methods/DrawCutOutBox";
import InitData from "@/module/main-entrance/InitData";
import { calculateToolLocation } from "@/module/split-methods/CalculateToolLocation";
import { drawRectangle } from "@/module/split-methods/DrawRectangle";
import { drawCircle } from "@/module/split-methods/DrawCircle";
import { drawLineArrow } from "@/module/split-methods/DrawLineArrow";
import { drawPencil, initPencil } from "@/module/split-methods/DrawPencil";
import { drawText } from "@/module/split-methods/DrawText";
import { saveCanvasToImage } from "@/module/common-methords/SaveCanvasToImage";
import { saveCanvasToBase64 } from "@/module/common-methords/SaveCanvasToBase64";
import { drawMosaic } from "@/module/split-methods/DrawMosaic";
import { calculateOptionIcoPosition } from "@/module/split-methods/CalculateOptionIcoPosition";
import { setSelectedClassName } from "@/module/common-methords/SetSelectedClassName";
import adapter from "webrtc-adapter";
import { getDrawBoundaryStatus } from "@/module/split-methods/BoundaryJudgment";
export default class EventMonitoring {
// 当前实例的响应式data数据
private readonly data: InitData;
private emit: ((event: string, ...args: any[]) => void) | undefined;
// 截图区域canvas容器
private screenShortController: Ref<HTMLCanvasElement | null>;
// 截图工具栏dom
private toolController: Ref<HTMLDivElement | null>;
// 截图图片存放容器
private screenShortImageController: HTMLCanvasElement | null;
// 截图区域画布
private screenShortCanvas: CanvasRenderingContext2D | undefined;
// 文本区域dom
private textInputController: Ref<HTMLDivElement | null> | undefined;
// 截图工具栏画笔选项dom
private optionController: Ref<HTMLDivElement | null> | undefined;
private optionIcoController: Ref<HTMLDivElement | null> | undefined;
// video容器用于存放屏幕MediaStream流
private readonly videoController: HTMLVideoElement;
// 图形位置参数
private drawGraphPosition: positionInfoType = {
startX: 0,
startY: 0,
width: 0,
height: 0
};
// 临时图形位置参数
private tempGraphPosition: positionInfoType = {
startX: 0,
startY: 0,
width: 0,
height: 0
};
// 裁剪框边框节点坐标事件
private cutOutBoxBorderArr: Array<cutOutBoxBorder> = [];
// 裁剪框顶点边框直径大小
private borderSize = 10;
// 当前操作的边框节点
private borderOption: number | null = null;
// 点击裁剪框时的鼠标坐标
private movePosition: movePositionType = {
moveStartX: 0,
moveStartY: 0
};
// 裁剪框修剪状态
private draggingTrim = false;
// 裁剪框拖拽状态
private dragging = false;
// 鼠标点击状态
private clickFlag = false;
// 鼠标拖动状态
private dragFlag = false;
// 单击截取屏启用状态
private clickCutFullScreen = false;
// 全屏截取状态
private getFullScreenStatus = false;
// 上一个裁剪框坐标信息
private drawGraphPrevX = 0;
private drawGraphPrevY = 0;
// 当前点击的工具栏条目
private toolName = "";
private fontSize = 17;
// 撤销点击次数
private undoClickNum = 0;
// 最大可撤销次数
private maxUndoNum = 15;
// 马赛克涂抹区域大小
private degreeOfBlur = 5;
private history: Array<Record<string, any>> = [];
// 文本输入框位置
private textInputPosition: { mouseX: number; mouseY: number } = {
mouseX: 0,
mouseY: 0
};
constructor(props: Record<string, any>, context: SetupContext<any>) {
// 实例化响应式data
this.data = new InitData();
// 获取截图区域canvas容器
this.screenShortController = this.data.getScreenShortController();
this.toolController = this.data.getToolController();
this.textInputController = this.data.getTextInputController();
this.optionController = this.data.getOptionController();
this.optionIcoController = this.data.getOptionIcoController();
this.videoController = document.createElement("video");
this.videoController.autoplay = true;
this.screenShortImageController = document.createElement("canvas");
// 设置实例与属性
this.data.setPropsData(context.emit);
onMounted(() => {
this.emit = this.data.getEmit();
const plugInParameters = new PlugInParameters();
// 单击截屏启用状态
this.clickCutFullScreen = plugInParameters.getClickCutFullScreenStatus();
// 设置需要隐藏的工具栏图标
this.data.setHiddenToolIco(plugInParameters.getHiddenToolIco());
// 设置截图区域canvas宽高
this.data.setScreenShortInfo(window.innerWidth, window.innerHeight);
if (this.screenShortImageController == null) return;
// 设置截图图片存放容器宽高
this.screenShortImageController.width = window.innerWidth;
this.screenShortImageController.height = window.innerHeight;
if (plugInParameters.getWebRtcStatus()) {
// 设置为屏幕宽高
this.data.setScreenShortInfo(window.screen.width, window.screen.height);
// 设置为屏幕宽高
this.screenShortImageController.width = window.screen.width;
this.screenShortImageController.height = window.screen.height;
}
// 获取截图区域画canvas容器画布
const context = this.screenShortController.value?.getContext("2d");
if (context == null) return;
if (!plugInParameters.getWebRtcStatus()) {
console.log("####################### test patch package 截屏 #######################");
console.log("####################### html2canvas截屏 #######################")
// html2canvas截屏
html2canvas(document.body, {useCORS: true, allowTaint: true}).then(canvas => {
// 装载截图的dom为null则退出
if (this.screenShortController.value == null) return;
// 调整截屏容器层级
this.screenShortController.value.style.zIndex =
plugInParameters.getLevel() + "";
// 调整截图工具栏层级
if (this.toolController.value == null) return;
this.toolController.value.style.zIndex = `${plugInParameters.getLevel() +
1}`;
// 存放html2canvas截取的内容
this.screenShortImageController = canvas;
// 存储屏幕截图
this.data.setScreenShortImageController(canvas);
// 赋值截图区域canvas画布
this.screenShortCanvas = context;
// 绘制蒙层
drawMasking(context);
// 添加监听
this.screenShortController.value?.addEventListener(
"mousedown",
this.mouseDownEvent
);
this.screenShortController.value?.addEventListener(
"mousemove",
this.mouseMoveEvent
);
this.screenShortController.value?.addEventListener(
"mouseup",
this.mouseUpEvent
);
});
return;
}
// 开始捕捉屏幕
this.startCapture().then(() => {
setTimeout(() => {
// 装载截图的dom为null则退出
if (this.screenShortController.value == null) return;
if (this.screenShortImageController == null) return;
const imageContext = this.screenShortImageController.getContext("2d");
if (imageContext == null) return;
// 将获取到的屏幕截图绘制到图片容器里
imageContext.drawImage(
this.videoController,
0,
0,
this.screenShortImageController.width,
this.screenShortImageController.height
);
// 存储屏幕截图
this.data.setScreenShortImageController(
this.screenShortImageController
);
// 赋值截图区域canvas画布
this.screenShortCanvas = context;
// 绘制蒙层
drawMasking(context);
// 添加监听
this.screenShortController.value?.addEventListener(
"mousedown",
this.mouseDownEvent
);
this.screenShortController.value?.addEventListener(
"mousemove",
this.mouseMoveEvent
);
this.screenShortController.value?.addEventListener(
"mouseup",
this.mouseUpEvent
);
// 停止捕捉屏幕
this.stopCapture();
// 调整截屏容器层级
this.screenShortController.value.style.zIndex =
plugInParameters.getLevel() + "";
// 调整截图工具栏层级
if (this.toolController.value == null) return;
this.toolController.value.style.zIndex = `${plugInParameters.getLevel() +
1}`;
}, 500);
});
});
onUnmounted(() => {
// 初始化initData中的数据
this.data.setInitStatus(true);
});
}
// 开始捕捉屏幕
private startCapture = async () => {
let captureStream = null;
try {
// eslint-disable-next-line @typescript-eslint/ban-ts-ignore
// @ts-ignore
// 捕获屏幕
captureStream = await navigator.mediaDevices.getDisplayMedia();
// 将MediaStream输出至video标签
this.videoController.srcObject = captureStream;
} catch (err) {
// 销毁组件
this.resetComponent();
throw "浏览器不支持webrtc或者用户未授权, 浏览器名称" +
adapter.browserDetails.browser +
",浏览器版本号" +
adapter.browserDetails.version +
err;
}
return captureStream;
};
// 停止捕捉屏幕
private stopCapture = () => {
const srcObject = this.videoController.srcObject;
if (srcObject && "getTracks" in srcObject) {
const tracks = srcObject.getTracks();
tracks.forEach(track => track.stop());
this.videoController.srcObject = null;
}
};
// 鼠标按下事件
private mouseDownEvent = (event: MouseEvent) => {
// 当前操作的是撤销
if (this.toolName == "undo") return;
this.dragging = true;
this.clickFlag = true;
const mouseX = nonNegativeData(event.offsetX);
const mouseY = nonNegativeData(event.offsetY);
// 如果当前操作的是截图工具栏
if (this.data.getToolClickStatus().value) {
// 记录当前鼠标开始坐标
this.drawGraphPosition.startX = mouseX;
this.drawGraphPosition.startY = mouseY;
}
// 当前操作的是画笔
if (this.toolName == "brush" && this.screenShortCanvas) {
// 初始化画笔
initPencil(this.screenShortCanvas, mouseX, mouseY);
}
// 当前操作的文本
if (
this.toolName == "text" &&
this.textInputController?.value &&
this.screenShortController?.value &&
this.screenShortCanvas
) {
// 修改鼠标样式
this.screenShortController.value.style.cursor = "text";
// 显示文本输入区域
this.data.setTextStatus(true);
// 判断输入框位置是否变化
if (
this.textInputPosition.mouseX != 0 &&
this.textInputPosition.mouseY != 0 &&
this.textInputPosition.mouseX != mouseX &&
this.textInputPosition.mouseY != mouseY
) {
drawText(
this.textInputController.value?.innerText,
this.textInputPosition.mouseX,
this.textInputPosition.mouseY,
this.data.getSelectedColor().value,
this.fontSize,
this.screenShortCanvas
);
// 清空文本输入区域的内容
this.textInputController.value.innerHTML = "";
// 保存绘制记录
this.addHistory();
}
// 计算文本框显示位置
const textMouseX = mouseX - 15;
const textMouseY = mouseY - 15;
// 修改文本区域位置
this.textInputController.value.style.left = textMouseX + "px";
this.textInputController.value.style.top = textMouseY + "px";
setTimeout(() => {
// 获取焦点
if (this.textInputController?.value) {
this.textInputController.value.focus();
// 记录当前输入框位置
this.textInputPosition = { mouseX: mouseX, mouseY: mouseY };
}
});
}
// 如果操作的是裁剪框
if (this.borderOption) {
// 设置为拖动状态
this.draggingTrim = true;
// 记录移动时的起始点坐标
this.movePosition.moveStartX = mouseX;
this.movePosition.moveStartY = mouseY;
} else {
// 保存当前裁剪框的坐标
this.drawGraphPrevX = this.drawGraphPosition.startX;
this.drawGraphPrevY = this.drawGraphPosition.startY;
// 绘制裁剪框,记录当前鼠标开始坐标
this.drawGraphPosition.startX = mouseX;
this.drawGraphPosition.startY = mouseY;
}
};
// 鼠标移动事件
private mouseMoveEvent = (event: MouseEvent) => {
if (
this.screenShortCanvas == null ||
this.screenShortController.value == null ||
this.toolName == "undo"
) {
return;
}
// 工具栏未选择且鼠标处于按下状态时
if (!this.data.getToolClickStatus().value && this.dragging) {
// 修改拖动状态为true;
this.dragFlag = true;
// 隐藏截图工具栏
this.data.setToolStatus(false);
}
this.clickFlag = false;
// 获取当前绘制中的工具位置信息
const { startX, startY, width, height } = this.drawGraphPosition;
// 获取当前鼠标坐标
const currentX = nonNegativeData(event.offsetX);
const currentY = nonNegativeData(event.offsetY);
// 绘制中工具的临时宽高
const tempWidth = currentX - startX;
const tempHeight = currentY - startY;
// 工具栏绘制
if (this.data.getToolClickStatus().value && this.dragging) {
// 获取裁剪框位置信息
const cutBoxPosition = this.data.getCutOutBoxPosition();
// 绘制中工具的起始x、y坐标不能小于裁剪框的起始坐标
// 绘制中工具的起始x、y坐标不能大于裁剪框的结束标作
// 当前鼠标的x坐标不能小于裁剪框起始x坐标,不能大于裁剪框的结束坐标
// 当前鼠标的y坐标不能小于裁剪框起始y坐标,不能大于裁剪框的结束坐标
if (
!getDrawBoundaryStatus(startX, startY, cutBoxPosition) ||
!getDrawBoundaryStatus(currentX, currentY, cutBoxPosition)
)
return;
// 当前操作的不是马赛克则显示最后一次画布绘制时的状态
if (this.toolName != "mosaicPen") {
this.showLastHistory();
}
switch (this.toolName) {
case "square":
drawRectangle(
startX,
startY,
tempWidth,
tempHeight,
this.data.getSelectedColor().value,
this.data.getPenSize().value,
this.screenShortCanvas,
this.screenShortController.value as HTMLCanvasElement,
this.screenShortImageController as HTMLCanvasElement
);
break;
case "round":
drawCircle(
this.screenShortCanvas,
currentX,
currentY,
startX,
startY,
this.data.getPenSize().value,
this.data.getSelectedColor().value
);
break;
case "right-top":
drawLineArrow(
this.screenShortCanvas,
startX,
startY,
currentX,
currentY,
30,
10,
this.data.getPenSize().value,
this.data.getSelectedColor().value
);
break;
case "brush":
// 画笔绘制
drawPencil(
this.screenShortCanvas,
currentX,
currentY,
this.data.getPenSize().value,
this.data.getSelectedColor().value
);
break;
case "mosaicPen":
// 绘制马赛克,为了确保鼠标位置在绘制区域中间,所以对x、y坐标进行-10处理
drawMosaic(
currentX - 10,
currentY - 10,
this.data.getPenSize().value,
this.degreeOfBlur,
this.screenShortCanvas
);
break;
default:
break;
}
return;
}
// 执行裁剪框操作函数
this.operatingCutOutBox(
currentX,
currentY,
startX,
startY,
width,
height,
this.screenShortCanvas
);
// 如果鼠标未点击或者当前操作的是裁剪框都return
if (!this.dragging || this.draggingTrim) return;
// 绘制裁剪框
this.tempGraphPosition = drawCutOutBox(
startX,
startY,
tempWidth,
tempHeight,
this.screenShortCanvas,
this.borderSize,
this.screenShortController.value as HTMLCanvasElement,
this.screenShortImageController as HTMLCanvasElement
) as drawCutOutBoxReturnType;
};
// 鼠标抬起事件
private mouseUpEvent = () => {
// 当前操作的是撤销
if (this.toolName == "undo") return;
// 绘制结束
this.dragging = false;
this.draggingTrim = false;
if (
this.screenShortController.value == null ||
this.screenShortCanvas == null ||
this.screenShortImageController == null
) {
return;
}
// 工具栏未点击且鼠标未拖动且单击截屏状态为false则复原裁剪框位置
if (
!this.data.getToolClickStatus().value &&
!this.dragFlag &&
!this.clickCutFullScreen
) {
// 复原裁剪框的坐标
this.drawGraphPosition.startX = this.drawGraphPrevX;
this.drawGraphPosition.startY = this.drawGraphPrevY;
return;
}
// 调用者尚未拖拽生成选区
// 鼠标尚未拖动
// 单击截取屏幕状态为true
// 则截取整个屏幕
const cutBoxPosition = this.data.getCutOutBoxPosition();
if (
cutBoxPosition.width === 0 &&
cutBoxPosition.height === 0 &&
cutBoxPosition.startX === 0 &&
cutBoxPosition.startY === 0 &&
!this.dragFlag &&
this.clickCutFullScreen
) {
this.getFullScreenStatus = true;
// 设置裁剪框位置为全屏
this.tempGraphPosition = drawCutOutBox(
0,
0,
this.screenShortController.value.width - this.borderSize / 2,
this.screenShortController.value.height - this.borderSize / 2,
this.screenShortCanvas,
this.borderSize,
this.screenShortController.value,
this.screenShortImageController
) as drawCutOutBoxReturnType;
}
if (this.data.getToolClickStatus().value) {
// 保存绘制记录
this.addHistory();
return;
}
// 保存绘制后的图形位置信息
this.drawGraphPosition = this.tempGraphPosition;
// 如果工具栏未点击则保存裁剪框位置
if (!this.data.getToolClickStatus().value) {
const { startX, startY, width, height } = this.drawGraphPosition;
this.data.setCutOutBoxPosition(startX, startY, width, height);
}
// 保存边框节点信息
this.cutOutBoxBorderArr = saveBorderArrInfo(
this.borderSize,
this.drawGraphPosition
);
if (this.screenShortController.value != null) {
// 修改鼠标状态为拖动
this.screenShortController.value.style.cursor = "move";
// 复原拖动状态
this.dragFlag = false;
// 显示截图工具栏
this.data.setToolStatus(true);
nextTick().then(() => {
if (this.toolController.value != null) {
// 计算截图工具栏位置
const toolLocation = calculateToolLocation(
this.drawGraphPosition,
this.toolController.value?.offsetWidth
);
// 当前截取的是全屏,则修改工具栏的位置到截图容器最底部,防止超出
if (this.getFullScreenStatus) {
toolLocation.mouseY -= 64;
}
// 设置截图工具栏位置
this.data.setToolInfo(toolLocation.mouseX, toolLocation.mouseY);
// 状态重置
this.getFullScreenStatus = false;
}
});
}
};
/**
* 操作裁剪框
* @param currentX 裁剪框当前x轴坐标
* @param currentY 裁剪框当前y轴坐标
* @param startX 鼠标x轴坐标
* @param startY 鼠标y轴坐标
* @param width 裁剪框宽度
* @param height 裁剪框高度
* @param context 需要进行绘制的canvas画布
* @private
*/
private operatingCutOutBox(
currentX: number,
currentY: number,
startX: number,
startY: number,
width: number,
height: number,
context: CanvasRenderingContext2D
) {
// canvas元素不存在
if (this.screenShortController.value == null) {
return;
}
// 获取鼠标按下时的坐标
const { moveStartX, moveStartY } = this.movePosition;
// 裁剪框边框节点事件存在且裁剪框未进行操作,则对鼠标样式进行修改
if (this.cutOutBoxBorderArr.length > 0 && !this.draggingTrim) {
// 标识鼠标是否在裁剪框内
let flag = false;
// 判断鼠标位置
context.beginPath();
for (let i = 0; i < this.cutOutBoxBorderArr.length; i++) {
context.rect(
this.cutOutBoxBorderArr[i].x,
this.cutOutBoxBorderArr[i].y,
this.cutOutBoxBorderArr[i].width,
this.cutOutBoxBorderArr[i].height
);
// 当前坐标点处于8个可操作点上,修改鼠标指针样式
if (context.isPointInPath(currentX, currentY)) {
switch (this.cutOutBoxBorderArr[i].index) {
case 1:
if (this.data.getToolClickStatus().value) {
this.screenShortController.value.style.cursor = "crosshair";
} else {
this.screenShortController.value.style.cursor = "move";
}
break;
case 2:
// 工具栏被点击则不改变指针样式
if (this.data.getToolClickStatus().value) break;
this.screenShortController.value.style.cursor = "ns-resize";
break;
case 3:
// 工具栏被点击则不改变指针样式
if (this.data.getToolClickStatus().value) break;
this.screenShortController.value.style.cursor = "ew-resize";
break;
case 4:
// 工具栏被点击则不改变指针样式
if (this.data.getToolClickStatus().value) break;
this.screenShortController.value.style.cursor = "nwse-resize";
break;
case 5:
// 工具栏被点击则不改变指针样式
if (this.data.getToolClickStatus().value) break;
this.screenShortController.value.style.cursor = "nesw-resize";
break;
default:
break;
}
this.borderOption = this.cutOutBoxBorderArr[i].option;
flag = true;
break;
}
}
context.closePath();
if (!flag) {
// 鼠标移出裁剪框重置鼠标样式
this.screenShortController.value.style.cursor = "default";
// 重置当前操作的边框节点为null
this.borderOption = null;
}
}
// 裁剪框正在被操作
if (this.draggingTrim) {
// 当前操作节点为1时则为移动裁剪框
if (this.borderOption === 1) {
// 计算要移动的x轴坐标
const x = fixedData(
currentX - (moveStartX - startX),
width,
this.screenShortController.value.width
);
// 计算要移动的y轴坐标
const y = fixedData(
currentY - (moveStartY - startY),
height,
this.screenShortController.value.height
);
// 重新绘制裁剪框
this.tempGraphPosition = drawCutOutBox(
x,
y,
width,
height,
context,
this.borderSize,
this.screenShortController.value as HTMLCanvasElement,
this.screenShortImageController as HTMLCanvasElement
) as drawCutOutBoxReturnType;
} else {
// 裁剪框其他8个点的拖拽事件
const {
tempStartX,
tempStartY,
tempWidth,
tempHeight
} = zoomCutOutBoxPosition(
currentX,
currentY,
startX,
startY,
width,
height,
this.borderOption as number
) as zoomCutOutBoxReturnType;
// 绘制裁剪框
this.tempGraphPosition = drawCutOutBox(
tempStartX,
tempStartY,
tempWidth,
tempHeight,
context,
this.borderSize,
this.screenShortController.value as HTMLCanvasElement,
this.screenShortImageController as HTMLCanvasElement
) as drawCutOutBoxReturnType;
}
}
}
/**
* 裁剪框工具栏点击事件
* @param toolName
* @param index
* @param mouseEvent
*/
public toolClickEvent = (
toolName: string,
index: number,
mouseEvent: MouseEvent
) => {
// 更新当前点击的工具栏条目
this.toolName = toolName;
const screenShortController = this.data.getScreenShortController();
const ScreenShortImageController = this.data.getScreenShortImageController();
if (
screenShortController.value == null ||
ScreenShortImageController == null
)
return;
// 获取canvas容器
const screenShortCanvas = screenShortController.value.getContext(
"2d"
) as CanvasRenderingContext2D;
// 工具栏尚未点击,当前属于首次点击,重新绘制一个无像素点的裁剪框
if (!this.data.getToolClickStatus().value) {
// 获取裁剪框位置信息
const cutBoxPosition = this.data.getCutOutBoxPosition();
// 开始绘制无像素点裁剪框
drawCutOutBox(
cutBoxPosition.startX,
cutBoxPosition.startY,
cutBoxPosition.width,
cutBoxPosition.height,
screenShortCanvas,
this.borderSize,
screenShortController.value,
ScreenShortImageController,
false
);
}
this.data.setToolName(toolName);
// 为当前点击项添加选中时的class名
setSelectedClassName(mouseEvent, index, false);
if (toolName != "text") {
// 显示画笔选择工具栏
this.data.setOptionStatus(true);
// 设置画笔选择工具栏三角形角标位置
this.data.setOptionIcoPosition(calculateOptionIcoPosition(index));
} else {
// 隐藏画笔工具栏
this.data.setOptionStatus(false);
}
// 清空文本输入区域的内容并隐藏文本输入框
if (this.textInputController?.value != null && this.data.getTextStatus()) {
this.textInputController.value.innerHTML = "";
this.data.setTextStatus(false);
}
// 初始化点击状态
this.dragging = false;
this.draggingTrim = false;
// 保存图片
if (toolName == "save") {
this.getCanvasImgData(true);
}
// 销毁组件
if (toolName == "close") {
this.resetComponent();
}
// 确认截图
if (toolName == "confirm" && this.screenShortCanvas && this.emit) {
const base64 = this.getCanvasImgData(false);
this.emit("get-image-data", base64);
}
// 撤销
if (toolName == "undo") {
// 隐藏画笔选项工具栏
this.data.setOptionStatus(false);
this.takeOutHistory();
}
// 设置裁剪框工具栏为点击状态
this.data.setToolClickStatus(true);
};
/**
* 保存当前画布状态
* @private
*/
private addHistory() {
if (
this.screenShortCanvas != null &&
this.screenShortController.value != null
) {
// 获取canvas画布与容器
const context = this.screenShortCanvas;
const controller = this.screenShortController.value;
if (this.history.length > this.maxUndoNum) {
// 删除最早的一条画布记录
this.history.shift();
}
// 保存当前画布状态
this.history.push({
data: context.getImageData(0, 0, controller.width, controller.height)
});
// 启用撤销按钮
this.data.setUndoStatus(true);
}
}
/**
* 显示最新的画布状态
* @private
*/
private showLastHistory() {
if (this.screenShortCanvas != null) {
const context = this.screenShortCanvas;
if (this.history.length <= 0) {
this.addHistory();
}
context.putImageData(this.history[this.history.length - 1]["data"], 0, 0);
}
}
/**
* 取出一条历史记录
*/
private takeOutHistory() {
const lastImageData = this.history.pop();
if (this.screenShortCanvas != null && lastImageData) {
const context = this.screenShortCanvas;
if (this.undoClickNum == 0 && this.history.length > 0) {
// 首次取出需要取两条历史记录
const firstPopImageData = this.history.pop() as Record<string, any>;
context.putImageData(firstPopImageData["data"], 0, 0);
} else {
context.putImageData(lastImageData["data"], 0, 0);
}
}
this.undoClickNum++;
// 历史记录已取完,禁用撤回按钮点击
if (this.history.length <= 0) {
this.undoClickNum = 0;
this.data.setUndoStatus(false);
}
}
/**
* 重置组件
*/
private resetComponent = () => {
if (this.emit) {
// 隐藏截图工具栏
this.data.setToolStatus(false);
// 初始化响应式变量
this.data.setInitStatus(true);
// 销毁组件
this.emit("destroy-component", false);
return;
}
throw "组件重置失败";
};
/**
* 将指定区域的canvas转为图片
* @private
*/
private getCanvasImgData = (isSave: boolean) => {
// 获取裁剪区域位置信息
const { startX, startY, width, height } = this.data.getCutOutBoxPosition();
let base64 = "";
// 保存图片,需要减去八个点的大小
if (this.screenShortCanvas) {
if (isSave) {
// 将canvas转为图片
saveCanvasToImage(
this.screenShortCanvas,
startX,
startY,
width,
height
);
} else {
// 将canvas转为base64
base64 = saveCanvasToBase64(
this.screenShortCanvas,
startX,
startY,
width,
height
);
}
}
// 重置组件
this.resetComponent();
return base64;
};
}