components: prepare components for multiple line selections

This commit is contained in:
Artur Tamborski 2020-11-27 21:00:56 +01:00
parent 9af3b68427
commit a383c0b1d7
5 changed files with 93 additions and 59 deletions

View File

@ -14,6 +14,7 @@ export default function App(): JSX.Element {
<Board
numRows={10}
numCols={10}
numLines={1}
/>
</div>
<div />

View File

@ -19,19 +19,13 @@ $LetterHoverColor: #d9d9ff;
height: 100%;
}
.Line {
stroke: red;
stroke-width: 10px;
opacity: 0.3;
}
.Board {
display: grid;
justify-content: center;
grid-template-columns: repeat(10, 60px);
}
.Letter {
.Cell {
width: 60px;
height: 60px;
font-weight: bold;

View File

@ -1,92 +1,101 @@
import React from 'react';
import Line from '../Line/Line';
import './Board.scss';
interface IBoardProps {
numRows: number;
numCols: number;
}
interface Position {
export type Point = {
x: number;
y: number;
}
interface IBoardProps {
numRows: number;
numCols: number;
numLines: number;
}
interface IBoardState {
board: string[][];
isSelectingWord: boolean;
startPos: Position;
cells: string[][];
lines: string[];
isSelecting: boolean;
startPos: Point;
endPos: Point;
}
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) {
super(props);
this.state = {
board: Array(props.numCols).fill(Array(props.numRows).fill('A')),
isSelectingWord: false,
cells: Array(props.numCols).fill(Array(props.numRows).fill('A')),
lines: Array(props.numLines).fill(''),
isSelecting: false,
startPos: {x: 0, y: 0},
endPos: {x: 0, y: 0},
}
}
this.line = React.createRef();
this.line1 = {x: 0, y: 0};
this.line2 = {x: 0, y: 0};
this.letterSize = 60;
handleMouseDown(startPos: Point) {
this.setState({...this.state, startPos, isSelecting: true});
}
handleMouseDown(startPos: Position) {
this.setState({...this.state, startPos, isSelectingWord: true});
handleMouseUp(endPos: Point) {
this.setState({...this.state, endPos, isSelecting: false});
}
handleMouseUp(startPos: Position) {
this.line1 = startPos;
this.line2 = this.state.startPos;
handleMouseOver(currentPos: Point) {
if (!this.state.isSelecting) {
this.setState({...this.state});
} else {
this.setState({...this.state, startPos, isSelectingWord: false});
}
}
handleMouseOver(currentPos: Position) {
if (!this.state.isSelectingWord)
return;
}
render(): JSX.Element {
let letters =
this.state.board.map((oy, y) =>
oy.map((s, x) =>
renderCell(s: string, pos: Point): JSX.Element {
return (
<button
key={`${x}${y}`}
className="Letter"
onMouseUp={() => this.handleMouseUp({x, y})}
onMouseDown={() => this.handleMouseDown({x, y})}
onMouseOver={() => this.handleMouseOver({x, y})}
className="Cell"
key={`Cell${pos.x}${pos.y}`}
onMouseUp={() => this.handleMouseUp(pos)}
onMouseDown={() => this.handleMouseDown(pos)}
onMouseOver={() => this.handleMouseOver(pos)}
>
{s}
</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 (
<div className="Container">
<div className="Content">
<div className="Board">
{letters}
{cells}
</div>
</div>
<div className="Overlay">
<svg className="Canvas">
<line
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}`}
/>
{lines}
</svg>
</div>
</div>

View File

@ -0,0 +1,5 @@
.Line {
stroke: red;
stroke-width: 10px;
opacity: 0.3;
}

View File

@ -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)}`}
/>
);
}