<template>
<div class="app-container signatures">
<div>
<div class="opt_btn" style="margin-bottom: 10px;">
<el-button class="btn-outline-dark" @click="prevPage">上一页</el-button>
<el-button class="btn-outline-dark" @click="nextPage">下一页</el-button>
<el-button class="btn-outline-dark">{{ pageNum }}/{{ numPages }}页</el-button>
<el-input-number style="margin:0 5px;border-radius:5px;" class="btn-outline-dark" v-model="npageNum"
@change="page_change" :min="1" :max="numPages" label="输入页码"></el-input-number>
<el-button class="btn-outline-dark" @click="cutover">跳转</el-button>
</div>
<!-- 展示pdf -->
<canvas id="pdf-canvas" />
<!-- 盖章 -->
<canvas id="Canvas"></canvas>
<i class="el-icon-error" id="deleteBtn" @click="deleteCanvas"></i>
</div>
<div>
<div class="sign_stamp">
<div class="add_sign">添加</div>
<div class="sign_type">
<div :class="sign_type==1?'active_type':''" @click="change_signTyp(1)">手动</div>
<div :class="sign_type==2?'active_type':''" @click="change_signTyp(2)">自动</div>
</div>
<div class="sign_tip" v-if="sign_type==1">请拖动样例章到附件盖章位置,如需盖多次章,拖动多次</div>
<el-input v-if="sign_type==2" v-model="keywords" placeholder="请输入关键字" clearable></el-input>
<div class="sign_part">
<div v-if="sign_type==1">
<draggable :group="{ name: 'itext', pull: 'clone' }" :sort="false" @end="end">
<transition-group type="transition">
<img id="sign_img" :src="mainImagelist" key="sign" width="160px" height="160px"
class="imgstyle" />
</transition-group>
</draggable>
</div>
<img id="sign_img" v-if="sign_type==2" :src="mainImagelist" key="sign" width="160px" height="160px"
class="imgstyle" />
<div class="sign_title">样例章</div>
</div>
<div class="sign_btn">
<div @click="submit_sign">签章预览</div>
<div class="btn2" @click="clear_sign">重新盖章</div>
<div class="btn3" @click="submit_sign">下载盖章版</div>
<div class="btn4" @click="down_pdf">下载原版</div>
</div>
<!-- <FileUpload></FileUpload> -->
</div>
</div>
</div>
</template>
<script>
import {
fabric
} from 'fabric';
let pdfjsLib = require("pdfjs-dist/build/pdf.js");
import workerSrc from "pdfjs-dist/build/pdf.worker.entry";
pdfjsLib.GlobalWorkerOptions.workerSrc = workerSrc;
import draggable from "vuedraggable";
export default {
components: {
draggable
},
data() {
return {
mainImagelist: require('./sign.png'), //电子签章图片
canvas: '', //pdf-canvas
canvasEle: '', //盖章-canvas
pdfUrl: 'http://192.168.5.25:9200/dev-api/profile/changeFile/%E8%A1%A8%E5%8D%95%E5%BB%BA%E8%AE%BE.pdf', //pdf路径
numPages: 1, //pdf总页数
pageNum: 1, //pdf当前页
npageNum: 1, //跳转的页数
sign_type: 1, // 1:手动 2:自动
keywords: '', //关键字
pdfDoc: null,
ctx: null,
pageRendering: false,
whDatas: null,
}
},
mounted() {
localStorage.removeItem('signs'); //清空数据
this.setPdfArea(); //展示pdf文件
},
watch: {
whDatas: {
handler() {
const loading = this.$loading({
lock: true,
text: 'Loading',
spinner: 'el-icon-loading',
background: 'rgba(0, 0, 0, 0.7)'
});
if (this.whDatas) {
loading.close();
this.renderFabric(); //生成绘图区域
// let eleCanvas = document.querySelector("#Canvas");
// eleCanvas.style = "border:1px solid #5ea6ef";
}
}
},
pageNum: function() {
this.commonSign(this.pageNum);
this.queueRenderPage(this.pageNum);
}
},
methods: {
/* 设置pdf区域 */
setPdfArea() {
this.$nextTick(() => {
this.showpdf(this.pdfUrl);
});
},
/* 渲染pdf,到时还会盖章信息,在渲染时,同时显示出来,不应该在切换页码时才显示印章信息 */
showpdf(pdfUrl) {
this.canvas = document.getElementById("pdf-canvas");
this.ctx = this.canvas.getContext("2d");
pdfjsLib.getDocument({
url: pdfUrl,
rangeChunkSize: 65536,
disableAutoFetch: false
}).promise.then((pdfDoc_) => {
this.pdfDoc = pdfDoc_;
this.numPages = this.pdfDoc.numPages;
this.renderPage(this.pageNum).then(() => {
this.renderPdf({
width: this.canvas.width,
height: this.canvas.height,
});
});
});
},
renderPage(num) {
let _this = this;
this.pageRendering = true;
return this.pdfDoc.getPage(num).then((page) => {
var scale = 1;
// 获取pdf尺寸
var viewport = page.getViewport(scale);
_this.canvas.height = viewport.height;
_this.canvas.width = viewport.width;
// Render PDF page into canvas context
let renderContext = {
canvasContext: _this.ctx,
viewport: viewport,
};
let renderTask = page.render(renderContext);
// Wait for rendering to finish
renderTask.promise.then(() => {
_this.pageRendering = false;
if (_this.pageNumPending !== null) {
// New page rendering is pending
this.renderPage(_this.pageNumPending);
_this.pageNumPending = null;
}
});
});
},
/* 翻页 */
queueRenderPage(num) {
this.renderPage(num);
},
/* 翻页展示盖章信息 */
commonSign(pageNum, isFirst = false) {
if (isFirst == false) this.canvasEle.remove(this.canvasEle.clear()); //清空页面所有签章
let caches = JSON.parse(localStorage.getItem('signs')); //获取缓存字符串后转换为对象
if (caches == null) return false;
let datas = caches[this.pageNum];
if (datas != null && datas != undefined) {
for (let index in datas) {
this.addSign(datas[index].x, datas[index].y, datas[index].index);
}
}
},
/* 设置绘图区域宽高 */
renderPdf(data) {
this.whDatas = data;
},
/* 生成绘图区域 */
renderFabric() {
let canvaEle = document.querySelector("#Canvas");
canvaEle.width = this.whDatas.width;
canvaEle.height = this.whDatas.height;
this.canvasEle = new fabric.Canvas('Canvas');
this.canvasEvents();
let container = document.querySelector(".canvas-container");
container.style.position = "absolute";
container.style.top = "65px";
},
/* 上一页 */
prevPage() {
this.confirmSignature();
if (this.pageNum <= 1) {
return;
}
this.pageNum--;
this.npageNum = this.pageNum;
},
/* 下一页 */
nextPage() {
this.confirmSignature();
if (this.pageNum >= this.numPages) {
return;
}
this.pageNum++;
this.npageNum = this.pageNum;
},
/* 跳转 */
cutover() {
this.confirmSignature();
},
/* */
page_change(value) {
this.confirmSignature();
this.pageNum = this.npageNum
},
/* 拖拽结束 */
end(e) {
this.addSign(e.originalEvent.layerX - 83, e.originalEvent.layerY - 80, e
.newDraggableIndex)
},
/* 生成电子签章 */
addSign(x, y, index) {
var imgElement = document.getElementById('sign_img');
var imgInstance = new fabric.Image(imgElement, {
left: x,
top: y,
scaleX: 0.5,
scaleY: 0.5,
index: index,
});
imgInstance.set({
borderColor: '#8ABBFF',
cornerSize: 0,
padding: 15,
borderDashArray: [5, 5],
hasRotatingPoint: false,
});
this.canvasEle.add(imgInstance);
},
/* 确认签章位置 */
confirmSignature() {
this.displayBtn(); //隐藏关闭按钮
let data = this.canvasEle.getObjects(); //获取当前页面内的所有签章信息
let result = JSON.parse(localStorage.getItem('signs')); //获取缓存字符串后转换为对象
let signDatas = {}; //存储当前页的所有签章信息
data && data.map((val, index) => {
signDatas[index] = {
x: val.left,
y: val.top,
index: val.index
}
})
if (result == null) {
result = {}
result[this.pageNum] = signDatas;
} else {
result[this.pageNum] = signDatas;
}
console.log(result, '最终结果')
localStorage.setItem('signs', JSON.stringify(result)); //对象转字符串后存储到缓存
},
/* 签章预览 */
submit_sign() {
this.confirmSignature(); //确认签章位置
},
/* 重新盖章 */
clear_sign() {
this.canvasEle.remove(this.canvasEle.clear()); //清空页面所有签章
localStorage.removeItem('signs'); //清除缓存
},
/* 下载原版 */
down_pdf() {
console.log('下载原版')
},
/* 电子签章相关事件 */
canvasEvents() {
var that = this;
var deleteBtn = document.getElementById('deleteBtn');
this.canvasEle.on('selection:created', function(e) {
that.addDeleteBtn(e.selected[0].lineCoords.tr.x, e.selected[0].lineCoords.tr.y);
});
this.canvasEle.on('selection:updated', function(e) {
that.addDeleteBtn(e.selected[0].lineCoords.tr.x, e.selected[0].lineCoords.tr.y);
});
this.canvasEle.on('mouse:down', function(e) {
if (!that.canvasEle.getActiveObject()) {
deleteBtn.style.display = 'none';
}
});
this.canvasEle.on('object:modified', function(e) {
that.addDeleteBtn(e.target.lineCoords.tr.x, e.target.lineCoords.tr.y);
});
this.canvasEle.on('object:scaling', function(e) {
deleteBtn.style.display = 'none';
});
this.canvasEle.on('object:moving', function(e) {
deleteBtn.style.display = 'none';
});
this.canvasEle.on('object:rotating', function(e) {
deleteBtn.style.display = 'none';
});
this.canvasEle.on('mouse:wheel', function(e) {
deleteBtn.style.display = 'none';
})
},
/* 隐藏关闭按钮 */
displayBtn() {
var deleteBtn = document.getElementById('deleteBtn');
deleteBtn.style.display = 'none';
},
/* 电子签章添加删除图标 */
addDeleteBtn(x, y) {
var left = document.getElementsByClassName('opt_btn')[0].offsetLeft;
left = left ? left - 10 : 0
var deleteBtn = document.getElementById('deleteBtn');
deleteBtn.style.display = 'none';
deleteBtn.style.left = x + left + 'px';
deleteBtn.style.top = y + 50 + 'px';
deleteBtn.style.display = 'block';
},
/* 删除签章 */
deleteCanvas() {
var deleteBtn = document.getElementById('deleteBtn');
if (this.canvasEle.getActiveObject()) {
this.canvasEle.remove(this.canvasEle.getActiveObject());
deleteBtn.style.display = 'none';
}
},
/* 签章类型切换 */
change_signTyp(type) {
this.clear_sign()
this.sign_type = type;
this.pageNum = 1;
}
}
}
</script>
<style lang="scss" scoped="scoped">
.signatures {
background-color: #F6F7FA;
display: flex;
justify-content: center;
#Canvas {
border: 1px solid #e6ebf5;
box-shadow: 0 2px 12px 0 rgba(0, 0, 0, 0.1);
}
#deleteBtn {
position: absolute;
top: 0px;
left: 0px;
cursor: pointer;
display: none;
font-size: 30px;
color: #1677FF;
}
/* 签章部分 */
.sign_stamp {
width: 265px;
margin-left: 50px;
.add_sign {
font-size: 21px;
font-family: PingFangSC-Regular, PingFang SC;
font-weight: 400;
color: #000000;
line-height: 29px;
}
.sign_type {
display: flex;
justify-content: center;
align-items: center;
width: 114px;
height: 34px;
background: #DDE2F0;
border-radius: 6px;
border: 0px solid rgba(0, 0, 0, 0.65);
margin: 19px 0 14px;
font-size: 15px;
font-family: PingFangSC-Regular, PingFang SC;
font-weight: 400;
color: rgba(0, 0, 0, 0.65);
line-height: 30px;
div {
width: 55px;
text-align: center;
cursor: pointer;
}
.active_type {
width: 55px;
height: 30px;
background: #FFFFFF;
box-shadow: 0px 1px 2px 0px rgba(0, 0, 0, 0.03), 0px 1px 6px -1px rgba(0, 0, 0, 0.02), 0px 2px 5px 0px rgba(0, 0, 0, 0.02);
border-radius: 4px;
border: 0px solid rgba(0, 0, 0, 0.88);
}
}
.sign_tip {
font-size: 15px;
font-family: PingFangSC-Regular, PingFang SC;
font-weight: 400;
color: rgba(0, 0, 0, 0.5);
line-height: 21px;
}
.sign_part {
width: 215px;
height: 215px;
background: #FFFFFF;
display: flex;
align-items: center;
flex-direction: column;
margin: 30px 0 40px;
img {
width: 164px;
height: 164px;
margin: 13px auto 0;
}
.sign_title {
font-size: 15px;
font-family: PingFangSC-Regular, PingFang SC;
font-weight: 400;
color: #000000;
line-height: 21px;
padding: 5px 0 7px;
}
}
.sign_btn {
display: flex;
flex-wrap: wrap;
div {
width: 122px;
height: 42px;
background: #22B35E;
border-radius: 6px;
font-size: 17px;
font-family: PingFangSC-Regular, PingFang SC;
font-weight: 400;
color: #FFFFFF;
line-height: 42px;
text-align: center;
margin: 0 20px 20px 0;
cursor: pointer;
}
div:nth-child(2n) {
margin-right: 0;
}
.btn2 {
background: #FF9F18;
}
.btn3 {
background: #1677FF;
}
.btn4 {
background: #FFFFFF;
border: 2px solid #1677FF;
color: #1677FF;
line-height: 38px;
}
}
}
.sortable-ghost {
background: transparent !important;
}
::v-deep .sign_stamp .el-input--medium .el-input__inner {
width: 264px;
height: 33px !important;
line-height: 33px !important;
}
/* 签章部分 */
}
</style>
Canvas和fabric电子签章盖章
最新推荐文章于 2024-05-24 13:39:19 发布