diff --git a/examples/website/quick-start/app.jsx b/examples/website/quick-start/app.jsx index 79323952..28397936 100644 --- a/examples/website/quick-start/app.jsx +++ b/examples/website/quick-start/app.jsx @@ -7,7 +7,7 @@ import {anticipate, easeIn, reverseEasing} from 'popmotion'; const INITIAL_VIEW_STATE = { longitude: -122.402, latitude: 37.79, - zoom: 11 + zoom: 14 }; const TIMECODE = { @@ -17,10 +17,23 @@ const TIMECODE = { }; const RESOLUTION = { - width: 640, - height: 480 + width: 1920, + height: 1080 }; +const FORMAT_CONFIGS = { + webm: { + quality: 0.99 + }, + gif: { + width: 480, + height: 270 + } +}; + +const BACKGROUND = [30 / 255, 30 / 255, 30 / 255, 1]; +const BLUE = [37, 80, 129]; + const Container = ({children}) => (
d.color, getRadius: d => d.radius, - opacity: 0.1, - radiusScale: 0.01 + opacity: 1, + radiusScale: 1 }), new TextLayer({ id: 'text', data: [{position: [-122.402, 37.79], text: 'Hello World'}], - opacity: 0.1, - getAngle: -90 + opacity: 1, + getPixelOffset: [0, -64], + getSize: 64 }) ]), layerKeyframes: [ @@ -89,10 +103,14 @@ export default function App() {
- { - setCameraFrame(vs as MapViewState); - }} - controller={true} - width={resolution.width} - height={resolution.height} - layers={layers} - {...adapter.getProps({deck, onNextFrame, extraProps: deckProps})} - /> + + {deckglStyle => ( + { + setCameraFrame(vs as MapViewState); + }} + controller={true} + width={resolution.width} + height={resolution.height} + layers={layers} + {...adapter.getProps({deck, onNextFrame, extraProps: deckProps})} + /> + )} +
{ + const aspect = internalCanvasResolution.width / internalCanvasResolution.height; + if (aspect > 1) { + // horizontal + return {width: Math.round(minAxis * aspect), height: minAxis}; + } else if (aspect < 1) { + // vertical + return {width: minAxis, height: Math.round(minAxis / aspect)}; + } + // square + return {width: minAxis, height: minAxis}; +}; + +export const DeckGLRender = ({renderResolution, previewPadding = 0, overlay = null, children}) => { + const canvasClientSize = getCanvasClientSize(renderResolution); + return ( + + {previewSize => { + const scalar = scale(previewSize, canvasClientSize); + const deckglStyle = { + width: `${canvasClientSize.width}px`, + height: `${canvasClientSize.height}px`, + transform: `scale(${scalar})`, + transformOrigin: 'top left' + }; + return ( +
+ {children(deckglStyle)} +
+ ); + }} +
+ ); +}; diff --git a/modules/react/src/renderer/pillarbox.js b/modules/react/src/renderer/pillarbox.js new file mode 100644 index 00000000..1f080269 --- /dev/null +++ b/modules/react/src/renderer/pillarbox.js @@ -0,0 +1,75 @@ +import React, {useCallback} from 'react'; +import styled from 'styled-components'; +import AutoSizer from 'react-virtualized-auto-sizer'; +import {nearestEven, scale} from './utils'; + +const AutoSizePillarbox = ({children, internalCanvasResolution, previewPadding}) => { + const getPreviewSize = useCallback( + ({width, height}) => { + // padding + if (width > height) { + width = width - previewPadding; + } else { + height = height - previewPadding; + } + const scalar = scale({width, height}, internalCanvasResolution); + return { + width: nearestEven(internalCanvasResolution.width * scalar, 0), + height: nearestEven(internalCanvasResolution.height * scalar, 0) + }; + }, + [internalCanvasResolution, previewPadding] + ); + + return ( + + {({width, height}) => { + const previewSize = getPreviewSize({width, height}); + return children({ + previewSize, + pillarboxSize: {width: nearestEven(width, 0), height: nearestEven(height, 0)} + }); + }} + + ); +}; + +const PillarboxBackground = styled.div` + display: flex; + justify-content: center; + align-items: center; + width: ${props => props.size.width}px; + height: ${props => props.size.height}px; +`; + +const PillarboxOverlay = styled.div` + position: absolute; + width: ${props => props.size.width}px; + height: ${props => props.size.height}px; +`; + +export const Pillarbox = ({children, overlay, internalCanvasResolution, previewPadding}) => { + return ( + + {({previewSize, pillarboxSize}) => ( + + {children ? ( + children(previewSize) + ) : ( +
+ )} + {overlay && {overlay}} + + )} + + ); +}; diff --git a/modules/react/src/renderer/utils.js b/modules/react/src/renderer/utils.js new file mode 100644 index 00000000..b39ddec4 --- /dev/null +++ b/modules/react/src/renderer/utils.js @@ -0,0 +1,10 @@ +export const nearestEven = (num, decimalPlaces = 3) => { + const factorTen = Math.pow(10, decimalPlaces); + num = num * factorTen; + num = 2 * Math.round(num / 2); + return num / factorTen; +}; + +export function scale(startingSize, targetSize) { + return Math.min(startingSize.width / targetSize.width, startingSize.height / targetSize.height); +} diff --git a/yarn.lock b/yarn.lock index e97f2914..37dc57af 100644 --- a/yarn.lock +++ b/yarn.lock @@ -3317,9 +3317,9 @@ camelize@^1.0.0: integrity sha512-W2lPwkBkMZwFlPCXhIlYgxu+7gC/NUlCtdK652DAJ1JdgV0sTrvuPFshNPrFa1TY2JOkLhgdeEBplB4ezEa+xg== caniuse-lite@^1.0.30001370: - version "1.0.30001374" - resolved "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001374.tgz" - integrity sha512-mWvzatRx3w+j5wx/mpFN5v5twlPrabG8NqX2c6e45LCpymdoGqNvRkRutFUqpRTXKFQFNQJasvK0YT7suW6/Hw== + version "1.0.30001414" + resolved "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001414.tgz" + integrity sha512-t55jfSaWjCdocnFdKQoO+d2ct9C59UZg4dY3OnUlSZ447r8pUtIKdp0hpAzrGFultmTC+Us+KpKi4GZl/LXlFg== caseless@~0.12.0: version "0.12.0"