[XState] Drag and Drop example (data-state, attr in css)
import { createMachine, assign, interpret } from "xstate"; const elBox = document.querySelector("#box"); const elBody = document.body; const assignPoint = assign({ px: (context, event) => event.clientX, py: (context, event) => event.clientY, }); const assignPosition = assign({ x: (context, event) => { return context.x + context.dx; }, y: (context, event) => { return context.y + context.dy; }, dx: 0, dy: 0, px: 0, py: 0, }); const assignDelta = assign({ dx: (context, event) => { return event.clientX - context.px; }, dy: (context, event) => { return event.clientY - context.py; }, }); const showDelta = (context) => { elBox.dataset.delta = `delta: ${context.dx}, ${context.dy}`; }; const resetPosition = assign({ dx: 0, dy: 0, px: 0, py: 0, }); const machine = createMachine({ initial: "idle", context: { x: 0, y: 0, dx: 0, dy: 0, px: 0, py: 0, }, states: { idle: { on: { mousedown: { actions: assignPoint, target: "dragging", }, }, }, dragging: { on: { mousemove: { actions: [assignDelta, showDelta], // no target! }, mouseup: { actions: assignPosition, target: "idle", }, }, }, }, }); const service = interpret(machine); service.onTransition((state) => { if (state.changed) { console.log(state.context); elBox.dataset.state = state.value; elBox.style.setProperty("--dx", state.context.dx); elBox.style.setProperty("--dy", state.context.dy); elBox.style.setProperty("--x", state.context.x); elBox.style.setProperty("--y", state.context.y); } }); service.start(); elBox.addEventListener("mousedown", (event) => { service.send(event); }); elBody.addEventListener("mousemove", (event) => { service.send(event); }); elBody.addEventListener("mouseup", (event) => { service.send(event); });
Css:
It uses many [data-state] selector
#box[data-state^='dragging'] { opacity: 0.8; box-shadow: 0 0.5rem 1rem rgba(0, 0, 0, 0.4); } #box[data-state='idle'] { transition: all 0.3s ease-in-out; } @import '../../styles/index.scss'; #box { opacity: 0.5; &[data-state='active'] { opacity: 1; } &:before { content: attr(data-delta); position: absolute; bottom: 100%; margin-bottom: 0.5rem; left: 0; background: black; padding: 0.25rem; color: white; font-family: monospace; border-radius: inherit; white-space: nowrap; } }
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· SQL Server 2025 AI相关能力初探
· Linux系列:如何用 C#调用 C方法造成内存泄露
· AI与.NET技术实操系列(二):开始使用ML.NET
· 记一次.NET内存居高不下排查解决与启示
· 探究高空视频全景AR技术的实现原理
· 阿里最新开源QwQ-32B,效果媲美deepseek-r1满血版,部署成本又又又降低了!
· Manus重磅发布:全球首款通用AI代理技术深度解析与实战指南
· 开源Multi-agent AI智能体框架aevatar.ai,欢迎大家贡献代码
· 被坑几百块钱后,我竟然真的恢复了删除的微信聊天记录!
· AI技术革命,工作效率10个最佳AI工具
2017-07-21 [Docker] Create Docker Volumes for Persistent Storage
2017-07-21 [Algorithms] Binary Search Algorithm using TypeScript
2017-07-21 [Node] Setup an Nginx Proxy for a Node.js App
2017-07-21 [Node] Run Local DevDependencies from the Command Line with npx
2016-07-21 [React Native] Up and Running