2021-01-21 15:56:49 +00:00
|
|
|
import { useState, useEffect, useCallback } from 'react'
|
|
|
|
import './App.css'
|
2021-01-21 15:57:02 +00:00
|
|
|
import download from 'downloadjs'
|
2021-01-21 18:11:37 +00:00
|
|
|
import FrameChooser from './FrameChooser.js'
|
2021-01-21 18:16:17 +00:00
|
|
|
import HeaderImage from './HeaderImage.svg'
|
2021-01-21 15:56:49 +00:00
|
|
|
|
|
|
|
import mergeImages from 'merge-images'
|
|
|
|
|
|
|
|
const frameSize = 1080
|
2021-01-21 14:18:25 +00:00
|
|
|
|
|
|
|
function App() {
|
2021-01-21 18:11:37 +00:00
|
|
|
const [frameURL, setFrameURL] = useState(null)
|
2021-01-21 19:54:45 +00:00
|
|
|
const [originalPhoto, setOriginalPhoto] = useState(null)
|
2021-01-21 15:56:49 +00:00
|
|
|
const [photo, setPhoto] = useState(null)
|
|
|
|
const [combinedImage, setCombinedImage] = useState(null)
|
|
|
|
|
2021-01-21 18:11:37 +00:00
|
|
|
const handleFrameURL = useCallback(newFrameURL => {
|
|
|
|
setFrameURL(newFrameURL)
|
|
|
|
}, [setFrameURL])
|
|
|
|
|
2021-01-21 15:56:49 +00:00
|
|
|
const handleImage = useCallback(files_event => {
|
|
|
|
const reader = new FileReader()
|
|
|
|
reader.onload = reader_event => {
|
|
|
|
const img = new Image()
|
|
|
|
img.onload = function () {
|
|
|
|
const offscreenCanvas = document.createElement('canvas')
|
|
|
|
offscreenCanvas.width = frameSize
|
|
|
|
offscreenCanvas.height = frameSize
|
|
|
|
|
|
|
|
|
|
|
|
const width = frameSize
|
|
|
|
const height = (img.height / img.width) * frameSize
|
2021-01-21 19:56:34 +00:00
|
|
|
const offscreenCanvas_ctx = offscreenCanvas.getContext('2d', { alpha: true })
|
2021-01-21 15:56:49 +00:00
|
|
|
offscreenCanvas_ctx.drawImage(
|
|
|
|
img,
|
|
|
|
(frameSize - width) / 2,
|
|
|
|
(frameSize - height) / 2,
|
|
|
|
width,
|
|
|
|
height,
|
|
|
|
);
|
|
|
|
|
|
|
|
const pngUrl = offscreenCanvas.toDataURL()
|
|
|
|
setPhoto(pngUrl)
|
|
|
|
}
|
|
|
|
img.src = reader_event.target.result
|
2021-01-21 19:54:45 +00:00
|
|
|
setOriginalPhoto(reader_event.target.result)
|
2021-01-21 15:56:49 +00:00
|
|
|
}
|
|
|
|
reader.readAsDataURL(files_event.target.files[0])
|
|
|
|
}, [setPhoto])
|
|
|
|
|
|
|
|
useEffect(() => {
|
|
|
|
mergeImages([
|
|
|
|
...(photo ? [photo] : []),
|
2021-01-21 18:11:37 +00:00
|
|
|
...(frameURL ? [frameURL] : []),
|
2021-01-21 15:56:49 +00:00
|
|
|
])
|
|
|
|
.then(b64 => setCombinedImage(b64))
|
2021-01-21 18:11:37 +00:00
|
|
|
}, [photo, frameURL])
|
2021-01-21 15:56:49 +00:00
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
return (
|
2021-01-21 14:18:25 +00:00
|
|
|
<div className="App">
|
2021-01-21 18:59:50 +00:00
|
|
|
<img src={HeaderImage} className="HeaderImage" alt="Volt Logo" />
|
2021-01-21 15:56:49 +00:00
|
|
|
|
2021-01-21 18:33:07 +00:00
|
|
|
<h2>Choose your Photo:</h2>
|
2021-01-21 19:54:09 +00:00
|
|
|
<p>It should best be a square image or your face in the middle. The photo is not saved and never leaves your computer.</p>
|
2021-01-21 18:33:07 +00:00
|
|
|
|
2021-01-21 18:31:57 +00:00
|
|
|
<label className="labelButton" tabIndex="0" style={{outline:'none'}}>
|
2021-01-21 19:54:45 +00:00
|
|
|
{!!photo ? <img src={originalPhoto} alt="Preview" /> : null}
|
2021-01-21 19:56:13 +00:00
|
|
|
<span>{!!photo ? 'Change Photo' : 'Load Photo'}</span>
|
2021-01-21 18:31:57 +00:00
|
|
|
<input onChange={handleImage} type="file" accept="image/*" style={{display: 'none'}} />
|
|
|
|
</label>
|
2021-01-21 15:56:49 +00:00
|
|
|
|
2021-01-21 18:11:37 +00:00
|
|
|
<FrameChooser onFrameChange={handleFrameURL} />
|
2021-01-21 18:33:07 +00:00
|
|
|
|
|
|
|
<h2>Download your Photo:</h2>
|
2021-01-21 18:32:45 +00:00
|
|
|
<img src={combinedImage} className="FinishedFrame" alt="Finished Frame" />
|
2021-01-21 18:31:13 +00:00
|
|
|
<button onClick={() => download(combinedImage, "volt-profile-picture.png", "image/png")}>Download Profile Picture</button>
|
2021-01-21 14:18:25 +00:00
|
|
|
</div>
|
2021-01-21 15:56:49 +00:00
|
|
|
)
|
2021-01-21 14:18:25 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
export default App;
|