Commit b9f974a1 authored by timel's avatar timel

feat: ui size/glowing

parent 7a6f7ae7
......@@ -98,6 +98,22 @@ section#mat {
.banish {
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 {
);
display: none;
}
.block.disabled {
.disabled-cross {
display: block;
.disabled-cross.show {
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 {
cardStore,
type PlaceInteractivity,
placeStore,
isMe,
} from "@/stores";
const BgBlock: React.FC<React.HTMLProps<HTMLDivElement>> = (props) => (
<div {...props} className={classnames("block", props.className)}>
const BgBlock: React.FC<
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 />}
{<DisabledCross />}
{<DisabledCross disabled={disabled} />}
</div>
);
......@@ -27,14 +46,13 @@ const BgExtraRow: React.FC<{
{Array.from({ length: 2 }).map((_, i) => (
<BgBlock
key={i}
className={classnames("extra", {
highlight: !!meSnap[i].interactivity || !!opSnap[i].interactivity,
disabled: meSnap[i].disabled || opSnap[i].disabled,
})}
className="extra"
onClick={() => {
onBlockClick(meSnap[i].interactivity);
onBlockClick(opSnap[i].interactivity);
}}
disabled={meSnap[i].disabled || opSnap[i].disabled}
highlight={!!meSnap[i].interactivity || !!opSnap[i].interactivity}
/>
))}
</div>
......@@ -42,47 +60,58 @@ const BgExtraRow: React.FC<{
};
const BgRow: React.FC<{
isSzone?: boolean;
szone?: boolean;
opponent?: boolean;
snap: Snapshot<BlockState[]>;
}> = ({ isSzone = false, opponent = false, snap }) => (
}> = ({ szone = false, opponent = false, snap }) => (
<div className={classnames("bg-row", { opponent })}>
{Array.from({ length: 5 }).map((_, i) => (
<BgBlock
key={i}
className={classnames({
szone: isSzone,
highlight: !!snap[i].interactivity,
disabled: snap[i].disabled,
})}
className={classnames({ szone })}
onClick={() => onBlockClick(snap[i].interactivity)}
disabled={snap[i].disabled}
highlight={!!snap[i].interactivity}
/>
))}
</div>
);
const BgOtherBlocks: React.FC<{ className?: string }> = ({ className }) => (
<div className={classnames("bg-other-blocks", className)}>
<BgBlock className="banish" />
<BgBlock className="graveyard" />
<BgBlock className="field" />
</div>
);
const BgOtherBlocks: React.FC<{ me?: boolean }> = ({ me }) => {
const snapCards = useSnapshot(cardStore);
const meController = isMe(0) ? 0 : 1;
const judgeGlowing = (zone: ygopro.CardZone) =>
!!snapCards
.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 = () => {
const snap = useSnapshot(placeStore.inner);
return (
<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 />
<BgExtraRow
meSnap={snap[ygopro.CardZone.MZONE].me.slice(5, 7)}
opSnap={snap[ygopro.CardZone.MZONE].op.slice(5, 7)}
/>
<BgRow snap={snap[ygopro.CardZone.MZONE].me} />
<BgRow snap={snap[ygopro.CardZone.SZONE].me} isSzone />
<BgOtherBlocks className="me" />
<BgOtherBlocks className="op" />
<BgRow snap={snap[ygopro.CardZone.SZONE].me} szone />
<BgOtherBlocks me />
<BgOtherBlocks />
</div>
);
};
......@@ -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 {
}
}
.mat-card.highlight .card-shadow {
.mat-card.glowing .card-shadow {
--card-shadow-color: #0099ff;
display: block !important;
background: var(--card-shadow-color) !important;
......
......@@ -89,9 +89,8 @@ export const Card: React.FC<{ idx: number }> = React.memo(({ idx }) => {
move(card.location.zone);
}, []);
const [highlight, setHighlight] = useState(false);
const [glowing, setGrowing] = useState(false);
const [classFocus, setClassFocus] = useState(false);
// const [shadowOpacity, setShadowOpacity] = useState(0); // TODO: 透明度
// >>> 动画 >>>
/** 动画序列的promise */
......@@ -143,7 +142,10 @@ export const Card: React.FC<{ idx: number }> = React.memo(({ idx }) => {
// >>> 效果 >>>
const idleInteractivities = snap.idleInteractivities;
useEffect(() => {
setHighlight(!!idleInteractivities.length);
setGrowing(
!!idleInteractivities.length &&
[MZONE, SZONE, HAND, TZONE].includes(card.location.zone)
);
}, [idleInteractivities]);
const [dropdownMenu, setDropdownMenu] = useState({
......@@ -295,7 +297,7 @@ export const Card: React.FC<{ idx: number }> = React.memo(({ idx }) => {
return (
<animated.div
className={classnames("mat-card", { highlight })}
className={classnames("mat-card", { glowing })}
style={
{
transform: to(
......
......@@ -26,12 +26,7 @@ export const moveToDeck: MoveFunc = async (props) => {
const rightX = DECK_OFFSET_X + 2 * (BLOCK_WIDTH + COL_GAP);
const leftX = -rightX;
const bottomY =
DECK_OFFSET_Y +
2 * BLOCK_HEIGHT_M +
BLOCK_HEIGHT_S +
2 * ROW_GAP -
BLOCK_HEIGHT_S;
const bottomY = DECK_OFFSET_Y + 2 * BLOCK_HEIGHT_M + 2 * ROW_GAP;
const topY = -bottomY;
let x = isMe(controller) ? rightX : leftX;
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