<template>
<el-form ref="form" :rules="rules" :model="form" label-width="80px" >
<el-row>
<el-col :span="10" :offset="1">
<el-form-item label="证书" prop="certificateUrl">
<el-upload
:disabled="disabled"
class="avatar-uploader"
action="#"
:show-file-list="false"
:on-change="handleAvatarChange"
:on-success="handleAvatarSuccess"
:before-upload="beforeAvatarUpload"
:with-credentials="true"
>
<img v-if="form.certificateUrl" :src="form.certificateUrl" class="avatar">
<i v-else class="el-icon-plus avatar-uploader-icon"></i>
</el-upload>
</el-form-item>
</el-col>
<el-col :span="10" :offset="1">
<el-form-item label="内容" prop="content">
<el-input
type="textarea"
placeholder="请输入内容"
v-model="form.content" resize="none" :disabled="disabled" @blur="contentBlur()"></el-input>
</el-form-item>
</el-col>
</el-row>
<el-row >
<el-col :span="21" :offset="1">
<el-form-item label="" prop="content">
<div ref="divCanvas" class="divCanvas">
<canvas ref="myCanvas" style="background-color: #FFFFFF;" @contextmenu="canvaContextmenu"
@mousedown="canvasClick" @mouseup="stopDragging" @mouseout="stopDragging" @mousemove="dragCircle">
您的浏览器不支持 HTML5 canvas 标签。
</canvas>
<el-menu ref="canvaRightMenu" class="el-menu-hidden" @select="handleRightMenuSelect">
<el-menu-item v-for="item in comboxData" :index="item.code" v-if="item.disabled">
<span slot="title">{{item.name}}</span>
</el-menu-item>
<el-menu-item index="clearAllTag">
<span slot="title">清除所有标签</span>
</el-menu-item>
</el-menu>
</div>
</el-form-item>
</el-col>
</el-row>
</el-form>
</template>
<script>
export default {
name: 'certificateEdit',
data() {
return {
form: {
certificateUrl: "",
content: "姓名________________,________________至________________,在我校人力资源培训中心进修。修完培养计划规定的全部内容,表现良好,准予结业。",
coordinates: []
},
rules: {
certificateUrl: [
{ required: true, message: '请上传图片', trigger: 'blur' }
],
},
comboxData: [{ code: 'name', name:'名称', disabled: true },{ code: 'createTimeStart', name:'开始时间', disabled: true},{ code: 'createTimeEnd', name:'结束时间', disabled: true}],
inParams: {},
disabled: false,
canvasX: 0,
canvasY: 0,
isDragging:false,
previousSelectedCircle:null
}
},
created() {
},
watch:{
'form.certificateUrl':{
handler(newValue,oldValue){
if(newValue)
{
this.initCanvas();
}
},
deep:true
}
},
methods: {
handleAvatarChange(file, fileList) {
//图片改变
this.form.certificateUrl = URL.createObjectURL(file.raw);
},
handleAvatarSuccess(res, file) {
//上传完成
// if(res && res.code==200)
//{
// this.form.certificateUrl = res.result.url;
//}
},
beforeAvatarUpload(file) {
const isJPG = file.type === 'image/jpeg' || file.type === 'image/png' || file.type === 'image/jpg';
const isLt2M = file.size / 1024 / 1024 < 2;
if (!isJPG) {
this.$message.error('上传头像图片只能是 JPG,png 格式!');
}
if (!isLt2M) {
this.$message.error('上传头像图片大小不能超过 2MB!');
}
return isJPG && isLt2M;
},
contentBlur() {
//内容输入完成初始化canvas
this.initCanvas();
},
canvaContextmenu(event) {
//canva右键列表
var event = event || window.event;
this.canvasX = event.offsetX+10;
this.canvasY = event.offsetY+20;
this.$refs.canvaRightMenu.$el.style.display = "block";
this.$refs.canvaRightMenu.$el.style.position = "absolute";
this.$refs.canvaRightMenu.$el.style.border = "solid 1px #dcdfe6";
this.$refs.canvaRightMenu.$el.style.left =event.offsetX + "px";
this.$refs.canvaRightMenu.$el.style.top = event.offsetY+ "px";
event.preventDefault();
},
handleRightMenuSelect(index, indexPath) {
//右键菜单选择标签
if (index === 'clearAllTag') {
this.form.coordinates = [];
} else {
let item = this.form.coordinates.find(t => t.labelCode === index);
if (!item) {
let value = this.comboxData.find(t => t.code === index);
this.form.coordinates.push({
labelCode: value.code,
labelName: value.name,
xaxis: this.canvasX,
yaxis: this.canvasY
});
value.disabled = false;
}
}
this.$refs.canvaRightMenu.$el.style.display = "none";
this.initCanvas();
},
initCanvas() {
//初始化canvas
console.log("initCanvas");
let vue = this;
if(!vue.form.certificateUrl)
{
return;
}
vue.$refs.divCanvas.style.display = "block";
let canvas = vue.$refs.myCanvas;
let ctx = canvas.getContext('2d');
let img = new Image();
img.src = vue.form.certificateUrl;
//图片加载完成添加图片及文字
img.onload = function() {
canvas.width = img.width;
canvas.height = img.height;
let x = 100;//内容X坐标
let y = 400;//内容Y坐标
let lineWidth = canvas.width - 200;//内容长度
let lineHeight = 30;//内容行高
let lineSpace = 20;//内容行间距
let font = "22px 微软雅黑";
//清除canvas
ctx.clearRect(0, 0, canvas.width, canvas.hegiht);
//添加背景
ctx.drawImage(img, 0, 0);
//添加内容
let resultLines = vue.breakLinesForCanvas(ctx, vue.form.content, lineWidth, font);
resultLines.forEach(function(line, index) {
ctx.fillText(line, x, (lineHeight * index + y + lineSpace * index));
});
//添加标签
vue.form.coordinates.forEach(item => {
ctx.fillText('{' + item.labelName + '}', item.xaxis, item.yaxis);
})
}
},
findBreakPoint(text, width, context) {
//寻找切换断点
let min = 0;
let max = text.length - 1;
while (min <= max) {
let middle = Math.floor((min + max) / 2);
let middleWidth = context.measureText(text.substr(0, middle)).width;
let oneCharWiderThanMiddleWidth = context.measureText(text.substr(0, middle + 1)).width;
if (middleWidth <= width && oneCharWiderThanMiddleWidth > width) {
return middle;
}
if (middleWidth < width) {
min = middle + 1;
} else {
max = middle - 1;
}
}
return -1;
},
breakLinesForCanvas(context, text, width, font) {
//内容换行
let result = [];
let breakPoint = 0;
if (font) {
context.font = font;
}
while ((breakPoint = this.findBreakPoint(text, width, context)) !== -1) {
result.push(text.substr(0, breakPoint));
text = text.substr(breakPoint);
}
if (text) {
result.push(text);
}
return result;
},
canvasClick(e) {
let canvas = this.$refs.myCanvas;
// 取得画布上被单击的点
var clickX = e.offsetX - canvas.offsetLeft;
var clickY = e.offsetY - canvas.offsetTop;
this.$refs.canvaRightMenu.$el.style.display = "none";
// 查找被单击的
let datas = this.form.coordinates;
for (var i = 0; i < datas.length; i++) {
var circle = datas[i];
// 判断这个点是否在中
let xz= clickX >= circle.xaxis && clickX <= circle.xaxis + 100;
let yz= clickY >= circle.yaxis-20 && clickY <= circle.yaxis + 5;
if (xz && yz) {
// 清除之前选择的
if (this.previousSelectedCircle != null) this.previousSelectedCircle = null;
this.previousSelectedCircle = circle;
// 使允许拖拽
this.isDragging = true;
//更新显示
this.initCanvas();
//停止搜索
return;
}
}
},
stopDragging() {
this.isDragging = false;
},
dragCircle(e) {
let canvas = this.$refs.myCanvas;
// 判断是否开始拖拽
if (this.isDragging == true) {
// 判断拖拽对象是否存在
if (this.previousSelectedCircle != null) {
// 取得鼠标位置
var x = e.offsetX - canvas.offsetLeft;
var y = e.offsetY - canvas.offsetTop;
// 将移动到鼠标位置
this.previousSelectedCircle.xaxis = x;
this.previousSelectedCircle.yaxis = y;
// 更新画布
this.initCanvas();
}
}
}
}
}
</script>
<style scoped>
.avatar-uploader >>> .el-upload {
border: 1px dashed #d9d9d9;
border-radius: 6px;
cursor: pointer;
position: relative;
overflow: hidden;
border-radius: 0%;
float: left;
}
.avatar-uploader >>> .el-upload:hover {
border-color: #409EFF;
}
.avatar-uploader-icon {
font-size: 28px;
color: #8c939d;
width: 178px;
height: 178px;
line-height: 178px;
text-align: center;
}
.avatar {
width: 178px;
height: 178px;
display: block;
}
.el-textarea >>> .el-textarea__inner{
height: 178px;
}
.el-dialog__wrapper >>> .el-dialog{
width: 1200px;
height: 880px;
}
.divCanvas {
width: 100%;
min-height: 300px;
max-height: 500px;
overflow: auto;
margin-bottom: 10px;
border: solid 1px #f0f2f5;
float: left;
position: relative;
display: none;
}
.el-tree-node {
font-size: 14px;
margin-right: 20px;
}
.el-menu-hidden {display: none;}
</style>
VUE canvas实现右键标签添加及拖动
最新推荐文章于 2024-08-29 15:10:00 发布