Skip to content
Open
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
61 changes: 56 additions & 5 deletions src/components/ImageUpload.tsx
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import React, { useState, useEffect } from 'react';
import React, { useState, useEffect, useRef } from 'react';
import './ImageUpload.css';
import { FirebaseStorage, ref, uploadBytes, list, getDownloadURL } from 'firebase/storage';
import { v4 } from 'uuid';
Expand All @@ -13,6 +13,30 @@ const ImageUpload = ({ storage }: ImageUploadProps) => {
const [imageList, setImageList] = useState<string[]>([]);
const [isUploading, setIsUploading] = useState<boolean>(false);

//picture collage on hover gameplan:
//only want to track cursor/pointer x and y when inside collage container (className=imageUploadBottom)
//pin the lead image to the x,y position (cursor) and fade the tail images out as a trail left behind the lead/active image

//track index changing without rendering with useRef hook
const leadIndexRef = useRef(0);
const leadXYRef = useRef([0, 0]);

//grab uploaded images out of DOM tree to dynamically style with mouse movement
const imagesFromDOM = Array.from(document.getElementsByClassName('imgUpload')) as HTMLElement[];

//activate/show images dynamically handler
const activateImg = (leadImg: HTMLElement, x: number, y: number): void => {
leadImg.style.left = `${x}px`;
leadImg.style.top = `${y}px`;
leadImg.style.opacity = '1.0';
// leadImg.style.display = 'flex';
};

const deactivateImg = (tailImg: HTMLElement): void => {
tailImg.style.opacity = `${(Math.random() * 0.5) + 0.1}`;
// tailImg.style.display = 'none';
};

useEffect(() => {
list(ref(storage, 'images/'), { maxResults: 20 }).then((response) => {
response.items.forEach((item) => {
Expand All @@ -23,7 +47,7 @@ const ImageUpload = ({ storage }: ImageUploadProps) => {
})
}, [imageList, storage]);

const uploadImage = () => {
const uploadImage = (): void => {
if (!imageUpload) return;
const imageRef = ref(storage, `images/${getTimestamp(new Date())}_${v4()}`);
if (imageRef && imageUpload) {
Expand All @@ -38,7 +62,9 @@ const ImageUpload = ({ storage }: ImageUploadProps) => {
const { files } = event.currentTarget;
const file = files?.length ? files[0] : null;
setImageUpload(file);
}
};

const imgUrls = Array.from(new Set(imageList));

return (
<div className='imageUploadWrapper'>
Expand All @@ -55,8 +81,33 @@ const ImageUpload = ({ storage }: ImageUploadProps) => {
{isUploading ? 'Uploading...' : 'Upload'}
</button>
</div>
<div className='imageUploadBottom'>
{Array.from(new Set(imageList)).map((url, id) => <img className='imgUpload' src={url} alt='memory snapshot' key={url + id}/>)}
<div className='imageUploadBottom'
onMouseMoveCapture={(e) => {
const [prevX, prevY] = leadXYRef.current;
const [curX, curY] = [e.clientX, e.clientY];
//perform position and render changes after x,y moves 100px
if (Math.hypot(curX - prevX, curY - prevY) > 100) {
//%wraps index around so lead img index cycles
const lead = imagesFromDOM[leadIndexRef.current % imagesFromDOM.length];
activateImg(lead, e.clientX, e.clientY);

//leave a trail of images behind lead/cursor image
const tail = imagesFromDOM[(leadIndexRef.current - 1) % imagesFromDOM.length];
if (tail) deactivateImg(tail);

//update ref pointers, useRef avoids ▲state-based re-renders
leadIndexRef.current += 1;
leadXYRef.current = [ curX, curY ];
}
}}
onMouseLeave={(e) => {
imagesFromDOM.forEach(img => {
img.style.display = 'flex';
img.style.opacity = '1.0';
});
}}
>
{imgUrls.map((url, id) => <img className='imgUpload' src={url} alt='memory snapshot' key={url + id}/>)}
</div>
</div>
);
Expand Down