tiefen_space_h5/components/ImagesMask/index.jsx

423 lines
15 KiB
JavaScript
Raw Permalink Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

"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,
faMinus,
faAdd,
} from "@fortawesome/free-solid-svg-icons";
import { createRoot } from "react-dom/client";
import { useRouter } from "next/navigation";
import baseRequest from "@/utils/baseRequest";
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(() => {
if (visible) {
const root = createRoot(document?.getElementById("maskDomBox"));
root.render(
<div>
<ImagesMaskContaint
images={images}
visible={visible}
ref={scrollRef}
setVisible={setVisible}
setImages={setImages}
router={router}
data={data}
defaultIndex={defaultIndex.current}
root={root}
/>
</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,
root,
},
ref
) => {
const [currentIndex, setCurrentIndex] = useState(0);
const [direction, setDirection] = useState("left");
const [initialX, setInitialX] = useState(0);
const [xOffset, setXOffset] = useState(0);
const [initialMoveX, setInitialMoveX] = useState(0);
const [initialMoveY, setInitialMoveY] = useState(0);
const [xOffsetMove, setXOffsetMove] = useState(0);
const [yOffsetMove, setYOffsetMove] = useState(0);
const [active, setActive] = useState(false);
const [zoomed, setZoomed] = useState(false);
const base = baseRequest();
const directionX = useRef(0);
// const imgDom = useRef(null);
const currentDistance = useRef(0);
// const getDistance = (e) => {
// e.stopPropagation();
// const distance = ref.current.scrollLeft;
// setDistance(distance);
// };
useEffect(() => {
// setCurrentIndex(defaultIndex);
// test3(defaultIndex - 1, "left");
if (defaultIndex) {
// console.log("defaultIndex.current", defaultIndex);
test3(defaultIndex - 1, "left", true);
}
}, [defaultIndex]);
useEffect(() => {
if (ref.current) {
ref.current.style.transform = `translateX(${
-window.innerWidth * currentIndex
}px)`;
}
}, [currentIndex]);
const test1 = (e) => {
var touches = e.touches;
// console.log(currentIndex, e.target.children[0].offsetLeft);
setInitialMoveX(touches[0].clientX - e.target.children[0].offsetLeft);
setInitialMoveY(touches[0].clientY - e.target.children[0].offsetTop);
// console.log(touches[0].pageX- ref.current.getBoundingClientRect().left);
if (touches.length === 2) {
var touch1 = touches[0];
var touch2 = touches[1];
currentDistance.current = Math.hypot(
touch2.pageX - touch1.pageX,
touch2.pageY - touch1.pageY
);
}
if (touches.length === 1 && !zoomed) {
setInitialX(touches[0].clientX - (!currentIndex ? 0 : xOffset));
// 单点触摸
setActive(true);
}
};
const test2 = (e) => {
var touches = e.touches;
// if (touches.length == 2) {
// var touch1 = touches[0];
// var touch2 = touches[1];
// currentDistance.current = Math.hypot(
// touch2.pageX - touch1.pageX,
// touch2.pageY - touch1.pageY
// );
// let scale = currentDistance.current / ref.current.startDistance;
// let matrix = new WebKitCSSMatrix(
// window.getComputedStyle(ref.current.children[0]).transform
// );
// let currentScale = matrix.m11;
// // alert(currentDistance.current + "-" + ref.current.startDistance);
// let size =
// currentScale * scale < 0.5
// ? 0.5
// : currentScale * scale > 3
// ? 3
// : currentScale * scale;
// ref.current.children[0].style.transform =
// "matrix(" + size + ", 0, 0, " + size + ", 0, 0)";
// }
if (zoomed) {
let currentX = touches[0].clientX - initialMoveX;
let currentY = touches[0].clientY - initialMoveY;
// console.log(currentX + xOffsetMove);
ref.current.children[currentIndex].style.left = `${
currentX + xOffsetMove
}px`;
ref.current.children[currentIndex].style.top = `${
currentY + yOffsetMove - 54
}px`;
} else {
if (active) {
let X = touches[0].clientX - initialX;
setDirection(
directionX.current > touches[0].clientX ? "left" : "right"
);
ref.current.style.transform = "translateX(" + X + "px)";
directionX.current = touches[0].clientX;
}
}
};
const test3 = (index, currentDirection, isActive) => {
// const rect = ref.current.getBoundingClientRect();
// console.log(ref.current.children[currentIndex].offsetTop);
setXOffsetMove(
ref.current.children[currentIndex].offsetLeft -
window.innerWidth * currentIndex
);
setYOffsetMove(ref.current.children[currentIndex].offsetTop + 54);
if (active || isActive) {
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
className="z-50 flex justify-between items-center absolute top-[12px] left-[12px]"
style={{ width: "calc(100% - 24px)" }}
>
<div>
{/* <div
onClick={() => downloadImage(images[currentIndex]?.url)}
className="flex justify-center items-center w-[38px] h-[38px] bg-[#ffffff1a] text-[#fff] rounded-full"
>
<FontAwesomeIcon icon={faDownload} size="xl" />
</div> */}
</div>
<div>
<div
onClick={() => {
setZoomed(!zoomed);
setActive(false);
ref.current.children[currentIndex].style.transform =
"matrix(" +
(zoomed ? 1 : 3) +
", 0, 0, " +
(zoomed ? 1 : 3) +
", 0, 0)";
ref.current.children[currentIndex].style.left = `0px`;
ref.current.children[currentIndex].style.top = `0px`;
}}
className="flex justify-center items-center w-[38px] h-[38px] bg-[#ffffff1a] text-[#fff] rounded-full"
>
<FontAwesomeIcon
icon={zoomed ? faMinus : faAdd}
size="xl"
/>
</div>
</div>
</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 relative"
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"
// onDoubleClick={() => {
// setZoomed(!zoomed);
// ref.current.children[0].style.transform =
// "matrix(" + zoomed
// ? 1
// : 3 + ", 0, 0, " + zoomed
// ? 1
// : 3 + ", 0, 0)";
// ref.current.style.left = `0px`;
// ref.current.style.top = `0px`;
// }}
>
{/* <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",
}}
// draggable={true}
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={() => {
setActive(true);
setZoomed(false);
setInitialMoveX(0);
setInitialMoveY(0);
setXOffsetMove(0);
setYOffsetMove(0);
ref.current.children[currentIndex].style.transform =
"matrix(1, 0, 0, 1, 0, 0)";
ref.current.children[currentIndex].style.left = `0px`;
ref.current.children[currentIndex].style.top = `0px`;
test3(currentIndex, "right", true);
}}
>
<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={() => {
setZoomed(false);
setInitialMoveX(0);
setInitialMoveY(0);
setXOffsetMove(0);
setYOffsetMove(0);
ref.current.children[currentIndex].style.transform =
"matrix(1, 0, 0, 1, 0, 0)";
ref.current.children[currentIndex].style.left = `0px`;
ref.current.children[currentIndex].style.top = `0px`;
test3(currentIndex, "left", true);
}}
>
<FontAwesomeIcon icon={faAngleRight} size="xl" />
</div>
</div>
</div>
</Mask>
</div>
);
}
);
export default forwardRef(ImagesMask);