125 lines
3.3 KiB
TypeScript
125 lines
3.3 KiB
TypeScript
"use client";
|
|
|
|
import { Piece } from "../types/chess";
|
|
|
|
interface ChessPieceProps {
|
|
piece: Piece;
|
|
isSelected?: boolean;
|
|
isValidMove?: boolean;
|
|
size?: number;
|
|
onClick?: () => void;
|
|
}
|
|
|
|
export default function ChessPiece({
|
|
piece,
|
|
isSelected = false,
|
|
isValidMove = false,
|
|
size = 44,
|
|
onClick,
|
|
}: ChessPieceProps) {
|
|
const isRed = piece.color === "red";
|
|
|
|
// 棋子颜色样式
|
|
const pieceColors = isRed
|
|
? {
|
|
text: "#d80000",
|
|
border: "#d80000",
|
|
innerShadow: "rgba(216, 0, 0, 0.15)",
|
|
}
|
|
: {
|
|
text: "#111111",
|
|
border: "#333333",
|
|
innerShadow: "rgba(0, 0, 0, 0.1)",
|
|
};
|
|
|
|
return (
|
|
<div
|
|
onClick={onClick}
|
|
style={{
|
|
width: `${size}px`,
|
|
height: `${size}px`,
|
|
borderRadius: "50%",
|
|
background: `linear-gradient(145deg, #ffffff 0%, #f0f0f0 50%, #e0e0e0 100%)`,
|
|
boxShadow: isSelected
|
|
? `0 0 0 3px #ffc800,
|
|
inset 0 2px 4px rgba(255,255,255,0.9),
|
|
inset 0 -2px 4px rgba(0,0,0,0.1),
|
|
0 4px 8px rgba(0,0,0,0.3),
|
|
0 6px 12px rgba(0,0,0,0.2)`
|
|
: `inset 0 2px 4px rgba(255,255,255,0.9),
|
|
inset 0 -2px 4px rgba(0,0,0,0.1),
|
|
0 3px 6px rgba(0,0,0,0.3),
|
|
0 4px 8px rgba(0,0,0,0.2)`,
|
|
border: `2px solid ${pieceColors.border}`,
|
|
display: "flex",
|
|
alignItems: "center",
|
|
justifyContent: "center",
|
|
cursor: onClick ? "pointer" : "default",
|
|
transition: "all 0.2s ease",
|
|
transform: isSelected ? "scale(1.1)" : "scale(1)",
|
|
position: "relative",
|
|
zIndex: isSelected ? 10 : 1,
|
|
}}
|
|
className="chess-piece"
|
|
>
|
|
{/* 内圈装饰 */}
|
|
<div
|
|
style={{
|
|
position: "absolute",
|
|
width: `${size * 0.75}px`,
|
|
height: `${size * 0.75}px`,
|
|
borderRadius: "50%",
|
|
border: `1px solid ${pieceColors.border}`,
|
|
opacity: 0.4,
|
|
}}
|
|
/>
|
|
|
|
{/* 棋子文字 */}
|
|
<span
|
|
style={{
|
|
fontSize: `${size * 0.55}px`,
|
|
fontWeight: "bold",
|
|
color: pieceColors.text,
|
|
fontFamily: '"SimSun", "STSong", "Songti SC", serif',
|
|
textShadow: "0 1px 2px rgba(255,255,255,0.8)",
|
|
userSelect: "none",
|
|
position: "relative",
|
|
zIndex: 2,
|
|
}}
|
|
>
|
|
{piece.type}
|
|
</span>
|
|
|
|
{/* 高光效果 */}
|
|
<div
|
|
style={{
|
|
position: "absolute",
|
|
top: "15%",
|
|
left: "20%",
|
|
width: "25%",
|
|
height: "15%",
|
|
borderRadius: "50%",
|
|
background: "linear-gradient(135deg, rgba(255,255,255,0.9) 0%, rgba(255,255,255,0) 100%)",
|
|
pointerEvents: "none",
|
|
}}
|
|
/>
|
|
|
|
{/* 可移动位置提示 */}
|
|
{isValidMove && !isSelected && (
|
|
<div
|
|
style={{
|
|
position: "absolute",
|
|
width: "12px",
|
|
height: "12px",
|
|
borderRadius: "50%",
|
|
backgroundColor: "rgba(0, 150, 0, 0.5)",
|
|
bottom: "-6px",
|
|
right: "-6px",
|
|
border: "2px solid white",
|
|
}}
|
|
/>
|
|
)}
|
|
</div>
|
|
);
|
|
}
|