components: prepare components for multiple line selections
This commit is contained in:
parent
9af3b68427
commit
a383c0b1d7
@ -14,6 +14,7 @@ export default function App(): JSX.Element {
|
|||||||
<Board
|
<Board
|
||||||
numRows={10}
|
numRows={10}
|
||||||
numCols={10}
|
numCols={10}
|
||||||
|
numLines={1}
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
<div />
|
<div />
|
||||||
|
@ -19,19 +19,13 @@ $LetterHoverColor: #d9d9ff;
|
|||||||
height: 100%;
|
height: 100%;
|
||||||
}
|
}
|
||||||
|
|
||||||
.Line {
|
|
||||||
stroke: red;
|
|
||||||
stroke-width: 10px;
|
|
||||||
opacity: 0.3;
|
|
||||||
}
|
|
||||||
|
|
||||||
.Board {
|
.Board {
|
||||||
display: grid;
|
display: grid;
|
||||||
justify-content: center;
|
justify-content: center;
|
||||||
grid-template-columns: repeat(10, 60px);
|
grid-template-columns: repeat(10, 60px);
|
||||||
}
|
}
|
||||||
|
|
||||||
.Letter {
|
.Cell {
|
||||||
width: 60px;
|
width: 60px;
|
||||||
height: 60px;
|
height: 60px;
|
||||||
font-weight: bold;
|
font-weight: bold;
|
||||||
|
@ -1,92 +1,101 @@
|
|||||||
import React from 'react';
|
import React from 'react';
|
||||||
|
|
||||||
|
import Line from '../Line/Line';
|
||||||
|
|
||||||
import './Board.scss';
|
import './Board.scss';
|
||||||
|
|
||||||
interface IBoardProps {
|
export type Point = {
|
||||||
numRows: number;
|
|
||||||
numCols: number;
|
|
||||||
}
|
|
||||||
|
|
||||||
interface Position {
|
|
||||||
x: number;
|
x: number;
|
||||||
y: number;
|
y: number;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
interface IBoardProps {
|
||||||
|
numRows: number;
|
||||||
|
numCols: number;
|
||||||
|
numLines: number;
|
||||||
|
}
|
||||||
|
|
||||||
interface IBoardState {
|
interface IBoardState {
|
||||||
board: string[][];
|
cells: string[][];
|
||||||
isSelectingWord: boolean;
|
lines: string[];
|
||||||
startPos: Position;
|
isSelecting: boolean;
|
||||||
|
startPos: Point;
|
||||||
|
endPos: Point;
|
||||||
}
|
}
|
||||||
|
|
||||||
export default class Board extends React.Component<IBoardProps, IBoardState> {
|
export default class Board extends React.Component<IBoardProps, IBoardState> {
|
||||||
private line: React.RefObject<SVGLineElement>;
|
|
||||||
private line1: Position;
|
|
||||||
private line2: Position;
|
|
||||||
private letterSize: number;
|
|
||||||
|
|
||||||
constructor(props: IBoardProps) {
|
constructor(props: IBoardProps) {
|
||||||
super(props);
|
super(props);
|
||||||
|
|
||||||
this.state = {
|
this.state = {
|
||||||
board: Array(props.numCols).fill(Array(props.numRows).fill('A')),
|
cells: Array(props.numCols).fill(Array(props.numRows).fill('A')),
|
||||||
isSelectingWord: false,
|
lines: Array(props.numLines).fill(''),
|
||||||
|
isSelecting: false,
|
||||||
startPos: {x: 0, y: 0},
|
startPos: {x: 0, y: 0},
|
||||||
|
endPos: {x: 0, y: 0},
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
this.line = React.createRef();
|
handleMouseDown(startPos: Point) {
|
||||||
this.line1 = {x: 0, y: 0};
|
this.setState({...this.state, startPos, isSelecting: true});
|
||||||
this.line2 = {x: 0, y: 0};
|
|
||||||
this.letterSize = 60;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
handleMouseDown(startPos: Position) {
|
handleMouseUp(endPos: Point) {
|
||||||
this.setState({...this.state, startPos, isSelectingWord: true});
|
this.setState({...this.state, endPos, isSelecting: false});
|
||||||
}
|
}
|
||||||
|
|
||||||
handleMouseUp(startPos: Position) {
|
handleMouseOver(currentPos: Point) {
|
||||||
this.line1 = startPos;
|
if (!this.state.isSelecting) {
|
||||||
this.line2 = this.state.startPos;
|
this.setState({...this.state});
|
||||||
|
} else {
|
||||||
|
|
||||||
this.setState({...this.state, startPos, isSelectingWord: false});
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
handleMouseOver(currentPos: Position) {
|
renderCell(s: string, pos: Point): JSX.Element {
|
||||||
if (!this.state.isSelectingWord)
|
return (
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
render(): JSX.Element {
|
|
||||||
let letters =
|
|
||||||
this.state.board.map((oy, y) =>
|
|
||||||
oy.map((s, x) =>
|
|
||||||
<button
|
<button
|
||||||
key={`${x}${y}`}
|
className="Cell"
|
||||||
className="Letter"
|
key={`Cell${pos.x}${pos.y}`}
|
||||||
onMouseUp={() => this.handleMouseUp({x, y})}
|
onMouseUp={() => this.handleMouseUp(pos)}
|
||||||
onMouseDown={() => this.handleMouseDown({x, y})}
|
onMouseDown={() => this.handleMouseDown(pos)}
|
||||||
onMouseOver={() => this.handleMouseOver({x, y})}
|
onMouseOver={() => this.handleMouseOver(pos)}
|
||||||
>
|
>
|
||||||
{s}
|
{s}
|
||||||
</button>
|
</button>
|
||||||
));
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
renderLine(x: number): JSX.Element {
|
||||||
|
return (
|
||||||
|
<Line
|
||||||
|
key={`Line${x}`}
|
||||||
|
startPos={this.state.startPos}
|
||||||
|
endPos={this.state.endPos}
|
||||||
|
cellSize={60}
|
||||||
|
/>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
render(): JSX.Element {
|
||||||
|
let cells =
|
||||||
|
this.state.cells.map((oy, y) =>
|
||||||
|
oy.map((s, x) =>
|
||||||
|
this.renderCell(s, {x, y})));
|
||||||
|
|
||||||
|
let lines = this.state.lines.map((ox, x) =>
|
||||||
|
this.renderLine(x));
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div className="Container">
|
<div className="Container">
|
||||||
<div className="Content">
|
<div className="Content">
|
||||||
<div className="Board">
|
<div className="Board">
|
||||||
{letters}
|
{cells}
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div className="Overlay">
|
<div className="Overlay">
|
||||||
<svg className="Canvas">
|
<svg className="Canvas">
|
||||||
<line
|
{lines}
|
||||||
className="Line"
|
|
||||||
ref={this.line}
|
|
||||||
x1={`${this.line1.x * this.letterSize + this.letterSize / 2}`}
|
|
||||||
y1={`${this.line1.y * this.letterSize + this.letterSize / 2}`}
|
|
||||||
x2={`${this.line2.x * this.letterSize + this.letterSize / 2}`}
|
|
||||||
y2={`${this.line2.y * this.letterSize + this.letterSize / 2}`}
|
|
||||||
/>
|
|
||||||
</svg>
|
</svg>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
@ -0,0 +1,5 @@
|
|||||||
|
.Line {
|
||||||
|
stroke: red;
|
||||||
|
stroke-width: 10px;
|
||||||
|
opacity: 0.3;
|
||||||
|
}
|
@ -0,0 +1,25 @@
|
|||||||
|
import React from 'react';
|
||||||
|
|
||||||
|
import {Point} from '../Board/Board'
|
||||||
|
|
||||||
|
import './Line.scss';
|
||||||
|
|
||||||
|
interface ILineProps {
|
||||||
|
startPos: Point;
|
||||||
|
endPos: Point;
|
||||||
|
cellSize: number;
|
||||||
|
}
|
||||||
|
|
||||||
|
export default function Line(props: ILineProps): JSX.Element {
|
||||||
|
const pos = (v: number) => v * props.cellSize + props.cellSize / 2;
|
||||||
|
|
||||||
|
return (
|
||||||
|
<line
|
||||||
|
className="Line"
|
||||||
|
x1={`${pos(props.endPos.x)}`}
|
||||||
|
y1={`${pos(props.endPos.y)}`}
|
||||||
|
x2={`${pos(props.startPos.x)}`}
|
||||||
|
y2={`${pos(props.startPos.y)}`}
|
||||||
|
/>
|
||||||
|
);
|
||||||
|
}
|
Loading…
Reference in New Issue
Block a user