Add RandomImage component

main
Jake Dexheimer 7 years ago committed by Michael Fix
parent 9499248e1c
commit f79d01ad9b

@ -59,7 +59,7 @@ export default class extends React.Component {
onClick={this.toggle}
className={`display ${this.state.isVisible ? 'is-visible' : ''}`}
>
<span className="label">Export Size</span>
<span className="label">Export size</span>
<span style={{ exportSize: selectedExportSize.id }}>{selectedExportSize.name}</span>
</div>
<div className="list">{this.renderExportSizes()}</div>

@ -1,7 +1,10 @@
import React from 'react'
import ReactCrop, { makeAspectCrop } from 'react-image-crop'
import Slider from './Slider'
import RandomImage from './RandomImage'
import { COLORS } from '../lib/constants'
import { fileToDataURL } from '../lib/util'
const getCroppedImg = (imageDataURL, pixelCrop) => {
const canvas = document.createElement('canvas')
@ -59,18 +62,16 @@ export default class extends React.Component {
}
selectImage(e) {
const file = e.target.files[0]
const file = e.target ? e.target.files[0] : e
const reader = new FileReader()
reader.onload = e =>
this.props.onChange({ backgroundImage: e.target.result, backgroundImageSelection: null })
reader.readAsDataURL(file)
return fileToDataURL(file).then(dataURL =>
this.props.onChange({ backgroundImage: dataURL, backgroundImageSelection: null })
)
}
removeImage() {
this.setState(INITIAL_STATE, () => {
this.props.onChange({
backgroundMode: 'color',
backgroundImage: null,
backgroundImageSelection: null
})
@ -108,18 +109,40 @@ export default class extends React.Component {
render() {
let content = (
<div className="upload-image">
<span>Click the button below to upload a background image</span>
<input type="file" accept="image/x-png,image/jpeg,image/jpg" onChange={this.selectImage} />
<div>
<div className="choose-image">
<span>Click the button below to upload a background image:</span>
<input
type="file"
accept="image/x-png,image/jpeg,image/jpg"
onChange={this.selectImage}
/>
</div>
<hr />
<div className="random-image">
<span>Or use a random unsplash image:</span>
<RandomImage onChange={this.selectImage} />
</div>
<style jsx>{`
.upload-image {
.choose-image,
.random-image {
padding: 8px;
}
input {
cursor: pointer;
outline: none;
}
span {
display: block;
margin-bottom: 16px;
}
hr {
border-bottom: none;
margin-bottom: 0;
}
`}</style>
</div>
)

@ -0,0 +1,93 @@
import React from 'react'
import axios from 'axios'
import { range, fileToDataURL } from '../lib/util'
const RAND_RANGE = 1000000
const UPDATE_SIZE = 10
const WALLPAPER_COLLECTION_ID = 1065396
const RANDOM_WALLPAPER_URL = `https://source.unsplash.com/collection/${WALLPAPER_COLLECTION_ID}/240x320`
const largerImage = url => url.replace(/w=\d+/, 'w=1920').replace(/&h=\d+/, '')
const smallerImage = url => url.replace(/w=\d+/, 'w=240')
async function getImage() {
// circumvent browser caching
const sig = Math.floor(Math.random() * RAND_RANGE)
const res = await axios.get(`${RANDOM_WALLPAPER_URL}?sig=${sig}`, { responseType: 'blob' })
return {
url: res.request.responseURL,
dataURL: await fileToDataURL(res.data)
}
}
export default class extends React.Component {
constructor() {
super()
this.state = { cache: [] }
this.selectImage = this.selectImage.bind(this)
this.updateCache = this.updateCache.bind(this)
this.nextImage = this.nextImage.bind(this)
}
// update in browser (we require window.FileReader)
componentDidMount() {
this.updateCache()
}
selectImage() {
axios
.get(largerImage(this.state.cache[0].url), { responseType: 'blob' })
.then(res => res.data)
.then(this.props.onChange)
}
updateCache() {
Promise.all(range(UPDATE_SIZE).map(getImage)).then(imgs =>
this.setState({ cache: this.state.cache.concat(imgs) })
)
}
nextImage() {
this.setState({ cache: this.state.cache.slice(1) })
if (this.state.cache.length < 3) {
this.updateCache()
}
}
render() {
const bgImage = this.state.cache[0] && this.state.cache[0].dataURL
return (
<div className="random-image-container">
<div className="controls">
<span onClick={this.selectImage}>Use Image</span>
<span onClick={this.nextImage}>Try Another</span>
</div>
<div className="image" />
<style jsx>{`
.image {
width: 100%;
height: 120px;
background: url(${bgImage});
background-size: cover;
background-repeat: no-repeat;
}
.controls {
display: flex;
justify-content: space-between;
margin-bottom: 4px;
}
span {
cursor: pointer;
user-select: none;
}
`}</style>
</div>
)
}
}

@ -24,3 +24,13 @@ export const getState = morph.compose(parse, escapeHtml, morph.get(KEY))
export const saveState = (window, v) => assign(window, JSON.stringify(v))
export const capitalizeFirstLetter = s => s.charAt(0).toUpperCase() + s.slice(1)
export const range = n => [...Array(n).keys()]
export const fileToDataURL = blob => {
return new Promise(res => {
const reader = new FileReader()
reader.onload = e => res(e.target.result)
reader.readAsDataURL(blob)
})
}

Loading…
Cancel
Save