需求: 摄像头抓拍图片, 在图片上绘制矩形区域, 最后将坐标上传到后台
html:
<canvas
id="canvas"
width="900"
height="600"
style="border: 1px solid #000000"
>
</canvas>
script:
(1)定义变量:
data() {
return {
canvas: null,
downPoint: null,
upPoint: null,
zhuangtai: true,
src: "h111",
position: {},
};
},
(2)初始化画布 + 画布监听事件:
mounted() {
this.canvas = new fabric.Canvas("canvas");
this.canvas.on("mouse:down", this.canvasMouseDown);
this.canvas.on("mouse:up", this.canvasMouseUp);
// this.canvas.on("mouse:move", this.canvasMouseMove);
}
(3)鼠标按下:
// 鼠标按下
canvasMouseDown(e) {
// 鼠标左键按下时,将当前坐标 赋值给 downPoint。{x: xxx, y: xxx} 的格式
this.downPoint = e.absolutePointer;
},
// 鼠标松开
canvasMouseUp(e) {
// console.log(e);
this.upPoint = e.absolutePointer;
if (this.zhuangtai != false) {
// 调用 创建矩形 的方法
canvas.selection = true; // 允许框选
// }
this.createRect();
}
}
这里记一下小坑”absolutePointer”, 本来是使用的Element里面的对话框, 但是将canvas放进对话框中,是拿不到absolutePointer的. 后来将canvas放在页面中,在打印”e”, 是有absolutePointer的.
(4)鼠标松开时创建矩形:
createRect() {
// 矩形参数计算
let top = Math.min(this.downPoint.y, this.upPoint.y);
let left = Math.min(this.downPoint.x, this.upPoint.x);
let width = Math.abs(this.downPoint.x - this.upPoint.x);
let height = Math.abs(this.downPoint.y - this.upPoint.y);
// 矩形对象
const rect = new fabric.Rect({
top,
left,
width,
height,
fill: "transparent", // 填充色:透明
stroke: "#4CEF41", // 边框/笔触颜色
strokeWidrth: 2, // 边框/笔触宽度
hasRotatingPoint: false, // 禁止旋转
borderColor: "#4CEF41", //边框颜色
// editingBorderColor: "red", //编辑框颜色
cornerSize: 10,
transparentCorners: false,
cornerColor: "#4CEF41",
});
// 将矩形添加到画布上
this.canvas.add(rect);
},
(5)给画布设置背景图:
fabric.Image.fromURL(url, (img) => {
img.set({
// 通过scale来设置图片大小,这里设置和画布一样大
scaleX: this.canvas.width / img.width, // 这里也可以写0 - 1
scaleY: this.canvas.height / img.height, // 这里也可以写0 - 1
});
// 设置背景
this.canvas.setBackgroundImage(
img,
this.canvas.renderAll.bind(this.canvas)
);
this.canvas.renderAll();
});
因为我是将获得背景图的url的请求和绘制区域分成了两个页面, 本来准备通过传值的方式到绘制页面, 但我发现跳转过来后,即使拿到了url, 再将其赋值给背景图的url, 也是不能显示的. 最后通过vuex 解决了这个问题.
(6) 禁止绘制的选框 超出画布区域
当然也是需要在松开鼠标的事件中使用
// 鼠标松开
canvasMouseUp(e) {
// console.log(e);
this.upPoint = e.absolutePointer;
if (this.zhuangtai != false) {
// 调用 创建矩形 的方法
canvas.selection = true; // 允许框选
// }
this.createRect();
}
if (this.zhuangtai == false && e.target != null) {
// 获取画布视口边界
let canvasBoundaries = this.canvas.calcViewportBoundaries();
// 矩形本身
let obj = e.target;
// 矩形的边界
let objBoundingRect = obj.getBoundingRect();
// 【公式1】
if (objBoundingRect.left < canvasBoundaries.tl.x) {
e.target.left = canvasBoundaries.tl.x;
}
// console.log(objBoundingRect)
// 【公式2】
if (
objBoundingRect.left + objBoundingRect.width >
canvasBoundaries.br.x
) {
e.target.left = canvasBoundaries.br.x - objBoundingRect.width;
}
// 【公式3】
if (objBoundingRect.top < canvasBoundaries.tl.y) {
e.target.top = canvasBoundaries.tl.y;
}
// 【公式4】
if (
objBoundingRect.top + objBoundingRect.height >
canvasBoundaries.br.y
) {
e.target.top = canvasBoundaries.br.y - objBoundingRect.height;
}
// 刷新画布
this.canvas.renderAll();
this.canvas.skipTargetFind = false;
}
this.canvas.skipTargetFind = false;
console.log(this.canvas.getObjects()[0].aCoords.bl);
this.position = this.canvas.getObjects()[0].aCoords;
this.zhuangtai = false;
console.log(this.canvas);
},
以上是Vue版本.
以下是原生js的:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Fabric</title>
<script src="fabric.min.js"></script>
</head>
<body>
<canvas id="canvas" width="600" height="300" onclick="canvasMouseDown" style="border:1px solid #000000;"></canvas>
<script>
let canvas; // 画布对象
let zhuangtai = true;
let topRect, leftRect, widthRect, heightRect;
let currentType = 'default' // 当前操作模式(默认 || 创建矩形)
let downPoint = null // 按下鼠标时的坐标
let upPoint = null // 松开鼠标时的坐标
// 初始化画板
function initCanvas() {
canvas = new fabric.Canvas('canvas')
console.log(canvas)
// canvas.selectionColor = 'rgba(100, 100, 255, 0.3)' // 选框填充色:半透明的蓝色
// canvas.selectionBorderColor = 'rgba(255, 255, 255, 0.3)' // 选框边框颜色:半透明灰色
canvas.on('mouse:down', canvasMouseDown) // 鼠标在画布上按下
canvas.on('mouse:up', canvasMouseUp) // 鼠标在画布上松开
// canvas.on('mouse:move', canvasMouseMove) // 鼠标在画布上松开
}
// 鼠标在画布上按下
function canvasMouseDown(e) {
// 鼠标左键按下时,将当前坐标 赋值给 downPoint。{x: xxx, y: xxx} 的格式
downPoint = e.absolutePointer
// console.log(e)
}
// 鼠标在画布上松开
function canvasMouseUp(e) {
upPoint = e.absolutePointer
if (zhuangtai != false) {
// 调用 创建矩形 的方法
canvas.selection = true // 允许框选
// }
createRect()
}
canvas.skipTargetFind = false
// console.log( canvas.skipTargetFind)
if (zhuangtai == false && e.target != null) {
// 获取画布视口边界
let canvasBoundaries = canvas.calcViewportBoundaries();
// 矩形本身
let obj = e.target
// 矩形的边界
let objBoundingRect = obj.getBoundingRect();
// 【公式1】
if (objBoundingRect.left < canvasBoundaries.tl.x) {
e.target.left = canvasBoundaries.tl.x
}
// console.log(objBoundingRect)
// 【公式2】
if (objBoundingRect.left + objBoundingRect.width > canvasBoundaries.br.x) {
e.target.left = canvasBoundaries.br.x - objBoundingRect.width
}
// 【公式3】
if (objBoundingRect.top < canvasBoundaries.tl.y) {
e.target.top = canvasBoundaries.tl.y
}
// 【公式4】
if (objBoundingRect.top + objBoundingRect.height > canvasBoundaries.br.y) {
e.target.top = canvasBoundaries.br.y - objBoundingRect.height
}
// 刷新画布
canvas.renderAll()
}
console.log(canvas.getObjects())
zhuangtai = false
}
// 创建矩形
function createRect() {
// 如果点击和松开鼠标,都是在同一个坐标点,不会生成矩形
// if (JSON.stringify(downPoint) === JSON.stringify(upPoint)) {
// return
// }
// 创建矩形
// 矩形参数计算(前面总结的4条公式)
let top = topRect = Math.min(downPoint.y, upPoint.y)
let left = leftRect = Math.min(downPoint.x, upPoint.x)
let width = widthRect = Math.abs(downPoint.x - upPoint.x)
let height = heightRect = Math.abs(downPoint.y - upPoint.y)
// 矩形对象
const rect = new fabric.Rect({
top,
left,
width,
height,
target: "test",
fill: 'transparent', // 填充色:透明
stroke: '#000', // 边框颜色:黑色
hasRotatingPoint: false // 禁止旋转
})
// 将矩形添加到画布上
canvas.add(rect)
// console.log(canvas.getObjects())
// 创建完矩形,清空 downPoint 和 upPoint。当然,你也可以不做这步。
// downPoint = null
// upPoint = null
}
// 页面加载的生命周期,在此执行 初始化画布 的操作
window.onload = function () {
initCanvas()
}
</script>
</body>
</html>
贴两个参考的链接:
https://gitee.com/denghuoan/fabricjs
Fabric.js 官网:
http://fabricjs.com/
版权声明:本文为weixin_39891473原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。