fixed controls buttons positioning in presentations
This commit is contained in:
parent
2bc7b64707
commit
e1f032b123
@ -34,6 +34,10 @@ interface RuntimeControlsProps {
|
||||
pages?: PreloadPage[];
|
||||
isFullscreen: boolean;
|
||||
toggleFullscreen: () => void;
|
||||
/** Canvas width in pixels (for positioning relative to canvas) */
|
||||
canvasWidth?: number;
|
||||
/** Canvas height in pixels (for positioning relative to canvas) */
|
||||
canvasHeight?: number;
|
||||
}
|
||||
|
||||
/**
|
||||
@ -381,12 +385,31 @@ function useCounterZoom() {
|
||||
return scale;
|
||||
}
|
||||
|
||||
/**
|
||||
* Hook to get viewport dimensions
|
||||
*/
|
||||
function useViewportSize() {
|
||||
const [size, setSize] = useState({ width: 0, height: 0 });
|
||||
|
||||
useEffect(() => {
|
||||
const update = () => {
|
||||
setSize({ width: window.innerWidth, height: window.innerHeight });
|
||||
};
|
||||
update();
|
||||
window.addEventListener('resize', update);
|
||||
return () => window.removeEventListener('resize', update);
|
||||
}, []);
|
||||
|
||||
return size;
|
||||
}
|
||||
|
||||
/**
|
||||
* RuntimeControls - Main component for presentation controls
|
||||
*
|
||||
* Renders offline toggle and fullscreen button using fixed pixel values
|
||||
* to maintain usable size regardless of canvas scaling.
|
||||
* Uses visualViewport API to counter pinch-zoom scaling on mobile.
|
||||
* Positions controls relative to the canvas area (not viewport edges).
|
||||
*/
|
||||
export default function RuntimeControls({
|
||||
projectId,
|
||||
@ -395,14 +418,28 @@ export default function RuntimeControls({
|
||||
pages,
|
||||
isFullscreen,
|
||||
toggleFullscreen,
|
||||
canvasWidth = 0,
|
||||
canvasHeight = 0,
|
||||
}: RuntimeControlsProps) {
|
||||
// Counter-scale to resist pinch-zoom
|
||||
const counterScale = useCounterZoom();
|
||||
const viewport = useViewportSize();
|
||||
|
||||
// Calculate position relative to centered canvas
|
||||
// Canvas is centered with: left: 50%, top: 50%, transform: translate(-50%, -50%)
|
||||
// So we offset from viewport edge by (viewport - canvas) / 2 + padding
|
||||
const padding = 16;
|
||||
const rightOffset = canvasWidth > 0 && viewport.width > 0
|
||||
? (viewport.width - canvasWidth) / 2 + padding
|
||||
: padding;
|
||||
const topOffset = canvasHeight > 0 && viewport.height > 0
|
||||
? (viewport.height - canvasHeight) / 2 + padding
|
||||
: padding;
|
||||
|
||||
const containerStyle: CSSProperties = {
|
||||
position: 'fixed',
|
||||
top: 16,
|
||||
right: 16,
|
||||
top: topOffset,
|
||||
right: rightOffset,
|
||||
display: 'flex',
|
||||
alignItems: 'center',
|
||||
gap: 8,
|
||||
|
||||
@ -92,7 +92,7 @@ export default function RuntimePresentation({
|
||||
|
||||
// Canvas scale for responsive UI elements and letterbox mode
|
||||
// Uses page's design dimensions (saved at constructor save time) for presentation isolation
|
||||
const { cssVars, letterboxStyles, isPortrait, showRotatePrompt } =
|
||||
const { cssVars, letterboxStyles, isPortrait, showRotatePrompt, canvasWidth, canvasHeight } =
|
||||
useCanvasScale({
|
||||
designWidth: currentPage?.design_width ?? undefined,
|
||||
designHeight: currentPage?.design_height ?? undefined,
|
||||
@ -774,6 +774,8 @@ export default function RuntimePresentation({
|
||||
pages={pages}
|
||||
isFullscreen={isFullscreen}
|
||||
toggleFullscreen={toggleFullscreen}
|
||||
canvasWidth={canvasWidth}
|
||||
canvasHeight={canvasHeight}
|
||||
/>
|
||||
|
||||
{/* Toast notifications for offline download status */}
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user