# 对象
- fabric.Circle 圆
- fabric.Ellipse 椭圆
- fabric.Line 直线
- fabric.Polygon 多边形
- fabric.Polyline 线
- fabric.Rect 矩形
- fabric.Triangle 三角形
# 方法
- add(object) 添加
- insertAt(object,index) 添加
- remove(object) 移除
- forEachObject 循环遍历
- getObjects() 获取所有对象
- item(int) 获取子项
- isEmpty() 判断是否空画板
- size() 画板元素个数
- contains(object) 查询是否包含某个元素
- fabric.util.cos
- fabric.util.sin
- fabric.util.drawDashedLine 绘制虚线
- getWidth() setWidth()
- getHeight()
- clear() 清空
- renderAll() 重绘
- requestRenderAll() 请求重新渲染
- rendercanvas() 重绘画板
- getCenter().top/left 获取中心坐标
- toDatalessJSON() 画板信息序列化成最小的json
- toJSON() 画板信息序列化成json
- moveTo(object,index) 移动
- dispose() 释放
- setCursor() 设置手势图标
- getSelectionContext()获取选中的context
- getSelectionElement()获取选中的元素
- getActiveObject() 获取选中的对象
- getActiveObjects() 获取选中的多个对象
- discardActiveObject()取消当前选中对象
- isType() 图片的类型
- setColor(color) = canvas.set("full","");
- rotate() 设置旋转角度
- setCoords() 设置坐标
# 事件
- object:added
- object:removed
- object:modified
- object:rotating
- object:scaling
- object:moving
- object:selected 这个方法v2已经废弃,使用selection:created替代,多选不会触发
- before:selection:cleared
- selection:cleared
- selection:updated
- selection:created
- path:created
- mouse:down
- mouse:move
- mouse:up
- mouse:over
- mouse:out
- mouse:dblclick
# 常用属性
- canvas.isDrawingMode = true; 可以自由绘制
- canvas.selectable = false; 控件不能被选择,不会被操作
- canvas.selection = true; 画板显示选中
- canvas.skipTargetFind = true; 整个画板元素不能被选中
- canvas.freeDrawingBrush.color = "#E34F51" 设置自由绘画笔的颜色
- freeDrawingBrush.width 自由绘笔触宽度
- canvas.setZoom(2); 设置画板缩放比例
# IText的方法
- selectAll() 选择全部
- getSelectedText() 获取选中的文本
- exitEditing() 退出编辑模式
# 绘制直线
var line = new fabric.Line([10, 10, 100, 100], {
fill: 'green',
stroke: 'green', //笔触颜色
strokeWidth: 2,//笔触宽度
});
canvas.add(line);
# 绘制虚线
var line = new fabric.Line([10, 10, 100, 100], {
fill: 'green',
stroke: 'green',
strokeDashArray:[3,1]
});
canvas.add(line);
//strokeDashArray[a,b] =》 每隔a个像素空b个像素。
# 绘制矩形
var rect = new fabric.Rect({
left:100,//距离画布左侧的距离,单位是像素
top:100,//距离画布上边的距离
fill:'red',//填充的颜色
width:30,//方形的宽度
height:30//方形的高度
});
canvas.add(rect);
# 图片操作
- oImg.hasControls = false; 只能移动不能(编辑)操作
- oImg.hasBorders = false; 去掉边框,可以正常操作
- hasRotatingPoint = false; 不能被旋转
- hasRotatingPoint 控制旋转点不可见
- scaleToHeight(value, absolute) 缩放图片高度到value scaleToWidth(value, absolute) 缩放图片宽度到value
fabric.Image.fromURL("img.jpg", function (oImg) {
img.scaleToHeight(400, false); //缩放图片的高度到400
img.scaleToWidth(400, false); //缩放图片的宽度到400
canvas.add(oImg);
oImg.hasControls = oImg.hasBorders = false;
});
# 右键菜单
# 实现原理
Fabric.js 的 Canvas 初始化完毕后,会自动在其上方覆盖一个 class 名为 upper-canvas 的 canvas。
我们可以在上层这个 canvas 上添加 contextmenu 事件监听。当右键按下时会触发该事件,然后将点击的坐标转换成底下实际的 canvas 里的坐标(坐标需要转换是因为下面 canvas 可能会被移动,缩放)。
# 实现步骤
- 默认情况下,鼠标左键点击对象即可选择中该对象。这里增加个右键选中功能,即通过右键同样可以选中对象
- Fabric.js 的 Canvas 有个 mouse:down 事件,通过它我们可以监听到鼠标按下的行为。不过该事件只对鼠标左键其作用,如果是右键按下则不会触发该事件。 而 Canvas 上又无法直接监听 contextmenu 事件,所以想要实现右键点击响应就需要换种方式实现
这里我们使用一个专门的第三方菜单组件(contextMenu)来实现,在上面的右键点击响应中将菜单弹出即可。
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<style>
canvas {
border: 1px dashed black;
}
</style>
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/jquery-contextmenu/2.7.1/jquery.contextMenu.min.css">
<script src="https://cdn.bootcss.com/fabric.js/4.0.0-beta.5/fabric.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery-contextmenu/2.7.1/jquery.contextMenu.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery-contextmenu/2.7.1/jquery.ui.position.js"></script>
<script>
var canvas;
//菜单项
var contextMenuItems;
window.onload = function () {
canvas = new fabric.Canvas('canvas');
var rect1 = new fabric.Rect({ top: 50, left: 50, width: 70, height: 70, fill: 'red' });
canvas.add(rect1);
var rect2 = new fabric.Rect({ top: 50, left: 150, width: 70, height: 70, fill: 'red' });
canvas.add(rect2);
var rect3 = new fabric.Rect({ top: 50, left: 250, width: 70, height: 70, fill: 'red' });
canvas.add(rect3);
//在canvas上层对象上添加右键事件监听
$(".upper-canvas").contextmenu(onContextmenu);
//初始化右键菜单
$.contextMenu({
selector: '#contextmenu-output',
trigger: 'none',
build: function ($trigger, e) {
//构建菜单项build方法在每次右键点击会执行
return {
callback: contextMenuClick,
items: contextMenuItems
};
},
});
}
//右键点击事件响应
function onContextmenu(event) {
var pointer = canvas.getPointer(event.originalEvent);
var objects = canvas.getObjects();
for (var i = objects.length - 1; i >= 0; i--) {
var object = objects[i];
//判断该对象是否在鼠标点击处
if (canvas.containsPoint(event, object)) {
//选中该对象
canvas.setActiveObject(object);
//显示菜单
showContextMenu(event, object);
continue;
}
}
//阻止系统右键菜单
event.preventDefault();
return false;
}
//右键菜单项点击
function showContextMenu(event, object) {
//定义右键菜单项
contextMenuItems = {
"delete": { name: "删除", icon: "delete", data: object },
"add": { name: "新增", icon: "add", data: object },
};
//右键菜单显示位置
var position = {
x: event.clientX,
y: event.clientY
}
$('#contextmenu-output').contextMenu(position);
}
//右键菜单项点击
function contextMenuClick(key, options) {
if (key == "delete") {
//得到对应的object并删除
var object = contextMenuItems[key].data;
canvas.remove(object);
}else if(key = "add"){
var rect3 = new fabric.Rect({ top: 50, left: 350, width: 70, height: 70, fill: 'red' });
canvas.add(rect3);
canvas.renderAll();
}
}
</script>
</head>
<body>
<canvas id="canvas" width="450" height="200"></canvas>
<div id="contextmenu-output"></div>
</body>
</html>
# vue中的使用
- 引入 fabric.js
npm install fabric --save
- main.js 导入
import { fabric } from 'fabric'
Vue.use(fabric);
- vue 页面实现
<template>
<div>
<div class="manager_detail">
<canvas id="canvas" width="1720" height="1050"></canvas>
</div>
</div>
</template>
<script>
export default {
components: {
},
watch: {},
data() {
return {
panning: false
};
},
methods: {
initCanvas() {
// 1. 实例化canvas 画布
var canvas = new fabric.Canvas("canvas");
// 2. 设置背景图片作为底图(这里导入图片使用require,不要 使用 '../../' 方式)
// canvas.width / 4764 (4764 是我底图图片宽度)
// canvas.height / 3367 (3367 是我底图图片宽度)
canvas.setBackgroundImage(
require("../../assets/images/map.png"),
canvas.renderAll.bind(canvas),
{
scaleX: canvas.width / 4764,
scaleY: canvas.height / 3367
}
);
//鼠标按下事件
canvas.on("mouse:down", function(e) {
this.panning = true;
canvas.selection = false;
});
//鼠标抬起事件
canvas.on("mouse:up", function(e) {
this.panning = false;
canvas.selection = true;
});
// 移动画布事件
canvas.on("mouse:move", function(e) {
if (this.panning && e && e.e) {
var delta = new fabric.Point(e.e.movementX, e.e.movementY);
canvas.relativePan(delta);
}
});
// 鼠标滚动画布放大缩小
canvas.on("mouse:wheel", function(e) {
var zoom = (event.deltaY > 0 ? -0.1 : 0.1) + _that.canvas.getZoom();
zoom = Math.max(0.1, zoom); //最小为原来的1/10
zoom = Math.min(3, zoom); //最大是原来的3倍
var zoomPoint = new fabric.Point(event.pageX, event.pageY);
_that.canvas.zoomToPoint(zoomPoint, zoom);
});
}
},
created() {
},
mounted() {
this.initCanvas();
}
};
</script>
<style scoped>
.manager_detail {
width: 100%;
height: calc(100vh - 112px);
overflow: hidden;
}
</style>
注意
图片使用require,不要 使用 '../../' 方式,否则图片加载不进去