Commit 61b0adb4 authored by timel's avatar timel Committed by Chunchi Che

feat: animation demo

parent 9c5dd29f
......@@ -11,6 +11,7 @@
"@ant-design/pro-components": "^2.4.4",
"@dnd-kit/core": "^6.0.8",
"@dnd-kit/sortable": "^7.0.2",
"@react-spring/web": "^9.7.2",
"@testing-library/jest-dom": "^5.16.5",
"@testing-library/react": "^13.4.0",
"@testing-library/user-event": "^13.5.0",
......@@ -3093,6 +3094,73 @@
"react-dom": ">=16.9.0"
}
},
"node_modules/@react-spring/animated": {
"version": "9.7.2",
"resolved": "https://registry.npmjs.org/@react-spring/animated/-/animated-9.7.2.tgz",
"integrity": "sha512-ipvleJ99ipqlnHkz5qhSsgf/ny5aW0ZG8Q+/2Oj9cI7LCc7COdnrSO6V/v8MAX3JOoQNzfz6dye2s5Pt5jGaIA==",
"dependencies": {
"@react-spring/shared": "~9.7.2",
"@react-spring/types": "~9.7.2"
},
"peerDependencies": {
"react": "^16.8.0 || ^17.0.0 || ^18.0.0"
}
},
"node_modules/@react-spring/core": {
"version": "9.7.2",
"resolved": "https://registry.npmjs.org/@react-spring/core/-/core-9.7.2.tgz",
"integrity": "sha512-fF512edZT/gKVCA90ZRxfw1DmELeVwiL4OC2J6bMUlNr707C0h4QRoec6DjzG27uLX2MvS1CEatf9KRjwZR9/w==",
"dependencies": {
"@react-spring/animated": "~9.7.2",
"@react-spring/rafz": "~9.7.2",
"@react-spring/shared": "~9.7.2",
"@react-spring/types": "~9.7.2"
},
"funding": {
"type": "opencollective",
"url": "https://opencollective.com/react-spring/donate"
},
"peerDependencies": {
"react": "^16.8.0 || ^17.0.0 || ^18.0.0"
}
},
"node_modules/@react-spring/rafz": {
"version": "9.7.2",
"resolved": "https://registry.npmjs.org/@react-spring/rafz/-/rafz-9.7.2.tgz",
"integrity": "sha512-kDWMYDQto3+flkrX3vy6DU/l9pxQ4TVW91DglQEc11iDc7shF4+WVDRJvOVLX+xoMP7zyag1dMvlIgvQ+dvA/A=="
},
"node_modules/@react-spring/shared": {
"version": "9.7.2",
"resolved": "https://registry.npmjs.org/@react-spring/shared/-/shared-9.7.2.tgz",
"integrity": "sha512-6U9qkno+9DxlH5nSltnPs+kU6tYKf0bPLURX2te13aGel8YqgcpFYp5Av8DcN2x3sukinAsmzHUS/FRsdZMMBA==",
"dependencies": {
"@react-spring/rafz": "~9.7.2",
"@react-spring/types": "~9.7.2"
},
"peerDependencies": {
"react": "^16.8.0 || ^17.0.0 || ^18.0.0"
}
},
"node_modules/@react-spring/types": {
"version": "9.7.2",
"resolved": "https://registry.npmjs.org/@react-spring/types/-/types-9.7.2.tgz",
"integrity": "sha512-GEflx2Ex/TKVMHq5g5MxQDNNPNhqg+4Db9m7+vGTm8ttZiyga7YQUF24shgRNebKIjahqCuei16SZga8h1pe4g=="
},
"node_modules/@react-spring/web": {
"version": "9.7.2",
"resolved": "https://registry.npmjs.org/@react-spring/web/-/web-9.7.2.tgz",
"integrity": "sha512-7qNc7/5KShu2D05x7o2Ols2nUE7mCKfKLaY2Ix70xPMfTle1sZisoQMBFgV9w/fSLZlHZHV9P0uWJqEXQnbV4Q==",
"dependencies": {
"@react-spring/animated": "~9.7.2",
"@react-spring/core": "~9.7.2",
"@react-spring/shared": "~9.7.2",
"@react-spring/types": "~9.7.2"
},
"peerDependencies": {
"react": "^16.8.0 || ^17.0.0 || ^18.0.0",
"react-dom": "^16.8.0 || ^17.0.0 || ^18.0.0"
}
},
"node_modules/@remix-run/router": {
"version": "1.5.0",
"resolved": "https://registry.npmjs.org/@remix-run/router/-/router-1.5.0.tgz",
......@@ -30586,6 +30654,56 @@
"rc-util": "^5.29.2"
}
},
"@react-spring/animated": {
"version": "9.7.2",
"resolved": "https://registry.npmjs.org/@react-spring/animated/-/animated-9.7.2.tgz",
"integrity": "sha512-ipvleJ99ipqlnHkz5qhSsgf/ny5aW0ZG8Q+/2Oj9cI7LCc7COdnrSO6V/v8MAX3JOoQNzfz6dye2s5Pt5jGaIA==",
"requires": {
"@react-spring/shared": "~9.7.2",
"@react-spring/types": "~9.7.2"
}
},
"@react-spring/core": {
"version": "9.7.2",
"resolved": "https://registry.npmjs.org/@react-spring/core/-/core-9.7.2.tgz",
"integrity": "sha512-fF512edZT/gKVCA90ZRxfw1DmELeVwiL4OC2J6bMUlNr707C0h4QRoec6DjzG27uLX2MvS1CEatf9KRjwZR9/w==",
"requires": {
"@react-spring/animated": "~9.7.2",
"@react-spring/rafz": "~9.7.2",
"@react-spring/shared": "~9.7.2",
"@react-spring/types": "~9.7.2"
}
},
"@react-spring/rafz": {
"version": "9.7.2",
"resolved": "https://registry.npmjs.org/@react-spring/rafz/-/rafz-9.7.2.tgz",
"integrity": "sha512-kDWMYDQto3+flkrX3vy6DU/l9pxQ4TVW91DglQEc11iDc7shF4+WVDRJvOVLX+xoMP7zyag1dMvlIgvQ+dvA/A=="
},
"@react-spring/shared": {
"version": "9.7.2",
"resolved": "https://registry.npmjs.org/@react-spring/shared/-/shared-9.7.2.tgz",
"integrity": "sha512-6U9qkno+9DxlH5nSltnPs+kU6tYKf0bPLURX2te13aGel8YqgcpFYp5Av8DcN2x3sukinAsmzHUS/FRsdZMMBA==",
"requires": {
"@react-spring/rafz": "~9.7.2",
"@react-spring/types": "~9.7.2"
}
},
"@react-spring/types": {
"version": "9.7.2",
"resolved": "https://registry.npmjs.org/@react-spring/types/-/types-9.7.2.tgz",
"integrity": "sha512-GEflx2Ex/TKVMHq5g5MxQDNNPNhqg+4Db9m7+vGTm8ttZiyga7YQUF24shgRNebKIjahqCuei16SZga8h1pe4g=="
},
"@react-spring/web": {
"version": "9.7.2",
"resolved": "https://registry.npmjs.org/@react-spring/web/-/web-9.7.2.tgz",
"integrity": "sha512-7qNc7/5KShu2D05x7o2Ols2nUE7mCKfKLaY2Ix70xPMfTle1sZisoQMBFgV9w/fSLZlHZHV9P0uWJqEXQnbV4Q==",
"requires": {
"@react-spring/animated": "~9.7.2",
"@react-spring/core": "~9.7.2",
"@react-spring/shared": "~9.7.2",
"@react-spring/types": "~9.7.2"
}
},
"@remix-run/router": {
"version": "1.5.0",
"resolved": "https://registry.npmjs.org/@remix-run/router/-/router-1.5.0.tgz",
......@@ -19,11 +19,19 @@ export default async (move: MsgMove) => {
const to = move.to;
const reason = move.reason;
const card = cardStore.at(from.location, from.controler, from.sequence);
card.zone = to.location;
card.sequence = to.sequence;
card.position = to.position;
card.code = code;
cardStore.move(
code,
{
zone: from.location,
controller: from.controler,
sequence: from.sequence,
},
{
zone: to.location,
controller: to.controler,
sequence: to.sequence,
}
);
// FIXME: 考虑超量素材的情况
......
......@@ -2,6 +2,8 @@ import { CardData, CardMeta, CardText, fetchCard, ygopro } from "@/api";
import { proxy } from "valtio";
import { Interactivity } from "./matStore/types";
const { HAND, GRAVE, REMOVED, DECK, EXTRA, MZONE, SZONE } = ygopro.CardZone;
/**
* 场上某位置的状态,
* 以后会更名为 BlockState
......@@ -44,6 +46,25 @@ class CardStore {
);
}
}
move(
code: number,
from: { zone: ygopro.CardZone; controller: number; sequence: number },
to: { zone: ygopro.CardZone; controller: number; sequence: number }
) {
// TODO:考虑超量素材的情况
const fromCards = this.at(from.zone, from.controller);
const toCards = this.at(to.zone, to.controller);
const target = this.at(from.zone, from.controller, from.sequence);
if ([HAND, GRAVE, REMOVED, DECK, EXTRA].includes(from.zone))
fromCards.forEach((c) => c.sequence > from.sequence && c.sequence--);
if ([HAND, GRAVE, REMOVED, DECK, EXTRA].includes(to.zone))
toCards.forEach((c) => c.sequence >= to.sequence && c.sequence++);
target.zone = to.zone;
target.controller = to.controller;
target.sequence = to.sequence;
target.code = code;
}
}
export const cardStore = proxy(new CardStore());
......
import { cardStore } from "@/stores";
import { useSnapshot } from "valtio";
import { FC } from "react";
import { FC, memo, useEffect, useState } from "react";
import { ygopro } from "@/api";
import {
useSpring,
SpringValue,
animated,
useSpringRef,
} from "@react-spring/web";
export const Test = () => {
return (
......@@ -16,25 +22,46 @@ export const Test = () => {
fontSize: 12,
}}
>
{cardStore.inner.map((cardState) => (
<Card state={cardState} key={cardState.uuid} />
{cardStore.inner.map((cardState, i) => (
<Card idx={i} key={cardState.uuid} />
))}
</div>
);
};
export const Card: FC<{ state: (typeof cardStore.inner)[number] }> = ({
state,
}) => {
const snap = useSnapshot(state);
const show = ![ygopro.CardZone.DECK].includes(snap.zone);
export const Card: FC<{ idx: number }> = memo(({ idx }) => {
const snap = useSnapshot(cardStore.inner[idx]);
const [show, setShow] = useState(false);
const api = useSpringRef();
const props = useSpring({
ref: api,
from: { x: 0 },
});
useEffect(() => {
setShow(
[
ygopro.CardZone.HAND,
ygopro.CardZone.MZONE,
ygopro.CardZone.SZONE,
].includes(snap.zone)
);
api.start({
to: {
x: props.x.get() === 100 ? 0 : 100,
},
});
}, [snap.zone]); // 添加 show 到依赖项中
return show ? (
<div>
<animated.div
style={{
transform: props.x.to((value) => `translateX(${value}px)`),
background: "white",
}}
>
<div>code: {snap.code}</div>
{/* <div>zone: {ygopro.CardZone[snap.zone]}</div> */}
<div>{(Math.random() * 100).toFixed(0)}</div>
</div>
</animated.div>
) : (
<></>
);
};
});
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment