<template>
<div class="box">
<el-scrollbar style="height: 100%;">
<canvas id="canvas"></canvas>
<div class="right" v-if="!editStatus">
<div
@click="selectType('painting')"
class="item"
:class="type == 'painting' ? 'selectItem' : ''"
>
<img :src="require('../../assets/images/k.png')" alt="" />
<div>选 框</div>
</div>
<div
@click="selectType('text')"
class="item"
:class="type == 'text' ? 'selectItem' : ''"
>
<img :src="require('../../assets/images/z.png')" alt="" />
<div>标 注</div>
</div>
<div class="item" @click="deleteSelect">
<img :src="require('../../assets/images/empty_fill.png')" alt="" />
<div>删 除</div>
</div>
<div class="item" @click="preservation">
<img :src="require('../../assets/images/preservation.png')" alt="" />
<div>保 存</div>
</div>
<div class="item" @click="signOut">
<img :src="require('../../assets/images/cl.png')" alt="" />
<div>退 出</div>
</div>
</div>
<img id="imgNode" :src="newImgString" style="display: none;" />
</el-scrollbar>
</div>
</template>
<script>
import { fabric } from "fabric";
export default {
props: ["imgString"],
data() {
return {
newImgString: "",
type: "", //选中绘画类型
editStatus: false, //true可编辑 false不可编辑
canvas: null, //舞台对象
textObj: null, //文本对象
mouseFrom: {}, //当前鼠标或手指触摸的位置
mouseTo: {}, //当前鼠标离开或手指触摸离开的位置
selectObj: null, //选中组件对象
drawingObject: null, //画图对象
imgInstance: null
};
},
created() {
this.newImgString = this.imgString;
},
watch: {
imgString(n, o) {
this.newImgString = n;
}
},
mounted() {
const imgElement = document.getElementById("imgNode");
imgElement.onload = res => {
console.log("图片信息", imgElement.width, imgElement.height);
//创建舞台
this.canvas = new fabric.Canvas("canvas", {
// isDrawingMode: false,
// skipTargetFind: false,
// selectable: false,
selection: false,
width: window.innerWidth > 768 ? 768 : window.innerWidth,
height:
window.innerWidth > 768
? 768 / (imgElement.width / imgElement.height)
: window.innerWidth / (imgElement.width / imgElement.height)
});
const imgInstance = new fabric.Image(imgElement, {
scaleX: this.canvas.width / imgElement.width,
scaleY: this.canvas.width / imgElement.width,
id: "bg",
hasControls: false,
hasBorders: false,
zIndex: 1,
selectable: false, //false 可移动
lockMovementX: true //垂直移动
});
this.imgInstance = imgInstance;
this.canvas.add(imgInstance);
//舞台事件
this.canvas.on("mouse:down", this.canvasMouseDown); //点击
this.canvas.on("mouse:move", this.canvasMouseMove);
this.canvas.on("mouse:up", this.canvasMouseUp); //离开
//this.canvas.on("mouse:wheel", this.canvasMouseWheel); //鼠标滚轮事件
this.canvas.on("selection:created", this.canvasSelectObjIn); //选中对象
this.canvas.on("selection:cleared", this.canvasSelectObjOut); //取消选中
};
// 添加对象后, 如下图
// fabric.Image.fromURL(imgElement.src, img => {
// img.set({
// // 通过scale来设置图片大小,这里设置和画布一样大
// scaleX: this.canvas.width / img.width,
// scaleY: this.canvas.height / img.height
// });
// // 设置背景
// this.canvas.setBackgroundImage(
// img,
// this.canvas.renderAll.bind(this.canvas)
// );
// this.canvas.renderAll();
// });
},
methods: {
signOut() {
this.$emit("out");
},
preservation() {
// console.log(this.canvas.toDataURL(), "=========------------");
let textList = "";
this.canvas.getObjects().filter(res => {
if (res.type == "textbox") {
// console.log(res.text)
textList += res.text + "\n";
}
});
this.$emit("getImgBlob", {
base64String: this.canvas.toDataURL(),
content: textList
});
},
//选择绘画类型
selectType(type) {
console.log("触发选择函数");
if (this.type == type) {
this.type = "";
if (this.textObj) {
this.textObj.exitEditing();
this.textObj = null;
}
} else {
this.type = type;
}
},
//删除选取
deleteSelect() {
this.canvas.remove(this.selectObj);
},
/*------------- 鼠标事件 start ---------------*/
canvasMouseDown(e) {
console.log(e, "鼠标点击");
//点击时开启编辑
//如果当前为选中对象 则不触发鼠标点击事件
if (this.selectObj) {
return;
}
this.editStatus = true; //开启编辑模式
this.mouseFrom = e.pointer;
if (this.textObj) {
this.textObj.exitEditing(); //关闭编辑
this.textObj = null; //清空
return;
}
if (this.type == "text") {
this.drawing();
}
},
//鼠标移动
canvasMouseMove(e) {
console.log(this.editStatus);
this.mouseTo = e.pointer;
//未开启编辑模式 或 处于选中对象时禁止鼠标移动
if (!this.editStatus || this.selectObj) {
return;
}
if (this.type != "text") {
this.drawing();
}
},
//鼠标离开
canvasMouseUp(e) {
console.log("触发鼠标离开", e);
this.mouseTo = e.pointer;
//离开后禁止编辑
this.editStatus = false;
this.drawingObject = null; //清空输入方法
},
//鼠标滚轮
canvasMouseWheel(e) {
if (this.type) {
return;
}
var zoom = (e.e.deltaY > 0 ? 0.1 : -0.1) + this.canvas.getZoom(); //缩放倍数
zoom = Math.max(1, zoom); //最小缩放0.5倍
zoom = Math.min(4, zoom); //最大是原来的3倍
var zoomPoint = new fabric.Point(
this.canvas.width / 2,
this.canvas.height / 2
); //居中缩放
this.canvas.zoomToPoint(zoomPoint, zoom);
// this.canvas.setZoom(zoom)
var vpt = this.canvas.viewportTransform;
console.log(vpt);
},
//组件对象操作
//选中
canvasSelectObjIn(e) {
//点击图像时阻止选中
if (e.target.id == "bg") {
return;
}
console.log(e.target, "对象选中");
this.selectObj = e.target; //存选中对象
// if (e.target.type == "textbox") {
// this.selectObj.enterEditing();
// }
if (this.textObj) {
this.textObj.exitEditing(); //关闭编辑
this.textObj = null; //清空
}
},
//取消选中
canvasSelectObjOut(e) {
console.log(e, "取消选中");
if (this.selectObj.type == "textbox") {
this.selectObj.exitEditing();
}
this.selectObj = null; //清空选中对象
},
/*------------- 鼠标事件 end------------------*/
//绘画函数
drawing() {
if (this.drawingObject) {
this.canvas.remove(this.drawingObject);
}
switch (this.type) {
case "text":
//添加一个 text 输入框
this.textObj = new fabric.Textbox("", {
left: this.mouseFrom.x,
top: this.mouseFrom.y,
fontSize: 18,
borderColor: "#FF0000",
fill: "#FF0000",
hasBorders: true
});
this.canvas.add(this.textObj);
//设置当前输入框为可编辑模式
this.textObj.enterEditing();
break;
case "painting":
let mouseFrom = this.mouseFrom;
let mouseTo = this.mouseTo;
var path =
"M " +
mouseFrom.x +
" " +
mouseFrom.y +
" L " +
mouseTo.x +
" " +
mouseFrom.y +
" L " +
mouseTo.x +
" " +
mouseTo.y +
" L " +
mouseFrom.x +
" " +
mouseTo.y +
" L " +
mouseFrom.x +
" " +
mouseFrom.y +
" z";
let canvasObject = new fabric.Path(path, {
left: this.mouseFrom.x,
top: this.mouseFrom.y,
stroke: "#FF0000",
strokeWidth: 3,
fill: "rgba(255, 255, 255, 0)",
hasControls: true,
zIndex: 1
});
this.canvas.add(canvasObject);
this.drawingObject = canvasObject;
console.log("画图开启");
break;
}
}
}
};
</script>
<style lang="scss" scoped>
.box {
position: relative;
height: 100vh;
overflow: hidden;
overflow-y: hidden;
display: flex;
justify-content: center;
align-content: center;
}
.right {
position: absolute;
width: 70px;
top: 30%;
right: 20px;
// transform: translate(-50%, -50%);
padding: 6px 0;
border-radius: 4px;
background: #ffffff;
box-shadow: 0px 0px 9px #d8d8d8;
display: flex;
flex-direction: column;
align-items: center;
}
.right .item {
display: flex;
flex-direction: column;
align-items: center;
margin-top: 10px;
font-size: 12px;
padding: 5px 0;
width: 50px;
}
.right .item:first-child {
margin-top: 0;
}
.selectItem {
background: #d2d2d2;
border-radius: 4px;
}
.right .item > img {
width: 30px;
height: 30px;
margin: 5px 0 4px;
}
</style>
这是代码,目前未完成的操作有缩放与平移,请各位麻烦告诉我一下 该怎么实现缩放 平移并不会超出界限?
我参考例子 http://fabricjs.com/fabric-intro-part-5 但是缩放时 会闪屏不知什么原因 而且缩放位置不正确