Простая интерактивная карта React Tile Map

Я изо всех сил пытаюсь достичь самой простой вещи. У меня есть эта карта тайлов: скриншот

При нажатии на плитку я могу получить индекс, и оттуда план состоял в том, чтобы заменить значение цвета и позволить государству изменить фон плитки. Проблема заключается в том, что все плитки одного цвета становятся черными, а не только та, по которой щелкнули.

скриншот после нажатия на тайл земли/пшеницы

Два компонента:

// 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' в ответ, так как я уверен, что мой подход к проблеме очень наивен. ТИА

ОБНОВЛЕНИЕ: Конечная цель — сохранить цвет каждой плитки в состоянии, чтобы я мог что-то с ним делать, например, сохранять позиции в локальном хранилище.


person Mr. Pol    schedule 06.11.2016    source источник
comment
После нажатия вы хотите изменить цвет плитки на черный?   -  person Pranesh Ravi    schedule 06.11.2016
comment
Да, Пранеш Рави, извините, если это было неясно, но английский не мой родной язык   -  person Mr. Pol    schedule 06.11.2016


Ответы (1)


Вам не нужно использовать states для изменения цвета. Используйте event.target, чтобы получить выбранный элемент и напрямую изменить 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>

person Pranesh Ravi    schedule 06.11.2016
comment
Я немного уточнил свой вопрос, Пранеш - person Mr. Pol; 06.11.2016
comment
@Mr.Pol Обновил ответ! - person Pranesh Ravi; 06.11.2016