Использование globalCompositeOperation для маскировки группы фигур в React Konva

В моем проекте используется React Konva (https://github.com/konvajs/react-konva)

Я пытаюсь нарисовать несколько фигур в Group и использовать это, чтобы замаскировать изображение «внизу».

Когда мой компонент рисует одну фигуру с примененным globalCompositeOperation, он дает ожидаемый результат. Вот код:

render() {
        return (

            <Group >
                <Group>
                    <Image 
                        image={this.state.image} 
                        ref={node => { this.image = node; }} 
                    />
                    <Group>
                        <Rect fill={"#555555"} 
                            width={200} height={200} 
                            x={100} y={100} 
                            globalCompositeOperation={"destination-in"}
                        />
                    </Group>
                </Group>
            </Group>
        )

    }

И результат:  введите описание изображения здесь

Обратите внимание, как изображение обрезается до прямоугольника, открывая текстовый слой ниже.

Однако, как только фигура перемещается внутри группы, и я применяю там globalCompositeOperation, маскирования не происходит. Соответствующая часть кода:

<Group>
            <Image 
                image={this.state.image} 
                ref={node => { this.image = node; }} 
            />
            <Group globalCompositeOperation={"destination-in"}>
                <Rect fill={"#555555"} 
                    width={200} height={200} 
                    x={100} y={100} 
                />
            </Group>
        </Group>

И результат:

введите здесь описание изображения

Это странно, потому что в документации Konva указано, что Group действительно имеет свойство globalCompositeOperation (см. https://konvajs.github.io/api/Konva.Group.html#globalCompositeOperation__anchor).

Есть идеи, как заставить (React) Konva применять globalCompositeOperation на уровне Group, а не только на уровне Shape?


person Anselan    schedule 04.09.2018    source источник


Ответы (1)


Ах, только что нашел решение.

Кажется, что перед применением globalCompositeOperation необходимо кэшировать весь Group. Я предполагаю, что это означает, что группа сначала сглаживается / растеризуется.

В моем компоненте React я нашел решение следующим образом:

 import React from 'react';
import { Image, Group, Rect } from 'react-konva';

class CutoutImage extends React.Component {
    state = {
        image: null,
        mask: null
    }

    componentDidMount() {
        const image = new window.Image();
        image.src = "/images/frisbee.jpg";
        image.onload = () => {
            this.setState({ image });
        }
    }

    componentDidUpdate() {
        if (this.image) {
            this.image.cache();
        }
        if (this.mask) {
            this.mask.cache();
        }
    }

    render() {
        return (

            <Group>
                <Image 
                    image={this.state.image} 
                    ref={node => { this.image = node; }} 
                />
                <Group 
                    globalCompositeOperation={"destination-in"} 
                    ref={node => {this.mask = node; }}
                    >
                    <Rect fill={"#555555"} 
                        width={200} height={200} 
                        x={100} y={100} 
                    />
                    <Rect fill={"#dddddd"} 
                        width={200} height={200} 
                        x={300} y={300} 
                    />
                    <Rect fill={"#dddddd"} 
                        width={200} height={100} 
                        x={150} y={350} 
                    />
                </Group>
            </Group>
        )

    }

}
export default CutoutImage;

И результат:

введите здесь описание изображения

person Anselan    schedule 04.09.2018