你把这个代码原封不动的写出来/* eslint-disable one-var */
/* eslint-disable no-invalid-this */
import {
domUtil
} from '../../utils';
import {
AbstractVerifyWidget
} from '../../providers/abstractWidget';
import basicUtils from '../../utils/basicUtils';
export default class SignatureTrace extends AbstractVerifyWidget {
constructor(options = {}) {
super(options);
this.lastX = 0;
this.lastY = 0;
this.ctx = null;
this.mousePressed = false;
this.signImage = null;
this.resultImg = [];
// 当前签字的索引
this.currentSignIndex = 0;
this.savedSignPicInfo = null;
this.savedSignWhitePicInfo = null;
this.whiteSign = [];
const {
namePicInfo,
signConfig,
signConfirmCallback
} = options;
this.namePicInfo = namePicInfo || [];
this.signConfig = signConfig;
this.signConfirmCallback = signConfirmCallback;
}
draw(x, y, isDown) {
if (isDown) {
this.ctx.beginPath();
// 颜色
this.ctx.strokeStyle = '#000';
// 线宽
this.ctx.lineWidth = this.signConfig?.lineWeight || 10;
this.ctx.lineJoin = 'round';
// 设置画笔最大线宽
this.ctx.lineMax = 20;
// 设置画笔最小线宽
this.ctx.lineMin = 10;
// 设置画笔笔触压力
this.ctx.linePressure = 1.2;
// 设置画笔笔触大小变化的平滑度
this.ctx.smoothness = 30;
// 设置背景底图颜色
const imageData = this.ctx.getImageData(0, 0, this.ctx.canvas.width, this.ctx.canvas.height);
for (let i = 0; i < imageData.data.length; i += 4) {
// 当该像素是透明的,则设置成白色
if (imageData.data[i + 3] === 0) {
imageData.data[i] = 255;
imageData.data[i + 1] = 255;
imageData.data[i + 2] = 255;
imageData.data[i + 3] = 255;
}
}
// this.ctx.putImageData(imageData, 0, 0);
this.ctx.moveTo(this.lastX, this.lastY);
this.ctx.lineTo(x, y);
this.ctx.closePath();
this.ctx.stroke();
}
this.lastX = x;
this.lastY = y;
if (!this.isCanvasBlank(this.canvasEle)) {
this.signatuBreTrauceDetermine.style.opacity = '1';
this.signatureTraceResetting.style.opacity = '1';
}
}
onCanvasTouchStart = (eventTs) => {
// 阻止浏览器默认事件(重要)
if (eventTs.targetTouches.length === 1) {
eventTs.preventDefault();
const touch = eventTs.targetTouches[0];
this.mousePressed = true;
this.draw(
touch.clientX - this.canvasEle.getBoundingClientRect().left,
touch.clientY - this.canvasEle.getBoundingClientRect().top,
false
);
}
}
onCanvasTouchMove = (eventTm) => {
if (eventTm.targetTouches.length === 1) {
// 阻止浏览器默认事件,重要
eventTm.preventDefault();
const touch = eventTm.targetTouches[0];
if (this.mousePressed) {
this.draw(
touch.clientX - this.canvasEle.getBoundingClientRect().left,
touch.clientY - this.canvasEle.getBoundingClientRect().top,
true
);
}
}
}
onCanvasTouchEnd = (evt) => {
if (evt.targetTouches.length === 1) {
// 阻止浏览器默认事件,防止手写的时候拖动屏幕,重要
evt.preventDefault();
this.mousePressed = false;
}
}
onCanvasMouseDown = (eventMd) => {
this.mousePressed = true;
this.draw(
eventMd.clientX - this.canvasEle.getBoundingClientRect().left,
eventMd.clientY - this.canvasEle.getBoundingClientRect().top,
false
);
}
onCanvasMouseMove = (eventMv) => {
if (this.mousePressed) {
this.draw(
eventMv.clientX - this.canvasEle.getBoundingClientRect().left,
eventMv.clientY - this.canvasEle.getBoundingClientRect().top,
true
);
}
}
onCanvasMouseUp = () => {
this.mousePressed = false;
}
getContext() {
return this.canvasEle.getContext('2d');
}
// 设置描红按钮文字
handleSignConfirmButtonText() {
this.signatuBreTrauceDetermine.innerHTML = this.currentSignIndex < this.namePicInfo.length - 1 ? '下一个' : '确定';
}
/**
* @method handleSignConfirm
* @desc 处理签字确认事件
**/
handleSignConfirm = () => {
// 判断签名处是否为空
if (this.isCanvasBlank(this.canvasEle)) {
return;
}
this.signImage = this.canvasEle.toDataURL('image/png');
// 装载当前签字的base64
this.resultImg.push(this.signImage);
// 获取白底图片并放置全局的whiteSign 获取白底的回掉函数是异步的在获取完白底后执行保存
this.transparentToWhiteSign(this.signImage, (whiteSign) => {
this.whiteSign.push(whiteSign);
// 最后一次点确定
if (this.currentSignIndex === this.namePicInfo.length - 1) {
// 保存以前的签名图片
this.savedSignPicInfo = this.getSignFileInfo();
this.savedSignWhitePicInfo = this.getSignWhiteFileInfo();
this.signConfirmCallback(this.savedSignPicInfo, this.savedSignWhitePicInfo);
this.close();
return;
}
// 累计签名索引
this.currentSignIndex++;
// 处理当是最后一个字的时候,按钮文字
this.handleSignConfirmButtonText(this.resultImg, this.namePicInfo);
// 第二次点确定看是否有图片如果有图片战术图片没有就展示文字
this.refreshImage();
});
}
/**
* @method transparentToWhiteSign
* @desc 白底图片转化
**/
transparentToWhiteSign(base64String, callback) {
const img = new Image();
img.onload = function () {
// 创建一个和原图尺寸一样大的Canvas
const canvas = document.createElement('canvas');
canvas.width = this.width;
canvas.height = this.height;
// 绘制白底
this.ctx2 = canvas.getContext('2d');
this.ctx2.fillStyle = '#fff';
this.ctx2.fillRect(0, 0, canvas.width, canvas.height);
// 绘制原图像素
this.ctx2.drawImage(this, 0, 0);
// 导出新的Base64字符串(默认为png格式)
this.newBase64String = canvas.toDataURL('image/png');
// 通过回掉函数获取闭包内的白底图片
callback(this.newBase64String);
};
img.src = base64String;
}
/**
* @method getSignWhiteFileInfo
* @desc 获取格式转化后的白底图片
**/
getSignWhiteFileInfo() {
this.signWhiteFileInfo = {};
if (this.savedSignWhitePicInfo) {
this.namePicInfo.forEach((item, index) => {
this.savedSignWhitePicInfo[item.characterId] = this.whiteSign[index];
});
this.signWhiteFileInfo = this.savedSignWhitePicInfo;
} else {
this.namePicInfo.forEach((item, index) => {
this.signWhiteFileInfo[item.characterId] = this.whiteSign[index];
});
}
return this.signWhiteFileInfo;
}
/**
* @method getSignFileInfo
* @desc 获取格式转化后的图片
**/
getSignFileInfo() {
this.signFileInfo = {};
if (this.savedSignPicInfo) {
this.namePicInfo.forEach((item, index) => {
this.savedSignPicInfo[item.characterId] = this.resultImg[index];
});
this.signFileInfo = this.savedSignPicInfo;
} else {
this.namePicInfo.forEach((item, index) => {
this.signFileInfo[item.characterId] = this.resultImg[index];
});
}
return this.signFileInfo;
}
/**
* @method isCanvasBlank
* @desc 判断签名处是否为空
**/
isCanvasBlank(canvas) {
const blank = document.createElement('canvas');
blank.width = canvas.width;
blank.height = canvas.height;
// 比较值相等则为空
return canvas.toDataURL() === blank.toDataURL();
}
/**
* @method clearSignArea
* @desc 清空签名
**/
clearSignArea = () => {
// 按钮样式修改
this.signatuBreTrauceDetermine.style.opacity = '0.3';
this.signatureTraceResetting.style.opacity = '0.3';
this.ctx.setTransform(1, 0, 0, 1, 0, 0);
this.ctx.clearRect(0, 0, this.ctx.canvas.width, this.ctx.canvas.height);
}
initDOM() {
this.signatureTraceRootElement = domUtil.createElement('div', 'signature-trace-drawer');
// 组件主容器
this.signatureTraceContentElement = domUtil.createElement('div', 'signature-trace-content');
// 内层包装器
const signatureTraceWrapperBodyElement = domUtil.createElement('div', 'signature-trace-wrapper-body');
// 关闭按钮
this.signatureTraceClose = domUtil.createElement('div', 'signature-trace-wrapper-close');
const signatureTraceCloseSpan = document.createElement('span');
signatureTraceCloseSpan.className = 'iconfont svg_ac_LEDClose';
// 标题
this.signatureTraceTitleElement = domUtil.createElement('div', 'signature-trace-title', '请根据展示描写');
// 米图背景颜色
this.imageContainer = domUtil.createElement('div', 'signature-trace-image-container');
// 按钮
const signatureTraceButton = domUtil.createElement('div', 'signature-trace-button');
// 重置
this.signatureTraceResetting = domUtil.createElement('div', 'signature-trace-resetting', '重签');
// 确定按钮
this.signatuBreTrauceDetermine = domUtil.createElement('div', 'signature-trace-determine', '下一个');
// 图片loading
this.signatureTraceSpinningElement = domUtil.createElement('div', 'signature-trace-spinner');
// 模板文字图片
this.signatureTraceTemplateTextImg = domUtil.createElement('img', 'signature-trace-template-img');
// 模板文字
this.signatureTraceTemplateText = domUtil.createElement('div', 'signature-trace-template-text');
// cavans 区域
this.signWrapEle = domUtil.createElement('div', 'ps-sign');
this.canvasEle = domUtil.createElement('canvas', 'canvas');
// 重新加载字段容器
this.signatureTraceReloadContent = domUtil.createElement('div', 'signature-trace-reload-content');
// 重新加载字段
this.signatureTraceReload = domUtil.createElement('div', 'signature-trace-reload', '加载失败,请点击刷新');
// 重新加载 loading
const signatureTraceSpanLoading = document.createElement('span');
signatureTraceSpanLoading.className = 'iconfont svg_nav_Refresh';
// 插入dom
document.body.appendChild(this.signatureTraceRootElement);
this.signatureTraceRootElement.appendChild(this.signatureTraceContentElement);
this.signatureTraceContentElement.appendChild(signatureTraceWrapperBodyElement);
signatureTraceWrapperBodyElement.appendChild(this.signatureTraceClose);
this.signatureTraceClose.appendChild(signatureTraceCloseSpan);
signatureTraceWrapperBodyElement.appendChild(this.signatureTraceTitleElement);
signatureTraceWrapperBodyElement.appendChild(this.imageContainer);
signatureTraceWrapperBodyElement.appendChild(signatureTraceButton);
signatureTraceButton.appendChild(this.signatureTraceResetting);
signatureTraceButton.appendChild(this.signatuBreTrauceDetermine);
this.imageContainer.appendChild(this.signWrapEle);
this.signWrapEle.appendChild(this.canvasEle);
this.imageContainer.appendChild(this.signatureTraceSpinningElement);
this.imageContainer.appendChild(this.signatureTraceTemplateTextImg);
this.imageContainer.appendChild(this.signatureTraceTemplateText);
this.imageContainer.appendChild(this.signatureTraceReloadContent);
this.signatureTraceReloadContent.appendChild(this.signatureTraceReload);
this.signatureTraceReloadContent.appendChild(signatureTraceSpanLoading);
// 遮罩层
this.modalBackdropElement = domUtil.createElement('div', 'signature-trace-backdrop signature-trace-fade');
this.closeRefresh();
}
addEvent() {
// 刷新描红图片
this.signatureTraceReloadContent.addEventListener('click', this.refreshImage.bind(this), false);
// 关闭事件
this.signatureTraceClose.addEventListener('click', () => {
this.clearSignArea();
return this.close();
}, false);
this.signatureTraceResetting.addEventListener('click', this.clearSignArea, false);
this.signatuBreTrauceDetermine.addEventListener('click', this.handleSignConfirm, false);
this.canvasEle.addEventListener('touchstart', this.onCanvasTouchStart, false);
this.canvasEle.addEventListener('touchmove', this.onCanvasTouchMove, false);
this.canvasEle.addEventListener('touchend', this.onCanvasTouchEnd, false);
this.canvasEle.addEventListener('mousedown', this.onCanvasMouseDown, false);
this.canvasEle.addEventListener('mousemove', this.onCanvasMouseMove, false);
this.canvasEle.addEventListener('mouseup', this.onCanvasMouseUp, false);
}
removeEvent() {
// 刷新描红图片
this.signatureTraceReloadContent.removeEventListener('click', this.refreshImage, false);
// 关闭事件
this.signatureTraceClose.removeEventListener('click', () => {
this.clearSignArea();
return this.close();
}
, false);
this.signatureTraceTemplateTextImg.onload = this.imageSuccessfully.bind(this);
this.signatureTraceTemplateTextImg.onerror = this.imageFailed.bind(this);
this.signatureTraceResetting.removeEventListener('click', this.clearSignArea, false);
this.signatuBreTrauceDetermine.removeEventListener('click', this.handleSignConfirm, false);
this.canvasEle.removeEventListener('touchstart', this.onCanvasTouchStart, false);
this.canvasEle.removeEventListener('touchmove', this.onCanvasTouchMove, false);
this.canvasEle.removeEventListener('touchend', this.onCanvasTouchEnd, false);
this.canvasEle.removeEventListener('mousedown', this.onCanvasMouseDown, false);
this.canvasEle.removeEventListener('mousemove', this.onCanvasMouseMove, false);
this.canvasEle.removeEventListener('mouseup', this.onCanvasMouseUp, false);
}
init() {
this.initDOM();
this.addEvent();
this.ctx = this.getContext();
// this.getInitSignature();
super.init();
}
start() {
// 为内容区域的tranform动画打开优化
this.signatureTraceRootElement.style.willChange = 'transform';
// 动态设置canvas宽高
this.canvasEle.width = this.imageContainer.offsetWidth;
this.canvasEle.height = this.imageContainer.offsetHeight;
// 动态设置兜底字体大小
this.signatureTraceTemplateText.style.fontSize = `${this.imageContainer.offsetWidth / 1.2}px`;
super.start();
// 清除默认滑动事件
document.body.style.overflow = 'hidden';
// 刷新第一张图片
this.refreshImage();
}
/**
* @method closeLoading
* @desc 隐藏loading
**/
closeLoading() {
this.signatureTraceSpinningElement.style.display = 'none';
this.signWrapEle.style.display = 'block';
}
/**
* @method openLoading
* @desc 打开loading
**/
openLoading() {
this.signatureTraceSpinningElement.style.display = 'block';
this.signatureTraceTemplateTextImg.style.display = 'none';
this.signatureTraceTemplateText.style.display = 'none';
this.signWrapEle.style.display = 'none';
// 十五秒图片未加载成功则打开刷新关闭loading
this.imgTimeout = setTimeout(() => {
this.closeLoading();
this.signatureTraceTemplateTextImg.src = '';
this.openRefresh();
}, 15000);
}
/**
* @method closeRefresh
* @desc 清空刷新按钮和文字
**/
closeRefresh() {
this.signatureTraceReloadContent.style.display = 'none';
}
/**
* @method openRefresh
* @desc 打开刷新按钮和文字
**/
openRefresh() {
this.signWrapEle.style.display = 'none';
this.signatureTraceReloadContent.style.display = 'flex';
}
/**
* @method imageFailed
* @desc 图片加载失败
**/
imageFailed() {
this.signatureTraceTemplateTextImg.style.display = 'none';
this.signatureTraceSpinningElement.style.display = 'none';
clearTimeout(this.imgTimeout);
this.openRefresh();
}
/**
* @method imageSuccessfully
* @desc 图片加载成功
**/
imageSuccessfully() {
this.signatureTraceTemplateTextImg.style.display = 'block';
clearTimeout(this.imgTimeout);
this.closeLoading();
}
/**
* @method refreshImage
* @desc 图片刷新加载
**/
refreshImage = () => {
console.log(this.resultImg);
console.log(this.namePicInfo);
// 绑定加载成功和失败事件
this.signatureTraceTemplateTextImg.onload = this.imageSuccessfully.bind(this);
this.signatureTraceTemplateTextImg.onerror = this.imageFailed.bind(this);
// 当前需要签署的图片信息
const currentNeedSignPictureInfo = this.namePicInfo[this.currentSignIndex];
const {picUrl: pictureUrl, character, isPoint = '0'} = currentNeedSignPictureInfo;
// 清空签字画布
this.clearSignArea();
// 关闭刷新按钮
this.closeRefresh();
// 使重签按钮恢复 画布恢复 (兼容上一个字是"●"的情况 , 会设置不同的样式和禁用签字区域)
this.signatureTraceResetting.style.display = 'block';
domUtil.removeClass(this.signatuBreTrauceDetermine, 'center-block');
// 恢复顶部提示文案(兼容上一个字是"●"的情况)
this.signatureTraceTitleElement.innerHTML = '请根据展示描写';
// 恢复滑动(兼容上一个字是"●"的情况, 禁用签字区域)
this.canvasEle.style.pointerEvents = 'auto';
// 处理服务端下发的图片
basicUtils.isNotEmpty(pictureUrl) ? this.loadSignImage(pictureUrl) : this.handleNoSignImage(isPoint, character);
}
handleNoSignImage(isPoint, character) {
// 处理未下发图片的情况
this.signatureTraceTemplateText.style.display = 'flex';
this.signatureTraceTemplateText.innerHTML = character;
// 动态设置兜底字体大小
this.signatureTraceTemplateText.style.fontSize = `${this.imageContainer.offsetWidth / 1.2}px`;
// 不显示服务端下发的图片
this.signatureTraceTemplateTextImg.style.display = 'none';
// 不符合 "●" 的情况不做处理
if (isPoint !== '1') {
return;
}
// 使重签按钮消失 画布失效
this.signatureTraceResetting.style.display = 'none';
// 使文字强制不显示
this.signatureTraceTemplateText.innerHTML = '';
this.signatuBreTrauceDetermine.style.opacity = '1';
// 使按钮应用新的样式(直接进行下一个, 它的按钮大小与非 "点"的有所不同)
domUtil.addClass(this.signatuBreTrauceDetermine, 'center-block');
const titleEndPartText = this.currentSignIndex < this.namePicInfo.length - 1 ? '下一个' : '确定';
// 顶部文字变换
this.signatureTraceTitleElement.innerHTML = `无需描写,请直接点击${titleEndPartText}`;
// 无法滑动
this.canvasEle.style.pointerEvents = 'none';
// 绘制原点(这个数据用于展示在最终签好的画板上供用户预览)
setTimeout(() => {
this.ctx2 = this.canvasEle.getContext('2d');
this.ctx2.fillStyle = 'black';
this.ctx2.beginPath();
this.ctx2.arc(this.canvasEle.width / 2, this.canvasEle.height / 2, 24, 0, Math.PI * 2, true);
this.ctx2.fill();
this.ctx2.stroke();
}, 0);
}
loadSignImage(pictureUrl) {
// 不显示通过文字渲染的底图
this.signatureTraceTemplateText.style.display = 'none';
// 启动loading
this.openLoading();
// 降低透明度 来达到视觉效果
this.signatureTraceTemplateTextImg.style.opacity = '0.4';
// 重新写入src , 迫使图片重新加载
this.signatureTraceTemplateTextImg.src = pictureUrl;
}
/**
* @method reSign
* @desc 重签显示组件
**/
reSign(renamePicInfo) {
// renamePicInfo为新改的字段[{character: '吴',characterId: '998E9CC42369F0AAEDE9988F3D6',picUrl: ''},] id必须和以前一致
this.resultImg = [];
this.whiteSign = [];
this.namePicInfo = renamePicInfo;
// 打开dom
this.signatureTraceRootElement.style.display = 'flex';
// 恢复签名索引
this.currentSignIndex = 0;
// 重签只有一个字,修改描红上的按钮为 确定
this.handleSignConfirmButtonText();
// 重置初始化模板字段
this.refreshImage();
}
/**
* @method close
* @desc 关闭组件
**/
close() {
// 移除遮罩层show样式
this.signatureTraceRootElement.style.display = 'none';
this.signWrapEle.style.display = 'block';
this.currentSignIndex = 0;
clearTimeout(this.imgTimeout);
this.closeRefresh();
}
/**
* @method destroy
* @desc 销毁组件
**/
destroy() {
// 清除默认滑动事件
document.body.style.overflow = '';
this.signatureTraceRootElement.remove();
this.removeEvent();
}
}