这个 19.4K 的 canvas 库,功能很强大
zhezhongyun 2025-01-24 14:46 25 浏览
来源于公众号前埔寨 ,
作者荣顶
1.导语
我们想在画布上画个基本的简单形状的时候,使用 Canvas 不会觉得有什么繁琐。但当画布上需要任何形式的互动,绘制复杂的图形和在特定情况需要改变图片的时候,使用原生 canvas API 将会变得很困难。
而 Fabric 旨在解决这个问题。
Fabric.js 是一个强大而简单的 Javascript HTML5 画布库 Fabric 在画布元素之上提供交互式对象模型 Fabric 还具有 SVG-to-canvas(和 canvas-to-SVG)解析器
为了方便,下面我将通过 vue项目 为大家讲解如何使用 Fabric
2. 安装
yarn add fabric -S
#or
npm i fabric -S
也可以在 官网 下载最新 js 文件,通过 script 标签引入
3. 使用
<!-- html -->
<canvas id="canvas" width="500" height="500"></canvas>
3.1 绘制一个简单的图形
Fabric 提供了 7 种基础形状:
fabric.Circle (圆)
fabric.Ellipse (椭圆)
fabric.Line (线)
fabric.Polyline (多条线绘制成图形)
fabric.triangle (三角形)
fabric.Rect (矩形)
fabric.Polygon (多边形)
- 矩形
//引入fabric
import { fabric } from "fabric";
// 创建一个fabric实例
let canvas = new fabric.Canvas("canvas"); //可以通过鼠标方法缩小,旋转
// or
// let canvas = new fabric.StaticCanvas("canvas");//没有鼠标交互的fabric对象
// 创建一个矩形对象
let rect = new fabric.Rect({
left: 200, //距离左边的距离
top: 200, //距离上边的距离
fill: "green", //填充的颜色
width: 200, //矩形宽度
height: 200, //矩形高度
});
// 将矩形添加到canvas画布上
canvas.add(rect);
可以看到界面中填充了一个可以通过鼠标放大缩小且可以旋转的绿色矩形
通过对象的形式配置元素样式,非常的方便!
- 圆形和三角形
let circle = new fabric.Circle({
left: 0, //距离左边的距离
top: 0, //距离上边的距离
fill: "red", //填充的颜色
radius: 50, //圆的半径
});
// 创建一个三角形对象
let triangle = new fabric.Triangle({
left: 200, //距离左边的距离
top: 0, //距离上边的距离
fill: "blue", //填充的颜色
width: 100, //宽度
height: 100, //高度
});
// 将图形形添加到canvas画布上
canvas.add(circle, triangle);
我们可以通过以下属性设置,决定是否可以对相关元素进行交互
rect.set("selectable", false); // 只是禁止这个矩形选中
3.2 绘制图片
主要有通过 url 和 img 标签绘制两种方式
fabric.Image.fromURL(
//本地图片需要通过require来引入,require("./xxx.jpeg")
"https://gimg2.baidu.com/image_search/src=http%3A%2F%2Fimg.thaihot.com.cn%2Fuploadimg%2Fico%2F2021%2F0711%2F1625982535739193.jpg&refer=http%3A%2F%2Fimg.thaihot.com.cn&app=2002&size=f9999,10000&q=a80&n=0&g=0n&fmt=jpeg?sec=1630940858&t=e1d24ff0a7eaeea2ff89cedf656a9374",
(img) => {
img.scale(0.5);
canvas.add(img);
}
);
//也可以通过标签绘制
let img = document.getElementById("img");
let image = new fabric.Image(img, {
left: 100,
top: 100,
opacity: 0.8,
});
canvas.add(image);
3.3 通过自定义的路径绘制
在此之前我们需要了解几个参数的含义
- M : “move”移动到某点
- L : “line”画线 x,y
- C : “curve”曲线
- A : “arc”弧
- z : 闭合路径(类似 PS 中的创建选区)
customPath.set({
left: 100,
top: 100,
fill: "green",
});
canvas.add(customPath);
"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"
);
可以看到通过路径绘制,我们可以制作非常复杂的图形(但是一般用不到,我们一般用它来解析 SVG 后拿到 path 复原图形)
3.4 动画
第一个参数是动画的属性,第二个参数是动画的最终位置,第三个参数是一个可选的对象,指定动画的细节:持续时间,回调,动效等。
第三个参数主要有
duration 默认为 500ms。可以用来改变动画的持续时间。
from 允许指定动画属性的起始值(如果我们不希望使用当前值)。
onComplete 动画结束之后的回调。
easing 动效函数。
绝对动画
let rect = new fabric.Rect({
left: 400, //距离左边的距离
top: 200, //距离上边的距离
fill: "green", //填充的颜色
width: 200, //宽度
height: 200, //高度
});
rect.animate("left", 100, {
onChange: canvas.renderAll.bind(canvas),
duration: 1000,
});
canvas.add(rect);
相对动画(第二个参数通过+=,-=等来决定动画的最终效果)
onChange: canvas.renderAll.bind(canvas),
duration: 1000,
});
rect.animate("angle", "-=90", {
onChange: canvas.renderAll.bind(canvas),
duration: 2000,
});
定义动画的动效函数
默认情况下,动画使用“easeInSine”动效执行。如果这不是你需要的,fabric 为我们提供了很多内置动画效果, fabric.util.ease 下有一大堆动效的选项。
常用的有easeOutBounce,easeInCubic,easeOutCubic,easeInElastic,easeOutElastic,easeInBounce 和 easeOutExpo等
onChange: canvas.renderAll.bind(canvas),
duration: 1000,
easing: fabric.util.ease.easeOutBounce,
});
3.5 图像滤镜
目前 Fabric 为我们提供了以下内置滤镜
- BaseFilter 基本过滤器
- Blur 模糊
- Brightness 亮度
- ColorMatrix 颜色矩阵
- Contrast 对比
- Convolute 卷积
- Gamma 伽玛
- Grayscale 灰度
- HueRotation 色调旋转
- Invert 倒置
- Noise 噪音
- Pixelate 像素化
- RemoveColor 移除颜色
- Resize 调整大小
- Saturation 饱和
单个滤镜
img.scale(0.5);
canvas.add(img);
});
fabric.Image.fromURL(require("./aaa.jpeg"), (img) => {
img.scale(0.5);
// 添加滤镜
img.filters.push(new fabric.Image.filters.Grayscale());
// 图片加载完成之后,应用滤镜效果
img.applyFilters();
img.set({
left: 300,
top: 250,
});
canvas.add(img);
});
叠加滤镜
“filters”属性是一个数组,我们可以用数组方法执行任何所需的操作:移除滤镜(pop,splice,shift),添加滤镜(push,unshift,splice),甚至可以组合多个滤镜。当我们调用 applyFilters 时,“filters”数组中存在的任何滤镜将逐个应用,所以让我们尝试创建一个既色偏又明亮(Brightness)的图像。
img.scale(0.5);
// 添加滤镜
img.filters.push(
new fabric.Image.filters.Grayscale(),
new fabric.Image.filters.Sepia(), //色偏
new fabric.Image.filters.Brightness({ brightness: 0.2 }) //亮度
);
// 图片加载完成之后,应用滤镜效果
img.applyFilters();
img.set({
left: 300,
top: 250,
});
canvas.add(img);
});
可以看到多个滤镜的效果叠加显示了,当然 Fabric 还支持自定义滤镜,在本篇文章点赞过 500 后我将更新 fabric 高级篇,感谢大家的支持~
3.6 颜色
无论你是使用十六进制,RGB 或 RGBA 颜色,Fabric 都能处理的很好
定义颜色
new fabric.Color("#aa3123");
new fabric.Color("356333");
new fabric.Color("rgb(100,50,100)");
new fabric.Color("rgba(100, 200, 30, 0.5)");
颜色转换
new fabric.Color('rgb(100,100,100)').toHex(); // "646464"
new fabric.Color('fff').toHex(); // "FFFFFF"
我们还可以用另一种颜色叠加,或将其转换为灰度版本。
let greenish = new fabric.Color("#5f5");
redish.overlayWith(greenish).toHex(); // "AAAA55"
redish.toGrayscale().toHex(); // "A1A1A1"
3.7 渐变
Fabric 通过 setGradient 方法支持渐变,在所有对象上定义。调用 setGradient('fill', { ... })就像设置一个对象的“fill”值一样。
left: 100,
top: 100,
radius: 50
});
circle.setGradient("fill", {
// 渐变开始的位置
x1: 0,
y1: 0,
// 渐变结束的位置
x2: circle.width,
y2: 0,
//渐变的颜色
colorStops: {
// 渐变的范围(0,0.1,0.3,0.5,0.75,1)0-1之间都可以
0: "red",
0.2: "orange",
0.4: "yellow",
0.6: "green",
0.8: "blue",
1: "purple"
},
});
3.8 文本
fabric.Text 对象对于文本,提供了比 canvas 更丰富的功能,包括:
支持多行 Multiline support 不幸的是,原生文本方法忽略了新建一行。
文本对齐 Text alignment 左,中,右。使用多行文本时很有用。
文本背景 Text background 背景也支持文本对齐。
文字装饰 Text decoration 下划线,上划线,贯穿线。
行高 Line Height 在使用多行文本时有用。
字符间距 Char spacing 使文本更紧凑或更间隔。
子范围 Subranges 将颜色和属性应用到文本对象的子对象中。
多字节 Multibyte 支持表情符号。
交互式画布编辑 On canvas editing 可以直接在画布上键入文本。
"大家好~这里是前埔寨\n我是荣顶~\n一个要成为开发王的男人!",
{
left: 0,
top: 200,
fontFamily: "Comic Sans", //字体
fontSize: 50, //字号
fontWeight: 800, //字体粗细,可以使用关键字(“normal”,“bold”)或数字(100,200,400,600,800)
shadow: "green 3px 3px 2px", //文字阴影,颜色,水平偏移,垂直偏移和模糊大小。
underline: true, //下划线
linethrough: true, //删除线
overline: true, //上划线
fontStyle: "italic", //字体风格,normal(正常)或italic(斜体)
stroke: "#c3bfbf", //描边的颜色
strokeWidth: 1, //描边的宽度
textAlign: "center", //文本对齐方式
lineHeight: 1.5, //行高
textBackgroundColor: "#91A8D0", //文本背景颜色
}
);
canvas.add(text);
3.9 事件
fabric 中通过 on 方法来初始化事件,off 方法用来删除事件。常用的事件有以下
- “mouse:down” 鼠标被按下
- “object:add” 对象被添加
- “after:render” 渲染完成
还有一大堆:
鼠标事件:“mouse:down” ,“mouse:move”和“mouse:up...” 选择相关的事件:“before:selection:cleared”, “selection:created”, 详细的可以查看 官方文档
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 = "你没点我0.0";
canvas.clear();
let text = new fabric.Text("你没点我0.0", {
left: 200,
top: 200,
});
canvas.add(text);
console.log(options.e.clientX, options.e.clientY);
});
Fabric 允许将侦听器直接附加到 canvas 画布中的对象上。
rect.on("selected", function() {
console.log("哦吼~你选择了我");
});
let circle = new fabric.Circle({ radius: 75, fill: "blue" });
circle.on("selected", function() {
console.log("哈哈哈~你选择了我");
});
3.10自由绘画
Fabric canvas 的 isDrawingMode 属性设置为 true 即可实现自由绘制模式.
这样画布上的点击和移动就会被立刻解释为铅笔或刷子。
canvas.isDrawingMode = true;
canvas.freeDrawingBrush.color = "blue";
canvas.freeDrawingBrush.width = 5;
4. 最后
很开心写下这篇文章,它是我用来总结归纳 fabric 的知识点,并且非常用心的一篇文章,希望这篇文章对你有所帮助。目前 fabric 在国内还不是很火,但是 github 上已经有 19.2k 的 star 了,也算是一个明星项目。我们日常开发经常会用到 canvas,但是它的 api 对于处理复杂的业务逻辑会令人感到非常的劳累,分享这篇文章,希望对大家有所帮助!
相关推荐
- JPA实体类注解,看这篇就全会了
-
基本注解@Entity标注于实体类声明语句之前,指出该Java类为实体类,将映射到指定的数据库表。name(可选):实体名称。缺省为实体类的非限定名称。该名称用于引用查询中的实体。不与@Tab...
- Dify教程02 - Dify+Deepseek零代码赋能,普通人也能开发AI应用
-
开始今天的教程之前,先解决昨天遇到的一个问题,docker安装Dify的时候有个报错,进入Dify面板的时候会出现“InternalServerError”的提示,log日志报错:S3_USE_A...
- 用离散标记重塑人体姿态:VQ-VAE实现关键点组合关系编码
-
在人体姿态估计领域,传统方法通常将关键点作为基本处理单元,这些关键点在人体骨架结构上代表关节位置(如肘部、膝盖和头部)的空间坐标。现有模型对这些关键点的预测主要采用两种范式:直接通过坐标回归或间接通过...
- B 客户端流RPC (clientstream Client Stream)
-
客户端编写一系列消息并将其发送到服务器,同样使用提供的流。一旦客户端写完消息,它就等待服务器读取消息并返回响应gRPC再次保证了单个RPC调用中的消息排序在客户端流RPC模式中,客户端会发送多个请...
- 我的模型我做主02——训练自己的大模型:简易入门指南
-
模型训练往往需要较高的配置,为了满足友友们的好奇心,这里我们不要内存,不要gpu,用最简单的方式,让大家感受一下什么是模型训练。基于你的硬件配置,我们可以设计一个完全在CPU上运行的简易模型训练方案。...
- 开源项目MessageNest打造个性化消息推送平台多种通知方式
-
今天介绍一个开源项目,MessageNest-可以打造个性化消息推送平台,整合邮件、钉钉、企业微信等多种通知方式。定制你的消息,让通知方式更灵活多样。开源地址:https://github.c...
- 使用投机规则API加快页面加载速度
-
当今的网络用户要求快速导航,从一个页面移动到另一个页面时应尽量减少延迟。投机规则应用程序接口(SpeculationRulesAPI)的出现改变了网络应用程序接口(WebAPI)领域的游戏规则。...
- JSONP安全攻防技术
-
关于JSONPJSONP全称是JSONwithPadding,是基于JSON格式的为解决跨域请求资源而产生的解决方案。它的基本原理是利用HTML的元素标签,远程调用JSON文件来实现数据传递。如果...
- 大数据Doris(六):编译 Doris遇到的问题
-
编译Doris遇到的问题一、js_generator.cc:(.text+0xfc3c):undefinedreferenceto`well_known_types_js’查找Doris...
- 网页内嵌PDF获取的办法
-
最近女王大人为了通过某认证考试,交了2000RMB,官方居然没有给线下教材资料,直接给的是在线教材,教材是PDF的但是是内嵌在网页内,可惜却没有给具体的PDF地址,无法下载,看到女王大人一点点的截图保...
- 印度女孩被邻居家客人性骚扰,父亲上门警告,反被围殴致死
-
微信的规则进行了调整希望大家看完故事多点“在看”,喜欢的话也点个分享和赞这样事儿君的推送才能继续出现在你的订阅列表里才能继续跟大家分享每个开怀大笑或拍案惊奇的好故事啦~话说只要稍微关注新闻的人,应该...
- 下周重要财经数据日程一览 (1229-0103)
-
下周焦点全球制造业PMI美国消费者信心指数美国首申失业救济人数值得注意的是,下周一希腊还将举行第三轮总统选举需要谷歌日历同步及部分智能手机(安卓,iPhone)同步日历功能的朋友请点击此链接,数据公布...
- PyTorch 深度学习实战(38):注意力机制全面解析
-
在上一篇文章中,我们探讨了分布式训练实战。本文将深入解析注意力机制的完整发展历程,从最初的Seq2Seq模型到革命性的Transformer架构。我们将使用PyTorch实现2个关键阶段的注意力机制变...
- 聊聊Spring AI的EmbeddingModel
-
序本文主要研究一下SpringAI的EmbeddingModelEmbeddingModelspring-ai-core/src/main/java/org/springframework/ai/e...
- 前端分享-少年了解过iframe么
-
iframe就像是HTML的「内嵌画布」,允许在页面中加载独立网页,如同在画布上叠加另一幅动态画卷。核心特性包括:独立上下文:每个iframe都拥有独立的DOM/CSS/JS环境(类似浏...
- 一周热门
- 最近发表
- 标签列表
-
- HTML 教程 (33)
- HTML 简介 (35)
- HTML 实例/测验 (32)
- HTML 测验 (32)
- HTML 参考手册 (28)
- JavaScript 和 HTML DOM 参考手册 (32)
- HTML 拓展阅读 (30)
- HTML中如何键入空格 (27)
- HTML常用标签 (29)
- HTML文本框样式 (31)
- HTML滚动条样式 (34)
- HTML5 浏览器支持 (33)
- HTML5 新元素 (33)
- HTML5 WebSocket (30)
- HTML5 代码规范 (32)
- HTML5 标签 (717)
- HTML5 标签 (已废弃) (75)
- HTML5电子书 (32)
- HTML5开发工具 (34)
- HTML5小游戏源码 (34)
- HTML5模板下载 (30)
- HTTP 状态消息 (33)
- HTTP 方法:GET 对比 POST (33)
- 键盘快捷键 (35)
- 标签 (226)