[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;
  }
}
复制代码

 

posted @   Zhentiw  阅读(182)  评论(0编辑  收藏  举报
编辑推荐:
· 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
点击右上角即可分享
微信分享提示