一、 安装
npm install fabric(或yarn add fabric)
二、 使用
在项目中导入:
import { fabric } from 'fabric'
创建frabicManager对象管理:
// css:
.container{
display: flex;
width: 100%;
height: 50%;
.top{
width: 50%;
height: 100%;
background-color: rgb(248, 249, 254);
display:flex;
align-items: center;
justify-content: center;
}
}
// html:
<div class="top" ref="top">
<canvas id="frabic" width="768" height="477"></canvas>
</div>
// js:
var frabicManager = {
w: 768,
h: 477,
scale: 1,
itemsArr: [],
init() {
//注意:创建不可交互的画布,其实只需把 `new fabric.Canvas` 改成 `new fabric.StaticCanvas` 即可。不可交互的画布添加鼠标事件不生效!!!
this.canvas = new fabric.StaticCanvas("canvas_l");
this.createline(400, "#000", 1, "E1= -13.6eV");
this.createStatic();
this.containerSize();
this.createSin(300, 300, "#FF8C00", 150);
},
resize() {
var container = document.querySelector(".top");
var width = container.clientWidth;
var height = container.clientHeight;
//////////////////////方式一//////////////////////////////////////
const canvas = document.querySelector("#frabic");
if (frabicManager.w / frabicManager.h < width / height) {
width = height/leftManager.h*leftManager.w
} else {
height = width/leftManager.w*leftManager.h
}
canvas.style.width = `${width}px`;
canvas.style.height = `${height}px`;
///////////////////////方式二////////////////////////////////
if (frabicManager.w / frabicManager.h < width / height) {
// h的减小更多的情况
frabicManager.scale = height / frabicManager.h;
} else {
frabicManager.scale = width / frabicManager.w;
}
let zoomPoint = new fabric.Point(width / 2 - 50, height / 2); // 中心点
this.canvas.zoomToPoint(zoomPoint, leftManager.scale);
},
createStatic() {
let text = new fabric.Text("文字内容", {
left: 300,
top: 5,
fontFamily: "Comic Sans", //字体
fontSize: 26, //字号
textAlign: "center", //文本对齐方式
lineHeight: 1.5, //行高
});
const line1 = new fabric.Line(
[
100,
403, // 起始点坐标
100,
50, // 结束点坐标
],
{
stroke: "#000",
strokeWidth: 3,
}
);
const triangle = new fabric.Triangle({
top: 30,
left: 91,
width: 20, // 底边长度
height: 20, // 底边到对角的距离
fill: "#000",
});
this.itemsArr.push(text, line1, triangle);
// 建组
this.group = new fabric.Group(this.itemsArr, {});
this.canvas.add(this.group);
},
//鼠标事件(必须设置可交互的画布:new fabric.Canvas("canvas_r");否则不生效)
event(){
// 创建一个矩形对象
const rect = new fabric.Rect({
left: 100,
top: 100,
fill: 'red',
width: 200,
height: 200
});
// 将矩形添加到画布上
this.canvas.add(rect);
// 为矩形添加鼠标悬浮事件
rect.on('mousedown', function() {
console.log('Mouse is over the rectangle');
// 你可以在这里改变对象的属性,比如颜色
this.set({ fill: 'blue' });
rightManager.canvas.renderAll();
});
// 你也可以添加鼠标移出事件来恢复原始状态
rect.on('mouseout', function() {
console.log('Mouse is out of the rectangle');
this.set({ fill: 'red' });
rightManager.canvas.renderAll();
});
rect.selectable = true//允许鼠标操作
rect.perPixelTargetFind = true
rect.lockMovementX = true// 不允许水平移动
rect.lockMovementY = true// 不允许垂直移动
rect.lockRotation = true// 不允许旋转
rect.lockScalingX = true// 不允许水平缩放
rect.lockScalingY = true// 不允许垂直缩放
},
createline(y, color, number, text) {//创建线段
const line = new fabric.Line(
[
105,
y, // 起始点坐标
550,
y, // 结束点坐标
],
{
stroke: `${color}`, // 笔触颜色
strokeWidth: 2,
}
);
const circle = new fabric.Circle({
top: 100,
left: 100,
radius: 50, // 半径:50px
backgroundColor: 'green', // 背景色:绿色
fill: 'orange', // 填充色:橙色
stroke: '#f6416c', // 边框颜色:粉色
strokeWidth: 5, // 边框粗细:5px
strokeDashArray: [20, 5, 14], // 边框虚线规则:填充20px 空5px 填充14px 空20px 填充5px ……
shadow: '10px 20px 6px rgba(10, 20, 30, 0.4)', // 投影:向右偏移10px,向下偏移20px,羽化6px,投影颜色及透明度
transparentCorners: false, // 选中时,角是被填充了。true 空心;false 实心
borderColor: '#16f1fc', // 选中时,边框颜色:天蓝
borderScaleFactor: 5, // 选中时,边的粗细:5px
borderDashArray: [20, 5, 10, 7], // 选中时,虚线边的规则
cornerColor: "#a1de93", // 选中时,角的颜色是 青色
cornerStrokeColor: 'pink', // 选中时,角的边框的颜色是 粉色
cornerStyle: 'circle', // 选中时,叫的属性。默认rect 矩形;circle 圆形
cornerSize: 20, // 选中时,角的大小为20
cornerDashArray: [10, 2, 6], // 选中时,虚线角的规则
selectionBackgroundColor: '#7f1300', // 选中时,选框的背景色:朱红
padding: 40, // 选中时,选择框离元素的内边距:40px
borderOpacityWhenMoving: 0.6, // 当对象活动和移动时,对象控制边界的不透明度
});
const text1 = new fabric.Text(`${number}`, {
top: 40,
left: 40,
fontSize: 120,
backgroundColor: 'green', // 背景色:绿色
fill: 'orange', // 填充色:橙色
stroke: '#f6416c', // 边框颜色:粉色
strokeWidth: 3, // 边框粗细:3px
strokeDashArray: [20, 5, 14], // 边框虚线规则:填充20px 空5px 填充14px 空20px 填充5px ……
shadow: '10px 20px 6px rgba(10, 20, 30, 0.4)', // 投影:向右偏移10px,向下偏移20px,羽化6px,投影颜色及透明度
transparentCorners: false, // 选中时,角是被填充了。true 空心;false 实心
borderColor: '#16f1fc', // 选中时,边框颜色:天蓝
borderScaleFactor: 5, // 选中时,边的粗细:5px
borderDashArray: [20, 5, 10, 7], // 选中时,虚线边的规则
cornerColor: "#a1de93", // 选中时,角的颜色是 青色
cornerStrokeColor: 'pink', // 选中时,角的边框的颜色是 粉色
cornerStyle: 'circle', // 选中时,叫的属性。默认rect 矩形;circle 圆形
cornerSize: 20, // 选中时,角的大小为20
cornerDashArray: [10, 2, 6], // 选中时,虚线角的规则
selectionBackgroundColor: '#7f1300', // 选中时,选框的背景色:朱红
padding: 40, // 选中时,选择框离元素的内边距:40px
borderOpacityWhenMoving: 0.6, // 当对象活动和移动时,对象控制边界的不透明度
overline: true, // 上划线
underline: true, // 下划线
linethrough: true, // 删除线
textAlign: 'left', // 左对齐
textAlign: 'center',// 居中对齐
textAlign: 'right', // 右对齐
lineHeight: 1, // 行高
});
//使用 `new fabric.IText` 可以创建**可编辑文本**,用法和 `new fabric.Text` 一样。
this.itemsArr.push(line, circle, text1);
},
createSin(left, top, color, length) {//创建螺旋形的线
var x = 1;
var y = 20;
let path = `M ${x} ${y}`;
for (let i = 1; i < length; i += 0.1) {
x = i * 2;
y = Math.sin(i) * 10 + 20;
path += `L ${x} ${y}`;
}
let customPath = new fabric.Path(path);
customPath.set({
left: left,
top: top,
stroke: `${color}`,
fill: "rgba(0,0,0,0)",
angle: 90,
});
this.itemsArr.push(customPath);
},
createGroup(){// 建组一定要最后建!!!等所有元素都建好了再建组push进去
this.group = new fabric.Group(this.groups, {
top: 10, // 整组距离顶部
left: 10, // 整组距离左侧
fill: '#DFECF7',
// angle: -10, // 整组旋转-10deg
})
this.canvas.add(this.group);
},
};
onMounted(()=>{
frabicManager.init()
})
window.addEventListener('resize',()=>{
frabicManager.resize()
})
2.1 绘制一个简单的图形
Fabric 提供了 7 种基础形状:
- fabric.Circle (圆)
- fabric.Ellipse (椭圆)
- fabric.Line (线)
- fabric.Polyline (多条线绘制成图形)
- fabric.triangle (三角形)
- fabric.Rect (矩形)
- fabric.Polygon (多边形)
我们可以通过设置以下属性,决定是否可以对相关元素进行交互
canvas.selection = false; // 禁止所有选中
rect.set("selectable", false); // 只是禁止这个矩形选中
2.2 绘制图片
有通过 url 和 img 标签绘制两种方式
//通过url绘制图片
import img from '@/assets/img.png' // 引入图片
fabric.Image.fromURL(img, oImg => {
oImg.scale(0.5) // 缩放
canvas.add(oImg) // 将图片加入到画布
})
}
//也可以通过标签绘制
<img src="@/assets/logo.png" id="img">
let img = document.getElementById("img");
imgElement.onload = function() {
let imgInstance = new fabric.Image(imgElement, {
left: 100,
top: 100,
width: 200,
height: 200,
angle: 50, // 旋转
})
canvas.add(imgInstance)
}
2.21组中常用的方法:
getObjects()返回一组中所有对象的数组size()所有对象的数量contains()检查特定对象是否在group中item()组中元素forEachObject()遍历组中对象add()添加元素对象remove()删除元素对象fabric.util.object.clone()克隆
2.3 通过自定义的路径绘制
let customPath = new fabric.Path("M 0 0 L 300 100 L 170 100 L 70 300 L 20 200 C136.19,2.98,128.98,0,121.32,0 z");
customPath.set({
left: 100,
top: 100,
fill: "green",
});
canvas.add(customPath);
2.4 颜色
2.41 定义颜色
new fabric.Color("#f55");
new fabric.Color("#aa3123");
new fabric.Color("356333");
new fabric.Color("rgb(100,50,100)");
new fabric.Color("rgba(100, 200, 30, 0.5)");
2.42 颜色转换
new fabric.Color('#f55').toRgb(); // "rgb(255,85,85)"
new fabric.Color('rgb(100,100,100)').toHex(); // "646464"
new fabric.Color('fff').toHex(); // "FFFFFF"
我们还可以用另一种颜色叠加,或将其转换为灰度版本。
let redish = new fabric.Color("#f55");
let greenish = new fabric.Color("#5f5");
redish.overlayWith(greenish).toHex(); // "AAAA55"
redish.toGrayscale().toHex(); // "A1A1A1"
2.5 渐变
Fabric 通过 setGradient 方法支持渐变,在所有对象上定义。调用 setGradient('fill', { ... })就像设置一个对象的“fill”值一样。
let circle = new fabric.Circle({
left: 100,
top: 100,
radius: 50
});
// 线性渐变
let gradient = new fabric.Gradient({
type: 'linear', // linear or radial
gradientUnits: 'pixels', // pixels or pencentage 像素 或者 百分比
coords: { x1: 0, y1: 0, x2: circle.width, y2: 0 }, // 至少2个坐标对(x1,y1和x2,y2)将定义渐变在对象上的扩展方式
colorStops:[ // 定义渐变颜色的数组
{ offset: 0, color: 'red' },
{ offset: 0.2, color: 'orange' },
{ offset: 0.4, color: 'yellow' },
{ offset: 0.6, color: 'green' },
{ offset: 0.8, color: 'blue' },
{ offset: 1, color: 'purple' },
]
})
circle.set('fill', gradient);
//径向渐变
let gradient = new fabric.Gradient({
type: 'radial',
coords: {
r1: 50, // 该属性仅径向渐变可用,外圆半径
r2: 0, // 该属性仅径向渐变可用,外圆半径
x1: 50, // 焦点的x坐标
y1: 50, // 焦点的y坐标
x2: 50, // 中心点的x坐标
y2: 50, // 中心点的y坐标
},
colorStops: [
{ offset: 0, color: '#fee140' },
{ offset: 1, color: '#fa709a' }
]
})
2.6 事件
fabric 中通过 on 方法来初始化事件,off 方法用来删除事件。
常用的事件有以下
- “mouse:down” 鼠标被按下
- “object:add” 对象被添加
- “after:render” 渲染完成
canvas.on("mouse:down", function(options) {
canvas.clear();
let text = new fabric.Text("点击触发", {
left: 200,
top: 200,
});
canvas.add(text);
console.log(options.e.clientX, options.e.clientY);
});
canvas.on("mouse:up", function(options) {
this.text = "没有发现点击";
canvas.clear();
let text = new fabric.Text("没有发现点击", {
left: 200,
top: 200,
});
canvas.add(text);
console.log(options.e.clientX, options.e.clientY);
});
Fabric 允许将侦听器直接附加到 canvas 画布中的对象上。
let rect = new fabric.Rect({ width: 100, height: 50, fill: "green" });
rect.on("selected", function() {
console.log("选择了目标");
});
let circle = new fabric.Circle({ radius: 75, fill: "blue" });
circle.on("selected", function() {
console.log("选择了目标");
});
2.7 自由绘画
Fabric canvas 的 isDrawingMode 属性设置为 true 即可实现自由绘制模式.
这样画布上的点击和移动就会被立刻解释为铅笔或刷子。
let canvas = new fabric.Canvas("canvas");
canvas.isDrawingMode = true;
canvas.freeDrawingBrush.color = "blue";
canvas.freeDrawingBrush.width = 5;