Commit b9f974a1 authored by timel's avatar timel

feat: ui size/glowing

parent 7a6f7ae7
...@@ -98,6 +98,22 @@ section#mat { ...@@ -98,6 +98,22 @@ section#mat {
.banish { .banish {
top: calc(var(--top) - var(--row-gap) - var(--height)); top: calc(var(--top) - var(--row-gap) - var(--height));
} }
.deck {
--left: calc(
var(--deck-offset-x) + 2 * (var(--block-width) + var(--col-gap))
);
left: var(--left);
top: calc(
var(--deck-offset-y) + 2 * var(--block-height-m) + 2 * var(--row-gap)
);
transform: translate(-50%, -50%) rotate(calc(-1 * var(--deck-rotate-z)));
height: var(--deck-card-height);
width: calc(var(--deck-card-height) * var(--card-ratio));
&.extra-deck {
left: calc(-1 * var(--left));
transform: translate(-50%, -50%) rotate(var(--deck-rotate-z));
}
}
} }
} }
...@@ -124,8 +140,19 @@ section#mat { ...@@ -124,8 +140,19 @@ section#mat {
); );
display: none; display: none;
} }
.block.disabled {
.disabled-cross { .disabled-cross.show {
display: block; display: block;
}
section#mat {
.block.glowing {
--card-shadow-color: #13a1ff;
box-shadow: 0 0 3px 3px var(--card-shadow-color), 0 0 25px 2px #0099ff87;
background: var(--card-shadow-color);
border-radius: 2px;
.triangle {
display: none;
}
} }
} }
...@@ -9,12 +9,31 @@ import { ...@@ -9,12 +9,31 @@ import {
cardStore, cardStore,
type PlaceInteractivity, type PlaceInteractivity,
placeStore, placeStore,
isMe,
} from "@/stores"; } from "@/stores";
const BgBlock: React.FC<React.HTMLProps<HTMLDivElement>> = (props) => ( const BgBlock: React.FC<
<div {...props} className={classnames("block", props.className)}> React.HTMLProps<HTMLDivElement> & {
disabled?: boolean;
highlight?: boolean;
glowing?: boolean;
}
> = ({
disabled = false,
highlight = false,
glowing = false,
className,
...rest
}) => (
<div
{...rest}
className={classnames("block", className, {
highlight,
glowing,
})}
>
{<DecoTriangles />} {<DecoTriangles />}
{<DisabledCross />} {<DisabledCross disabled={disabled} />}
</div> </div>
); );
...@@ -27,14 +46,13 @@ const BgExtraRow: React.FC<{ ...@@ -27,14 +46,13 @@ const BgExtraRow: React.FC<{
{Array.from({ length: 2 }).map((_, i) => ( {Array.from({ length: 2 }).map((_, i) => (
<BgBlock <BgBlock
key={i} key={i}
className={classnames("extra", { className="extra"
highlight: !!meSnap[i].interactivity || !!opSnap[i].interactivity,
disabled: meSnap[i].disabled || opSnap[i].disabled,
})}
onClick={() => { onClick={() => {
onBlockClick(meSnap[i].interactivity); onBlockClick(meSnap[i].interactivity);
onBlockClick(opSnap[i].interactivity); onBlockClick(opSnap[i].interactivity);
}} }}
disabled={meSnap[i].disabled || opSnap[i].disabled}
highlight={!!meSnap[i].interactivity || !!opSnap[i].interactivity}
/> />
))} ))}
</div> </div>
...@@ -42,47 +60,58 @@ const BgExtraRow: React.FC<{ ...@@ -42,47 +60,58 @@ const BgExtraRow: React.FC<{
}; };
const BgRow: React.FC<{ const BgRow: React.FC<{
isSzone?: boolean; szone?: boolean;
opponent?: boolean; opponent?: boolean;
snap: Snapshot<BlockState[]>; snap: Snapshot<BlockState[]>;
}> = ({ isSzone = false, opponent = false, snap }) => ( }> = ({ szone = false, opponent = false, snap }) => (
<div className={classnames("bg-row", { opponent })}> <div className={classnames("bg-row", { opponent })}>
{Array.from({ length: 5 }).map((_, i) => ( {Array.from({ length: 5 }).map((_, i) => (
<BgBlock <BgBlock
key={i} key={i}
className={classnames({ className={classnames({ szone })}
szone: isSzone,
highlight: !!snap[i].interactivity,
disabled: snap[i].disabled,
})}
onClick={() => onBlockClick(snap[i].interactivity)} onClick={() => onBlockClick(snap[i].interactivity)}
disabled={snap[i].disabled}
highlight={!!snap[i].interactivity}
/> />
))} ))}
</div> </div>
); );
const BgOtherBlocks: React.FC<{ className?: string }> = ({ className }) => ( const BgOtherBlocks: React.FC<{ me?: boolean }> = ({ me }) => {
<div className={classnames("bg-other-blocks", className)}> const snapCards = useSnapshot(cardStore);
<BgBlock className="banish" /> const meController = isMe(0) ? 0 : 1;
<BgBlock className="graveyard" /> const judgeGlowing = (zone: ygopro.CardZone) =>
<BgBlock className="field" /> !!snapCards
</div> .at(zone, meController)
); .reduce((sum, c) => (sum += c.idleInteractivities.length), 0);
const glowingExtra = judgeGlowing(ygopro.CardZone.EXTRA);
const glowingGraveyard = judgeGlowing(ygopro.CardZone.GRAVE);
const glowingBanish = judgeGlowing(ygopro.CardZone.REMOVED);
return (
<div className={classnames("bg-other-blocks", { me, op: !me })}>
<BgBlock className="banish" glowing={me && glowingBanish} />
<BgBlock className="graveyard" glowing={me && glowingGraveyard} />
<BgBlock className="field" />
<BgBlock className="deck" />
<BgBlock className="deck extra-deck" glowing={me && glowingExtra} />
</div>
);
};
export const Bg: React.FC = () => { export const Bg: React.FC = () => {
const snap = useSnapshot(placeStore.inner); const snap = useSnapshot(placeStore.inner);
return ( return (
<div className="mat-bg"> <div className="mat-bg">
<BgRow snap={snap[ygopro.CardZone.SZONE].op} isSzone opponent /> <BgRow snap={snap[ygopro.CardZone.SZONE].op} szone opponent />
<BgRow snap={snap[ygopro.CardZone.MZONE].op} opponent /> <BgRow snap={snap[ygopro.CardZone.MZONE].op} opponent />
<BgExtraRow <BgExtraRow
meSnap={snap[ygopro.CardZone.MZONE].me.slice(5, 7)} meSnap={snap[ygopro.CardZone.MZONE].me.slice(5, 7)}
opSnap={snap[ygopro.CardZone.MZONE].op.slice(5, 7)} opSnap={snap[ygopro.CardZone.MZONE].op.slice(5, 7)}
/> />
<BgRow snap={snap[ygopro.CardZone.MZONE].me} /> <BgRow snap={snap[ygopro.CardZone.MZONE].me} />
<BgRow snap={snap[ygopro.CardZone.SZONE].me} isSzone /> <BgRow snap={snap[ygopro.CardZone.SZONE].me} szone />
<BgOtherBlocks className="me" /> <BgOtherBlocks me />
<BgOtherBlocks className="op" /> <BgOtherBlocks />
</div> </div>
); );
}; };
...@@ -103,4 +132,6 @@ const DecoTriangles: React.FC = () => ( ...@@ -103,4 +132,6 @@ const DecoTriangles: React.FC = () => (
</> </>
); );
const DisabledCross: React.FC = () => <div className="disabled-cross"></div>; const DisabledCross: React.FC<{ disabled: boolean }> = ({ disabled }) => (
<div className={classnames("disabled-cross", { show: disabled })}></div>
);
...@@ -106,7 +106,7 @@ section#mat { ...@@ -106,7 +106,7 @@ section#mat {
} }
} }
.mat-card.highlight .card-shadow { .mat-card.glowing .card-shadow {
--card-shadow-color: #0099ff; --card-shadow-color: #0099ff;
display: block !important; display: block !important;
background: var(--card-shadow-color) !important; background: var(--card-shadow-color) !important;
......
...@@ -89,9 +89,8 @@ export const Card: React.FC<{ idx: number }> = React.memo(({ idx }) => { ...@@ -89,9 +89,8 @@ export const Card: React.FC<{ idx: number }> = React.memo(({ idx }) => {
move(card.location.zone); move(card.location.zone);
}, []); }, []);
const [highlight, setHighlight] = useState(false); const [glowing, setGrowing] = useState(false);
const [classFocus, setClassFocus] = useState(false); const [classFocus, setClassFocus] = useState(false);
// const [shadowOpacity, setShadowOpacity] = useState(0); // TODO: 透明度
// >>> 动画 >>> // >>> 动画 >>>
/** 动画序列的promise */ /** 动画序列的promise */
...@@ -143,7 +142,10 @@ export const Card: React.FC<{ idx: number }> = React.memo(({ idx }) => { ...@@ -143,7 +142,10 @@ export const Card: React.FC<{ idx: number }> = React.memo(({ idx }) => {
// >>> 效果 >>> // >>> 效果 >>>
const idleInteractivities = snap.idleInteractivities; const idleInteractivities = snap.idleInteractivities;
useEffect(() => { useEffect(() => {
setHighlight(!!idleInteractivities.length); setGrowing(
!!idleInteractivities.length &&
[MZONE, SZONE, HAND, TZONE].includes(card.location.zone)
);
}, [idleInteractivities]); }, [idleInteractivities]);
const [dropdownMenu, setDropdownMenu] = useState({ const [dropdownMenu, setDropdownMenu] = useState({
...@@ -295,7 +297,7 @@ export const Card: React.FC<{ idx: number }> = React.memo(({ idx }) => { ...@@ -295,7 +297,7 @@ export const Card: React.FC<{ idx: number }> = React.memo(({ idx }) => {
return ( return (
<animated.div <animated.div
className={classnames("mat-card", { highlight })} className={classnames("mat-card", { glowing })}
style={ style={
{ {
transform: to( transform: to(
......
...@@ -26,12 +26,7 @@ export const moveToDeck: MoveFunc = async (props) => { ...@@ -26,12 +26,7 @@ export const moveToDeck: MoveFunc = async (props) => {
const rightX = DECK_OFFSET_X + 2 * (BLOCK_WIDTH + COL_GAP); const rightX = DECK_OFFSET_X + 2 * (BLOCK_WIDTH + COL_GAP);
const leftX = -rightX; const leftX = -rightX;
const bottomY = const bottomY = DECK_OFFSET_Y + 2 * BLOCK_HEIGHT_M + 2 * ROW_GAP;
DECK_OFFSET_Y +
2 * BLOCK_HEIGHT_M +
BLOCK_HEIGHT_S +
2 * ROW_GAP -
BLOCK_HEIGHT_S;
const topY = -bottomY; const topY = -bottomY;
let x = isMe(controller) ? rightX : leftX; let x = isMe(controller) ? rightX : leftX;
let y = isMe(controller) ? bottomY : topY; let y = isMe(controller) ? bottomY : topY;
......
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