Приложение React Native (Expo) - рисование из локального изображения на холст с помощью метода drawImage () - PullRequest
1 голос
/ 10 июля 2020

У меня есть прозрачный лист спрайтов PNG, который я загружаю в тег, а затем, когда срабатывает 'onload', я сохраняю элемент в контекстном объекте (ImageLoader. js), чтобы позже использовать его с drawImage на холсте ( Sprite. js) для извлечения различных спрайтов и наложения их для создания составного тайла для игры.

Home. js просто выбирает отображение фиктивного сообщения об удержании, но возвращает aws, как только ' onload 'срабатывает, который затем отображает компонент

Я пытался использовать react-native-canvas и другие различные подходы, но я не уверен, возможно ли то, что я пытаюсь сделать.

Ниже приведены различные фрагменты кода, которые, возможно, легче показать, чем пытаться описать ...

Код отлично работает в браузере, но это приложение React Native, использующее платформу Expo, и оно не работает из-за моего тега в ImageLoader . js компонент. В идеале я бы использовал React Native Image, но это не вариант для метода Canvas drawImage, который требует объекта Image в стиле DOM.

Я открыт для других способов достижения этого, но, по сути, мне нужно иметь возможность создать настраиваемый компонент React Native Image, в котором базовое изображение создается в приложении с помощью локального прозрачного листа спрайтов PNG и наложения его различных его частей на холст, чтобы я создавал составное изображение ...

Приложение. 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>
    );
  }
}

Домашнее. js

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;

ImageLoader. js

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;

ConfigContext. js

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;

Sprite. js

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;
...