Membuat Image Viewer Sederhana Menggunakan ReactJs
Komponen image viewer ini digunakan pada sebuah project saya yang hanya dibutuhkan untuk melihat sebuah gambar menjadi lebih detail, dimana saat dibuka menggunakan smartphone gambarnya harus bisa di zoom.
Sebelumnya kami menggunakan sebuah library untuk hal ini, namun setelah dipertimbangkan lagi fitur pada library ini sangat banyak sekali namun yang kita butuhkan hanya lah untuk sebuah view image atau untuk melihat sebuah gambar pada dengan ukuran yang lebih besar dan jelas.
Jika menggunakan new tab di browser untuk membuka gambar tersebut terasa kurang bagus untuk user experience nya.
Oleh karena itu dibuatlah sebuah komponen yang berfungsi hanya untuk melihat gambar dengan ukuran lebih besar sepenuh layar atau bisa di zoom saat di mobile device.
Berikut Adalah komponen snippetnya:
1. Image Viewer Menggunakan Tailwind
import React, { ReactNode, useCallback, useState } from "react"
interface ImageViewerDialogProps {
url: string
children: ReactNode
}
const ImageViewerDialog: React.FC<ImageViewerDialogProps> = ({
url,
children,
}) => {
const [isOpen, setIsOpen] = useState(false)
const openModal = () => setIsOpen(true)
const closeModal = () => setIsOpen(false)
const handleBackgroundClick = useCallback(
(e: React.MouseEvent<HTMLDivElement>) => {
if (e.target === e.currentTarget) {
closeModal()
}
},
[]
)
return (
<div>
<div onClick={openModal}>{children}</div>
{isOpen && (
<div
onClick={handleBackgroundClick}
className="fixed top-0 left-0 w-full h-full transition-all ease-in-out
bg-black bg-opacity-80 z-50 flex justify-center items-center"
>
<img
src={url}
alt="Image View"
className="max-w-full max-h-full block"
/>
<button
autoFocus
aria-label="Close Image Viewer Dialog"
onClick={closeModal}
className="absolute w-10 h-10 top-4 right-4 text-white bg-red-500 hover:bg-red-700
focus:outline-none focus:ring-2 focus:ring-red-500 focus:ring-opacity-50 rounded-full p-2"
>
<span className="text-white font-bold">✕</span>
</button>
</div>
)}
</div>
)
}
export default ImageViewerDialog
2. Image Viewer Inline Style
Pada komponen ini kita berusaha mengikuti behavior seperti yang ada pada component yang menggunakan tailwind diatas, yaitu untuk handling on hover atau on focus nya.
import React, { useState, useCallback } from "react";
type Props = {
url: string;
children: React.ReactNode;
};
const ImageViewerDialog = ({ url, children }: Props) => {
const [isOpen, setIsOpen] = useState(false);
const [isHovered, setIsHovered] = useState(false);
const [isFocused, setIsFocused] = useState(false);
const openModal = () => setIsOpen(true);
const closeModal = () => setIsOpen(false);
const handleBackgroundClick = useCallback((e: any) => {
if (e.target === e.currentTarget) {
closeModal();
}
}, []);
const handleMouseEnter = () => setIsHovered(true);
const handleMouseLeave = () => setIsHovered(false);
const handleFocus = () => setIsFocused(true);
const handleBlur = () => setIsFocused(false);
const createStyle = (styles: unknown) => styles as React.CSSProperties;
const overlayStyle = createStyle({
position: "fixed",
top: 0,
left: 0,
width: "100%",
height: "100%",
transition: "all ease-in-out",
backgroundColor: "rgba(0, 0, 0, 0.8)", // bg-black with opacity 80%
zIndex: 50,
display: "flex",
justifyContent: "center",
alignItems: "center",
});
const imageStyle = createStyle({
maxWidth: "100%",
maxHeight: "100%",
display: "block",
});
const baseButtonStyle = createStyle({
position: "absolute",
width: "40px",
height: "40px",
top: "16px",
right: "16px",
color: "white",
backgroundColor: "#f56565", // bg-red-500
borderRadius: "50%",
padding: "8px",
cursor: "pointer",
});
const hoverStyle = createStyle({
backgroundColor: "#c53030", // bg-red-700
});
const focusStyle = createStyle({
outline: "2px solid #f56565", // ring-2 ring-red-500
outlineOpacity: 0.5,
});
const buttonStyle = createStyle({
...baseButtonStyle,
...(isHovered ? hoverStyle : {}),
...(isFocused ? focusStyle : {}),
});
return (
<div>
<div onClick={openModal}>{children}</div>
{isOpen && (
<div style={overlayStyle} onClick={handleBackgroundClick}>
<img src={url} alt="Image View" style={imageStyle} />
<button
autoFocus
aria-label="Close Image Viewer Dialog"
onClick={closeModal}
onMouseEnter={handleMouseEnter}
onMouseLeave={handleMouseLeave}
onFocus={handleFocus}
onBlur={handleBlur}
style={buttonStyle}
>
<span style={{ color: "white", fontWeight: "bold" }}>✕</span>
</button>
</div>
)}
</div>
);
};
export default ImageViewerDialog;
Berikut adalah screenshoot nya, bagaimana react image view ini saat di gunakan menggunakan codesandbox.
Hal Yang bisa di Improve
Kita bisa menambahkan wrapper dan icon arrow agar bisa menjadikan viewer component ini untuk photo gallery atau seperti carousel
Kita bisa tambahkan juga sebuah loader image untuk meningkatkan user experience
Menambahkan props untuk custom style atau button close
Dan masih banyak lagi yang bisa kita improve atau custom sesuai kebutuhan.
Semoga bermanfaat yaa!