当前位置: 首页 > news >正文

基于Fabric.js的选座布局系统开发笔记

项目概述

最近开发了一个简单的选座布局系统,主要用于会议、活动或餐厅等场景的座位和桌子布局设计。系统基于HTML5 Canvas和Fabric.js库实现,支持添加座位、桌子,并能保存布局数据。

技术栈

• HTML5 Canvas:作为绘图的基础

• Fabric.js:强大的Canvas操作库,简化了Canvas对象的创建、选择和变换

• JavaScript:实现交互逻辑

核心功能实现

  1. 初始化画布

const canvas = new fabric.Canvas('seatCanvas');

使用Fabric.js创建Canvas实例,相比原生Canvas API,Fabric提供了更高级的对象模型和事件系统。

  1. 添加座位功能

function addSeat() {fabric.Image.fromURL('seat.png', (img) => {img.scaleToWidth(40);const label = new fabric.Text('S' + seatCount, {fontSize: 12,originX: 'center',originY: 'center',fill: 'black',});const group = new fabric.Group([img, label], {left: 100,top: 100,hasRotatingPoint: true,lockScalingFlip: true,hasControls: true,selectable: true});canvas.add(group);seatCount++;});
}

关键点:
• 使用fabric.Image.fromURL加载座位图片

• 创建文本标签并组合成组

• 设置组的交互属性(旋转、缩放等)

  1. 添加桌子功能

类似座位功能,但使用不同的图片和标签前缀:

function addTable() {fabric.Image.fromURL('table.png', (img) => {img.scaleToWidth(60);const label = new fabric.Text('T' + tableCount, {fontSize: 12,originX: 'center',originY: 'center',fill: 'black',});const group = new fabric.Group([img], {left: 200,top: 200,hasRotatingPoint: true,lockScalingFlip: true,hasControls: true,selectable: true});canvas.add(group);tableCount++;});
}
  1. 保存布局功能

document.getElementById('saveBtn').addEventListener('click', () => {const layoutData = canvas.getObjects().map(obj => {return {id: obj._objects?.[1]?.text || '',left: obj.left,top: obj.top};});console.log('保存的布局:', JSON.stringify(layoutData, null, 2));alert('布局已输出到控制台!');
});

保存当前画布上所有对象的位置和ID信息,便于后续加载或存储到数据库。

  1. 复制粘贴功能

通过监听键盘事件实现Ctrl+C/V的复制粘贴:

document.addEventListener('keydown', (event) => {if (event.ctrlKey && event.key === 'c') {// 复制逻辑...}if (event.ctrlKey && event.key === 'v') {// 粘贴逻辑...}
});

效果图

开发心得

  1. Fabric.js的优势:
    • 简化了Canvas对象的创建和管理

    • 内置了丰富的交互功能(选择、旋转、缩放等)

    • 提供了便捷的分组功能

  2. 遇到的挑战:
    • 图片加载的异步处理需要注意

    • 复制粘贴多个对象时需要处理对象集合

    • 保存数据时需要合理设计数据结构

  3. 改进方向:
    • 添加网格对齐功能

    • 实现布局的导入/导出

    • 增加更多类型的元素(如舞台、讲台等)

    • 添加撤销/重做功能

相关文章:

基于Fabric.js的选座布局系统开发笔记

项目概述 最近开发了一个简单的选座布局系统,主要用于会议、活动或餐厅等场景的座位和桌子布局设计。系统基于HTML5 Canvas和Fabric.js库实现,支持添加座位、桌子,并能保存布局数据。 技术栈 • HTML5 Canvas:作为绘图的基础 •…...

PHP怎样连接MySQL数据库?

方法一&#xff1a;使用 mysqli 扩展 mysqli 是 MySQL 的改进版扩展&#xff0c;提供了面向对象和过程化的接口。 面向对象风格 <?php$servername "localhost"; $username "your_username"; $password "your_password"; $dbname &quo…...

将飞帆制作的网页作为 Vue 2 组件引入到自己网页中使用

飞帆平台有一个功能&#xff1a;不仅所有的网页都是通过控件搭建而成&#xff0c;而且生成的网页又是一个大控件&#xff0c;可以导入到你自己的网页使用。 这篇文章&#xff0c;我们要讲的就是如何将飞帆生成的网页作为控件&#xff08;组件&#xff09;导入到自己的网页中。…...

Python制作简易PDF查看工具PDFViewerV1.0显示优化

原文说明 为不破坏原文结构,因此功能优化不在原文中维护了。关于这款工具原文请通过下面链接访问。Python制作简易PDF查看工具PDFViewerV1.0 这款小工具基本功能已经可以作为一款文档浏览器使用,但还有一些美中不足的地方,本文将介绍对文本查找功能的优化调整。 优化效果 …...

YOLOv11改进有效涨点专栏:从理论到实战的深度优化指南

## YOLOv11的进化之路 在目标检测领域,YOLO系列算法始终保持着革命性的创新步伐。YOLOv11作为该系列的最新演进版本,在保持实时检测优势的同时,通过架构层面的深度优化实现了精度与速度的平衡。本文将从**七大核心模块**出发,系统性地解析针对YOLOv11的有效改进方案,涵盖从…...

【EDA软件】【设计约束和分析操作方法】

1. 设计约束 设计约束主要分为物理约束和时序约束。 物理约束主要包括I/O接口约束&#xff08;如引脚分配、电平标准设定等物理属性的约束&#xff09;、布局约束、布线约束以及配置约束。 时序约束是FPGA内部的各种逻辑或走线的延时&#xff0c;反应系统的频率和速度的约束…...

JVM基础认知:JVM到底是什么?为什么它如此重要?

随着 Java 语言在企业级应用、互联网服务、嵌入式系统等领域的广泛采用&#xff0c;JVM&#xff08;Java Virtual Machine&#xff0c;Java虚拟机&#xff09;成为了支撑整个生态的核心基础。初学者往往会把注意力集中在 Java 代码本身&#xff0c;却忽视了背后那台“看不见的机…...

javassist

使用javassist获取参数名 1&#xff0c;添加依赖 需要在pom.xml文件中添加下面的依赖&#xff1a; <dependency><groupId>org.javassist</groupId><artifactId>javassist</artifactId><version>3.28.0-GA</version> </depende…...

【C++算法】66.栈_比较含退格的字符串

文章目录 题目链接&#xff1a;题目描述&#xff1a;解法C 算法代码&#xff1a; 题目链接&#xff1a; 844. 比较含退格的字符串 题目描述&#xff1a; 解法 用字符串来模拟栈。 C 算法代码&#xff1a; class Solution { public:bool backspaceCompare(string s, string t…...

游戏引擎学习第235天:在 Windows 上初始化 OpenGL

奇怪有问题 之前没注意到 这个问题是Count 0 GlobalConstants_Renderer_UsedDebugCamer 打开的话会有Bug Count是零的话就不让排序了 game.h: 查阅 TODO 列表 大家好&#xff0c;欢迎来到 game Hero&#xff0c;这是一档我们在直播中一起编写完整游戏的节目。不幸的是&a…...

FPGA系列之DDS信号发生器设计(DE2-115开发板)

一、IP核 IP(Intellectual Property)原指知识产权、著作权等&#xff0c;在IC设计领域通常被理解为实现某种功能的设计。IP模块则是完成某种比较复杂算法或功能&#xff08;如FIR滤波器、FFT、SDRAM控制器、PCIe接口、CPU核等&#xff09;并且参数可修改的电路模块&#xff0c…...

修改Theme SHELL美化panel

安装 使用 使用Tweaks进行设置 需要创建.themes文件夹&#xff0c;在当前目录下 mkdir ~/.themes从官网下载文件 https://www.gnome-look.org/p/1013030 将打包压缩文件移动到~/themes&#xff0c;并解压 tar -xvf 01-Flat-Remix-Light-20250413.tar.xz然后使用 按 Alt F2…...

Sentinel源码—5.FlowSlot借鉴Guava的限流算法二

大纲 1.Guava提供的RateLimiter限流使用示例 2.Guava提供的RateLimiter简介与设计 3.继承RateLimiter的SmoothBursty源码 4.继承RateLimiter的SmoothWarmingUp源码 3.继承RateLimiter的SmoothBursty源码 (1)SmoothBursty的初始化流程 (2)SmoothBursty的初始化完成后的变量…...

自由学习记录(56)

从贴图空间&#xff08;texture space&#xff09;将值还原到切线空间&#xff08;tangent space&#xff09;向量 tangentNormal.xy (packedNormal.xy * 2 - 1) * _BumpScale; 背后的知识点&#xff1a;法线贴图中的 RGB 是在 0~1 范围内编码的向量 所以贴图法线是怎么“压…...

计算机网络八股——HTTP协议与HTTPS协议

前言&#xff1a; 到时候我想要写一篇文章就是&#xff1a;在浏览器中输入URL并按下回车会发生什么&#xff1f; 然后将几篇文章全部串联到一起&#xff0c;现在几天的任务就是将这里的每个小部分进行一个详细的介绍 HTTP1.1简述与特性 Web 上的通信都是建⽴在 HTTP 协议上的…...

JAVAEE(网络原理—UDP报头结构)

我们本篇文章要讲的是UDP的报头结构以及注意事项。 下面呢&#xff0c;我先说一下UDP是什么&#xff1f; 1.UDP是什么&#xff1f; UDP是一种网络协议。网络协议是计算机网络中&#xff0c;为了使不同设备之间能够准确、高效地进行数据交换和通信&#xff0c;而预先制定的一…...

Redis-分布式锁

Redis-分布式锁 文章目录 Redis-分布式锁1.基本原理和不同方式实现方式对比2.Redis分布式锁的基本实现思路3.分布式锁误删问题一4.分布式锁误删问题二5.Redission1.功能介绍2.快速入门3.可重入锁原理4.锁重试和WatchDog机制1.锁重试2. WatchDog 机制&#xff08;锁自动续期&…...

如何优雅地为 Axios 配置失败重试与最大尝试次数

在 Vue 3 中&#xff0c;除了使用自定义的 useRequest 钩子函数外&#xff0c;还可以通过 axios 的拦截器 或 axios-retry 插件实现接口请求失败后的重试逻辑。以下是两种具体方案的实现方式&#xff1a; 方案一&#xff1a;使用 axios 拦截器实现重试 实现步骤&#xff1a; 通…...

Windows使用SonarQube时启动脚本自动关闭

一、解决的问题 Windows使用SonarQube时启动脚本自动关闭&#xff0c;并发生报错&#xff1a; ERROR: Elasticsearch did not exit normally - check the logs at E:\Inori_Code\Year3\SE\sonarqube-25.2.0.102705\sonarqube-25.2.0.102705\logs\sonarqube.log ERROR: Elastic…...

MYSQL初阶(暂为自用草稿)

目录 基本操作 database操作 table操作 数据类型 INT类型 bit类型 FLOAT类型 CHAR类型 DATE类型 SEL类型 表的约束 列约束 NULL DEFAULT PRIMARY KEY UNIQUE KEY 表约束 PRIMARY KEY FOREIGN KEY 其他补充 AUTO_INCREMENT COMMENT ZEROFILL 表的CRUD …...

交换排序——快速排序

交换排序的基本思路&#xff1a;把序列中的两个元素进行比较&#xff0c;根据需求对两个元素进行交换。特点是较大的元素向序列的尾部移动&#xff0c;较小的元素向序列的前部移动。 hoare法 在序列中任取一个元素作为基准值&#xff0c;一趟排序完成之后&#xff0c;以基准值为…...

资源-又在网上淘到金了

前言&#xff1a; 本期再分享网上冲浪发现的特效/动画/视频资源网站。 一、基本介绍&#xff1a; mantissa.xyz&#xff0c;about作者介绍为&#xff1a;Midge “Mantissa” Sinnaeve &#xff08;米奇辛纳夫&#xff09;是一位屡获殊荣的艺术家和导演&#xff0c;提供动画、…...

CSS中的`transform-style`属性:3D变换的秘密武器

在CSS中&#xff0c;当我们尝试创建复杂的3D场景时&#xff0c;transform-style属性变得尤为重要。它决定了子元素是在3D空间中呈现还是被展平到2D平面中。本文将深入探讨transform-style的用法&#xff0c;并通过具体的代码示例来展示如何利用这个属性来增强你的网页设计。 什…...

Step文件无法编辑怎么办?

Step文件无法编辑怎么办&#xff1f; 这里介绍两种方法&#xff0c; 1、 直接导入 准备step文件&#xff0c;solidworks导入后是这样&#xff0c;不能在上面直接编辑 图 1 点击右键&#xff0c;选择解除特征&#xff08;不同版本的可能不太一样&#xff0c;这里是solidworks2…...

从 LabelImg 到 Label Studio!AI 数据标注神器升级,Web 版真香

视频讲解&#xff1a; 从 LabelImg 到 Label Studio&#xff01;AI 数据标注神器升级&#xff0c;Web 版真香 Label Studio 支持图像、文本、音频、视频、时间序列等多类型数据标注&#xff0c;覆盖计算机视觉&#xff08;目标检测、语义分割&#xff09;、自然语言处理&#x…...

纯FPGA实现驱动AD9361配置的思路和实现之一 概述

我们在做ZYNQ系统开发时候做的IP基本都是AXI_LITE_SLAVE&#xff0c;是SLAVE&#xff0c;从设备。就是提供了若干寄存器接口供MASTER进行读写。SLAVE里面的逻辑通过读写动作或者读写的数据进行响应的动作。这种方式的好处是硬件层面可以访问寄存器&#xff0c;软件层面是可以实…...

Nacos配置中心服务端源码解析

文章目录 概述一、配置持久化到数据库二、发布事件2.1、事件发布者端2.1.1、DefaultPublisher#publish2.1.2、DefaultPublisher#run2.1.3、DefaultPublisher#receiveEvent 2.2、事件订阅者端2.2.1、Subscriber#onEvent2.2.2、ConfigCacheService#dump 总结&#xff1a;Nacos 配…...

SAP系统工艺路线的分配物料出现旧版包材

问题:工艺路线的物料错了 这是3月份技术部发现的问题,10000209这个成品有两个版本的BOM, 在创建新版的工艺路线里,发现分配的物料仍然是旧版的物料. 原因排查: 1 BOM中物料错误? 2 选错了生产版本,选了版本1? 3 生产版本设置中的可选BOM错误? 解决&#xff1a;把可选的BOM…...

JVM虚拟机--JVM的组成

(一)JVM的组成 一、JVM介绍 &#xff08;1&#xff09;JVM的作用 我们知道&#xff0c;Java代码要想在计算机中正常运行&#xff0c;就需要经过编译为class二进制字节码文件&#xff0c;而JVM就提供了class二进制字节码的运行环境。 一次编写&#xff0c;到处运行 因为JVM是…...

科学研究:怎么做

科研&#xff08;科学研究&#xff09;​​ 是指通过系统化的方法&#xff0c;探索自然、社会或人文领域的未知问题&#xff0c;以发现新知识、验证理论或解决实际问题的活动。它的核心是​​基于证据的探索与创新​​&#xff0c;旨在推动人类认知和技术的进步。 科研的核心要…...

PyTorch数据操作基础教程:从张量创建到高级运算

本文通过示例代码全面讲解PyTorch中张量的基本操作&#xff0c;包含创建、运算、广播机制、索引切片等核心功能&#xff0c;并提供完整的代码和输出结果。 1. 张量创建与基本属性 import torch# 创建连续数值张量 x torch.arange(12, dtypetorch.float32) print("原始张…...

微服务治理与可观测性

服务注册与发现 核心功能 服务实例动态变化&#xff1a;实例可能因扩缩容、故障或迁移导致IP变动。服务依赖解耦&#xff1a;调用方无需硬编码服务地址&#xff0c;降低耦合度。负载均衡&#xff1a;自动选择健康实例&#xff0c;提升系统可用性。 核心组件 服务注册中心&am…...

如何对docker镜像存在的gosu安全漏洞进行修复——筑梦之路

这里以mysql的官方镜像为例进行说明&#xff0c;主要流程为&#xff1a; 1. 分析镜像存在的安全漏洞具体是什么 2. 根据分析结果有针对性地进行修复处理 3. 基于当前镜像进行修复安全漏洞并复核验证 # 镜像地址mysql:8.0.42 安全漏洞现状分析 dockerhub网站上获取该镜像的…...

OpenCV 04.19 练习

1. 创建一个 PyQt 应用程序&#xff0c;该应用程序能够&#xff1a; 1.使用 OpenCV 加载一张图像。 2.在 PyQt 的窗口中显示这张图像。 3.提供四个按钮&#xff08;QPushButton&#xff09;&#xff1a; - 一个用于将图像转换为灰度图 - 一个用于将图像恢复为原始彩色图 - 一个…...

uv:重新定义Python开发效率的下一代工具链

在Python生态系统中,包管理和项目工具链的复杂性一直是开发者面临的一大挑战。从依赖管理、虚拟环境创建到多版本Python切换,传统的工具链(如pip、virtualenv、poetry等)虽然功能强大,但操作繁琐、性能不足的问题长期存在。而uv的出现,以颠覆性的速度和功能集成,为Pytho…...

【Easylive】​​Gateway模块 bootstrap.yml 解析

【Easylive】项目常见问题解答&#xff08;自用&持续更新中…&#xff09; 汇总版 Gateway模块 bootstrap.yml 常规解析 该配置文件定义了 Spring Cloud Gateway 的核心配置&#xff0c;包括 环境配置、服务注册、动态路由规则 等。以下是逐项解析&#xff1a; 1. 基础配…...

Warcraft Logs [Classic] [WCL] Usage Wizard <HTOC>

‌HTOC&#xff08;十字军的试炼&#xff09;副本中各个BOSS的ID如下‌&#xff1a; ‌629 - 诺森德野兽‌ ‌633 - 加拉克苏斯大王‌ ‌637 - 派系冠军‌ ‌641 - 瓦格里双子‌ ‌645 - 阿努巴拉克‌ encounterID!637 and encounterID!641 encounterID NOT IN (637,641) 伤害 …...

多模态大语言模型arxiv论文略读(二十八)

MM-SAP: A Comprehensive Benchmark for Assessing Self-Awareness of Multimodal Large Language Models in Perception ➡️ 论文标题&#xff1a;MM-SAP: A Comprehensive Benchmark for Assessing Self-Awareness of Multimodal Large Language Models in Perception ➡️…...

JavaScript数据类型简介

在JavaScript中&#xff0c;理解不同的数据类型是掌握这门语言的基础。数据类型决定了变量可以存储什么样的值以及这些值能够执行的操作。JavaScript支持多种数据类型&#xff0c;每种都有其特定的用途和特点。本文将详细介绍JavaScript中的主要数据类型&#xff0c;并提供一些…...

CasualLanguage Model和Seq2Seq模型的区别

**问题1&#xff1a;**Causal Language Modeling 和 Conditional Generation 、Sequence Classification 的区别是什么&#xff1f; 因果语言模型(Causal Language Model)&#xff1a; 预测给定文本序列中的下一个字符&#xff0c;一般用于文本生成、补全句子等&#xff0c;模型…...

在Qt和OSG中动态改变部分3D模型数据

要在Qt和OSG环境中导入3D模型并只对部分数据进行动态改变,你可以采用以下方法: 基本实现步骤 加载模型:使用OSG的读取器加载3D模型文件 访问特定部分:识别并获取模型中需要修改的部分 动态修改:在Qt界面或逻辑中设置修改这些部分的机制 更新显示:确保修改后的模型能够实…...

命令update-alternatives

❯ which pip /home/ying/anaconda3/bin/pipying192 ~ [2]> which pip /usr/bin/pip使用update-alternatives对他们进行管理和切换 快捷方式 和 实际路径不可以相同 所以我这边选择了/usr/local/bin目录作为介质存储快捷方式&#xff0c;另外该快捷方式会自己创建我们只需选…...

10.thinkphp的响应

响应输出 响应操作 1. 响应输出&#xff0c;有好几种&#xff1a;包括return、json()和view()等等&#xff1b; 2. 默认输出方式是以html格式输出&#xff0c;如果你发起json请求&#xff0c;则输出json&#xff1b; 3. 而背后是response对象&#xff0c;可以用response()输…...

【技术派后端篇】技术派中的白名单机制:基于Redis的Set实现

在技术派社区中&#xff0c;为了保证文章的质量和社区的良性发展&#xff0c;所有发布的文章都需要经过审核。然而&#xff0c;并非所有作者的文章都需要审核&#xff0c;我们通过白名单机制来优化这一流程。本文将详细介绍技术派中白名单的实现方式&#xff0c;以及如何利用Re…...

Keil A51汇编伪指令

以下是 Keil A51 汇编器支持的常用伪指令 及其详细说明&#xff0c;涵盖代码结构、数据定义、条件编译等关键功能&#xff0c;结合实际应用场景进行分类和示例&#xff1a; 一、程序结构与地址控制 伪指令功能语法示例说明ORG设置代码/数据起始地址ORG 0000H后续代码从指定地址…...

Windows上安装FFmpeg的详细指南

1.下载FFmpeg 访问FFmpeg官方下载页面&#xff1a;https://ffmpeg.org/download.html 点击"Windows builds from gyan.dev"或"Windows builds by BtbN" gyan.dev版本&#xff1a;https://www.gyan.dev/ffmpeg/builds/ BtbN版本&#xff1a;https://githu…...

jmeter利用csv进行参数化和自动断言

1.测试数据 csv测试数据如下&#xff08;以注册接口为例&#xff09; 2.jemer参数化csv设置 打开 jmeter&#xff0c;添加好线程组、HTTP信息头管理器、CSV 数据文件设置、注册请求、响应断言、查看结果树 1&#xff09; CSV 数据文件设置 若 CSV 中数据包含中文&#xff0c;…...

《Android 应用开发基础教程》——第二章:Activity 与生命周期详解

目录 第二章&#xff1a;Activity 与生命周期详解 2.1 什么是 Activity&#xff1f; 作用&#xff1a; 2.2 创建一个 Activity 示例代码 Manifest 注册&#xff1a; 2.3 Activity 生命周期&#xff08;Life Cycle&#xff09; 生命周期图解&#xff1a; 2.4 生命周期代…...

[Java]反射、String类补充

目录 1、反射定义 2、用途(了解) 3、反射相关的类 4、Class类(反射机制的起源) 4.1、相关方法 5、反射示例 5.1、获取Class对象 5.2、反射的使用 6、反射优点和缺点 7、String类补充 7.1、创建对象的思考 8、字符串常量池 9、再谈String对象创建 10、intern方法 …...

word表格批量操作——宏

word中所有表格代码 这个是表格的模板代码 Sub 表格通用代码() For i ActiveDocument.Tables.Count To 1 Step -1ActiveDocument.Tables (i) Next End Sub1、根据内容自动调整表格 Sub 表格适用内容() For i ActiveDocument.Tables.Count To 1 Step -1ActiveDocument.Tabl…...