276 lines
9.2 KiB
JavaScript
276 lines
9.2 KiB
JavaScript
"use client";
|
||
|
||
import React, {
|
||
useState,
|
||
useEffect,
|
||
useRef,
|
||
forwardRef,
|
||
useImperativeHandle,
|
||
} from "react";
|
||
import { Mask, Image } from "antd-mobile";
|
||
import { FontAwesomeIcon } from "@fortawesome/react-fontawesome";
|
||
import {
|
||
faAngleLeft,
|
||
faAngleRight,
|
||
faDownload,
|
||
} from "@fortawesome/free-solid-svg-icons";
|
||
import { createRoot } from "react-dom/client";
|
||
import { useRouter } from "next/navigation";
|
||
import baseRequest from "@/utils/baseRequest";
|
||
const root = createRoot(document?.getElementById("maskDomBox"));
|
||
function ImagesMask({}, ref) {
|
||
const [visible, setVisible] = useState(false);
|
||
const [images, setImages] = useState([]);
|
||
const [data, setData] = useState(null);
|
||
const scrollRef = useRef(null);
|
||
const defaultIndex = useRef(null);
|
||
const router = useRouter();
|
||
useEffect(() => {
|
||
root.render(
|
||
<div>
|
||
<ImagesMaskContaint
|
||
images={images}
|
||
visible={visible}
|
||
ref={scrollRef}
|
||
setVisible={setVisible}
|
||
setImages={setImages}
|
||
router={router}
|
||
data={data}
|
||
defaultIndex={defaultIndex.current}
|
||
/>
|
||
</div>
|
||
);
|
||
// root.render(<div>xxxx</div>);
|
||
}, [visible]);
|
||
|
||
useImperativeHandle(ref, () => ({
|
||
show: (arr, index, data) => {
|
||
defaultIndex.current = index;
|
||
setImages(arr);
|
||
setData(data);
|
||
setVisible((old) => {
|
||
// console.log(arr, index, old);
|
||
return !old;
|
||
});
|
||
|
||
// Mask.show
|
||
// const maskDomBox = document.getElementById("maskDomBox");
|
||
},
|
||
close: () => setVisible(false),
|
||
}));
|
||
|
||
return <></>;
|
||
}
|
||
|
||
const ImagesMaskContaint = forwardRef(
|
||
(
|
||
{ visible, images, setVisible, setImages, router, data, defaultIndex = 0 },
|
||
ref
|
||
) => {
|
||
const [currentIndex, setCurrentIndex] = useState(0);
|
||
const [direction, setDirection] = useState("left");
|
||
const [initialX, setInitialX] = useState(0);
|
||
const [xOffset, setXOffset] = useState(0);
|
||
const [active, setActive] = useState(false);
|
||
const base = baseRequest();
|
||
const directionX = useRef(0);
|
||
// const getDistance = (e) => {
|
||
// e.stopPropagation();
|
||
// const distance = ref.current.scrollLeft;
|
||
// setDistance(distance);
|
||
// };
|
||
useEffect(() => {
|
||
// setCurrentIndex(defaultIndex);
|
||
// test3(defaultIndex - 1, "left");
|
||
if (defaultIndex) {
|
||
test3(defaultIndex - 1, "left");
|
||
}
|
||
}, [defaultIndex]);
|
||
useEffect(() => {
|
||
if (ref.current) {
|
||
ref.current.style.transform = `translateX(${
|
||
-window.innerWidth * currentIndex
|
||
}px)`;
|
||
}
|
||
}, [currentIndex]);
|
||
const test1 = (e) => {
|
||
setInitialX(e.touches[0].clientX - (!currentIndex ? 0 : xOffset));
|
||
if (e.touches.length === 1) {
|
||
// 单点触摸
|
||
setActive(true);
|
||
}
|
||
};
|
||
const test2 = (e) => {
|
||
if (active) {
|
||
let X = e.touches[0].clientX - initialX;
|
||
setDirection(
|
||
directionX.current > e.touches[0].clientX ? "left" : "right"
|
||
);
|
||
ref.current.style.transform = "translateX(" + X + "px)";
|
||
directionX.current = e.touches[0].clientX;
|
||
}
|
||
};
|
||
const test3 = (index, currentDirection) => {
|
||
setActive(false);
|
||
let cxOffset = window.innerWidth;
|
||
if (currentDirection == "left") {
|
||
if (index < images.length - 1) {
|
||
setCurrentIndex(index + 1);
|
||
} else {
|
||
ref.current.style.transform = `translateX(${-cxOffset * index}px)`;
|
||
}
|
||
} else {
|
||
if (index > 0) {
|
||
setCurrentIndex(index - 1);
|
||
} else {
|
||
ref.current.style.transform = `translateX(${-cxOffset * index}px)`;
|
||
}
|
||
}
|
||
// setInitialX(currentX);
|
||
setInitialX(-cxOffset * (index + (currentDirection == "left" ? 1 : -1)));
|
||
if (currentDirection == "left" && index > images.length - 2) return;
|
||
setXOffset(-cxOffset * (index + (currentDirection == "left" ? 1 : -1)));
|
||
};
|
||
function downloadImage(url) {
|
||
let randomNum = "";
|
||
for (let i = 0; i < 10; i++) {
|
||
randomNum += Math.floor(Math.random() * 10);
|
||
}
|
||
fetch(url)
|
||
.then((res) => res.blob())
|
||
.then((blob) => {
|
||
var a = document.createElement("a");
|
||
a.href = URL.createObjectURL(blob);
|
||
a.download = randomNum + ".jpg";
|
||
a.click();
|
||
});
|
||
}
|
||
return (
|
||
<div>
|
||
<Mask
|
||
visible={visible}
|
||
className="z-[1002] h-screen flex justify-center items-center"
|
||
onMaskClick={() => {
|
||
setVisible(false), setImages([]), setCurrentIndex(null);
|
||
// root.unmount();
|
||
}}
|
||
color="#000000d9"
|
||
>
|
||
<div className="relative">
|
||
{images[currentIndex]?.type != "hid" && (
|
||
<div
|
||
onClick={() => downloadImage(images[currentIndex]?.url)}
|
||
className="z-50 flex justify-center items-center w-[38px] h-[38px] bg-[#ffffff1a] text-[#fff] rounded-full absolute top-[12px] left-[12px]"
|
||
>
|
||
<FontAwesomeIcon icon={faDownload} size="xl" />
|
||
</div>
|
||
)}
|
||
<div className="text-center mb-2 leading-[54px]">
|
||
{currentIndex + 1}/{images.length}
|
||
</div>
|
||
<div
|
||
className="flex justify-start items-center"
|
||
style={{ height: "calc(100vh - 174px)" }}
|
||
onClick={() => {
|
||
setVisible(false), setImages([]), setCurrentIndex(null);
|
||
// root.unmount();
|
||
}}
|
||
>
|
||
<div
|
||
ref={ref}
|
||
id="imagesScrollBox"
|
||
className="flex justify-center items-center transition-transform duration-300 h-full"
|
||
draggable={true}
|
||
onTouchStart={test1}
|
||
onTouchMove={test2}
|
||
onTouchEnd={() => test3(currentIndex, direction)}
|
||
>
|
||
{images.map((item, index) => {
|
||
return (
|
||
<div
|
||
key={index}
|
||
className="flex-none w-screen relative h-full"
|
||
>
|
||
{/* <img
|
||
src={item.url}
|
||
className="h-full m-auto"
|
||
style={{
|
||
filter: item.type == "hid" ? "blur(10px)" : "none",
|
||
}}
|
||
/> */}
|
||
<Image
|
||
className="h-full m-auto"
|
||
src={item.url}
|
||
style={{
|
||
filter: item.type == "hid" ? "blur(10px)" : "none",
|
||
}}
|
||
height={"100%"}
|
||
fit="contain"
|
||
placeholder={
|
||
<div className="w-full h-full min-h-96 bg-[#1d1d1d] rounded"></div>
|
||
}
|
||
/>
|
||
|
||
<div className="absolute top-1/2 left-1/2 -ml-[100px] -mt-[14px]">
|
||
{item.type == "hid" && (
|
||
<div className="flex justify-center">
|
||
<div
|
||
className="rounded-full text-sm h-max w-max px-4 py-1 bg-primary"
|
||
onClick={() => {
|
||
router.push(
|
||
"/webView/" +
|
||
encodeURIComponent(
|
||
"/zone/pay/" +
|
||
data?.zid +
|
||
"/h5_zone_moment/" +
|
||
data?.id +
|
||
"?base=" +
|
||
encodeURIComponent(JSON.stringify(base))
|
||
)
|
||
);
|
||
}}
|
||
>
|
||
此内容暂未解锁,立即解锁
|
||
</div>
|
||
</div>
|
||
)}
|
||
</div>
|
||
</div>
|
||
);
|
||
})}
|
||
</div>
|
||
</div>
|
||
<div
|
||
className="flex justify-between items-center w-screen absolute top-1/2 px-4 pointer-events-none"
|
||
style={{
|
||
marginTop: "calc(-50vh + 118px)",
|
||
height: "calc(100vh - 174px)",
|
||
visibility: images.length > 1 ? "visible" : "hidden",
|
||
}}
|
||
>
|
||
<div
|
||
className="w-12 h-full flex items-center justify-center rounded-full float-left pointer-events-auto"
|
||
onClick={() => {
|
||
test3(currentIndex, "right");
|
||
}}
|
||
>
|
||
<FontAwesomeIcon icon={faAngleLeft} size="xl" />
|
||
</div>
|
||
<div
|
||
className="w-12 h-full flex items-center justify-center rounded-full float-left pointer-events-auto"
|
||
onClick={() => {
|
||
test3(currentIndex, "left");
|
||
}}
|
||
>
|
||
<FontAwesomeIcon icon={faAngleRight} size="xl" />
|
||
</div>
|
||
</div>
|
||
</div>
|
||
</Mask>
|
||
</div>
|
||
);
|
||
}
|
||
);
|
||
|
||
export default forwardRef(ImagesMask);
|