Skip to content

Instantly share code, notes, and snippets.

@saitoxu
Created March 22, 2017 07:52
Show Gist options
  • Save saitoxu/70aa7204b3b3fb4e82b749fa55115a1b to your computer and use it in GitHub Desktop.
Save saitoxu/70aa7204b3b3fb4e82b749fa55115a1b to your computer and use it in GitHub Desktop.
2017-03-22
import React, { Component, PropTypes } from 'react';
import Knight from './Knight';
import BoardSquare from './BoardSquare';
import { canMoveKnight, moveKnight } from './Game';
import { DragDropContext } from 'react-dnd';
import HTML5Backend from 'react-dnd-html5-backend';
class Board extends Component {
renderSquare(i) {
const x = i % 8;
const y = Math.floor(i / 8);
return (
<div key={i}
style={{ width: '12.5%', height: '12.5%' }}
onClick={() => this.handleSquareClick(x, y)}>
<BoardSquare x={x}
y={y}>
{this.renderPiece(x, y)}
</BoardSquare>
</div>
);
}
renderPiece(x, y) {
const [knightX, knightY] = this.props.knightPosition;
if (x === knightX && y === knightY) {
return <Knight />;
}
}
handleSquareClick(toX, toY) {
if (canMoveKnight(toX, toY)) {
moveKnight(toX, toY);
}
}
render() {
const squares = [];
for (let i = 0; i < 64; i++) {
squares.push(this.renderSquare(i));
}
return (
<div style={{
width: '100%',
height: '100%',
display: 'flex',
flexWrap: 'wrap'
}}>
{squares}
</div>
)
}
}
Board.propTypes = {
knightPosition: PropTypes.arrayOf(
PropTypes.number.isRequired
).isRequired
};
export default DragDropContext(HTML5Backend)(Board);
import React, { Component, PropTypes } from 'react';
import Square from './Square';
import { canMoveKnight, moveKnight } from './Game';
import { ItemTypes } from './Constants';
import { DropTarget } from 'react-dnd';
const squareTarget = {
drop(props, monitor) {
moveKnight(props.x, props.y);
},
canDrop(props) {
return canMoveKnight(props.x, props.y);
}
};
function collect(connect, monitor) {
return {
connectDropTarget: connect.dropTarget(),
isOver: monitor.isOver(),
canDrop: monitor.canDrop()
};
}
class BoardSquare extends Component {
renderOverlay(color) {
return (
<div style={{
position: 'absolute',
top: 0,
left: 0,
height: '100%',
width: '100%',
zIndex: 1,
opacity: 0.5,
backgroundColor: color
}} />
)
}
render() {
const { x, y, connectDropTarget, isOver, canDrop } = this.props;
const black = (x + y) % 2 === 1;
return connectDropTarget(
<div style={{
position: 'relative',
width: '100%',
height: '100%'
}}>
<Square black={black}>
{this.props.children}
</Square>
{isOver && !canDrop && this.renderOverlay('red')}
{!isOver && canDrop && this.renderOverlay('yellow')}
{isOver && canDrop && this.renderOverlay('green')}
</div>
);
}
}
BoardSquare.propTypes = {
x: PropTypes.number.isRequired,
y: PropTypes.number.isRequired,
isOver: PropTypes.bool.isRequired,
canDrop: PropTypes.bool.isRequired
}
export default DropTarget(ItemTypes.KNIGHT, squareTarget, collect)(BoardSquare);
export const ItemTypes = {
KNIGHT: 'knight'
};
let knightPosition = [1, 7];
let observer = null;
function emitChange() {
observer(knightPosition);
}
export function observe(o) {
if (observer) {
throw new Error('Multiple observers not implemented.');
}
observer = o;
emitChange();
}
export function moveKnight(toX, toY) {
knightPosition = [toX, toY];
emitChange();
}
export function canMoveKnight(toX, toY) {
const [x, y] = knightPosition;
const dx = toX - x;
const dy = toY - y;
return (Math.abs(dx) === 2 && Math.abs(dy) === 1) ||
(Math.abs(dx) === 1 && Math.abs(dy) === 2);
}
import React from 'react';
import ReactDOM from 'react-dom';
import Board from './Board';
import { observe } from './Game';
const rootEl = document.getElementById('root');
observe(knightPosition =>
ReactDOM.render(
<Board knightPosition={knightPosition} />,
rootEl
)
);
import React, { Component, PropTypes } from 'react';
import { ItemTypes } from './Constants';
import { DragSource } from 'react-dnd';
const knightSource = {
beginDrag(props) {
return {};
}
};
function collect(connect, monitor) {
return {
connectDragSource: connect.dragSource(),
connectDragPreview: connect.dragPreview(),
isDragging: monitor.isDragging()
}
}
class Knight extends Component {
componentDidMount() {
const img = new Image();
img.src = 'data:image/png;base64,iVBORw0KGgoAAAA...'; // svg全体はチュートリアルを確認してください
img.onload = () => this.props.connectDragPreview(img);
}
render() {
const { connectDragSource, isDragging } = this.props;
return connectDragSource(
<div style={% raw %}{{
opacity: isDragging ? 0.5 : 1,
fontSize: 25,
fontWeight: 'bold',
cursor: 'move'
}}{% endraw %}>
</div>
)
}
}
Knight.propTypes = {
connectDragSource: PropTypes.func.isRequired,
connectDragPreview: PropTypes.func.isRequired,
isDragging: PropTypes.bool.isRequired
}
export default DragSource(ItemTypes.KNIGHT, knightSource, collect)(Knight);
import React, { Component, PropTypes } from 'react';
export default class Square extends Component {
render() {
const { black } = this.props;
const fill = black? 'black' : 'white';
const stroke = black? 'white' : 'black';
return <div style={{
backgroundColor: fill,
color: stroke,
width: '100%',
height: '100%',
}}>
{this.props.children}
</div>;
}
}
Square.propTypes = {
black: PropTypes.bool
};
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment