Skip to content

Commit

Permalink
UI refined for PC
Browse files Browse the repository at this point in the history
  • Loading branch information
mac authored and mac committed Oct 4, 2024
1 parent e57c58a commit 913b7cc
Show file tree
Hide file tree
Showing 5 changed files with 162 additions and 69 deletions.
61 changes: 33 additions & 28 deletions src/App.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@ import {
templateMatchingForPiece,
} from './chessboard/templateMatching';
import { ImageUploader } from './components/ImageUploader';
import { ChessboardOverlay } from './components/ChessboardOverlay';
import { BoardResult } from './components/BoardResult';
import { FENDisplay } from './components/FENDisplay';
import { SolutionDisplay } from './components/SolutionDisplay';
import { generateFenFromPieces } from './chessboard/fenGeneration';
Expand Down Expand Up @@ -188,7 +188,7 @@ export function App() {
setLoading(true);
setError(null);
try {
const move = await engine.getBestMove(fen, depth); // 传递深度值
const move = await engine.getBestMove(fen, depth); // 传递度值
setBestMove(move);
if (move === 'red_wins' || move === 'black_wins') {
setLoading(false);
Expand Down Expand Up @@ -254,44 +254,49 @@ export function App() {
<main className="app-container">
<div className="content-wrapper">
<div className="left-column">
<SolutionDisplay
bestMove={bestMove}
loading={loading}
error={error}
onNextMove={handleNextMove}
onPreviousMove={handlePreviousMove}
moveHistory={moveHistory}
fenCode={fenCode}
fenHistory={fenHistory}
/>
</div>
<div className="right-column">
<ImageUploader onImageUpload={handleImageUpload} />
<ChessboardOverlay
<BoardResult
overlayImageSrc={overlayImageSrc}
chessboardRect={chessboardRect}
originalImageSize={originalImageSize}
/>
<FENDisplay fenCode={fenCode} onCopy={handleCopyFEN} />
<div>
<label htmlFor="depth-slider">搜索深度: {depth}</label>
<input
id="depth-slider"
type="range"
min="10"
max="30"
value={depth}
onChange={(e) => {
if (e.target instanceof HTMLInputElement) {
handleDepthChange(Number(e.target.value));
}
}}
/>
<div className="depth-control-section">
<h2>搜索深度控制</h2>
<div className="depth-slider-container">
<label htmlFor="depth-slider">当前深度: {depth}</label>
<input
id="depth-slider"
type="range"
min="10"
max="30"
value={depth}
onChange={(e) => {
if (e.target instanceof HTMLInputElement) {
handleDepthChange(Number(e.target.value));
}
}}
/>
</div>
</div>
</div>
<SolutionDisplay
bestMove={bestMove}
loading={loading}
error={error}
onNextMove={handleNextMove}
onPreviousMove={handlePreviousMove}
moveHistory={moveHistory}
fenCode={fenCode}
fenHistory={fenHistory}
/>
</div>
</main>
<footer>
<p>© 2023 象棋棋盘识别与分析系统</p>
</footer>
</>
);
}
}
115 changes: 88 additions & 27 deletions src/app.css
Original file line number Diff line number Diff line change
Expand Up @@ -108,27 +108,50 @@ main {

.content-wrapper {
display: flex;
flex-direction: column;
flex-wrap: wrap;
gap: 2rem;
width: 100%;
max-width: 850px;
margin: 0 auto 2rem;
max-width: 1200px;
margin: 0 auto;
padding: 0 1rem;
box-sizing: border-box;
}

.left-column {
.left-column,
.right-column {
width: 100%;
}

.solution-section,
.upload-section,
.board-result-section,
.fen-section,
.depth-control-section {
background-color: #fff;
border-radius: 8px;
box-shadow: 0 2px 4px rgba(0, 0, 0, 0.1);
padding: 1.5rem;
margin-bottom: 1rem;
}

.solution-column,
.image-column {
flex: 1;
display: flex;
flex-direction: column;
gap: 1rem;
}

.upload-section, .result-section, .fen-section {
.solution-section,
.upload-section,
.board-result-section,
.depth-control-section,
.fen-section {
background-color: #fff;
border-radius: 8px;
box-shadow: 0 2px 4px rgba(0, 0, 0, 0.1);
padding: 1.5rem;
margin-bottom: 1rem;
}

.solution-section {
Expand Down Expand Up @@ -204,45 +227,69 @@ footer {
color: #ecf0f1;
}

@media (min-width: 769px) {
@media (max-width: 768px) {
.content-wrapper {
flex-direction: row;
align-items: flex-start;
flex-direction: column;
gap: 0;
}

.left-column {
width: 50%;
max-width: 600px;
.left-column,
.right-column {
width: 100%;
}

.solution-section {
width: 50%;
max-width: 600px;
order: 1;
}

.upload-section {
order: 0;
}

.board-result-section {
order: 2;
}

.fen-section {
order: 3;
}

.depth-control-section {
order: 4;
}
}

@media (max-width: 768px) {
@media (min-width: 769px) {
.content-wrapper {
flex-direction: column;
padding: 0 0.5rem;
flex-direction: row;
align-items: flex-start;
}

.left-column {
width: calc(50% - 1rem);
position: sticky;
top: 1rem;
align-self: flex-start;
}

.right-column {
width: calc(50% - 1rem);
}

.left-column,
.solution-section {
width: 100%;
height: calc(100vh - 2rem);
overflow-y: auto;
}

.chessboard {
max-width: 100%;
height: auto;
.solution-column,
.image-column {
width: 50%;
max-width: 600px;
}
.solution-section {
order: -1;
}
}

.result-section {
box-sizing: border-box;
max-width: 600px;
margin: 0 auto;
width: 100%;
}

.chessboard {
Expand Down Expand Up @@ -281,4 +328,18 @@ footer {
background-color: #95a5a6;
cursor: not-allowed;
opacity: 0.7;
}

.depth-slider-container {
display: flex;
flex-direction: column;
gap: 0.5rem;
}

.depth-slider-container label {
font-weight: bold;
}

#depth-slider {
width: 100%;
}
Original file line number Diff line number Diff line change
@@ -1,18 +1,18 @@
import './ChessboardOverlay.css';

interface ChessboardOverlayProps {
interface BoardResultProps {
overlayImageSrc: string;
chessboardRect?: { x: number; y: number; width: number; height: number };
originalImageSize?: { width: number; height: number };
}

const MAX_WIDTH = 400; // 在 JavaScript 中定义 max-width
const MAX_WIDTH = 360; // 在 JavaScript 中定义 max-width

export function ChessboardOverlay({
export function BoardResult({
overlayImageSrc,
chessboardRect = { x: 0, y: 0, width: 0, height: 0 },
originalImageSize = { width: 0, height: 0 },
}: ChessboardOverlayProps) {
}: BoardResultProps) {
// 添加间隙
const padding = 15;

Expand Down Expand Up @@ -43,7 +43,7 @@ export function ChessboardOverlay({
const leftOffset = (finalWidth - stretchedWidth) / 2;

return (
<section className="result-section">
<section className="board-result-section">
<h2>分析结果</h2>
<div
className="image-container"
Expand Down
39 changes: 36 additions & 3 deletions src/components/ChessboardDisplay.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,7 @@ interface Piece {
export function ChessboardDisplay({ fen, bestMove }: ChessboardDisplayProps) {
const [board, setBoard] = useState<(Piece | null)[][]>([]);
const canvasRef = useRef<HTMLCanvasElement>(null);
const [scale, setScale] = useState(1);

useEffect(() => {
const newBoard = parseFEN(fen);
Expand All @@ -45,6 +46,22 @@ export function ChessboardDisplay({ fen, bestMove }: ChessboardDisplayProps) {
}
}, [board, bestMove]);

useEffect(() => {
function handleResize() {
if (canvasRef.current) {
const screenWidth = window.innerWidth;
const maxWidth = screenWidth * 0.8;
const originalWidth = 8 * 40 + 40; // 8 cells + 2 margins
const newScale = Math.min(1, maxWidth / originalWidth);
setScale(newScale);
}
}

handleResize();
window.addEventListener('resize', handleResize);
return () => window.removeEventListener('resize', handleResize);
}, []);

function parseFEN(fen: string): (Piece | null)[][] {
const rows = fen.split(' ')[0].split('/');
const board: (Piece | null)[][] = [];
Expand Down Expand Up @@ -80,8 +97,13 @@ export function ChessboardDisplay({ fen, bestMove }: ChessboardDisplayProps) {
const margin = cellSize / 2;
const boardWidth = 8 * cellSize + 2 * margin;
const boardHeight = 9 * cellSize + 2 * margin;
canvas.width = boardWidth;
canvas.height = boardHeight;

// Set canvas size based on scale
canvas.width = boardWidth * scale;
canvas.height = boardHeight * scale;

// Scale the context
ctx.scale(scale, scale);

// 绘制棋盘背景
ctx.fillStyle = '#f0d9b5';
Expand Down Expand Up @@ -304,5 +326,16 @@ export function ChessboardDisplay({ fen, bestMove }: ChessboardDisplayProps) {
ctx.fill();
}

return <canvas ref={canvasRef} className="chessboard"></canvas>;
return (
<div style={{ width: '100%', display: 'flex', justifyContent: 'center' }}>
<canvas
ref={canvasRef}
className="chessboard"
style={{
maxWidth: '80vw',
height: 'auto'
}}
></canvas>
</div>
);
}
6 changes: 0 additions & 6 deletions src/components/ChessboardOverlay.css
Original file line number Diff line number Diff line change
@@ -1,9 +1,3 @@
.result-section {
box-sizing: border-box;
margin: 0 auto;
width: 100%;
}

.image-container {
position: relative;
width: 100%;
Expand Down

0 comments on commit 913b7cc

Please sign in to comment.