tiefen_space_h5/components/ImagesMask/index.jsx

481 lines
18 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 } 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(() => {
let body = document.body;
if (visible) {
body.style.touchAction = "none";
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>
);
} else {
body.style.touchAction = "auto";
}
// 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 [isNotFirstImg, setIsNotFirstImg] = useState(false);
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 currentDistance = useRef(0);
useEffect(() => {
if (defaultIndex) {
setIsNotFirstImg(true);
// console.log("defaultIndex.current", defaultIndex);
handleEnd(defaultIndex - 1, "left", true);
}
}, [defaultIndex]);
useEffect(() => {
if (ref.current) {
ref.current.style.transform = `translateX(${
-window.innerWidth * currentIndex
}px)`;
}
}, [currentIndex]);
const handleStart = (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 handleMove = (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);
let currentDom =
ref.current.children[currentIndex].getBoundingClientRect();
if (Math.abs(currentX + xOffsetMove) > currentDom.width / 3) return;
ref.current.children[currentIndex].style.left = `${
currentX + xOffsetMove
}px`;
if (Math.abs(currentY + yOffsetMove) > currentDom.height / 3) return;
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 handleEnd = (index, currentDirection, isActive) => {
// const rect = ref.current.getBoundingClientRect();
// console.log(ref.current.children[currentIndex].offsetTop);
if (index != defaultIndex - 1) {
setIsNotFirstImg(false);
}
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 {
// setCurrentIndex(0);
ref.current.style.transform = `translateX(${-cxOffset * index}px)`;
}
} else {
if (index > 0) {
setCurrentIndex(index - 1);
} else {
// setCurrentIndex(images.length - 1);
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) => {
if (typeof window == "undefined") return;
var a = document.createElement("a");
a.href = URL.createObjectURL(blob);
a.download = randomNum + ".jpg";
a.click();
});
}
return (
<Mask
destroyOnClose={false}
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"
>
{!zoomed ? (
<svg
t="1723822459763"
className="icon"
viewBox="0 0 1024 1024"
version="1.1"
xmlns="http://www.w3.org/2000/svg"
p-id="4557"
width="24"
height="24"
>
<path
d="M919.264 905.984l-138.912-138.912C851.808 692.32 896 591.328 896 480c0-229.376-186.624-416-416-416S64 250.624 64 480s186.624 416 416 416c95.008 0 182.432-32.384 252.544-86.208l141.44 141.44a31.904 31.904 0 0 0 45.248 0 32 32 0 0 0 0.032-45.248zM128 480C128 285.92 285.92 128 480 128s352 157.92 352 352-157.92 352-352 352S128 674.08 128 480z"
p-id="4558"
fill="#ffffff"
></path>
<path
d="M625.792 448H512v-112a32 32 0 0 0-64 0V448h-112a32 32 0 0 0 0 64H448v112a32 32 0 1 0 64 0V512h113.792a32 32 0 1 0 0-64z"
p-id="4559"
fill="#ffffff"
></path>
</svg>
) : (
<svg
t="1723822428728"
className="icon"
viewBox="0 0 1024 1024"
version="1.1"
xmlns="http://www.w3.org/2000/svg"
p-id="4379"
width="24"
height="24"
>
<path
d="M919.264 905.984l-138.912-138.912C851.808 692.32 896 591.328 896 480c0-229.376-186.624-416-416-416S64 250.624 64 480s186.624 416 416 416c95.008 0 182.432-32.384 252.544-86.208l141.44 141.44a31.904 31.904 0 0 0 45.248 0 32 32 0 0 0 0.032-45.248zM128 480C128 285.92 285.92 128 480 128s352 157.92 352 352-157.92 352-352 352S128 674.08 128 480z"
p-id="4380"
fill="#ffffff"
></path>
<path
d="M625.792 448H336a32 32 0 0 0 0 64h289.792a32 32 0 1 0 0-64z"
p-id="4381"
fill="#ffffff"
></path>
</svg>
)}
</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 h-full relative"
draggable={true}
style={{
transitionDuration: !isNotFirstImg ? "300ms" : "0ms",
transitionProperty: "transform",
transitionTimingFunction: "cubic-bezier(0.4, 0, 0.2, 1)",
}}
onTouchStart={handleStart}
onTouchMove={handleMove}
onTouchEnd={() => handleEnd(currentIndex, direction)}
>
{images.map((item, index) => {
return (
<div
draggable={true}
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
draggable={true}
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`;
handleEnd(currentIndex, "right", true);
}}
>
<FontAwesomeIcon
icon={faAngleLeft}
size="xl"
style={{ maxWidth: "12px" }}
/>
</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`;
handleEnd(currentIndex, "left", true);
}}
>
<FontAwesomeIcon
icon={faAngleRight}
size="xl"
style={{ maxWidth: "12px" }}
/>
</div>
</div>
</div>
</Mask>
);
}
);
export default forwardRef(ImagesMask);