From 792471bf00e4e7e6ba200602d76eae09b034a906 Mon Sep 17 00:00:00 2001 From: Bill Thiede Date: Sun, 23 Feb 2020 08:45:06 -0800 Subject: [PATCH] Shuffle slideshow, only show images in the same orientation as screen. --- react-slideshow/src/App.js | 109 ++++++++++++++++++++++++++++++------ react-slideshow/src/rand.js | 30 ++++++++++ 2 files changed, 121 insertions(+), 18 deletions(-) create mode 100644 react-slideshow/src/rand.js diff --git a/react-slideshow/src/App.js b/react-slideshow/src/App.js index c29cf84..8f596a1 100644 --- a/react-slideshow/src/App.js +++ b/react-slideshow/src/App.js @@ -5,9 +5,22 @@ import { Route, useParams } from "react-router-dom"; - +import Random from './rand'; import './App.css'; +let CONFIG; +if (process.env.NODE_ENV === 'production') { + CONFIG = { + sleepTimeSeconds: 5 * 60, + showUI: false, + } +} else { + CONFIG = { + sleepTimeSeconds: 10, + showUI: true, + } +} + const IMAGE_CHUNK = 256; const roundup = (v, mod) => { let r = v % mod; @@ -18,6 +31,20 @@ const roundup = (v, mod) => { } }; +/** + * Shuffles array in place. ES6 version + * From https://stackoverflow.com/questions/6274339/how-can-i-shuffle-an-array + * @param {Array} a items An array containing the items. + */ +function shuffle(a) { + let rng = new Random(new Date().getDay()); + for (let i = a.length - 1; i > 0; i--) { + const j = Math.floor(rng.nextFloat() * (i + 1)); + [a[i], a[j]] = [a[j], a[i]]; + } + return a; +} + class Album extends React.Component { constructor(props) { super(props); @@ -25,6 +52,7 @@ class Album extends React.Component { error: null, mediaItems: null, idx: 0, + showUI: props.showUI, }; } componentDidMount() { @@ -52,18 +80,44 @@ class Album extends React.Component { h = roundup(h, IMAGE_CHUNK); w = (h/ratio).toFixed(); } + console.log(`Window size ${window.innerWidth}x${window.innerHeight} with a devicePixelRatio of ${window.devicePixelRatio} for a total size of ${w}x${h}`); //let w = roundup(window.innerWidth*window.devicePixelRatio, IMAGE_CHUNK); //let h = roundup(window.innerHeight*window.devicePixelRatio, IMAGE_CHUNK); - let {idx, error, mediaItems} = this.state; + let {idx, error, mediaItems, showUI} = this.state; if (error !== null) { return

Error: {JSON.stringify(error)}

; } else if (mediaItems !== null) { - let numImages = mediaItems.length; + let landscapes = mediaItems.filter((mi) => { + let md = mi.mediaMetadata; + let ratio = md.width/md.height; + return ratio > 1; + }); + + let portraits = mediaItems.filter((mi) => { + let md = mi.mediaMetadata; + let ratio = md.width/md.height; + return ratio <= 1; + }); + + console.log(`${landscapes.length} landscape photos`); + console.log(`${portraits.length} portraits photos`); + let photos; + if (ratio > 1) { + console.log('display in landscape mode'); + photos = landscapes; + } else { + console.log('display in portrait mode'); + photos = portraits; + } + photos = shuffle(photos); + + let numImages = photos.length; let nextIdx = (idx+1)%numImages; let prevIdx = (numImages+idx-1)%numImages; - let image = mediaItems[idx]; - let nextImage = mediaItems[nextIdx]; + let image = photos[idx]; + let nextImage = photos[nextIdx]; + let prevImage = photos[prevIdx]; let style = { height: '100%', width: '100%', @@ -74,26 +128,44 @@ class Album extends React.Component { backgroundSize: 'cover', }; let prefetchStyle = { - // display: 'none' position: 'absolute', - right: 0, - bottom: 0, width: '25%', height: '25%', + bottom: 0, }; - console.log(`window.devicePixelRatio ${window.devicePixelRatio}`); - return
{ - e.stopPropagation(); - this.setState({idx: nextIdx}) - }}> - + { e.stopPropagation(); this.setState({idx: prevIdx}) }} + src={`/api/image/${prevImage.id}?w=${w}&h=${h}`} alt="prefetch prev" /> + { + e.stopPropagation(); + this.setState({idx: nextIdx}) + }} src={`/api/image/${nextImage.id}?w=${w}&h=${h}`} alt="prefetch next" />
; + } + return
{ + e.stopPropagation(); + this.setState({showUI: !showUI}) + }}> + { ui } +
; } else { return

Loading...

; } @@ -141,14 +213,15 @@ class AlbumIndex extends React.Component { } } -const AlbumRoute = () => { +const AlbumRoute = ({showUI}) => { // We can use the `useParams` hook here to access // the dynamic pieces of the URL. let { albumId } = useParams(); - return ; + return ; } const App = () => { + let {showUI} = CONFIG; return @@ -157,7 +230,7 @@ const App = () => { - + diff --git a/react-slideshow/src/rand.js b/react-slideshow/src/rand.js new file mode 100644 index 0000000..2d2344d --- /dev/null +++ b/react-slideshow/src/rand.js @@ -0,0 +1,30 @@ +// From https://gist.github.com/blixt/f17b47c62508be59987b +/** + * Creates a pseudo-random value generator. The seed must be an integer. + * + * Uses an optimized version of the Park-Miller PRNG. + * http://www.firstpr.com.au/dsp/rand31/ + */ +function Random(seed) { + console.log(`Seeding prng with ${seed}`); + this._seed = seed % 2147483647; + if (this._seed <= 0) this._seed += 2147483646; +} + +/** + * Returns a pseudo-random value between 1 and 2^32 - 2. + */ +Random.prototype.next = function () { + return this._seed = this._seed * 16807 % 2147483647; +}; + + +/** + * Returns a pseudo-random floating point number in range [0, 1). + */ +Random.prototype.nextFloat = function (opt_minOrMax, opt_max) { + // We know that result of next() will be 1 to 2147483646 (inclusive). + return (this.next() - 1) / 2147483646; +}; + +export default Random;