React Native(Expo)应用程序-使用drawImage()方法将本地图像绘制到画布中

React Native(Expo)应用程序-使用drawImage()方法将本地图像绘制到画布中,image,react-native,canvas,expo,drawimage,Image,React Native,Canvas,Expo,Drawimage,我有一个透明的PNG精灵表,我将它加载到一个标记中,然后当“onload”触发时,我将元素保存到一个上下文对象(ImageLoader.js)中,这样我以后可以将它与画布上的drawImage(sprite.js)一起使用,以提取各种精灵并覆盖它们,为游戏生成一个复合瓷砖 Home.js只是选择显示一个虚拟的保留消息,但一旦触发“onload”就会重新绘制,然后呈现一个组件 我曾尝试使用react native canvas和各种其他方法,但我不确定我所尝试的是否可行 下面是各种代码片段,它们可

我有一个透明的PNG精灵表,我将它加载到一个标记中,然后当“onload”触发时,我将元素保存到一个上下文对象(ImageLoader.js)中,这样我以后可以将它与画布上的drawImage(sprite.js)一起使用,以提取各种精灵并覆盖它们,为游戏生成一个复合瓷砖

Home.js只是选择显示一个虚拟的保留消息,但一旦触发“onload”就会重新绘制,然后呈现一个组件

我曾尝试使用react native canvas和各种其他方法,但我不确定我所尝试的是否可行

下面是各种代码片段,它们可能比试图描述更容易显示

该代码在浏览器中运行良好,但这是一个使用Expo框架的React本机应用程序,由于ImageLoader.js组件中的标记而失败。理想情况下,我会使用React原生图像,但这不是Canvas drawImage方法的选项,该方法需要DOM样式的图像对象

我对实现这一点的其他方法持开放态度,但实际上我需要能够创建一个自定义的React本机图像组件,其中基础图像在应用程序中生成,方法是使用本地透明PNG sprite表并将其各个部分覆盖到画布中,以便我创建一个合成图像

App.js

import { Text, View } from 'react-native';
import Home from './components/Home';
import ConfigContextProvider from './contexts/ConfigContext';

export default class App extends Component {
  render() {
    return (
      <ConfigContextProvider>
        <Home />
      </ConfigContextProvider>
    );
  }
}
import { Text, View, Button } from 'react-native';
import { ConfigContext } from '../contexts/ConfigContext';
import Sprite from './Sprite';
import ImageLoader from './ImageLoader';

class Home extends Component {
    render() { 
        return ( 
            <ConfigContext.Consumer>{(configContext) => {
                if(configContext.spriteMapIsLoaded) {
                    return (
                        <View>
                        <Text>It's Alive!</Text>
                        <Text>Screen Width: {configContext.screenWidth}</Text>
                        <Text>Screen Height: {configContext.screenHeight}</Text>
                        <Sprite />
                    </View>
                    );
                }
                else {
                    return (
                        <View>
                            <Text>Image is not loaded!</Text>
                            <ImageLoader />
                        </View>
                    );
                }
            }}</ConfigContext.Consumer>
        );
    }
}

export default Home;
import { ConfigContext } from '../contexts/ConfigContext';

class ImageLoader extends Component {
    static contextType = ConfigContext;
    componentDidMount() {
        const spriteMapImage = this.refs.spritemap;
        spriteMapImage.onload = () => {
            console.log("Image has loaded");
            this.context.setSpriteMapImage(this.refs.spritemap);
        }
    }
    render() { 
        return (
            <img ref="spritemap" src={require('../assets/SpriteMap.png')} style={{width:0, height:0}} />
        )
    }
}
 
export default ImageLoader;
import { Dimensions } from 'react-native';

export const ConfigContext = createContext();

class ConfigContextProvider extends Component {
    state = { 
        screenWidth: Dimensions.get('window').width,
        screenHeight: Dimensions.get('window').height,
        spriteSize: 50,
        spriteMapIsLoaded: false,
        spriteMapImage: null
    }
    setSpriteMapImage = (spriteMapImage) => {
        this.setState({
            spriteMapIsLoaded: true,
            spriteMapImage: spriteMapImage});
    }
    render() { 
        return ( 
            <ConfigContext.Provider value={{...this.state, setSpriteMapImage: this.setSpriteMapImage}}>
                {this.props.children}
            </ConfigContext.Provider>
         );
    }
}
 
export default ConfigContextProvider;
import { ConfigContext } from '../contexts/ConfigContext';

class Sprite extends Component {
    static contextType = ConfigContext;
    componentDidMount() {
        console.log(this.context);
        const canvas = this.refs.canvas;
        const ctx = canvas.getContext('2d');
        for(let x = 0; x <= 360; x += 120) {
            let y = Math.floor(Math.random() * 8) * 120;
            console.log(x, y);
            ctx.drawImage(this.context.spriteMapImage, x, y, 120, 120, 0, 0, this.context.spriteSize, this.context.spriteSize);
        }
        ctx.drawImage(this.context.spriteMapImage, 960, 120, 120, 120, 0, 0, this.context.spriteSize, this.context.spriteSize);
        const cardColour = Math.floor(Math.random() * 2);
        const cardSuit = Math.floor(Math.random() * 2);
        const cardSymbol = Math.floor(Math.random() * 4);
        ctx.drawImage(this.context.spriteMapImage, 480 + cardSymbol * 120, cardColour * 120, 120, 120, 0, 0, this.context.spriteSize, this.context.spriteSize);
        ctx.drawImage(this.context.spriteMapImage, 480 + cardColour * 240 + cardSuit * 120, 240, 120, 120, 0, 0, this.context.spriteSize, this.context.spriteSize);
    }
    render() {
        return (
            <div>
                <canvas ref="canvas" width={this.context.spriteSize} height={this.context.spriteSize} /> 
            </div>
        );
    }
}
 
export default Sprite;
从'react native'导入{Text,View};
从“./components/Home”导入Home;
从“./contexts/ConfigContext”导入ConfigContextProvider;
导出默认类应用程序扩展组件{
render(){
返回(
);
}
}
Home.js

import { Text, View } from 'react-native';
import Home from './components/Home';
import ConfigContextProvider from './contexts/ConfigContext';

export default class App extends Component {
  render() {
    return (
      <ConfigContextProvider>
        <Home />
      </ConfigContextProvider>
    );
  }
}
import { Text, View, Button } from 'react-native';
import { ConfigContext } from '../contexts/ConfigContext';
import Sprite from './Sprite';
import ImageLoader from './ImageLoader';

class Home extends Component {
    render() { 
        return ( 
            <ConfigContext.Consumer>{(configContext) => {
                if(configContext.spriteMapIsLoaded) {
                    return (
                        <View>
                        <Text>It's Alive!</Text>
                        <Text>Screen Width: {configContext.screenWidth}</Text>
                        <Text>Screen Height: {configContext.screenHeight}</Text>
                        <Sprite />
                    </View>
                    );
                }
                else {
                    return (
                        <View>
                            <Text>Image is not loaded!</Text>
                            <ImageLoader />
                        </View>
                    );
                }
            }}</ConfigContext.Consumer>
        );
    }
}

export default Home;
import { ConfigContext } from '../contexts/ConfigContext';

class ImageLoader extends Component {
    static contextType = ConfigContext;
    componentDidMount() {
        const spriteMapImage = this.refs.spritemap;
        spriteMapImage.onload = () => {
            console.log("Image has loaded");
            this.context.setSpriteMapImage(this.refs.spritemap);
        }
    }
    render() { 
        return (
            <img ref="spritemap" src={require('../assets/SpriteMap.png')} style={{width:0, height:0}} />
        )
    }
}
 
export default ImageLoader;
import { Dimensions } from 'react-native';

export const ConfigContext = createContext();

class ConfigContextProvider extends Component {
    state = { 
        screenWidth: Dimensions.get('window').width,
        screenHeight: Dimensions.get('window').height,
        spriteSize: 50,
        spriteMapIsLoaded: false,
        spriteMapImage: null
    }
    setSpriteMapImage = (spriteMapImage) => {
        this.setState({
            spriteMapIsLoaded: true,
            spriteMapImage: spriteMapImage});
    }
    render() { 
        return ( 
            <ConfigContext.Provider value={{...this.state, setSpriteMapImage: this.setSpriteMapImage}}>
                {this.props.children}
            </ConfigContext.Provider>
         );
    }
}
 
export default ConfigContextProvider;
import { ConfigContext } from '../contexts/ConfigContext';

class Sprite extends Component {
    static contextType = ConfigContext;
    componentDidMount() {
        console.log(this.context);
        const canvas = this.refs.canvas;
        const ctx = canvas.getContext('2d');
        for(let x = 0; x <= 360; x += 120) {
            let y = Math.floor(Math.random() * 8) * 120;
            console.log(x, y);
            ctx.drawImage(this.context.spriteMapImage, x, y, 120, 120, 0, 0, this.context.spriteSize, this.context.spriteSize);
        }
        ctx.drawImage(this.context.spriteMapImage, 960, 120, 120, 120, 0, 0, this.context.spriteSize, this.context.spriteSize);
        const cardColour = Math.floor(Math.random() * 2);
        const cardSuit = Math.floor(Math.random() * 2);
        const cardSymbol = Math.floor(Math.random() * 4);
        ctx.drawImage(this.context.spriteMapImage, 480 + cardSymbol * 120, cardColour * 120, 120, 120, 0, 0, this.context.spriteSize, this.context.spriteSize);
        ctx.drawImage(this.context.spriteMapImage, 480 + cardColour * 240 + cardSuit * 120, 240, 120, 120, 0, 0, this.context.spriteSize, this.context.spriteSize);
    }
    render() {
        return (
            <div>
                <canvas ref="canvas" width={this.context.spriteSize} height={this.context.spriteSize} /> 
            </div>
        );
    }
}
 
export default Sprite;
从'react native'导入{文本、视图、按钮};
从“../Context/ConfigContext”导入{ConfigContext};
从“/Sprite”导入精灵;
从“/ImageLoader”导入ImageLoader;
类Home扩展组件{
render(){
报税表(
{(配置上下文)=>{
if(configContext.spriteMapIsLoaded){
返回(
它还活着!
屏幕宽度:{configContext.screenWidth}
屏幕高度:{configContext.screenHeight}
);
}
否则{
返回(
图像未加载!
);
}
}}
);
}
}
导出默认主页;
ImageLoader.js

import { Text, View } from 'react-native';
import Home from './components/Home';
import ConfigContextProvider from './contexts/ConfigContext';

export default class App extends Component {
  render() {
    return (
      <ConfigContextProvider>
        <Home />
      </ConfigContextProvider>
    );
  }
}
import { Text, View, Button } from 'react-native';
import { ConfigContext } from '../contexts/ConfigContext';
import Sprite from './Sprite';
import ImageLoader from './ImageLoader';

class Home extends Component {
    render() { 
        return ( 
            <ConfigContext.Consumer>{(configContext) => {
                if(configContext.spriteMapIsLoaded) {
                    return (
                        <View>
                        <Text>It's Alive!</Text>
                        <Text>Screen Width: {configContext.screenWidth}</Text>
                        <Text>Screen Height: {configContext.screenHeight}</Text>
                        <Sprite />
                    </View>
                    );
                }
                else {
                    return (
                        <View>
                            <Text>Image is not loaded!</Text>
                            <ImageLoader />
                        </View>
                    );
                }
            }}</ConfigContext.Consumer>
        );
    }
}

export default Home;
import { ConfigContext } from '../contexts/ConfigContext';

class ImageLoader extends Component {
    static contextType = ConfigContext;
    componentDidMount() {
        const spriteMapImage = this.refs.spritemap;
        spriteMapImage.onload = () => {
            console.log("Image has loaded");
            this.context.setSpriteMapImage(this.refs.spritemap);
        }
    }
    render() { 
        return (
            <img ref="spritemap" src={require('../assets/SpriteMap.png')} style={{width:0, height:0}} />
        )
    }
}
 
export default ImageLoader;
import { Dimensions } from 'react-native';

export const ConfigContext = createContext();

class ConfigContextProvider extends Component {
    state = { 
        screenWidth: Dimensions.get('window').width,
        screenHeight: Dimensions.get('window').height,
        spriteSize: 50,
        spriteMapIsLoaded: false,
        spriteMapImage: null
    }
    setSpriteMapImage = (spriteMapImage) => {
        this.setState({
            spriteMapIsLoaded: true,
            spriteMapImage: spriteMapImage});
    }
    render() { 
        return ( 
            <ConfigContext.Provider value={{...this.state, setSpriteMapImage: this.setSpriteMapImage}}>
                {this.props.children}
            </ConfigContext.Provider>
         );
    }
}
 
export default ConfigContextProvider;
import { ConfigContext } from '../contexts/ConfigContext';

class Sprite extends Component {
    static contextType = ConfigContext;
    componentDidMount() {
        console.log(this.context);
        const canvas = this.refs.canvas;
        const ctx = canvas.getContext('2d');
        for(let x = 0; x <= 360; x += 120) {
            let y = Math.floor(Math.random() * 8) * 120;
            console.log(x, y);
            ctx.drawImage(this.context.spriteMapImage, x, y, 120, 120, 0, 0, this.context.spriteSize, this.context.spriteSize);
        }
        ctx.drawImage(this.context.spriteMapImage, 960, 120, 120, 120, 0, 0, this.context.spriteSize, this.context.spriteSize);
        const cardColour = Math.floor(Math.random() * 2);
        const cardSuit = Math.floor(Math.random() * 2);
        const cardSymbol = Math.floor(Math.random() * 4);
        ctx.drawImage(this.context.spriteMapImage, 480 + cardSymbol * 120, cardColour * 120, 120, 120, 0, 0, this.context.spriteSize, this.context.spriteSize);
        ctx.drawImage(this.context.spriteMapImage, 480 + cardColour * 240 + cardSuit * 120, 240, 120, 120, 0, 0, this.context.spriteSize, this.context.spriteSize);
    }
    render() {
        return (
            <div>
                <canvas ref="canvas" width={this.context.spriteSize} height={this.context.spriteSize} /> 
            </div>
        );
    }
}
 
export default Sprite;
从“../context/ConfigContext”导入{ConfigContext};
类ImageLoader扩展组件{
静态contextType=ConfigContext;
componentDidMount(){
const spriteMapImage=this.refs.spritemap;
spriteMapImage.onload=()=>{
log(“图像已加载”);
this.context.setPriteMapImage(this.refs.spritemap);
}
}
render(){
返回(
)
}
}
导出默认图像加载器;
ConfigContext.js

import { Text, View } from 'react-native';
import Home from './components/Home';
import ConfigContextProvider from './contexts/ConfigContext';

export default class App extends Component {
  render() {
    return (
      <ConfigContextProvider>
        <Home />
      </ConfigContextProvider>
    );
  }
}
import { Text, View, Button } from 'react-native';
import { ConfigContext } from '../contexts/ConfigContext';
import Sprite from './Sprite';
import ImageLoader from './ImageLoader';

class Home extends Component {
    render() { 
        return ( 
            <ConfigContext.Consumer>{(configContext) => {
                if(configContext.spriteMapIsLoaded) {
                    return (
                        <View>
                        <Text>It's Alive!</Text>
                        <Text>Screen Width: {configContext.screenWidth}</Text>
                        <Text>Screen Height: {configContext.screenHeight}</Text>
                        <Sprite />
                    </View>
                    );
                }
                else {
                    return (
                        <View>
                            <Text>Image is not loaded!</Text>
                            <ImageLoader />
                        </View>
                    );
                }
            }}</ConfigContext.Consumer>
        );
    }
}

export default Home;
import { ConfigContext } from '../contexts/ConfigContext';

class ImageLoader extends Component {
    static contextType = ConfigContext;
    componentDidMount() {
        const spriteMapImage = this.refs.spritemap;
        spriteMapImage.onload = () => {
            console.log("Image has loaded");
            this.context.setSpriteMapImage(this.refs.spritemap);
        }
    }
    render() { 
        return (
            <img ref="spritemap" src={require('../assets/SpriteMap.png')} style={{width:0, height:0}} />
        )
    }
}
 
export default ImageLoader;
import { Dimensions } from 'react-native';

export const ConfigContext = createContext();

class ConfigContextProvider extends Component {
    state = { 
        screenWidth: Dimensions.get('window').width,
        screenHeight: Dimensions.get('window').height,
        spriteSize: 50,
        spriteMapIsLoaded: false,
        spriteMapImage: null
    }
    setSpriteMapImage = (spriteMapImage) => {
        this.setState({
            spriteMapIsLoaded: true,
            spriteMapImage: spriteMapImage});
    }
    render() { 
        return ( 
            <ConfigContext.Provider value={{...this.state, setSpriteMapImage: this.setSpriteMapImage}}>
                {this.props.children}
            </ConfigContext.Provider>
         );
    }
}
 
export default ConfigContextProvider;
import { ConfigContext } from '../contexts/ConfigContext';

class Sprite extends Component {
    static contextType = ConfigContext;
    componentDidMount() {
        console.log(this.context);
        const canvas = this.refs.canvas;
        const ctx = canvas.getContext('2d');
        for(let x = 0; x <= 360; x += 120) {
            let y = Math.floor(Math.random() * 8) * 120;
            console.log(x, y);
            ctx.drawImage(this.context.spriteMapImage, x, y, 120, 120, 0, 0, this.context.spriteSize, this.context.spriteSize);
        }
        ctx.drawImage(this.context.spriteMapImage, 960, 120, 120, 120, 0, 0, this.context.spriteSize, this.context.spriteSize);
        const cardColour = Math.floor(Math.random() * 2);
        const cardSuit = Math.floor(Math.random() * 2);
        const cardSymbol = Math.floor(Math.random() * 4);
        ctx.drawImage(this.context.spriteMapImage, 480 + cardSymbol * 120, cardColour * 120, 120, 120, 0, 0, this.context.spriteSize, this.context.spriteSize);
        ctx.drawImage(this.context.spriteMapImage, 480 + cardColour * 240 + cardSuit * 120, 240, 120, 120, 0, 0, this.context.spriteSize, this.context.spriteSize);
    }
    render() {
        return (
            <div>
                <canvas ref="canvas" width={this.context.spriteSize} height={this.context.spriteSize} /> 
            </div>
        );
    }
}
 
export default Sprite;
从'react native'导入{Dimensions};
export const ConfigContext=createContext();
类ConfigContextProvider扩展组件{
状态={
屏幕宽度:尺寸。获取('窗口')。宽度,
屏幕高度:尺寸。获取(“窗口”)。高度,
精灵化:50,
spriteMapIsLoaded:错误,
spriteMapImage:null
}
setSpriteMapImage=(spriteMapImage)=>{
这是我的国家({
spriteMapIsLoaded:没错,
spriteMapImage:spriteMapImage});
}
render(){
报税表(
{this.props.children}
);
}
}
导出默认ConfigContextProvider;
Sprite.js

import { Text, View } from 'react-native';
import Home from './components/Home';
import ConfigContextProvider from './contexts/ConfigContext';

export default class App extends Component {
  render() {
    return (
      <ConfigContextProvider>
        <Home />
      </ConfigContextProvider>
    );
  }
}
import { Text, View, Button } from 'react-native';
import { ConfigContext } from '../contexts/ConfigContext';
import Sprite from './Sprite';
import ImageLoader from './ImageLoader';

class Home extends Component {
    render() { 
        return ( 
            <ConfigContext.Consumer>{(configContext) => {
                if(configContext.spriteMapIsLoaded) {
                    return (
                        <View>
                        <Text>It's Alive!</Text>
                        <Text>Screen Width: {configContext.screenWidth}</Text>
                        <Text>Screen Height: {configContext.screenHeight}</Text>
                        <Sprite />
                    </View>
                    );
                }
                else {
                    return (
                        <View>
                            <Text>Image is not loaded!</Text>
                            <ImageLoader />
                        </View>
                    );
                }
            }}</ConfigContext.Consumer>
        );
    }
}

export default Home;
import { ConfigContext } from '../contexts/ConfigContext';

class ImageLoader extends Component {
    static contextType = ConfigContext;
    componentDidMount() {
        const spriteMapImage = this.refs.spritemap;
        spriteMapImage.onload = () => {
            console.log("Image has loaded");
            this.context.setSpriteMapImage(this.refs.spritemap);
        }
    }
    render() { 
        return (
            <img ref="spritemap" src={require('../assets/SpriteMap.png')} style={{width:0, height:0}} />
        )
    }
}
 
export default ImageLoader;
import { Dimensions } from 'react-native';

export const ConfigContext = createContext();

class ConfigContextProvider extends Component {
    state = { 
        screenWidth: Dimensions.get('window').width,
        screenHeight: Dimensions.get('window').height,
        spriteSize: 50,
        spriteMapIsLoaded: false,
        spriteMapImage: null
    }
    setSpriteMapImage = (spriteMapImage) => {
        this.setState({
            spriteMapIsLoaded: true,
            spriteMapImage: spriteMapImage});
    }
    render() { 
        return ( 
            <ConfigContext.Provider value={{...this.state, setSpriteMapImage: this.setSpriteMapImage}}>
                {this.props.children}
            </ConfigContext.Provider>
         );
    }
}
 
export default ConfigContextProvider;
import { ConfigContext } from '../contexts/ConfigContext';

class Sprite extends Component {
    static contextType = ConfigContext;
    componentDidMount() {
        console.log(this.context);
        const canvas = this.refs.canvas;
        const ctx = canvas.getContext('2d');
        for(let x = 0; x <= 360; x += 120) {
            let y = Math.floor(Math.random() * 8) * 120;
            console.log(x, y);
            ctx.drawImage(this.context.spriteMapImage, x, y, 120, 120, 0, 0, this.context.spriteSize, this.context.spriteSize);
        }
        ctx.drawImage(this.context.spriteMapImage, 960, 120, 120, 120, 0, 0, this.context.spriteSize, this.context.spriteSize);
        const cardColour = Math.floor(Math.random() * 2);
        const cardSuit = Math.floor(Math.random() * 2);
        const cardSymbol = Math.floor(Math.random() * 4);
        ctx.drawImage(this.context.spriteMapImage, 480 + cardSymbol * 120, cardColour * 120, 120, 120, 0, 0, this.context.spriteSize, this.context.spriteSize);
        ctx.drawImage(this.context.spriteMapImage, 480 + cardColour * 240 + cardSuit * 120, 240, 120, 120, 0, 0, this.context.spriteSize, this.context.spriteSize);
    }
    render() {
        return (
            <div>
                <canvas ref="canvas" width={this.context.spriteSize} height={this.context.spriteSize} /> 
            </div>
        );
    }
}
 
export default Sprite;
从“../context/ConfigContext”导入{ConfigContext};
类Sprite扩展组件{
静态contextType=ConfigContext;
componentDidMount(){
log(this.context);
const canvas=this.refs.canvas;
const ctx=canvas.getContext('2d');
对于(设x=0;x