added choosing of a frame
13
src/App.css
|
@ -4,6 +4,19 @@
|
||||||
|
|
||||||
.App-logo {
|
.App-logo {
|
||||||
height: 40vmin;
|
height: 40vmin;
|
||||||
|
.FrameChooser .frame{
|
||||||
|
height: 12vh;
|
||||||
|
margin: 2vh;
|
||||||
|
cursor: pointer;
|
||||||
|
box-shadow: 0 0 0 1vh rgba(255,255,255,0);
|
||||||
|
transition: transform 0.2s ease;
|
||||||
|
}
|
||||||
|
.FrameChooser .frame:hover{
|
||||||
|
transform-origin: center center;
|
||||||
|
transform: scale(1.1);
|
||||||
|
}
|
||||||
|
.FrameChooser .frame.choosen{
|
||||||
|
box-shadow: 0 0 0 1vh white;
|
||||||
}
|
}
|
||||||
|
|
||||||
.App-header {
|
.App-header {
|
||||||
|
|
13
src/App.js
|
@ -1,17 +1,21 @@
|
||||||
import { useState, useEffect, useCallback } from 'react'
|
import { useState, useEffect, useCallback } from 'react'
|
||||||
import './App.css'
|
import './App.css'
|
||||||
import download from 'downloadjs'
|
import download from 'downloadjs'
|
||||||
|
import FrameChooser from './FrameChooser.js'
|
||||||
import frame_mixed from './frames/ProfileFrame Mixed Bars.png'
|
|
||||||
|
|
||||||
import mergeImages from 'merge-images'
|
import mergeImages from 'merge-images'
|
||||||
|
|
||||||
const frameSize = 1080
|
const frameSize = 1080
|
||||||
|
|
||||||
function App() {
|
function App() {
|
||||||
|
const [frameURL, setFrameURL] = useState(null)
|
||||||
const [photo, setPhoto] = useState(null)
|
const [photo, setPhoto] = useState(null)
|
||||||
const [combinedImage, setCombinedImage] = useState(null)
|
const [combinedImage, setCombinedImage] = useState(null)
|
||||||
|
|
||||||
|
const handleFrameURL = useCallback(newFrameURL => {
|
||||||
|
setFrameURL(newFrameURL)
|
||||||
|
}, [setFrameURL])
|
||||||
|
|
||||||
const handleImage = useCallback(files_event => {
|
const handleImage = useCallback(files_event => {
|
||||||
const reader = new FileReader()
|
const reader = new FileReader()
|
||||||
reader.onload = reader_event => {
|
reader.onload = reader_event => {
|
||||||
|
@ -44,10 +48,10 @@ function App() {
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
mergeImages([
|
mergeImages([
|
||||||
...(photo ? [photo] : []),
|
...(photo ? [photo] : []),
|
||||||
...(frame_mixed ? [frame_mixed] : []),
|
...(frameURL ? [frameURL] : []),
|
||||||
])
|
])
|
||||||
.then(b64 => setCombinedImage(b64))
|
.then(b64 => setCombinedImage(b64))
|
||||||
}, [photo])
|
}, [photo, frameURL])
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
@ -61,6 +65,7 @@ return (
|
||||||
|
|
||||||
<button onClick={() => download(combinedImage, "volt-profile-picture.png", "image/png")}>Download Profile Picture</button>
|
<button onClick={() => download(combinedImage, "volt-profile-picture.png", "image/png")}>Download Profile Picture</button>
|
||||||
</header>
|
</header>
|
||||||
|
<FrameChooser onFrameChange={handleFrameURL} />
|
||||||
</div>
|
</div>
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
59
src/FrameChooser.js
Normal file
|
@ -0,0 +1,59 @@
|
||||||
|
import { useState, useEffect, useCallback } from 'react'
|
||||||
|
|
||||||
|
function FrameChooser({onFrameChange}) {
|
||||||
|
const [frames, setFrames] = useState([])
|
||||||
|
const [choosenFrame, setChoosenFrame] = useState(null)
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
async function loadFrames(){
|
||||||
|
Promise.all(
|
||||||
|
[
|
||||||
|
'ProfileFrame Purple',
|
||||||
|
'ProfileFrame Yellow Bars',
|
||||||
|
'ProfileFrame Red Bars',
|
||||||
|
'ProfileFrame Blue Bars',
|
||||||
|
'ProfileFrame Green Bars',
|
||||||
|
'ProfileFrame White Bars',
|
||||||
|
'ProfileFrame Mixed Bars',
|
||||||
|
'ProfileFrame R&Y Bars',
|
||||||
|
'ProfileFrame B&G Bars',
|
||||||
|
]
|
||||||
|
.map(async frame_filename => {
|
||||||
|
return {
|
||||||
|
name: frame_filename,
|
||||||
|
src: await import(`./frames/${frame_filename}.png`),
|
||||||
|
}
|
||||||
|
})
|
||||||
|
)
|
||||||
|
.then(new_frames => {
|
||||||
|
console.log(new_frames)
|
||||||
|
setFrames(new_frames)
|
||||||
|
setChoosenFrame(new_frames[0].src.default)
|
||||||
|
})
|
||||||
|
}
|
||||||
|
loadFrames()
|
||||||
|
}, [])
|
||||||
|
|
||||||
|
const handleImageChoosing = useCallback(event => {
|
||||||
|
setChoosenFrame(event.target.dataset.src)
|
||||||
|
}, [setChoosenFrame])
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
onFrameChange(choosenFrame)
|
||||||
|
}, [onFrameChange, choosenFrame])
|
||||||
|
|
||||||
|
return (
|
||||||
|
<div className="FrameChooser">
|
||||||
|
<h2>Choose a frame:</h2>
|
||||||
|
{
|
||||||
|
frames.map(frame => {
|
||||||
|
const frame_src_path = frame.src.default
|
||||||
|
const isChoosen = choosenFrame === frame_src_path
|
||||||
|
return <img alt={frame.name} key={frame_src_path} data-src={frame_src_path} src={frame_src_path} className={isChoosen ? 'frame choosen' : 'frame'} onClick={handleImageChoosing}/>
|
||||||
|
})
|
||||||
|
}
|
||||||
|
</div>
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
export default FrameChooser;
|
BIN
src/frames/ProfileFrame B&G Bars.png
Normal file
After Width: | Height: | Size: 164 KiB |
BIN
src/frames/ProfileFrame Blue Bars.png
Normal file
After Width: | Height: | Size: 234 KiB |
BIN
src/frames/ProfileFrame Green Bars.png
Normal file
After Width: | Height: | Size: 228 KiB |
BIN
src/frames/ProfileFrame Purple.png
Normal file
After Width: | Height: | Size: 28 KiB |
BIN
src/frames/ProfileFrame R&Y Bars.png
Normal file
After Width: | Height: | Size: 169 KiB |
BIN
src/frames/ProfileFrame Red Bars.png
Normal file
After Width: | Height: | Size: 226 KiB |
BIN
src/frames/ProfileFrame White Bars.png
Normal file
After Width: | Height: | Size: 248 KiB |
BIN
src/frames/ProfileFrame Yellow Bars.png
Normal file
After Width: | Height: | Size: 248 KiB |