import { Rect } from "./Rect.web"; import { IHTMLElement } from "./types"; export class RNSharedElementContent { public readonly element: IHTMLElement; public readonly size: Rect; constructor(element: IHTMLElement, size: Rect) { this.element = element; this.size = size; } static getSize(element: IHTMLElement): Promise { return new Promise((resolve) => { if (element.style.backgroundImage) { const img = document.createElement("img"); img.onload = () => { resolve( new Rect({ x: 0, y: 0, width: img.width, height: img.height, }) ); }; img.onerror = () => resolve(null); const url = element.style.backgroundImage; img.src = url.substring(5, url.length - 2); return; } resolve( new Rect({ x: 0, y: 0, width: element.clientWidth || 0, height: element.clientHeight || 0, }) ); }); } static getLayout( layout: Rect, content: RNSharedElementContent | null, resizeMode: string, reverse?: boolean ) { if (!content) return layout; if (!content.element.style.backgroundImage) return layout; let { width, height } = layout; const contentAspectRatio = content.size.width / content.size.height; const lo = width / height < contentAspectRatio; const aspectRatioCriteria = reverse ? !lo : lo; switch (resizeMode) { case "stretch": case "100% 100%": // nop break; case "cover": if (aspectRatioCriteria) { width = height * contentAspectRatio; } else { height = width / contentAspectRatio; } break; case "center": width = content.size.width; height = content.size.height; break; case "contain": default: if (aspectRatioCriteria) { height = width / contentAspectRatio; } else { width = height * contentAspectRatio; } break; } return new Rect({ x: layout.x + (layout.width - width) / 2, y: layout.y + (layout.height - height) / 2, width, height, }); } }