自定义图片滚动组件
This commit is contained in:
parent
d976b642ff
commit
f442b82354
|
@ -101,20 +101,26 @@ footer{
|
|||
overflow-y: auto;
|
||||
scroll-behavior: smooth;
|
||||
}
|
||||
.scrollbarBoxX {
|
||||
/* IE 10+ */
|
||||
overflow-y: hidden;
|
||||
overflow-x: auto;
|
||||
scroll-behavior: smooth;
|
||||
}
|
||||
|
||||
.scrollbarBox::-webkit-scrollbar {
|
||||
.scrollbarBoxX::-webkit-scrollbar, .scrollbarBox::-webkit-scrollbar {
|
||||
/* display:none; */
|
||||
width: 6px;
|
||||
}
|
||||
|
||||
.scrollbarBox::-webkit-scrollbar-thumb {
|
||||
.scrollbarBoxX::-webkit-scrollbar-thumb,.scrollbarBox::-webkit-scrollbar-thumb {
|
||||
border-radius: 10px;
|
||||
-webkit-box-shadow: inset 0 0 5px rgba(138, 138, 138, 0.2);
|
||||
background: nb-theme(background-basic-color-4);
|
||||
|
||||
}
|
||||
|
||||
.scrollbarBox::-webkit-scrollbar-track {
|
||||
.scrollbarBoxX::-webkit-scrollbar-track,.scrollbarBox::-webkit-scrollbar-track {
|
||||
-webkit-box-shadow: inset 0 0 5px rgba(138, 138, 138, 0.2);
|
||||
border-radius: 10px;
|
||||
background: nb-theme(background-basic-color-2);
|
||||
|
|
|
@ -72,10 +72,7 @@ export default function RootLayout({ children }) {
|
|||
<meta name="apple-mobile-web-app-capable" content="yes" />
|
||||
{/* <!-- 用来定义顶部状态栏的形式默认是default为白色 black为黑色 black-translucent为灰色半透明(会占据屏幕的约20px,不同的设备可能会有差异)--> */}
|
||||
{/* <!-- 在定义了apple-mobile-web-app-capable的前提下,设置状态栏的属性值apple-mobile-web-app-status-bar-style才有效; --> */}
|
||||
<meta
|
||||
name="apple-mobile-web-app-status-bar-style"
|
||||
content="#ffffff"
|
||||
/>
|
||||
<meta name="apple-mobile-web-app-status-bar-style" content="#ffffff" />
|
||||
{/* <!-- apple-touch-startup-image用来配置启动动画 --> */}
|
||||
{/* <!-- 这里要注意,这里图片的尺寸要和设备的静态图片显示尺寸完全对应,差一个像素都会导致启动动画无法显示 --> */}
|
||||
{/* <!-- 下面列举了iPhone的所有尺寸(ps:为了方便大家就全部贴出来了!!) --> */}
|
||||
|
@ -191,9 +188,16 @@ export default function RootLayout({ children }) {
|
|||
</head>
|
||||
<body className={`${inter.className} h-full`}>
|
||||
<main className={`w-full bg-deepBg h-full`}>
|
||||
{withAuth(<Provider store={store}>{children}</Provider>)}
|
||||
<div id="maskDomBox"></div>
|
||||
{withAuth(
|
||||
<Provider store={store}>
|
||||
<div>
|
||||
{children}
|
||||
{/* <ImagesMask ref={imagesMaskRef} /> */}
|
||||
</div>
|
||||
</Provider>
|
||||
)}
|
||||
{/* <Provider store={store}>{children}</Provider> */}
|
||||
<div id="maskDomBox"></div>
|
||||
</main>
|
||||
<footer className="fixed left-0 w-screen bg-black">
|
||||
<div>
|
||||
|
|
|
@ -10,12 +10,32 @@ import React, {
|
|||
import { Mask, Image } from "antd-mobile";
|
||||
import { FontAwesomeIcon } from "@fortawesome/react-fontawesome";
|
||||
import { faAngleLeft, faAngleRight } from "@fortawesome/free-solid-svg-icons";
|
||||
import { createRoot } from "react-dom/client";
|
||||
|
||||
const maskDomBox = window ? document?.getElementById("maskDomBox") : null;
|
||||
console.log(maskDomBox);
|
||||
const root = createRoot(maskDomBox);
|
||||
function ImagesMask({}, ref) {
|
||||
const [currentIndex, setCurrentIndex] = useState(0);
|
||||
const [visible, setVisible] = useState(false);
|
||||
const [images, setImages] = useState([]);
|
||||
const [distance, setDistance] = useState(0);
|
||||
const scrollRef = useRef(null);
|
||||
useEffect(() => {
|
||||
root.render(
|
||||
<div>
|
||||
<ImagesMaskContaint
|
||||
images={images}
|
||||
visible={visible}
|
||||
currentIndex={currentIndex}
|
||||
ref={scrollRef}
|
||||
setCurrentIndex={setCurrentIndex}
|
||||
setVisible={setVisible}
|
||||
setImages={setImages}
|
||||
/>
|
||||
</div>
|
||||
);
|
||||
// root.render(<div>xxxx</div>);
|
||||
}, [visible]);
|
||||
useEffect(() => {
|
||||
if (scrollRef.current) {
|
||||
setTimeout(() => {
|
||||
|
@ -27,91 +47,91 @@ function ImagesMask({}, ref) {
|
|||
show: (arr, index) => {
|
||||
setCurrentIndex(index);
|
||||
setImages(arr);
|
||||
setVisible(true);
|
||||
setVisible(old=>{
|
||||
console.log(arr, index,old)
|
||||
return !old
|
||||
});
|
||||
|
||||
// Mask.show
|
||||
// const maskDomBox = document.getElementById("maskDomBox");
|
||||
},
|
||||
close: () => setVisible(false),
|
||||
}));
|
||||
const getDistance = (e) => {
|
||||
e.stopPropagation();
|
||||
const distance = scrollRef.current.scrollLeft;
|
||||
setDistance(distance);
|
||||
};
|
||||
const handleMoveImages = (e,index) => {
|
||||
e.stopPropagation();
|
||||
// console.log("distance",distance)
|
||||
if (
|
||||
distance > window.innerWidth * currentIndex &&
|
||||
distance < window.innerWidth + window.innerWidth * currentIndex
|
||||
) {
|
||||
setCurrentIndex(Math.ceil(distance/414))
|
||||
} else if(distance < window.innerWidth * currentIndex) {
|
||||
setCurrentIndex(Math.ceil(distance/414)-1)
|
||||
}
|
||||
};
|
||||
return (
|
||||
<Mask
|
||||
visible={visible}
|
||||
className="z-[99] h-screen flex justify-center items-center"
|
||||
>
|
||||
<div className="relative">
|
||||
<div className="text-center mb-2">
|
||||
{currentIndex + 1}/{images.length}
|
||||
</div>
|
||||
<div
|
||||
ref={scrollRef}
|
||||
id="imagesScrollBox"
|
||||
className="flex overflow-auto"
|
||||
>
|
||||
{images.map((item, index) => {
|
||||
return (
|
||||
// <Image
|
||||
// key={index}
|
||||
// fit="cover"
|
||||
// className="mr-3"
|
||||
// // src={process.env.NEXT_PUBLIC_WEB_ASSETS_URL+"/icons/nodata.png"}
|
||||
// src={item}
|
||||
// placeholder=""
|
||||
// width="100vw"
|
||||
// // height="90vh"
|
||||
// />
|
||||
<img
|
||||
key={index}
|
||||
src={item}
|
||||
// onTouchMove={(e) => handleMoveImages(e, index)}
|
||||
onTouchMove={getDistance}
|
||||
onTouchEnd={(e) => handleMoveImages(e,index)}
|
||||
onClick={() => {
|
||||
setVisible(false), setImages([]), setCurrentIndex(0);
|
||||
}}
|
||||
/>
|
||||
);
|
||||
})}
|
||||
</div>
|
||||
<div className="flex justify-between items-center w-screen absolute top-1/2 px-4 pointer-events-none">
|
||||
<div
|
||||
className="w-9 h-9 flex items-center justify-center bg-[#FFFFFF1A] rounded-full float-left pointer-events-auto"
|
||||
onClick={() => {
|
||||
setCurrentIndex((old) => (old > 0 ? old - 1 : old));
|
||||
}}
|
||||
>
|
||||
<FontAwesomeIcon icon={faAngleLeft} size="xl" />
|
||||
</div>
|
||||
<div
|
||||
className="w-9 h-9 flex items-center justify-center bg-[#FFFFFF1A] rounded-full float-left pointer-events-auto"
|
||||
onClick={() => {
|
||||
setCurrentIndex((old) =>
|
||||
old < images.length - 1 ? old + 1 : old
|
||||
);
|
||||
}}
|
||||
>
|
||||
<FontAwesomeIcon icon={faAngleRight} size="xl" />
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</Mask>
|
||||
);
|
||||
|
||||
return <></>;
|
||||
}
|
||||
|
||||
const ImagesMaskContaint = forwardRef(
|
||||
({ visible, images, currentIndex,setCurrentIndex,setVisible,setImages }, ref) => {
|
||||
const [distance, setDistance] = useState(0);
|
||||
const getDistance = (e) => {
|
||||
e.stopPropagation();
|
||||
const distance = ref.current.scrollLeft;
|
||||
setDistance(distance);
|
||||
};
|
||||
const handleMoveImages = (e, index) => {
|
||||
e.stopPropagation();
|
||||
// console.log("distance",distance)
|
||||
if (
|
||||
distance > window.innerWidth * currentIndex &&
|
||||
distance < window.innerWidth + window.innerWidth * currentIndex
|
||||
) {
|
||||
setCurrentIndex(Math.ceil(distance / 414));
|
||||
} else if (distance < window.innerWidth * currentIndex) {
|
||||
setCurrentIndex(Math.ceil(distance / 414) - 1);
|
||||
}
|
||||
};
|
||||
return (
|
||||
<div>
|
||||
<Mask
|
||||
visible={visible}
|
||||
className="z-[1002] h-screen flex justify-center items-center"
|
||||
>
|
||||
<div className="relative">
|
||||
<div className="text-center mb-2">
|
||||
{currentIndex + 1}/{images.length}
|
||||
</div>
|
||||
<div ref={ref} id="imagesScrollBox" className="flex overflow-auto scrollbarBoxX">
|
||||
{images.map((item, index) => {
|
||||
return (
|
||||
<img
|
||||
key={index}
|
||||
src={item}
|
||||
// onTouchMove={(e) => handleMoveImages(e, index)}
|
||||
onTouchMove={getDistance}
|
||||
onTouchEnd={(e) => handleMoveImages(e, index)}
|
||||
onClick={() => {
|
||||
setVisible(false), setImages([]), setCurrentIndex(0);
|
||||
}}
|
||||
/>
|
||||
);
|
||||
})}
|
||||
</div>
|
||||
<div className="flex justify-between items-center w-screen absolute top-1/2 px-4 pointer-events-none">
|
||||
<div
|
||||
className="w-9 h-9 flex items-center justify-center bg-[#FFFFFF1A] rounded-full float-left pointer-events-auto"
|
||||
onClick={() => {
|
||||
setCurrentIndex((old) => (old > 0 ? old - 1 : old));
|
||||
}}
|
||||
>
|
||||
<FontAwesomeIcon icon={faAngleLeft} size="xl" />
|
||||
</div>
|
||||
<div
|
||||
className="w-9 h-9 flex items-center justify-center bg-[#FFFFFF1A] rounded-full float-left pointer-events-auto"
|
||||
onClick={() => {
|
||||
setCurrentIndex((old) =>
|
||||
old < images.length - 1 ? old + 1 : old
|
||||
);
|
||||
}}
|
||||
>
|
||||
<FontAwesomeIcon icon={faAngleRight} size="xl" />
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</Mask>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
);
|
||||
|
||||
export default forwardRef(ImagesMask);
|
||||
|
|
|
@ -7,8 +7,8 @@ import { faAngleUp, faClose } from "@fortawesome/free-solid-svg-icons";
|
|||
import { useRouter } from "next/navigation";
|
||||
import baseRequest from "@/utils/baseRequest";
|
||||
import Player from "next-video/player";
|
||||
// import ImagesMask from "@/components/ImagesMask";
|
||||
// import Viewer from 'react-viewer';
|
||||
import ImagesMask from "@/components/ImagesMask";
|
||||
|
||||
export default function Photos({
|
||||
isUnlocked,
|
||||
mediaVisibleRange,
|
||||
|
@ -23,9 +23,10 @@ export default function Photos({
|
|||
const [visible, setVisible] = useState(false);
|
||||
const currentIndex = useRef();
|
||||
const swiper = useRef(null);
|
||||
// const imagesMaskRef = useRef(null);
|
||||
const imagesMaskRef = useRef(null);
|
||||
const router = useRouter();
|
||||
const base = baseRequest();
|
||||
|
||||
useEffect(() => {
|
||||
if (media) {
|
||||
let imgArr = media.images.map((item) => ({
|
||||
|
@ -74,88 +75,92 @@ export default function Photos({
|
|||
// }, 400);
|
||||
|
||||
// 添加左右切换按钮
|
||||
const btns = document.createElement("div");
|
||||
btns.className = "imagesBtnsControllers";
|
||||
const btnL = document.createElement("div");
|
||||
btnL.className = "imagesBtnsControllerLeft";
|
||||
btnL.addEventListener("click", () => {
|
||||
if (currentIndex.current > 0) {
|
||||
currentIndex.current = currentIndex.current - 1;
|
||||
handleShowImages(currentIndex.current, photos, btns);
|
||||
if (!currentIndex.current) {
|
||||
btnL.style.opacity = 0.5;
|
||||
btnR.style.opacity = 1;
|
||||
} else {
|
||||
btnR.style.opacity = 1;
|
||||
btnL.style.opacity = 1;
|
||||
}
|
||||
}
|
||||
});
|
||||
const btnR = document.createElement("div");
|
||||
btnR.className = "imagesBtnsControllerRight";
|
||||
btnR.addEventListener("click", () => {
|
||||
if (currentIndex.current < currentPhotos.length - 1) {
|
||||
currentIndex.current = currentIndex.current + 1;
|
||||
handleShowImages(currentIndex.current, photos, btns);
|
||||
if (currentIndex.current == currentPhotos.length - 1) {
|
||||
btnR.style.opacity = 0.5;
|
||||
btnL.style.opacity = 1;
|
||||
} else {
|
||||
btnR.style.opacity = 1;
|
||||
btnL.style.opacity = 1;
|
||||
}
|
||||
}
|
||||
});
|
||||
btns.append(btnL, btnR);
|
||||
handleShowImages(index, photos, btns);
|
||||
// const btns = document.createElement("div");
|
||||
// btns.className = "imagesBtnsControllers";
|
||||
// const btnL = document.createElement("div");
|
||||
// btnL.className = "imagesBtnsControllerLeft";
|
||||
// btnL.addEventListener("click", () => {
|
||||
// if (currentIndex.current > 0) {
|
||||
// currentIndex.current = currentIndex.current - 1;
|
||||
// handleShowImages(currentIndex.current, photos, btns,interval);
|
||||
// if (!currentIndex.current) {
|
||||
// btnL.style.opacity = 0.5;
|
||||
// btnR.style.opacity = 1;
|
||||
// } else {
|
||||
// btnR.style.opacity = 1;
|
||||
// btnL.style.opacity = 1;
|
||||
// }
|
||||
// }
|
||||
// });
|
||||
// const btnR = document.createElement("div");
|
||||
// btnR.className = "imagesBtnsControllerRight";
|
||||
// btnR.addEventListener("click", () => {
|
||||
// if (currentIndex.current < currentPhotos.length - 1) {
|
||||
// currentIndex.current = currentIndex.current + 1;
|
||||
// handleShowImages(currentIndex.current, photos, btns,interval);
|
||||
// if (currentIndex.current == currentPhotos.length - 1) {
|
||||
// btnR.style.opacity = 0.5;
|
||||
// btnL.style.opacity = 1;
|
||||
// } else {
|
||||
// btnR.style.opacity = 1;
|
||||
// btnL.style.opacity = 1;
|
||||
// }
|
||||
// }
|
||||
// });
|
||||
// btns.append(btnL, btnR);
|
||||
// handleShowImages(index, photos, btns,interval);
|
||||
|
||||
// setVisible(true)
|
||||
// imagesMaskRef.current.show(photos.map((item) => item?.url),index)
|
||||
console.log(imagesMaskRef.current);
|
||||
imagesMaskRef.current.show(
|
||||
photos.map((item) => item?.url),
|
||||
index
|
||||
);
|
||||
};
|
||||
const handleShowImages = (index, photos, btns) => {
|
||||
const mediaDom = document.createElement("div");
|
||||
mediaDom.style.width = "100vw";
|
||||
document.body.appendChild(mediaDom);
|
||||
mediaDom.className = `${
|
||||
photos[index]?.type == "hid" ? "mediaDom photos-body" : "mediaDom"
|
||||
}`;
|
||||
mediaDom.appendChild(btns);
|
||||
ImageViewer.clear();
|
||||
ImageViewer.Multi.show({
|
||||
images: photos.map((item) => item?.url),
|
||||
defaultIndex: index,
|
||||
renderFooter: (image, index) => {
|
||||
return renderFooter(photos[index]?.type == "hid", mediaDom);
|
||||
},
|
||||
// const handleShowImages = (index, photos, btns) => {
|
||||
// const mediaDom = document.createElement("div");
|
||||
// mediaDom.style.width = "100vw";
|
||||
// document.body.appendChild(mediaDom);
|
||||
// mediaDom.className = `${
|
||||
// photos[index]?.type == "hid" ? "mediaDom photos-body" : "mediaDom"
|
||||
// }`;
|
||||
// mediaDom.appendChild(btns);
|
||||
// ImageViewer.clear();
|
||||
// ImageViewer.Multi.show({
|
||||
// images: photos.map((item) => item?.url),
|
||||
// defaultIndex: index,
|
||||
// renderFooter: (image, index) => {
|
||||
// return renderFooter(photos[index]?.type == "hid", mediaDom);
|
||||
// },
|
||||
|
||||
getContainer: mediaDom,
|
||||
onIndexChange: (index) => {
|
||||
currentIndex.current = index;
|
||||
mediaDom.className = `${
|
||||
photos[index]?.type == "hid" ? "mediaDom photos-body" : "mediaDom"
|
||||
}`;
|
||||
const leftBtn = document.getElementsByClassName("imagesBtnsControllerLeft")[0]
|
||||
const rightBtn = document.getElementsByClassName("imagesBtnsControllerRight")[0]
|
||||
if(leftBtn && rightBtn){
|
||||
if(!index){
|
||||
leftBtn.style.opacity=0.5
|
||||
rightBtn.style.opacity=1
|
||||
}else if(index==currentPhotos.length-1){
|
||||
leftBtn.style.opacity=1
|
||||
rightBtn.style.opacity=0.5
|
||||
}else{
|
||||
leftBtn.style.opacity=1
|
||||
rightBtn.style.opacity=1
|
||||
}
|
||||
}
|
||||
},
|
||||
afterClose: () => {
|
||||
mediaDom.remove();
|
||||
// clearInterval(interval);
|
||||
},
|
||||
classNames: { body: "photos-bodyBox" },
|
||||
});
|
||||
};
|
||||
// getContainer: mediaDom,
|
||||
// onIndexChange: (index) => {
|
||||
// currentIndex.current = index;
|
||||
// mediaDom.className = `${
|
||||
// photos[index]?.type == "hid" ? "mediaDom photos-body" : "mediaDom"
|
||||
// }`;
|
||||
// const leftBtn = document.getElementsByClassName("imagesBtnsControllerLeft")[0]
|
||||
// const rightBtn = document.getElementsByClassName("imagesBtnsControllerRight")[0]
|
||||
// if(leftBtn && rightBtn){
|
||||
// if(!index){
|
||||
// leftBtn.style.opacity=0.5
|
||||
// rightBtn.style.opacity=1
|
||||
// }else if(index==currentPhotos.length-1){
|
||||
// leftBtn.style.opacity=1
|
||||
// rightBtn.style.opacity=0.5
|
||||
// }else{
|
||||
// leftBtn.style.opacity=1
|
||||
// rightBtn.style.opacity=1
|
||||
// }
|
||||
// }
|
||||
// },
|
||||
// afterClose: () => {
|
||||
// mediaDom.remove();
|
||||
// // clearInterval(interval);
|
||||
// },
|
||||
// classNames: { body: "photos-bodyBox" },
|
||||
// });
|
||||
// };
|
||||
const handleShowVideo = (video) => {
|
||||
Dialog.className = "videoMask";
|
||||
Dialog.show({
|
||||
|
@ -354,7 +359,7 @@ export default function Photos({
|
|||
);
|
||||
})}
|
||||
</div>
|
||||
{/* <ImagesMask ref={imagesMaskRef}/> */}
|
||||
<ImagesMask ref={imagesMaskRef} />
|
||||
{/* <Viewer
|
||||
visible={visible}
|
||||
onClose={() => { setVisible(false); } }
|
||||
|
|
Loading…
Reference in New Issue