React实现拖拽特效
前言
最近,我看到一个工程师的个人网站上,采用了拖拽作品集的互动特效,既有趣又吸引眼球。经过一些研究,我发现其实借助一些现成的套件,就能轻松实现这样的效果。今天就带大家一起看看,如何通过 Framer Motion 来制作这个特效吧!
安装 React + Framer Motion
我将使用 React 和 Framer Motion 来实现这个特效。首先,用 Vite 来快速搭建一个 React 开发环境:
npm create vite@latest my-react-app -- --template react
执行完成后就依序执行以下指令,分别是:
cd my-react-app: 移动到my-react-app资料夹npm install: 安装相关依赖npm run dev: 执行
cd my-react-app
npm install
npm run dev
打开浏览器,访问 http://localhost:5173,你应该会看到一个基础的 React 应用如下图。
并且也可以看到你的资料夹结构,如果只是想练习这个特效,直接改 App.jsx 就好
下一步就是安装 Framer Motion,直接在终端机打上以下指令就好:
npm install framer-motion
引入图片 & 创建容器
我们将图片保存在 ./public/drag-img/ 文件夹中,并用数组来存储图片路径。通过 Array.map() 方法,我们可以轻松地渲染出所有的图片。
const images = ['/drag-img/image-1.png','/drag-img/image-2.png','/drag-img/image-3.png','/drag-img/image-4.png','/drag-img/image-5.png','/drag-img/image-6.png','/drag-img/image-7.png','/drag-img/image-8.png','/drag-img/image-9.png','/drag-img/image-10.png','/drag-img/image-11.png','/drag-img/image-12.png','/drag-img/image-13.png','/drag-img/image-14.png',
];
然后,我们创建一个容器来存放这些图片。为了方便后续操作,我们使用 useRef 来引用容器,以便后面获取容器的宽高。
export default function DragImg() {const containerRef = useRef(null);return (<divref={containerRef}className='drag-img__container'>{/* 图片渲染 */}</div>);
}
接下来,稍微修改一下style样式
.drag-img__container {position: relative;width: 100vw;height: 100vh;overflow: hidden;background: #f0f0f0;
}
渲染图片 & 随机位置
通过刚才定义的 images 数组来渲染所有图片。这里使用的是 motion.img 标签,这样才能使用 Framer Motion 提供的动画和交互功能。
export default function DragImg() {const containerRef = useRef(null);return (<divref={containerRef}className='drag-img__container'>{images.map((src, index) => (<motion.imgkey={index}src={src}className='drag-img__img'alt={`Image ${index + 1}`}/>))}</div>);
}
.drag-img__img {width: 200px;aspect-ratio: 4/3;object-fit: contain;padding: 4px;position: absolute;background: rgba(255, 255, 255, 0.2);border-radius: 6px;box-shadow: 0 0 2px rgba(0, 0, 0, 0.1);cursor: grab;
}
稍微调整图片的宽度、比例,并让他的 position 是 absolute,其他就是一些小装饰,例如 padding、shadow 等等,现在所有的图片都会在右上角,因为我们还没调整他们的位置
接著可以利用 JavaScript 来随机图片的位置,顺便随机旋转的角度,让他有种散落在整个 container 的感觉。
{images.map((src, index) => (<motion.imgkey={index}src={src}className='drag-img__img'alt={`Image ${index + 1}`}style={{top: `${Math.random() * (window.innerHeight - 200)}px`,left: `${Math.random() * (window.innerWidth - 150)}px`,rotate: `${Math.random() * 40 - 20}deg`,}}/>
))}

实现拖拽效果
接下来,重点来了——使用 Framer Motion 来实现拖拽效果。由于 Framer Motion 内置了 drag 属性,整个过程非常简单,只需要在 motion.img 上添加 drag 属性,并指定拖拽范围。
{images.map((src, index) => (<motion.imgkey={index}src={src}className="drag-img__img"alt={`Image ${index + 1}`}style={{top: `${Math.random() * (window.innerHeight - 200)}px`,left: `${Math.random() * (window.innerWidth - 150)}px`,rotate: `${Math.random() * 40 - 20}deg`,}}dragdragConstraints={containerRef} // 限制拖拽范围whileDrag={{ scale: 1.1, rotate: 0 }} // 拖拽时的样式调整/>
))}
这里,我们添加了 dragConstraints,使图片只能在容器内拖动,不会超出边界。同时,使用 whileDrag 来调整拖拽时图片的缩放和旋转效果。
完整代码示例
到此为止就完全搞定了,其实非常简单!以下附上全部的代码:
import { useRef } from 'react';
import { motion } from 'framer-motion';const images = ['/drag-img/image-1.png','/drag-img/image-2.png','/drag-img/image-3.png','/drag-img/image-4.png','/drag-img/image-5.png','/drag-img/image-6.png','/drag-img/image-7.png','/drag-img/image-8.png','/drag-img/image-9.png','/drag-img/image-10.png','/drag-img/image-11.png','/drag-img/image-12.png','/drag-img/image-13.png','/drag-img/image-14.png',
];export default function DragImg() {const containerRef = useRef(null);return (<divref={containerRef}className='drag-img__container'>{images.map((src, index) => (<motion.imgkey={index}src={src}className='drag-img__img'alt={`Image ${index + 1}`}style={{top: `${Math.random() * (window.innerHeight - 200)}px`,left: `${Math.random() * (window.innerWidth - 150)}px`,rotate: `${Math.random() * 40 - 20}deg`,}}dragdragConstraints={containerRef}whileDrag={{ scale: 1.1, rotate: 0 }}/>))}</div>);
}
.drag-img__container {position: relative;width: 100vw;height: 100vh;overflow: hidden;background: #f0f0f0;
}.drag-img__img {width: 200px;aspect-ratio: 4/3;object-fit: contain;padding: 4px;position: absolute;background: rgba(255, 255, 255, 0.2);border-radius: 6px;box-shadow: 0 0 2px rgba(0, 0, 0, 0.1);cursor: grab;
}
通过以上步骤就成功创建了一个可以拖拽的图片展示特效。操作非常简单,而且效果十分酷炫!快来试试看吧!
相关文章:
React实现拖拽特效
前言 最近,我看到一个工程师的个人网站上,采用了拖拽作品集的互动特效,既有趣又吸引眼球。经过一些研究,我发现其实借助一些现成的套件,就能轻松实现这样的效果。今天就带大家一起看看,如何通过 Framer Mo…...
【竞技宝】LOL:ning直播再次锐评
北京时间1月18日,目前英雄联盟LPL2025正在如火如荼的进行之中,很多队伍都已经打完了新赛季的首场比赛,其中就包括AL战队,AL在休赛期进行了大幅度的人员调整,整体实力相比之前增强了不少,在16日的比赛中,AL3-0轻松击败LGD拿下了赛季开门红,而AL的打野选手tarzan在本场比赛中表现…...
ThreeJS能力演示——界面点选交互能力
1、支持界面点选 点选模型整体思路是:根据camera位置作为起始点,叠加鼠标相对位置作为偏置,摄像头方向作为射线方向。 根据射线方向中的遇到的3D物体列表,第一个遇到的物体作为被点选的物体。 // 鼠标事件处理let selectedObjec…...
flutter的web页面
有几个服务器 有几个后台 直接通过web端进去虽然说很方便,但… 于是把web页面镶嵌到应用里面去, 这样就换了个方式打开web页面了 比如这里有有个列表 这里是写死了,活的列表可以通过io去获取 import package:flutter/material.dart; imp…...
2025.1.17——三、SQLi regexp正则表达式|
题目来源:buuctf [NCTF2019]SQLi1 目录 一、打开靶机,整理信息 二、解题思路 step 1:正常注入 step 2:弄清关键字黑名单 1.目录扫描 2.bp爆破 step 3:根据过滤名单构造payload step 4:regexp正则注…...
虚幻基础2:gameplay框架
能帮到你的话,就给个赞吧 😘 文章目录 ue框架:gameplay组成game modeactorcomponent player controllergame state 工作流程 ue框架:gameplay 组成 game mode 游戏类型和规则。可以控制游戏的开始与结束以及一些其他功能。 ac…...
使用 Go 语言生成样式美观的 PDF 文件
文章精选推荐 1 JetBrains Ai assistant 编程工具让你的工作效率翻倍 2 Extra Icons:JetBrains IDE的图标增强神器 3 IDEA插件推荐-SequenceDiagram,自动生成时序图 4 BashSupport Pro 这个ides插件主要是用来干嘛的 ? 5 IDEA必装的插件&…...
鸿蒙-点击Notification通知并打开App的具体页面
意图通知 获取router事件中传递参数并跳转 目前点击通知消息打开应用的指定页面,通过为通知添加行为意图的方式。也就是在wants的parameters中设置自定义参数,然后在UIAbility的onNewWant或者onCreate方法中 解析配置的自定义参数信息判断跳转不同页面&a…...
非科班转码第5年零241天
文章目录 非科班转码第5年零241天第一份工作鸭梨山大同事的帮助第二份工作新公司学到很多出海计划 非科班转码第5年零241天 第一份工作 2019年5月24日,我从机械工程转码后找到第一份工作——图像算法工程师,能得到这份工作纯属偶然,当时公司…...
数据库:MongoDB命令行帮助解释
MongoDB命令: mongodmongosmongoperrormongoexportmongofilesmongoimportmongorestoreMongostat MongoDB包中的核心组件包括: mongod 是 MongoDB 的核心服务器进程,负责数据存储和管理。mongos 是分片集群的路由进程,负责将请求路由到正确…...
MongoDB单机版安装
MongoDB单机版安装 在CentOS Linux release 7.9.2009 (Core)下安装MongoDB的步骤如下: 1 创建用户和组(可选,根据需要) 如果您希望以非root用户运行MongoDB服务,可以创建一个专用的用户和组。 groupadd mongodb us…...
Azure面试
文章目录 项目地址一、Azure Storage1. What are the benefits of Azure Storage? 二、汇总 项目地址 教程作者:教程地址: 代码仓库地址: 所用到的框架和插件: dbt airflow一、Azure Storage 1. What are the bene…...
在.NET用C#将Word文档转换为HTML格式
将Word文档转换为HTML格式尤其具有显著的优势,它不仅能够确保文档内容在多种设备和平台上保持一致灵活的显示,还便于通过网络进行传播和集成到各种Web应用中。随着越来越多的企业和开发者寻求更灵活、更具兼容性的文件处理方式,.NET框架下的C…...
macOS 安装JDK17
文章目录 前言介绍新特性下载安装1.下载完成后打开downloads 双击进行安装2.配置环境变量3.测试快速切换JDK 小结 前言 近期找开源软件,发现很多都已经使用JDK17springboot3 了,之前的JDK8已经被替换下场,所以今天就在本机安装了JDK17&#…...
Django SimpleUI 自定义功能实战
1. 引言 Django SimpleUI 是一个基于 Django 的后台管理界面美化工具,旨在帮助开发者快速构建现代化的后台管理系统。除了默认的功能外,SimpleUI 还支持高度自定义,开发者可以根据需求添加各种实用功能。本文将详细介绍如何在 Django SimpleUI 中实现自定义功能,包括数据同…...
C语言/C++自然序列重排列——相邻序号不相邻问题⭐
同类题目:C语言自然序列重排——相邻元素的差值集合恰好有 k 个不同的值。⭐⭐-CSDN博客 题目描述(难度⭐) 一场针对 n 学生的考试将在一个又长又窄的房间里举行,因此学生们将按某种顺序排成一行。老师怀疑相邻编号的学生…...
Spring boot面试题---- Spring boot项目运行原理
1.启动流程概述 Spring Boot 的启动是从一个带有main方法的主类开始的。这个主类通常会有一个@SpringBootApplication注解。这个注解是一个组合注解,它包含了@Configuration、@EnableAutoConfiguration和@ComponentScan。@Configuration注解表明这个类是一个配置类,它可以定义…...
Qt/C++ 基于 QGraphicsView 的绘图软件 (附源码下载链接)
基于 Qt 的 QGraphicsView 绘图软件项目进行深入讲解,分析其核心代码与功能实现,帮助开发者理解 QGraphicsView 的用法。 项目概览 该项目实现了一个简单的绘图应用,用户可以在界面中创建和编辑矩形、椭圆、直线、多边形和文本等图形对象。功…...
如何使用 useMemo 和 memo 优化 React 应用性能?
使用 useMemo 和 memo 优化 React 应用性能 在构建复杂的 React 应用时,性能优化是确保应用流畅运行的关键。React 提供了多种工具来帮助开发者优化组件的渲染和计算逻辑,其中 useMemo 和 memo 是两个非常有用的 Hook。本文将详细介绍这两个工具的使用方…...
数据结构(链表 哈希表)
在Python中,链表和哈希表都是常见的数据结构,可以用来存储和处理数据。 链表是一种线性数据结构,由一系列节点组成,每个节点包含一个数据元素和一个指向下一个节点的指针。链表可以用来实现栈、队列以及其他数据结构。Python中可…...
内存分配函数malloc kmalloc vmalloc
内存分配函数malloc kmalloc vmalloc malloc实现步骤: 1)请求大小调整:首先,malloc 需要调整用户请求的大小,以适应内部数据结构(例如,可能需要存储额外的元数据)。通常,这包括对齐调整,确保分配的内存地址满足特定硬件要求(如对齐到8字节或16字节边界)。 2)空闲…...
树莓派超全系列教程文档--(62)使用rpicam-app通过网络流式传输视频
使用rpicam-app通过网络流式传输视频 使用 rpicam-app 通过网络流式传输视频UDPTCPRTSPlibavGStreamerRTPlibcamerasrc GStreamer 元素 文章来源: http://raspberry.dns8844.cn/documentation 原文网址 使用 rpicam-app 通过网络流式传输视频 本节介绍来自 rpica…...
通过Wrangler CLI在worker中创建数据库和表
官方使用文档:Getting started Cloudflare D1 docs 创建数据库 在命令行中执行完成之后,会在本地和远程创建数据库: npx wranglerlatest d1 create prod-d1-tutorial 在cf中就可以看到数据库: 现在,您的Cloudfla…...
如何在看板中体现优先级变化
在看板中有效体现优先级变化的关键措施包括:采用颜色或标签标识优先级、设置任务排序规则、使用独立的优先级列或泳道、结合自动化规则同步优先级变化、建立定期的优先级审查流程。其中,设置任务排序规则尤其重要,因为它让看板视觉上直观地体…...
【单片机期末】单片机系统设计
主要内容:系统状态机,系统时基,系统需求分析,系统构建,系统状态流图 一、题目要求 二、绘制系统状态流图 题目:根据上述描述绘制系统状态流图,注明状态转移条件及方向。 三、利用定时器产生时…...
OPenCV CUDA模块图像处理-----对图像执行 均值漂移滤波(Mean Shift Filtering)函数meanShiftFiltering()
操作系统:ubuntu22.04 OpenCV版本:OpenCV4.9 IDE:Visual Studio Code 编程语言:C11 算法描述 在 GPU 上对图像执行 均值漂移滤波(Mean Shift Filtering),用于图像分割或平滑处理。 该函数将输入图像中的…...
初学 pytest 记录
安装 pip install pytest用例可以是函数也可以是类中的方法 def test_func():print()class TestAdd: # def __init__(self): 在 pytest 中不可以使用__init__方法 # self.cc 12345 pytest.mark.api def test_str(self):res add(1, 2)assert res 12def test_int(self):r…...
AI+无人机如何守护濒危物种?YOLOv8实现95%精准识别
【导读】 野生动物监测在理解和保护生态系统中发挥着至关重要的作用。然而,传统的野生动物观察方法往往耗时耗力、成本高昂且范围有限。无人机的出现为野生动物监测提供了有前景的替代方案,能够实现大范围覆盖并远程采集数据。尽管具备这些优势…...
脑机新手指南(七):OpenBCI_GUI:从环境搭建到数据可视化(上)
一、OpenBCI_GUI 项目概述 (一)项目背景与目标 OpenBCI 是一个开源的脑电信号采集硬件平台,其配套的 OpenBCI_GUI 则是专为该硬件设计的图形化界面工具。对于研究人员、开发者和学生而言,首次接触 OpenBCI 设备时,往…...
tomcat入门
1 tomcat 是什么 apache开发的web服务器可以为java web程序提供运行环境tomcat是一款高效,稳定,易于使用的web服务器tomcathttp服务器Servlet服务器 2 tomcat 目录介绍 -bin #存放tomcat的脚本 -conf #存放tomcat的配置文件 ---catalina.policy #to…...
