[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;
  }
}

 

[XState] Drag and Drop example (data-state, attr in css)

上一篇:HTML5 规定了一种通过 video 元素


下一篇:WEB前端第十课——CSS字体、文本、列表属性