// Based on https://codepen.io/inlet/pen/yLVmPWv. // Copyright (c) 2018 Patrick Brouwer, distributed under the MIT license. import { PixiComponent, useApp } from '@pixi/react'; import { Viewport } from 'pixi-viewport'; import { Application } from 'pixi.js'; import { MutableRefObject, ReactNode } from 'react'; export type ViewportProps = { app: Application; viewportRef?: MutableRefObject; screenWidth: number; screenHeight: number; worldWidth: number; worldHeight: number; children?: ReactNode; }; // https://davidfig.github.io/pixi-viewport/jsdoc/Viewport.html export default PixiComponent('Viewport', { create(props: ViewportProps) { const { app, children, viewportRef, ...viewportProps } = props; const viewport = new Viewport({ // eslint-disable-next-line @typescript-eslint/no-unsafe-assignment, @typescript-eslint/no-unsafe-member-access events: app.renderer.events, passiveWheel: false, ...viewportProps, }); if (viewportRef) { viewportRef.current = viewport; } // Activate plugins viewport .drag() .pinch({}) .wheel() .decelerate() .clamp({ direction: 'all', underflow: 'center' }) .setZoom(-10) .clampZoom({ minScale: (1.04 * props.screenWidth) / (props.worldWidth / 2), maxScale: 3.0, }); return viewport; }, applyProps(viewport, oldProps: any, newProps: any) { Object.keys(newProps).forEach((p) => { if (p !== 'app' && p !== 'viewportRef' && p !== 'children' && oldProps[p] !== newProps[p]) { // @ts-expect-error Ignoring TypeScript here // eslint-disable-next-line @typescript-eslint/no-unsafe-assignment viewport[p] = newProps[p]; } }); }, });