code improvement and accept image only for image uploader input
This commit is contained in:
parent
0c3ec98062
commit
867e582342
2 changed files with 31 additions and 30 deletions
|
@ -6,8 +6,8 @@ export default function ImageUploader({target, id, buttonMsg, handleAvatarChange
|
||||||
const [imageDataUrl, setImageDataUrl] = useState<string>();
|
const [imageDataUrl, setImageDataUrl] = useState<string>();
|
||||||
const [croppedAreaPixels, setCroppedAreaPixels] = useState();
|
const [croppedAreaPixels, setCroppedAreaPixels] = useState();
|
||||||
const [rotation] = useState(1);
|
const [rotation] = useState(1);
|
||||||
const [crop, setCrop] = useState({ x: 0, y: 0 })
|
const [crop, setCrop] = useState({ x: 0, y: 0 });
|
||||||
const [zoom, setZoom] = useState(1)
|
const [zoom, setZoom] = useState(1);
|
||||||
const [imageLoaded, setImageLoaded] = useState(false);
|
const [imageLoaded, setImageLoaded] = useState(false);
|
||||||
const [isImageShown, setIsImageShown] = useState(false);
|
const [isImageShown, setIsImageShown] = useState(false);
|
||||||
const [shownImage, setShownImage] = useState<string>();
|
const [shownImage, setShownImage] = useState<string>();
|
||||||
|
@ -16,7 +16,7 @@ export default function ImageUploader({target, id, buttonMsg, handleAvatarChange
|
||||||
// TODO
|
// TODO
|
||||||
// PUSH cropped image to the database in column = target
|
// PUSH cropped image to the database in column = target
|
||||||
const openUploaderModal = () => {
|
const openUploaderModal = () => {
|
||||||
imageRef ? (setIsImageShown(true), setShownImage(imageRef)) : setIsImageShown(false)
|
imageRef ? (setIsImageShown(true), setShownImage(imageRef)) : setIsImageShown(false);
|
||||||
setImageUploadModalOpen(!imageUploadModalOpen)
|
setImageUploadModalOpen(!imageUploadModalOpen)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -34,14 +34,14 @@ export default function ImageUploader({target, id, buttonMsg, handleAvatarChange
|
||||||
|
|
||||||
const readFile = (file) => {
|
const readFile = (file) => {
|
||||||
return new Promise((resolve) => {
|
return new Promise((resolve) => {
|
||||||
const reader = new FileReader()
|
const reader = new FileReader();
|
||||||
reader.addEventListener('load', () => resolve(reader.result), false)
|
reader.addEventListener('load', () => resolve(reader.result), false);
|
||||||
reader.readAsDataURL(file)
|
reader.readAsDataURL(file)
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
const onCropComplete = useCallback((croppedArea, croppedAreaPixels) => {
|
const onCropComplete = useCallback((croppedArea, croppedAreaPixels) => {
|
||||||
setCroppedAreaPixels(croppedAreaPixels)
|
setCroppedAreaPixels(croppedAreaPixels);
|
||||||
|
|
||||||
}, [])
|
}, [])
|
||||||
|
|
||||||
|
@ -53,53 +53,53 @@ export default function ImageUploader({target, id, buttonMsg, handleAvatarChange
|
||||||
|
|
||||||
const createImage = (url) =>
|
const createImage = (url) =>
|
||||||
new Promise<HTMLImageElement>((resolve, reject) => {
|
new Promise<HTMLImageElement>((resolve, reject) => {
|
||||||
const image = new Image()
|
const image = new Image();
|
||||||
image.addEventListener('load', () => resolve(image))
|
image.addEventListener('load', () => resolve(image));
|
||||||
image.addEventListener('error', error => reject(error))
|
image.addEventListener('error', error => reject(error));
|
||||||
image.setAttribute('crossOrigin', 'anonymous') // needed to avoid cross-origin issues on CodeSandbox
|
image.setAttribute('crossOrigin', 'anonymous'); // needed to avoid cross-origin issues on CodeSandbox
|
||||||
image.src = url
|
image.src = url;
|
||||||
})
|
})
|
||||||
|
|
||||||
function getRadianAngle(degreeValue) {
|
function getRadianAngle(degreeValue) {
|
||||||
return (degreeValue * Math.PI) / 180
|
return (degreeValue * Math.PI) / 180;
|
||||||
}
|
}
|
||||||
|
|
||||||
async function getCroppedImg(imageSrc, pixelCrop, rotation = 0) {
|
async function getCroppedImg(imageSrc, pixelCrop, rotation = 0) {
|
||||||
const image = await createImage(imageSrc)
|
const image = await createImage(imageSrc);
|
||||||
const canvas = document.createElement('canvas')
|
const canvas = document.createElement('canvas');
|
||||||
const ctx = canvas.getContext('2d')
|
const ctx = canvas.getContext('2d');
|
||||||
|
|
||||||
const maxSize = Math.max(image.width, image.height)
|
const maxSize = Math.max(image.width, image.height);
|
||||||
const safeArea = 2 * ((maxSize / 2) * Math.sqrt(2))
|
const safeArea = 2 * ((maxSize / 2) * Math.sqrt(2));
|
||||||
|
|
||||||
// set each dimensions to double largest dimension to allow for a safe area for the
|
// set each dimensions to double largest dimension to allow for a safe area for the
|
||||||
// image to rotate in without being clipped by canvas context
|
// image to rotate in without being clipped by canvas context
|
||||||
canvas.width = safeArea
|
canvas.width = safeArea;
|
||||||
canvas.height = safeArea
|
canvas.height = safeArea;
|
||||||
|
|
||||||
// translate canvas context to a central location on image to allow rotating around the center.
|
// translate canvas context to a central location on image to allow rotating around the center.
|
||||||
ctx.translate(safeArea / 2, safeArea / 2)
|
ctx.translate(safeArea / 2, safeArea / 2);
|
||||||
ctx.rotate(getRadianAngle(rotation))
|
ctx.rotate(getRadianAngle(rotation));
|
||||||
ctx.translate(-safeArea / 2, -safeArea / 2)
|
ctx.translate(-safeArea / 2, -safeArea / 2);
|
||||||
|
|
||||||
// draw rotated image and store data.
|
// draw rotated image and store data.
|
||||||
ctx.drawImage(
|
ctx.drawImage(
|
||||||
image,
|
image,
|
||||||
safeArea / 2 - image.width * 0.5,
|
safeArea / 2 - image.width * 0.5,
|
||||||
safeArea / 2 - image.height * 0.5
|
safeArea / 2 - image.height * 0.5
|
||||||
)
|
);
|
||||||
const data = ctx.getImageData(0, 0, safeArea, safeArea)
|
const data = ctx.getImageData(0, 0, safeArea, safeArea);
|
||||||
|
|
||||||
// set canvas width to final desired crop size - this will clear existing context
|
// set canvas width to final desired crop size - this will clear existing context
|
||||||
canvas.width = pixelCrop.width
|
canvas.width = pixelCrop.width;
|
||||||
canvas.height = pixelCrop.height
|
canvas.height = pixelCrop.height;
|
||||||
|
|
||||||
// paste generated rotate image with correct offsets for x,y crop values.
|
// paste generated rotate image with correct offsets for x,y crop values.
|
||||||
ctx.putImageData(
|
ctx.putImageData(
|
||||||
data,
|
data,
|
||||||
Math.round(0 - safeArea / 2 + image.width * 0.5 - pixelCrop.x),
|
Math.round(0 - safeArea / 2 + image.width * 0.5 - pixelCrop.x),
|
||||||
Math.round(0 - safeArea / 2 + image.height * 0.5 - pixelCrop.y)
|
Math.round(0 - safeArea / 2 + image.height * 0.5 - pixelCrop.y)
|
||||||
)
|
);
|
||||||
|
|
||||||
// As Base64 string
|
// As Base64 string
|
||||||
return canvas.toDataURL('image/jpeg');
|
return canvas.toDataURL('image/jpeg');
|
||||||
|
@ -128,7 +128,7 @@ export default function ImageUploader({target, id, buttonMsg, handleAvatarChange
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
console.error(e)
|
console.error(e)
|
||||||
}
|
}
|
||||||
}, [croppedAreaPixels, rotation])
|
}, [croppedAreaPixels, rotation]);
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div className="flex justify-center items-center">
|
<div className="flex justify-center items-center">
|
||||||
|
@ -205,6 +205,7 @@ export default function ImageUploader({target, id, buttonMsg, handleAvatarChange
|
||||||
name={id}
|
name={id}
|
||||||
placeholder="Upload image"
|
placeholder="Upload image"
|
||||||
className="mt-4 cursor-pointer opacity-0 absolute"
|
className="mt-4 cursor-pointer opacity-0 absolute"
|
||||||
|
accept="image/*"
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
|
@ -46,9 +46,9 @@ export default function Settings(props) {
|
||||||
|
|
||||||
const handleAvatarChange = (newAvatar) => {
|
const handleAvatarChange = (newAvatar) => {
|
||||||
avatarRef.current.value = newAvatar;
|
avatarRef.current.value = newAvatar;
|
||||||
var nativeInputValueSetter = Object.getOwnPropertyDescriptor(window.HTMLInputElement.prototype, "value").set;
|
const nativeInputValueSetter = Object.getOwnPropertyDescriptor(window.HTMLInputElement.prototype, "value").set;
|
||||||
nativeInputValueSetter.call(avatarRef.current, newAvatar);
|
nativeInputValueSetter.call(avatarRef.current, newAvatar);
|
||||||
var ev2 = new Event('input', { bubbles: true});
|
const ev2 = new Event('input', { bubbles: true});
|
||||||
avatarRef.current.dispatchEvent(ev2);
|
avatarRef.current.dispatchEvent(ev2);
|
||||||
updateProfileHandler(ev2);
|
updateProfileHandler(ev2);
|
||||||
setImageSrc(newAvatar);
|
setImageSrc(newAvatar);
|
||||||
|
|
Loading…
Reference in a new issue