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
	
	 Syed Ali Shahbaz
						Syed Ali Shahbaz