简单的交互式 React Tile 地图

Simple interactive React Tile Map

我正在努力实现有史以来最简单的事情。我有这张瓷砖地图: screenshot

单击 Tile 时,我可以获得索引,计划是从那里替换颜色值并让 State 更改 Tile 的背景。问题似乎是所有具有相同颜色的图块都变为黑色,而不仅仅是被单击的图块。

screenshot after clicking on a Land/Wheat Tile

两个组件:

// Map.js 

var mapData = [
1, 1, 1, 1, 0, 0, 0, 0, 0, 1, 1,0,1,1,1,
1, 1, 1, 0, 0, 0, 0, 0, 0, 1, 1,0,1,1,1,
1, 1, 0, 0, 0, 0, 0, 0, 1, 1, 0,0,1,1,1,
1, 1, 0, 0, 0, 0, 0, 1, 0, 0, 0,0,1,1,1,
1, 1, 1, 0, 0, 0, 0, 2, 0, 0, 0,0,1,1,1,
1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0,0,1,1,1,  
]

var tileTypes = {
0: { name: 'Sea', color: 'lightBlue' },
1: { name: 'Land', color: 'wheat' },
2: { name: 'Ship', color: 'black' }
}

var temporalTiles=[];


export default class extends React.Component {


constructor(props) {

super(props)

this.state = {
tile: 0,
tiles:[]
  }
}


componentDidMount() {


const numTiles = mapData.length;

for (let y = 0; y < numTiles; y++) {
    const tileId = mapData[y]
    const tileType = tileTypes[tileId]
    temporalTiles.push(tileType);
    this.setState({tiles: temporalTiles})
  }

}



makeBlack() {
var idx= this.state.tile;

console.log(idx);  // tile index 
console.log(temporalTiles[idx].color); // current tile color 

temporalTiles[idx].color = 'black'; // change color

console.log(temporalTiles[idx].color); // did it work ? yes(!)

this.setState({tiles: temporalTiles})

console.log(temporalTiles);
}


handleIndexToState(idx) {

this.setState({tile: idx})

}

render () {

var quickDemo ={
  display:'block',
  textAlign:'center'
}

return ( <div>

  {this.state.tile ? (

    <div>          
      <p style={quickDemo}> Index of clicked cell {this.state.tile}</p>
      <p style={quickDemo}
        onClick={this.makeBlack.bind(this)}>
        Change to black 
      </p>
    </div>
    ) : null
  }

      {this.state.tiles.map((tile,index) =>(

        <Tile
          bgcolor={tile.color}
          key={index}
          position={index}
          onClick={this.handleIndexToState.bind(this, index)}
        />

        ))}

   </div>)
  }}

这是父组件,Tile组件是这样的

 // Tile.js 


 export default class extends React.Component {

 render () {

  var bgColor = {
  backgroundColor: this.props.bgcolor ,
  width: '83px',
  height:'83px',
  border:'1px solid rgba(0,0,0,.1)'

  };

  return (

  <div
  onClick={this.props.onClick}
  style={bgColor}>

  {this.props.position}

  </div>


    )
  }
  }

有什么关于我遗漏的指示吗?我对 Tile map 'mgmt' 的其他策略持开放态度,因为我确信我对这个问题的处理方式非常幼稚。 TIA

更新:最终目标是将每个图块的颜色保留在状态中,以便我可以用它做一些事情,例如将位置保存到本地存储。

您不需要使用 states 来更改颜色。用event.target获取点击的item直接改成css

希望对您有所帮助!

var mapData = [
1, 1, 1, 1, 0, 0, 0, 0, 0, 1, 1,0,1,1,1,
1, 1, 1, 0, 0, 0, 0, 0, 0, 1, 1,0,1,1,1,
1, 1, 0, 0, 0, 0, 0, 0, 1, 1, 0,0,1,1,1,
1, 1, 0, 0, 0, 0, 0, 1, 0, 0, 0,0,1,1,1,
1, 1, 1, 0, 0, 0, 0, 2, 0, 0, 0,0,1,1,1,
1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0,0,1,1,1,  
]

var tileTypes = {
0: { name: 'Sea', color: 'lightBlue' },
1: { name: 'Land', color: 'wheat' },
2: { name: 'Ship', color: 'black' }
}

class Tiles extends React.Component{
  constructor(props){
    super(props)
    this.onClick = this.onClick.bind(this)
    this.state = {
      clickedIndex: []
    }
  }
  
  onClick(i){
    const index = this.state.clickedIndex.slice()
    if(index.indexOf(i) === -1){ //handle duplicates
      index.push(i)
      this.setState({clickedIndex: index})
     } 
  } 
  
  render() {
    console.log('clicked Index:', this.state.clickedIndex)
    const nodes = mapData.map((el, i) => {
      const bg = this.state.clickedIndex.indexOf(i) > -1 ? 'black' : tileTypes[el].color
      return <div className="box" onClick={() => this.onClick(i)} style={{background: bg}}>{i}</div>
    })
    return <div>{nodes}</div>
  }
}

ReactDOM.render(<Tiles/>, document.getElementById('app'))
.box{
  height: 40px;
  width: 40px;
  border: 1px solid grey;
  float: left;
  transition: all 0.2s ease;
  cursor: pointer;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/15.1.0/react.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/15.1.0/react-dom.min.js"></script>
<div id="app"></div>