import React from 'react' import ReactCrop, { makeAspectCrop } from 'react-image-crop' import RandomImage, { downloadThumbnailImage } from './RandomImage' import PhotoCredit from './PhotoCredit' import Input from './Input' import { fileToDataURL } from '../lib/util' const getCroppedImg = (imageDataURL, pixelCrop) => { const canvas = document.createElement('canvas') canvas.width = pixelCrop.width canvas.height = pixelCrop.height const ctx = canvas.getContext('2d') return new Promise(resolve => { const image = new Image() image.src = imageDataURL image.onload = () => { ctx.drawImage( image, pixelCrop.x, pixelCrop.y, pixelCrop.width, pixelCrop.height, 0, 0, pixelCrop.width, pixelCrop.height ) resolve(canvas.toDataURL('image/jpeg')) } }) } const INITIAL_STATE = { mode: 'file', crop: null, imageAspectRatio: null, pixelCrop: null, photographer: null } export default class ImagePicker extends React.Component { constructor(props) { super(props) this.state = INITIAL_STATE this.handleURLInput = this.handleURLInput.bind(this) this.selectImage = this.selectImage.bind(this) this.removeImage = this.removeImage.bind(this) this.onImageLoaded = this.onImageLoaded.bind(this) this.onCropChange = this.onCropChange.bind(this) this.onDragEnd = this.onDragEnd.bind(this) this.selectMode = this.selectMode.bind(this) } static getDerivedStateFromProps(nextProps, state) { if (state.crop) { // update crop for editor container aspect-ratio change return { crop: makeAspectCrop( { ...state.crop, aspect: nextProps.aspectRatio }, state.imageAspectRatio ) } } return null } async onDragEnd() { if (this.state.pixelCrop) { const croppedImg = await getCroppedImg(this.props.imageDataURL, this.state.pixelCrop) this.props.onChange({ backgroundImageSelection: croppedImg }) } } onCropChange(crop, pixelCrop) { this.setState({ crop: { ...crop, aspect: this.props.aspectRatio }, pixelCrop }) } onImageLoaded(image) { const imageAspectRatio = image.width / image.height const initialCrop = { x: 0, y: 0, width: 100, aspect: this.props.aspectRatio } this.setState({ imageAspectRatio, crop: makeAspectCrop(initialCrop, imageAspectRatio) }) } handleURLInput(e) { e.preventDefault() const url = e.target[0].value return downloadThumbnailImage({ url }) .then(({ dataURL }) => this.props.onChange({ backgroundImage: dataURL, backgroundImageSelection: null, photographer: null }) ) .catch(err => { if (err.message.indexOf('Network Error') > -1) { this.setState({ error: 'Fetching the image failed. This is probably a CORS-related issue. You can either enable CORS in your browser, or use another image.' }) } }) } selectMode(mode) { this.setState({ mode }) } selectImage(e, { photographer } = {}) { const file = e.target ? e.target.files[0] : e return fileToDataURL(file).then(dataURL => this.setState({ photographer }, () => { this.props.onChange({ backgroundImage: dataURL, backgroundImageSelection: null, photographer }) }) ) } removeImage() { this.setState(INITIAL_STATE, () => { this.props.onChange({ backgroundImage: null, backgroundImageSelection: null }) }) } render() { let content = (
Upload a background image: {this.state.mode === 'file' ? ( ) : (
)} {this.state.error && {this.state.error}}

Or use a random Unsplash image:
) if (this.props.imageDataURL) { content = (
Background image ×
{this.state.photographer && }
) } return (
{content}
) } }