fixed controls buttons positioning in presentations
This commit is contained in:
parent
2bc7b64707
commit
e1f032b123
@ -34,6 +34,10 @@ interface RuntimeControlsProps {
|
|||||||
pages?: PreloadPage[];
|
pages?: PreloadPage[];
|
||||||
isFullscreen: boolean;
|
isFullscreen: boolean;
|
||||||
toggleFullscreen: () => void;
|
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;
|
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
|
* RuntimeControls - Main component for presentation controls
|
||||||
*
|
*
|
||||||
* Renders offline toggle and fullscreen button using fixed pixel values
|
* Renders offline toggle and fullscreen button using fixed pixel values
|
||||||
* to maintain usable size regardless of canvas scaling.
|
* to maintain usable size regardless of canvas scaling.
|
||||||
* Uses visualViewport API to counter pinch-zoom scaling on mobile.
|
* Uses visualViewport API to counter pinch-zoom scaling on mobile.
|
||||||
|
* Positions controls relative to the canvas area (not viewport edges).
|
||||||
*/
|
*/
|
||||||
export default function RuntimeControls({
|
export default function RuntimeControls({
|
||||||
projectId,
|
projectId,
|
||||||
@ -395,14 +418,28 @@ export default function RuntimeControls({
|
|||||||
pages,
|
pages,
|
||||||
isFullscreen,
|
isFullscreen,
|
||||||
toggleFullscreen,
|
toggleFullscreen,
|
||||||
|
canvasWidth = 0,
|
||||||
|
canvasHeight = 0,
|
||||||
}: RuntimeControlsProps) {
|
}: RuntimeControlsProps) {
|
||||||
// Counter-scale to resist pinch-zoom
|
// Counter-scale to resist pinch-zoom
|
||||||
const counterScale = useCounterZoom();
|
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 = {
|
const containerStyle: CSSProperties = {
|
||||||
position: 'fixed',
|
position: 'fixed',
|
||||||
top: 16,
|
top: topOffset,
|
||||||
right: 16,
|
right: rightOffset,
|
||||||
display: 'flex',
|
display: 'flex',
|
||||||
alignItems: 'center',
|
alignItems: 'center',
|
||||||
gap: 8,
|
gap: 8,
|
||||||
|
|||||||
@ -92,7 +92,7 @@ export default function RuntimePresentation({
|
|||||||
|
|
||||||
// Canvas scale for responsive UI elements and letterbox mode
|
// Canvas scale for responsive UI elements and letterbox mode
|
||||||
// Uses page's design dimensions (saved at constructor save time) for presentation isolation
|
// 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({
|
useCanvasScale({
|
||||||
designWidth: currentPage?.design_width ?? undefined,
|
designWidth: currentPage?.design_width ?? undefined,
|
||||||
designHeight: currentPage?.design_height ?? undefined,
|
designHeight: currentPage?.design_height ?? undefined,
|
||||||
@ -774,6 +774,8 @@ export default function RuntimePresentation({
|
|||||||
pages={pages}
|
pages={pages}
|
||||||
isFullscreen={isFullscreen}
|
isFullscreen={isFullscreen}
|
||||||
toggleFullscreen={toggleFullscreen}
|
toggleFullscreen={toggleFullscreen}
|
||||||
|
canvasWidth={canvasWidth}
|
||||||
|
canvasHeight={canvasHeight}
|
||||||
/>
|
/>
|
||||||
|
|
||||||
{/* Toast notifications for offline download status */}
|
{/* Toast notifications for offline download status */}
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user