试图让ReactJS在画布上绘制图像

时间:2017-06-16 20:35:09

标签: javascript reactjs canvas

我正在使用ReactJS和Electron开发游戏。我有一个React组件,我想加载我的游戏地图(它是一个2d的tileset地图)。为此,我将组件传递给我要加载资源的目录的名称。一旦它读入game.json文件,它就知道在哪里查找地图tileset数据。 一旦它加载了tileset数据,我希望它计算tile的sprite并将它们放在适当的区域。

我的问题如下:

  1. 将此功能放在componentWillMount()函数中是否有意义?

  2. 异步性是否与图像文件未正确加载有关?

  3. 假设一切都结束了,为什么画布不能画出我传递的图像?

  4. 查看数据,sx / sy / dx / dy坐标就是我想要的位置。取消注释componentDidMount()函数会显示获取图像文件会导致控制台中的../path/null。

    有什么建议吗?

    import React from 'react';
    import ReactDOM from 'react-dom';
    import axios from 'axios';
    
    export default class Map extends React.Component{
        //Set all vars to null
        constructor(props){
            super(props);
            this.state={
                mapArr:     [],
                directory:  null,
                data:       null,
                players:    null,
                enemies:    null,
                objective:  null,
                map:        null,
                tileset:    null
            }
        }
    
        // Given this.props.gamemap, load the game.json file that it points to
        // Given the game.json, set the path to the map it references
        componentWillMount(){
            //Process game data
            this.directory = this.props.gamemap;
            this.data = require('./content/' + this.directory + '/game.json');
            this.players = this.data.players;             //Players
            this.enemies = this.data.enemies;             //Enemies
            this.objective = this.data.objective;         //Game Objective
            this.map = this.data.map;                     //Map name
    
            this.setState({
                data:       this.data,
                players:    this.players,
                enemies:    this.enemies,
                objective:  this.objective,
            });
    
            // Read in map data
            let _this = this;
            axios({
                method: 'get',
                url: './content/' + _this.directory + '/' + _this.map,
                responseType: 'text',
                timeout:1000
            })
            .then(function(response){
                // console.log(response.data);
                var tileSize = 16;
                var mapData = response.data.split("\n");
                var mapArr = [];
                var tileset = "";
                var mapWidthTiles = 0;
                var mapHeightTiles = 0;
                var mapWidthPX = 0;
                var mapHeightPX = 0;
    
                var acc = 0;
                var line;
                for(line in mapData){
                    if(acc === 0)
                        tileset = './content/' + _this.directory + '/' + mapData[line] + '.png';
                    else if(acc === 1){
                        mapWidthTiles = mapData[line].split(" ")[0];
                        mapHeightTiles = mapData[line].split(" ")[1];
                        mapWidthPX = mapWidthTiles * tileSize;
                        mapHeightPX = mapHeightTiles * tileSize;
                    }
                    else
                        mapArr.push(mapData[line].split(" "));
                    acc++;
                }
                _this.setState({
                    mapArr:         mapArr,
                    mapWidthTiles:  mapWidthTiles,
                    mapHeightTiles: mapHeightTiles,
                    mapWidthPX:     mapWidthPX,
                    mapHeightPX:    mapHeightPX,
                    tileset:        tileset,
                });
            })
            .catch(function(error){
            });
        }
    
        componentDidMount(){
             this.paint();
        }
    
        componentDidUpdate(){
            this.paint();
        }
        //Paint Canvas with map data
        // * BUG HERE *
        paint(){
            var context = ReactDOM.findDOMNode(this.refs.gameMap).getContext('2d');
            var tileSize = 16;
            this.mapArr = this.state.mapArr;
            this.tileset = this.state.tileset;
            this.image = new Image();
            this.image.src = this.tileset;
    
            //Given a map and a tileset location, we can now render the map
            //  mapArr[x][y] = val
            //  val divided by 32 (whole int) = y
            //  remainder = x
            let _this = this;
            if(this.image.complete){
                console.log("Image complete");
                for(var dx=0 ; dx<_this.mapArr.length ; dx++){
                    for(var dy=0 ; dy<_this.mapArr[dx].length ; dy++){
                        var sy = Math.floor(_this.mapArr[dx][dy]/32);
                        var sx = _this.mapArr[dx][dy]%32;
                        context.drawImage(
                            _this.image,
                            sx*this.tileSize, sy*this.tileSize, this.tileSize, this.tileSize,
                            dx*this.tileSize, dy*this.tileSize, this.tileSize, this.tileSize);
                    }
                }       
            }
            else{
                this.image.onload = function(){
                    console.log("Image loaded");
                    for(var dx=0 ; dx<_this.mapArr.length ; dx++){
                        for(var dy=0 ; dy<_this.mapArr[dx].length ; dy++){
                            var sy = Math.floor(_this.mapArr[dx][dy]/32);
                            var sx = _this.mapArr[dx][dy]%32;
                            context.drawImage(
                                _this.image,
                                sx*this.tileSize, sy*this.tileSize, this.tileSize, this.tileSize,
                                dx*this.tileSize, dy*this.tileSize, this.tileSize, this.tileSize);
                        }
                    }       
                }
                this.image.onerror = function(res){
                    console.log("Could not load game map");
                    console.log(res);
                }
            }
        }
    
        render(){
            return <canvas 
                    id="map"
                    ref="gameMap"
                    width={this.state.mapWidthPX} 
                    height={this.state.mapHeightPX}/>            
        }
    }
    

0 个答案:

没有答案