Fabric.js 喷雾笔刷 从入门到放肆

news/2024/5/18 22:52:45/文章来源:https://blog.csdn.net/weixin_39415598/article/details/126989736

theme: smartblue

我报名参加金石计划1期挑战——瓜分10万奖池,这是我的第18篇文章,点击查看活动详情


本文简介

点赞 + 关注 + 收藏 = 学会了

喷雾笔刷 SprayBrushfabric.js 提供的一个很好玩的工具,而且 fabric.js 也封装好了很多非常方便的属性让我们配置,用起来非常简单的。

先看看效果:

01.gif

常规配置

喷雾笔刷作为一款笔刷工具,要使用它首先要让画布开启“绘画模式”。

isDrawingMode 设为 true 就可以开启。

02.gif

```html

```

如果不在画布初始化时开启绘画模式,也可以之后再开启

js canvas.isDrawingMode = true

如果想切换回普通模式,只需把 isDrawingMode 改回 false 即可。

注册喷雾笔刷

喷雾笔刷叫 SprayBrush

注册喷雾笔刷时需要把初始化的画布传进去,然后再赋值给 canvas.freeDrawingBrush

03.gif

```js // 省略部分代码

canvas.freeDrawingBrush = new fabric.SprayBrush(canvas)

// 更推荐的写法 let sprayBrush = new fabric.SprayBrush(canvas) canvas.freeDrawingBrush = sprayBrush ```

我更推荐把 sprayBrush 保存到一个变量里,这样比较方便之后配置各种效果。

除了上面这种写法,也可以这样写:

```js // 省略部分代码

let sprayBrush = new fabric.SprayBrush() sprayBrush.initialize(canvas) canvas.freeDrawingBrush = sprayBrush ```

initialize()SprayBrush 初始化的一个方法,里面接收的参数是当前的画布 canvas

设置笔刷粗细

为了方便其他属性演示,所以先把笔刷的宽度设置大点。

04.gif

```js // 省略部分代码

sprayBrush.width = 200 ```

width 属性就是用来设置画笔粗细的,数值越大画笔就越粗。

设置喷雾密度

可以使用 density 属性设置喷雾密度,数值越大密度就越大。

density 的默认值是 20。

05.gif

```js // 省略部分代码

sprayBrush.width = 200 sprayBrush.density = 100 // 设置喷雾密度 ```

density 设置得小点对比一下

js sprayBrush.width = 200 sprayBrush.density = 10

06.gif

很直观的看到差距了。

设置喷点大小

“喷点” 就是喷雾中的每一个点,设置喷点宽度的属性名叫 dotWidth

dotWidth 默认值是 1。数值越大,喷点就越大。

07.gif

```js // 省略部分代码

sprayBrush.width = 200 // 设置喷雾宽度

sprayBrush.dotWidth = 10 // 设置喷点大小 ```

设置喷点方差

可以使用 dotWidthVariance 属性设置喷点的方差。

dotWidthVariance 可以在规定范围内随机生成大小不一的喷点。

dotWidthVariance 的默认值是1。数值越大,喷点随机大小就越大。

08.gif

```js // 省略部分代码

sprayBrush.width = 200 sprayBrush.dotWidthVariance = 10 ```

设置了 dotWidthVariance 后,dotWidth 的意义就不大了。

防重叠

喷雾笔刷默认是会删除重叠的点,官方文档说这是处于性能考虑的原因。

如果不希望删除重叠的点,可以将 optimizeOverlapping 设为 false

```js // 省略部分代码

sprayBrush.optimizeOverlapping = false ```

设置喷点的随机不透明度

可以通过 randomOpacity 属性设置喷点的不透明度是否随机。

```js // 省略部分代码

sprayBrush.randomOpacity = true ```

设置喷雾阴影

在喷雾笔刷的文档里没提到阴影,但既然基础笔刷可以设置阴影,喷雾笔刷同样也可以设置阴影的。

09.gif

```js // 省略部分代码

sprayBrush.width = 200 sprayBrush.dotWidthVariance = 10

// 设置阴影效果 sprayBrush.shadow = new fabric.Shadow({ blur: 10, offsetX: 10, offsetY: 10, color: '#30e3ca' }) ```

设置喷雾颜色

喷雾笔刷可以通过 color 设置喷雾颜色的,但官方文档好像忘了写这个属性了。

10.gif

```js // 省略部分代码

sprayBrush.color = 'pink' ```

事件

前面讲到 initialize() 方法可以初始化画笔,除此之外喷雾笔刷还有其他事件方法。

喷雾准备生成前和生成后

喷雾也是一种路径,所以可以监听 canvas 的路径生成时的周期。

在喷雾准备生成前,可以监听 before:path:created ;喷雾生成后,可以监听 path:created

```js // 省略部分代码

// 准备生成前 canvas.on('before:path:created', opt => { console.log(opt.path) })

// 生成后 canvas.on('path:created', opt => { console.log(opt.path) }) ```

鼠标按下时 onMouseDown

js sprayBrush.onMouseDown = function(t) { this.sprayChunks.length = 0, this.canvas.clearContext(this.canvas.contextTop), this._setShadow(), this.addSprayChunk(t), this.render(this.sprayChunkPoints) }

鼠标移动时 onMouseMove

js sprayBrush.onMouseMove = function(t) { !0 === this.limitedToCanvasSize && this._isOutSideCanvas(t) || (this.addSprayChunk(t), this.render(this.sprayChunkPoints)) }

松开鼠标时 onMouseUp

js sprayBrush.onMouseUp = function() { var t = this.canvas.renderOnAddRemove; this.canvas.renderOnAddRemove = !1; for (var e = [], i = 0, r = this.sprayChunks.length; i < r; i++) for (var n = this.sprayChunks[i], s = 0, o = n.length; s < o; s++) { var a = new fabric.Rect({ width: n[s].width, height: n[s].width, left: n[s].x + 1, top: n[s].y + 1, originX: "center", originY: "center", fill: this.color }); e.push(a) } this.optimizeOverlapping && (e = this._getOptimizedRects(e)); var c = new fabric.Group(e); this.shadow && c.set("shadow", new fabric.Shadow(this.shadow)), this.canvas.fire("before:path:created", { path: c }), this.canvas.add(c), this.canvas.fire("path:created", { path: c }), this.canvas.clearContext(this.canvas.contextTop), this._resetShadow(), this.canvas.renderOnAddRemove = t, this.canvas.requestRenderAll() }

注意上面的注释,找到 circle 那段就是本例的重点


以上就是喷雾的基础用法,如果都搞明白了,那就做2个案例练练手呗~

🔴 修改喷点图形

喷雾的生成其实关键是在 onMouseUp 事件。

我们看到官方的代码中,生成喷雾使用了 Reat 元素作为喷点

我有个大胆的想法,如果把 Rect 改成其他元素是否可以生成其他图形的喷雾呢?

于是我用了 圆形 Circle

11.png

```js // 省略部分代码

sprayBrush.onMouseUp = function() { var t = this.canvas.renderOnAddRemove; this.canvas.renderOnAddRemove = !1; for (var e = [], i = 0, r = this.sprayChunks.length; i < r; i++) for (let n = this.sprayChunks[i], s = 0, o = n.length; s < o; s++) {

// 改成圆形喷头 !!!!!!!!!!!!!!!!!const circle = new fabric.Circle({radius: n[s].width,top: n[s].y + 1,left: n[s].x + 1,originX: "center",originY: "center",fill: this.color})e.push(circle)
}

this.optimizeOverlapping && (e = this.getOptimizedRects(e)); let c = new fabric.Group(e); this.shadow && c.set("shadow", new fabric.Shadow(this.shadow)), this.canvas.fire("before:path:created", { path: c }), this.canvas.add(c), this.canvas.fire("path:created", { path: c }), this.canvas.clearContext(this.canvas.contextTop), this.resetShadow(), this.canvas.renderOnAddRemove = t, this.canvas.requestRenderAll() } ```

注意上面的代码注释,搜索 Circle 那行看看吧,这是修改喷点图形的关键点。

这个圆形喷雾是不是有点像 圆形笔刷 CircleBrush 的效果~

喷点除了改成圆形,还可以设置成其他图形,其他图形可以查看 Fabric.js 入门 - 基础图形 。

甚至还能自定义图形。

12.png

要实现这种自定义图形,可以查看 Fabric.js 自定义子类,创建属于自己的图形 ,然后在 onMouseUp() 事件中,把图形改成自己创建的那个即可。

🎨 随机色喷雾

理解了前面 “修改喷点图形” 的话,那要搞个随机色喷雾也是洒洒水啦~

只需把每个图形的 fill 设置成不一样就行了。

13.png

```js sprayBrush.onMouseUp = function() { var t = this.canvas.renderOnAddRemove; this.canvas.renderOnAddRemove = !1; for (var e = [], i = 0, r = this.sprayChunks.length; i < r; i++) for (let n = this.sprayChunks[i], s = 0, o = n.length; s < o; s++) {

// 每个点都生成自己的随机色(rgb)!!!!!!!!!!!!!!!let r = Math.floor(Math.random() * 255)let g = Math.floor(Math.random() * 255)let b = Math.floor(Math.random() * 255)let rect = new fabric.Rect({width: n[s].width,height: n[s].width,left: n[s].x + 1,top: n[s].y + 1,originX: "center",originY: "center",fill: `rgb(${r}, ${g}, ${b})` // 每个图形的填充色都不一样了!!!!!!!!!!!});e.push(rect)
}

this.optimizeOverlapping && (e = this.getOptimizedRects(e)); let c = new fabric.Group(e); this.shadow && c.set("shadow", new fabric.Shadow(this.shadow)), this.canvas.fire("before:path:created", { path: c }), this.canvas.add(c), this.canvas.fire("path:created", { path: c }), this.canvas.clearContext(this.canvas.contextTop), this.resetShadow(), this.canvas.renderOnAddRemove = t, this.canvas.requestRenderAll() } ```

好了,上面这个案例其实只是提供一个思路。这种随机色的配色是真的丑。。。

代码仓库

⭐ 喷雾笔刷

推荐阅读

👍《Fabric.js 从入门到_ _ _ _ _ _》

👍《Fabric.js 铅笔笔刷》

👍《Fabric.js 拖拽平移画布》

👍《Fabric.js 使用图片遮盖画布(前景图)》

点赞 + 关注 + 收藏 = 学会了

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.luyixian.cn/news_show_12150.aspx

如若内容造成侵权/违法违规/事实不符,请联系dt猫网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

ASP.NET 错误机制

部分包括设置为 On 的 mode 属性。mode 属性用于控制错误重定向发生的方式。例如&#xff0c;如果您正开发应用程序&#xff0c;则很可能希望查看实际的 ASP.NET 错误信息&#xff0c;并且不希望被重定向到更用户友好的错误页。mode 属性包括以下设置&#xff1a; On&#xff1…

【C语言】规范掌握C语言函数|数组名的妙用|指针快速入门|综合使用小案例

✅作者简介&#xff1a;热爱后端语言的大学生&#xff0c;CSDN内容合伙人 ✨精品专栏&#xff1a;C面向对象 文章目录1、函数的结构1.1、无参无返1.2、无参有返1.3、有参无返1.4、有参有返1.5、主函数中的调用及运行效果2、C语言数组创建和基本操作2.1、数组创建的方式2.2、数组…

CVE-2017-0143(永恒之蓝)漏洞复现By metasploit

一、永恒之蓝介绍 永恒之蓝是在Windows的SMB服务处理SMB v1请求时发生的漏洞,这个漏洞导致攻击者在目标系统上可以执行任意代码。通过永恒之蓝漏洞会扫描开放445文件共享端口的Windows机器,无需用户任何操作,只要开机上网,不法分子就能在电脑和服务器中植入勒索软件、远程控…

笔记-设备相关知识

目录 设备类 接口类 Windows 如何安装设备 步骤 1&#xff1a;标识设备 步骤 2&#xff1a;选择设备的驱动程序包 搜索驱动程序包 选择驱动程序 步骤 3&#xff1a;已安装设备的驱动程序包 硬件 为设备创建硬件 ID 根枚举设备的硬件 ID 获取设备的硬件 ID 列表 硬件…

低浓度阿拉特津(ATZ)诱导MCF-7细胞增殖的生物标志物发现及其代谢组学机制探究

低浓度阿拉特津&#xff08;ATZ&#xff09;诱导MCF-7细胞增殖的生物标志物发现及其代谢组学机制探究 文章标题&#xff1a;Integrated metabolomics and transcriptomics analysis reveals new biomarkers and mechanistic insights on atrazine exposures in MCF7 cells 发…

【转】详谈判断点在多边形内的七种方法

原帖地址: https://blog.csdn.net/WilliamSun0122/article/details/77994526 射线法时间复杂度:O(n) 适用范围:任意多边形算法思想:以被测点Q为端点,向任意方向作射线(一般水平向右作射线),统计该射线与多边形的交点数。如果为奇数,Q在多边形内;如果为偶数,Q在多边…

用工具刺探主机通信和用系统ping命令有何区别(新人常犯的错误)

ping是操作系统自带的命令,经常用来刺探对端主机是否在线,通信能否畅通。它的原理是在调用ping命令时驱动TCP/IP协议栈的ICMP模块发送icmp echo request消息,待对方主机的ICMP模块收到后,会自动回复icmp echo response消息。本方收到icmp echo response即可确认对方主机在线…

15天深度复习JavaWeb的详细笔记(十)——Filter、Listener、Ajax

文章目录demo10-Filter、Listener、Ajax1&#xff0c;Filter1.1 Filter概述1.2 Filter快速入门1.2.1 开发步骤1.2.2 代码演示1.3 Filter执行流程1.4 Filter拦截路径配置1.5 过滤器链1.5.1 概述1.5.2 代码演示2&#xff0c;Listener2.1 概述2.2 分类2.3 代码演示3&#xff0c;Aj…

Dev C++中窗口输出中文问题解决

1、window+R+regedit调出注册表 2、点击Dec_Dev-Cpp_ConsolePauser.exe 3、鼠标左键双击“CodePage”,弹出设置页面。选择“十进制”,输入65001 4、右键点击运行窗口的图标,选择属性,取消使用旧版控制台5、重新运行完美!!!

vue后台系统管理项目-角色权限分配管理功能

⭐️⭐️⭐️ 作者&#xff1a;船长在船上 &#x1f6a9;&#x1f6a9;&#x1f6a9; 主页&#xff1a;来访地址船长在船上的博客 &#x1f528;&#x1f528;&#x1f528; 简介&#xff1a;CSDN前端领域优质创作者&#xff0c;资深前端开发工程师&#xff0c;专注前端开发…

Java_面向对象的三大特征之_继承

继承 如何继承一个类&#xff1f; 使用继承有什么好处&#xff1f; super如何使用&#xff1f; 重写的概念使用&#xff1f; 继承的关键字是什么&#xff1f; 抽象的关键字是什么&#xff1f; 抽象类有什么特点&#xff1f; Final关键字都能修饰什么&#xff1f;修饰完…

DolphinScheduler任务调度源码剖析

1.数据表 t_ds_process_definition&#xff1a;工作流定义表 t_ds_process_definition_log t_ds_process_instance&#xff1a;工作流运行实例表 t_ds_task_definition&#xff1a;任务定义表 t_ds_task_definition_log t_ds_process_task_relation&#xff1a;任务关系表 …

Appium入门自动化测试(6)—— Appium 常用方法的自己动手封装

Appium 常用方法的自己动手封装 前言 阅读此文大概需要5分钟&#xff0c;之后需要自己动手实践。 之前我们已经对Appium的一些常用的API有所了解&#xff0c;在实际测试过程中&#xff0c;大多数自动化测试工程师&#xff0c;尤其是UI自动化测试工程师&#xff0c;遇到更多的…

c语言分层理解(枚举和联合体)

文章目录1. 枚举1.1 枚举定义1.2 枚举常量的理解1.3 枚举的优点1.4 枚举大小1.5 枚举变量的使用2.联合体&#xff08;共同体&#xff09;2.1 联合体定义1.2 联合体特点1.2.1 联合体实现判断大小端1.3 联合体的大小1.3.1 实例一1.3.2 实例二1. 枚举 1.1 枚举定义 枚举的意思就是…

第四:Fiddler抓包教程(4)-会话面板和HTTP会话数据操作详解

一.会话列表 (Session list) 概览 1.Fiddler抓取到的每条http请求&#xff08;每一条称为一个session&#xff09;&#xff0c;会话列表 主要是Fiddler所抓取到的每一条http请求都会显示到这里。主要包含了请求的ID编号、状态码、协议、主机名、URL、内容类型、body大小、进程…

基于安卓(Android)的即时实时聊天APP软件

安卓即时聊天软件 实习目的及要求 Android 开发提高&#xff1a; 提供&#xff16;个基础样例代码&#xff0c;发挥想象力和创造力对其中一个进行改进和提高&#xff0c;比如&#xff1a;增加程序的功能&#xff0c;改进程序的人机交互性&#xff0c;以及提高程序运行的性能…

出海非洲新启示?传音控股供应链合作的本土化融合

近日&#xff0c;美媒发表报道称&#xff0c;中国品牌正成为非洲智能手机市场领导者。该报道透露&#xff0c;传音控股的智能机在第二季度市场份额占比为48%&#xff0c;超过三星&#xff0c;进一步夯实非洲智能机市场领导者的地位。 在全球经济疲弱且市场竞争越发激烈的背景下…

CSS中的BFC是什么?

BFC就是符合一些特性的HTML标签 1、什么是BFC? BFC格式化上下文 指一个独立的渲染区域&#xff0c;或者说是一个隔离的独立容器&#xff0c;可以理解为一个独立的封闭空间。无论如何不会影响到它的外面。 2、形成BFC的条件 浮动元素&#xff0c;float除none以外的值&#…

SDN实验一

1、基础版 a) 第1步Mininet运行结果截图b) 第2步的执行结果截图c) 第3步提交修改过的“学号.py”代码、Mininet运行结果 #!/usr/bin/env pythonfrom mininet.net import Mininet from mininet.node import Controller, RemoteController, OVSController from mininet.node impo…

有关anaconda常见指令操作

有关anaconda常见指令操作 查看已安装的包 conda list [PACKAGE]卸载包 conda uninstall PACKAGE更新包 conda update PACKAGE查看虚拟环境及其位置 conda env list创建环境 conda create --name [my_env]激活环境 conda activate my_env退出环境 conda deactivate删除环境 co…