基于 Vue + Interact.js 实现可拖拽缩放柜子设计器

实现可视化设计工具已成为前端开发的重要挑战之一。本文将介绍如何使用 Vue.js 配合 Interact.js 库创建一个功能完整的橱柜设计器,兼容PC和移动终端。

核心功能

  • 网格系统:基于 CSS 网格实现精准定位

  • 拖拽功能:实现单元格的自由移动

  • 缩放控制:8个方向的手柄缩放支持

  • 智能吸附:移动和缩放时自动吸附到网格

支持拖拽、缩放、网格吸附等核心功能。

技术实现

1. 网格系统设计

.cabinet {background-image: linear-gradient(#ddd 1px, transparent 1px),linear-gradient(90deg, #ddd 1px, transparent 1px);background-size: 10px 10px;
}

通过 CSS 线性渐变创建网格背景,提供视觉参考,设置 GRID = 10 作为基础吸附粒度。

2. 数据结构设计

data() {return {cols: 40,    // 横向格数rows: 30,    // 纵向格数cells: [     // 单元格数据{ id: uid(), x: 0, y: 0, w: 100, h: 100 },{ id: uid(), x: 110, y: 0, w: 100, h: 100 }],handles: ["tl", "tm", "tr", "ml", "mr", "bl", "bm", "br"], // 8个手柄curCell: null // 当前选中单元格};
}

3. Interact.js 集成

记得先install interact.js

拖拽实现
bindDrag() {const vm = this; // <-- 缓存 thisinteract(".cell").draggable({modifiers: [interact.modifiers.snap({targets: [interact.createSnapGrid({ x: 10, y: 10 })]}),interact.modifiers.restrictRect({restriction: "parent",elementRect: { left: 0, right: 1, top: 0, bottom: 1 }})],listeners: {move(e) {const cell = vm.cells.find(c => c.id === e.target.dataset.id);cell.x = Math.round((cell.x + e.dx) / 10) * 10;cell.y = Math.round((cell.y + e.dy) / 10) * 10;}}});
}
缩放实现
bindResize() {const vm = this; // <-- 缓存 thisinteract(".cell").resizable({edges: {left: ".resize-handle.tl, .resize-handle.ml, .resize-handle.bl",right: ".resize-handle.tr, .resize-handle.mr, .resize-handle.br",top: ".resize-handle.tl, .resize-handle.tm, .resize-handle.tr",bottom: ".resize-handle.bl, .resize-handle.bm, .resize-handle.br"},modifiers: [interact.modifiers.snapSize({targets: [interact.createSnapGrid({ x: 10, y: 10 })]}),interact.modifiers.restrictRect({ restriction: "parent" })],listeners: {move(e) {const cell = vm.cells.find(c => c.id === e.target.dataset.id);cell.x = Math.round(e.rect.left / 10) * 10;cell.y = Math.round(e.rect.top / 10) * 10;cell.w = Math.round(e.rect.width / 10) * 10;cell.h = Math.round(e.rect.height / 10) * 10;}}});
}

4. 手势控制优化

为防止移动端和桌面端的默认行为干扰交互体验,添加了以下优化:

.cabinet {touch-action: none; /* 新标准 */-webkit-user-select: none; /* 旧 webkit */-webkit-touch-callout: none;user-select: none;
}

5. 响应式设计

通过计算属性动态计算画布尺寸:

computed: {cabStyle() {return {width: this.cols * GRID + "px",height: this.rows * GRID + "px",backgroundSize: `${GRID}px ${GRID}px`};}
}

关键问题与解决方案

1. 事件冒泡处理

@click.stop="curCell = cell.id"

使用 Vue 的 .stop 修饰符阻止事件冒泡,确保点击单元格时不会触发画布的点击事件。

2. 精准定位

cellStyle(c) {return {transform: `translate(${c.x}px, ${c.y}px)`,width: c.w + "px",height: c.h + "px"};
}

使用 transform: translate() 而非 top/left 实现更流畅的定位效果。

总结

通过 Vue.js 和 Interact.js 的组合,我们实现了一个功能完整的柜子设计器。这种方案不仅适用于柜子设计,还可以扩展到其他可视化设计场景,如室内设计、UI 布局等。关键在于合理的数据结构设计和与第三方库的有效整合。

Interact.js 提供了强大的底层交互支持,而 Vue.js 则负责数据管理和界面渲染,两者结合可以快速构建出高性能的可视化编辑工具。

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

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

相关文章

今日科技速递 | 智能芯片突围、AI+行动深化、服贸会科技成果亮相

今日科技速递 | 智能芯片突围、AI行动深化、服贸会科技成果亮相 一、乐鑫科技涨停&#xff1a;Wi-Fi 6/7 与 AIoT 芯片双路径创新驱动 新闻回顾 2025 年 8 月 27 日&#xff0c;科创板公司 乐鑫科技&#xff08;688018&#xff09; 盘中一度涨停&#xff0c;股价达到 225 元&am…

PDF压缩如何平衡质量与体积?

在日常工作或者生活中&#xff0c;我们常常要处理PDF文档&#xff0c;很多人可能会遇到这样的困扰&#xff1f;使用WPS处理PDF时&#xff0c;部分功能需要付费&#xff0c;这给我们带来了许多不便。 它的使用方式十分简单&#xff0c;你只要双击图标&#xff0c;它就能启动&am…

Flask 之上下文详解:从原理到实战

一、引言&#xff1a;为什么 Flask 需要“上下文”&#xff1f;在 Web 开发中&#xff0c;我们经常需要访问当前请求的信息&#xff08;如 URL、表单数据&#xff09;、当前应用实例&#xff08;如配置、数据库连接&#xff09;或用户会话状态。传统做法是使用全局变量&#xf…

深入探索Vue:前端开发的强大框架

在当今的前端开发领域&#xff0c;Vue作为一款备受瞩目的JavaScript框架&#xff0c;以其简洁易用、高效灵活等特性&#xff0c;赢得了众多开发者的青睐。无论是构建小型的交互页面&#xff0c;还是开发大型的单页应用&#xff0c;Vue都能展现出卓越的性能和出色的表现。本文将…

B树与B+树的原理区别应用

在磁盘存储和内存有序的数据管理中&#xff0c;B 树与 B 树是核心的数据结构&#xff0c;二者均通过 “多路平衡” 特性减少 IO 次数&#xff0c;但在数据存储方式、查询逻辑上存在本质差异。一、B 树&#xff08;Balance Tree&#xff09;&#xff1a;多路平衡搜索树B 树是 “…

从零到一:使用anisble自动化搭建kubernetes集群

在我们云原生俱乐部的暑期学习中&#xff0c;我们了解并学习了需要关于云原生的技术&#xff0c;其中在应用层面上最重要的就是shell编程和ansible&#xff0c;而想要掌握这两项技术离不开的就是实践&#xff0c;而kubernetes是我们云原生技术栈的核心技术&#xff0c;在生产实…

【LangGraph】langgraph.prebuilt.create_react_agent() 函数:快速创建基于 ReAct(Reasoning + Acting)架构的智能代理

本文是对 langgraph.prebuilt.create_react_agent 函数的详细且全面的介绍&#xff0c;涵盖其定义、功能、设计理念、参数、返回值、使用场景、实现原理、示例代码、高级用法、注意事项、与其他方法的对比&#xff0c;以及学习建议。 1. 概述 langgraph.prebuilt.create_react…

北斗导航 | RAIM算法改进方案及性能对比分析报告

github&#xff1a;https://github.com/MichaelBeechan CSDN&#xff1a;https://blog.csdn.net/u011344545 文章目录RAIM算法改进方案及性能对比分析报告一、RAIM算法改进技术框架1.1 多假设分组算法&#xff08;MHSS&#xff09;1.2 动态噪声估计算法1.3 多源信息融合技术二、…

数据结构第8章 排序(竟成)

第 8 章 排序【考纲内容】1.排序的基本概念&#xff1b;2. 直接插入排序&#xff1b;3. 折半插入排序&#xff1b;4. 起泡排序&#xff08;Bubble Sort&#xff09;&#xff1b;5.简单选择排序&#xff1b;6. 希尔排序&#xff08;Shell Sort&#xff09;&#xff1b;7. 快速排…

【学Python自动化】 5. Python 数据结构学习笔记

一、 列表详解 1 列表方法总结方法描述等价操作rust Vec类似操作list.append(x)末尾添加元素a[len(a):] [x]vec.push(x);list.extend(iterable)扩展列表a[len(a):] iterablevec.extend([4, 5, 6]); 或者更高效&#xff1a;vec.extend_from_slice(&[4, 5, 6]);list.inser…

Python爬虫实战:研究Radar chart,构建多维度数据采集和分析系统

1. 引言 1.1 研究背景与意义 在信息爆炸的时代,互联网蕴含的海量数据已成为企业决策、学术研究和产品评估的重要依据。这些数据往往包含多个维度的特征,如电商平台的商品信息涵盖价格、销量、评价、性能参数等,社交媒体的用户数据涉及活跃度、互动量、内容偏好等。传统的单…

[灵动微电子 MM32BIN560CN MM32SPIN0280]读懂电机MCU之串口DMA

在 MM32SPIN560C 微控制器中&#xff0c;串口&#xff08;UART&#xff09;的 DMA 传输可大幅减轻 CPU 负担&#xff0c;实现数据的“自动收发”。结合《MM32SPIN560C 用户手册&#xff08;中文版&#xff09;》中 UART 和 DMA 相关章节&#xff0c;以下从“原理匹配”“配置步…

【机器学习】-torch相关知识01

学习代码时遇到的问题&#xff0c;GPT给的答案&#xff0c;如有错误请指出。 问题1 torch.empty nn.init.xavier 问题2 nn.Parameter 是什么&#xff1f; 问题3 self.add_module 问题4 torch.matmul torch.mm 文章目录问题1 torch.empty nn.init.xavier问题2 nn.Parameter 是什…

Hutool DsFactory多数据源切换

一、简单上手&#xff1a;从配置到使用全流程 DsFactory 的核心优势是零侵入配置&#xff0c;支持多种配置方式&#xff0c;不管是 properties 文件还是代码里直接定义&#xff0c;都能快速初始化数据源。先引依赖&#xff08;Maven&#xff09;&#xff1a; <dependency>…

Mysql中事务隔离级别有哪些?

Mysql中事务隔离级别有哪些&#xff1f; 读未提交&#xff1a; 一个事务可以看到另一个事务尚未提交的数据。可能导致脏读。 读已提交&#xff1a; 一个事务只能看到其他事务提交后的数据。避免了脏读&#xff0c;仍可能引发不可重复读。 可重复读&#xff1a; 可以确保一个事务…

el-carousel在新增或者删除el-carousel-item时默认跳到第一页的原因和解决

现象 使用走马灯效果时 当el-carousel-item增加或者减少时&#xff0c;页会跳到第一页 体验很不友好。 原因 当新增或这删除el-carousel-item时&#xff0c;会触发setActiveIndex&#xff08;props.initialindex&#xff09;, setActiveIndex的行为是小于0或者大于最大页会有一…

人工智能学习:机器学习相关面试题(二)

7、有监督学习和无监督学习的区别 有监督学习&#xff1a; 对具有概念标记&#xff08;分类&#xff09;的训练样本进行 学习&#xff0c;以尽可能对训练样本集外的数据进行 标记&#xff08;分类&#xff09;预测。 这里 &#xff0c;所有的标记&#xff08;分类&#xff09…

python如何下载svg图片

# 生成博客文章框架代码 import datetimeblog_content f"""# Python如何下载SVG图片## 引言 SVG&#xff08;可缩放矢量图形&#xff09;作为一种基于XML的矢量图形格式&#xff0c;在Web开发中广泛应用。本文将介绍如何使用Python从网络下载SVG图片&#xff0…

Linux(一) | 初识Linux与目录管理基础命令掌握

个人主页-爱因斯晨 文章专栏-Linux 最近学习人工智能时遇到一个好用的网站分享给大家&#xff1a; 人工智能学习 文章目录个人主页-爱因斯晨文章专栏-Linux一、前言1.为什么学习Linux2.操作系统概述&#xff1a;3.常见的操作系统&#xff1a;二、初识Linux1.诞生2.什么是Linux…

android-studio 安装

下载地址 国内&#xff1a;https://developer.android.google.cn/studio?hlzh-cn 全国&#xff1a;https://developer.android.com/studio 1.设置 ANDROID_HOME 环境变量 ANDROID_HOME D:\zhy\android-studio\sdk 2. 更新 PATH 环境变量 %ANDROID_HOME%\platform-tools %AN…