图片预览组件添加切换按钮,修改其他有关样式

This commit is contained in:
al 2024-08-07 16:00:39 +08:00
parent e7886b717a
commit bfcdbb60f4
17 changed files with 342 additions and 66 deletions

View File

@ -37,6 +37,9 @@ footer{
/* .adm-image-viewer-slides-inner > *{
margin: 0;
} */
.adm-swiper-horizontal .adm-swiper-track {
transform: none;
}
.custom-tabs .adm-tabs {
border: none;
--active-line-color: #ff8383;
@ -301,4 +304,5 @@ footer{
.adm-checkbox.adm-checkbox-checked .adm-checkbox-icon {
border-color: #FF669E;
background-color: #FF669E;
}
}

View File

@ -35,4 +35,29 @@
}
.imagesBtnsControllers{
position: fixed;
top: 50%;
width: 100%;
display: flex;
padding: 0 12px;
justify-content: space-between;
z-index: 10001;
pointer-events: none;
}
.imagesBtnsControllerLeft,.imagesBtnsControllerRight{
width: 42px;
height: 42px;
border-radius: 53px;
background-color: #0000001A;
background-size: contain;
background-repeat: no-repeat;
pointer-events: all;
}
.imagesBtnsControllerLeft{
background-image: url("/icons/left.png");
opacity: 0.5;
}
.imagesBtnsControllerRight{
background-image: url("/icons/right.png");
}

View File

@ -193,6 +193,7 @@ export default function RootLayout({ children }) {
<main className={`w-full bg-deepBg h-full`}>
{withAuth(<Provider store={store}>{children}</Provider>)}
{/* <Provider store={store}>{children}</Provider> */}
<div id="maskDomBox"></div>
</main>
<footer className="fixed left-0 w-screen bg-black">
<div>

View File

@ -60,10 +60,7 @@ function Login({ handleLogin }) {
if(res && account){
router.replace("/")
}
})
}, []);
useEffect(() => {
let interval;
@ -158,11 +155,11 @@ function Login({ handleLogin }) {
}
);
if (data.ret === -1) {
Toast.show({
icon: "fail",
content: data.msg,
position: "top",
});
// Toast.show({
// icon: "fail",
// content: data.msg,
// position: "top",
// });
return;
}
//登录

View File

@ -116,7 +116,7 @@ export default function UnlockedWechat() {
streamerData={{
streamer_ext: {
wechat_lock_type:
currentStreamer.current?.streamer?.wechat_lock_type,
currentStreamer.current?.lock_type,
},
}}
/>

View File

@ -76,6 +76,7 @@ export default function Home() {
</div>
<Swiper
direction="horizontal"
allowTouchMove={false}
loop={false}
indicator={() => null}
ref={swiperRef}
@ -83,6 +84,7 @@ export default function Home() {
onIndexChange={(index) => {
setActiveIndex(index);
}}
>
<Swiper.Item>
{!activeIndex && (
@ -97,7 +99,7 @@ export default function Home() {
</Swiper>
<div
id="rightddd"
className={`fixed bottom-[96px] right-4 z-[999] w-10 h-10 flex items-center justify-center bg-[#1d1d1d71] rounded-full text-white
className={`fixed bottom-[96px] right-4 z-[50] w-10 h-10 flex items-center justify-center bg-[#1d1d1d71] rounded-full text-white
}`}
onClick={childrenFunc}
>

View File

@ -179,6 +179,8 @@ const ZoneItem = ({ data, showMore, link,search }) => {
<Image
className="flex-none w-10 h-10 rounded-full mr-2"
src={data?.avatar?.images[0]?.urls[0]}
width="2.5rem"
height="2.5rem"
alt=""
fit="cover"
/>

View File

@ -434,7 +434,7 @@ export default function PersonSpace() {
</JumboTabs>
</FloatingPanel>
<div
className={`fixed bottom-[96px] right-4 z-[999] w-10 h-10 flex items-center justify-center bg-[#1d1d1d71] rounded-full text-white ${
className={`fixed bottom-[96px] right-4 z-[50] w-10 h-10 flex items-center justify-center bg-[#1d1d1d71] rounded-full text-white ${
loading && !offset ? "animate-spin" : ""
}`}
>

View File

@ -129,10 +129,7 @@ export default function Space() {
}
}
return (
<div
className=""
>
<div className="">
<div className="flex justify-between items-center px-2 custom-tabs text-gray-400 sticky top-0 z-10 bg-deepBg">
<Tabs
activeKey={tabItems[activeIndex].key}
@ -299,7 +296,7 @@ export default function Space() {
</Swiper.Item>
</Swiper>
<div
className={`fixed bottom-[96px] right-4 z-[999] w-10 h-10 flex items-center justify-center bg-[#1d1d1d71] rounded-full text-white ${
className={`fixed bottom-[96px] right-4 z-[50] w-10 h-10 flex items-center justify-center bg-[#1d1d1d71] rounded-full text-white ${
loading && !offset ? "animate-spin" : ""
}`}
>

View File

@ -1,42 +1,88 @@
"use client";
import React,{useState,useEffect} from "react";
import { Image ,Toast} from "antd-mobile";
import React, { useState, useEffect } from "react";
import { Image } from "antd-mobile";
import { get,save } from "@/utils/storeInfo";
import { FontAwesomeIcon } from "@fortawesome/react-fontawesome";
import { faAngleUp, faClose } from "@fortawesome/free-solid-svg-icons";
export default function AddToHome() {
const [firstLogin, setFirstLogin] = useState("0");
const [firstLogin, setFirstLogin] = useState({ first: "0", second: false });
useEffect(() => {
if(!(("standalone" in window.navigator) && window.navigator.standalone)
){
setFirstLogin(get("firstLogin"))
if (!("standalone" in window.navigator && window.navigator.standalone)) {
setFirstLogin((old) => ({ ...old, first: get("firstLogin") }));
}
}, []);
return (
firstLogin=="1"?<div
className="fixed top-0 z-[999] flex flex-col justify-end items-center h-screen w-screen bg-[#262626b0]"
onClick={() => {save("firstLogin", 0);setFirstLogin("0")}}
return firstLogin.first == "1" ? (
<div
className="fixed z-[50]"
style={{ bottom: !firstLogin.second ? "57px" : "0" }}
>
<div className="font-bold text-xl mb-2 flex items-center">
点击
<Image
fit="cover"
// src={process.env.NEXT_PUBLIC_WEB_ASSETS_URL+"/icons/nodata.png"}
src={"/icons/ios_share.png"}
placeholder=""
width={32}
height={32}
/>
添加到主屏幕
</div>
<Image
fit="cover"
// src={process.env.NEXT_PUBLIC_WEB_ASSETS_URL+"/icons/nodata.png"}
src={"/images/addToHome.png"}
placeholder=""
width={54}
height={54}
/>
</div>:null
);
{!firstLogin.second ? (
<div className="bg-[#13121f] p-3 w-screen flex items-center justify-between relative">
<div className="flex items-center">
<Image
fit="cover"
className="rounded-md mr-3"
// src={process.env.NEXT_PUBLIC_WEB_ASSETS_URL+"/icons/nodata.png"}
src={"/images/icon.png"}
placeholder=""
width={46}
height={46}
/>
<div>
<p className="font-bold text-[0.9rem]">
建议您添加<span className="text-primary">铁粉空间</span>
到手机桌面
</p>
<p className="text-[#ffffffb2] text-xs">以便随时关注圈子动态</p>
</div>
</div>
<div
className="bg-primary px-4 py-2 rounded-full font-bold"
onClick={() => setFirstLogin((old) => ({ ...old, second: true }))}
>
去添加
</div>
<FontAwesomeIcon
icon={faClose}
size=""
className="absolute left-1 top-1"
onClick={() => {
save("firstLogin", 0);
setFirstLogin((old) => ({ first: "0", second: false }));
}}
/>
</div>
) : (
<div
className="flex flex-col justify-end items-center h-screen w-screen bg-[#00000099]"
onClick={() => {
save("firstLogin", 0);
setFirstLogin((old) => ({ first: "0", second: false }));
}}
>
<div className="font-bold text-xl mb-2 flex items-center">
点击
<Image
fit="cover"
// src={process.env.NEXT_PUBLIC_WEB_ASSETS_URL+"/icons/nodata.png"}
src={"/icons/ios_share.png"}
placeholder=""
width={32}
height={32}
/>
添加到主屏幕
</div>
<Image
fit="contain"
// src={process.env.NEXT_PUBLIC_WEB_ASSETS_URL+"/icons/nodata.png"}
src={"/images/addToHome.png"}
placeholder=""
width={54}
height={70}
/>
</div>
)}
</div>
) : null;
}

View File

@ -0,0 +1,117 @@
"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";
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(() => {
if (scrollRef.current) {
setTimeout(() => {
scrollRef.current.scrollLeft = 414 * currentIndex;
}, 200);
}
}, [currentIndex]);
useImperativeHandle(ref, () => ({
show: (arr, index) => {
setCurrentIndex(index);
setImages(arr);
setVisible(true);
// 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>
);
}
export default forwardRef(ImagesMask);

View File

@ -1,12 +1,14 @@
"use client";
import React, { useEffect, useState,useRef } from "react";
import React, { useEffect, useState, useRef } from "react";
import { Image, ImageViewer, Dialog } from "antd-mobile";
import { FontAwesomeIcon } from "@fortawesome/react-fontawesome";
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';
export default function Photos({
isUnlocked,
mediaVisibleRange,
@ -18,7 +20,10 @@ export default function Photos({
const [seeAllPhotos, setSeeAllPhotos] = useState(false);
const [currentPhotos, setCurrentPhotos] = useState([]);
const [photos, setPhotos] = useState([]);
const [visible, setVisible] = useState(false);
const currentIndex = useRef();
const swiper = useRef(null);
// const imagesMaskRef = useRef(null);
const router = useRouter();
const base = baseRequest();
useEffect(() => {
@ -57,22 +62,65 @@ export default function Photos({
}
}, [media]);
const showPhotos = (photos, index) => {
currentIndex.current=index;
currentIndex.current = index;
// const interval = setInterval(() => {
// const bodyBox = document.getElementsByClassName("photos-bodyBox")[0];
// if (bodyBox) {
// bodyBox.firstChild.lastChild.style.transform = `translateX(-${
// currentIndex.current * (window.innerWidth + 16)
// }px)`;
// // console.log(bodyBox.firstChild.lastChild.style.transform);
// }
// }, 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);
// setVisible(true)
// 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"
}`;
const interval = setInterval(() => {
const bodyBox = document.getElementsByClassName("photos-bodyBox")[0];
if(bodyBox){
bodyBox.firstChild.lastChild.style.transform = `translateX(-${
(currentIndex.current) * (window.innerWidth + 16)
}px)`;
// console.log(bodyBox.firstChild.lastChild.style.transform);
}
}, 400);
mediaDom.appendChild(btns);
ImageViewer.clear();
ImageViewer.Multi.show({
images: photos.map((item) => item?.url),
defaultIndex: index,
@ -82,18 +130,31 @@ export default function Photos({
getContainer: mediaDom,
onIndexChange: (index) => {
currentIndex.current=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);
// clearInterval(interval);
},
classNames: { body: "photos-bodyBox" },
});
};
const handleShowVideo = (video) => {
Dialog.className = "videoMask";
@ -293,6 +354,12 @@ export default function Photos({
);
})}
</div>
{/* <ImagesMask ref={imagesMaskRef}/> */}
{/* <Viewer
visible={visible}
onClose={() => { setVisible(false); } }
images={currentPhotos.map((it,index)=>({src:it.url,alt:index}))}
/> */}
</>
);
}

View File

@ -219,7 +219,7 @@ export default function PostItem({
"天前"
}有更新`}
空间 */}
{formatZoneUpdateTime(
空间{formatZoneUpdateTime(
data?.streamer_ext
?.days_elapsed_since_the_last_zones_update
)}

17
package-lock.json generated
View File

@ -26,6 +26,7 @@
"react-dom": "^18",
"react-player": "^2.16.0",
"react-redux": "^9.1.2",
"react-viewer": "^3.2.2",
"redux": "^5.0.1",
"sass": "^1.77.6"
},
@ -5876,6 +5877,14 @@
}
}
},
"node_modules/react-viewer": {
"version": "3.2.2",
"resolved": "https://registry.npmmirror.com/react-viewer/-/react-viewer-3.2.2.tgz",
"integrity": "sha512-DHOq1x6cXsAViY43204ILRzLVR5ovP1MgzsC+LzZCWlInRuHjzAgpQZ8GzWm1CkiNYuHGwCxH36X0JUHl2xDSg==",
"dependencies": {
"classnames": "^2.2.5"
}
},
"node_modules/read-cache": {
"version": "1.0.0",
"resolved": "https://registry.npmmirror.com/read-cache/-/read-cache-1.0.0.tgz",
@ -11195,6 +11204,14 @@
"use-sync-external-store": "^1.0.0"
}
},
"react-viewer": {
"version": "3.2.2",
"resolved": "https://registry.npmmirror.com/react-viewer/-/react-viewer-3.2.2.tgz",
"integrity": "sha512-DHOq1x6cXsAViY43204ILRzLVR5ovP1MgzsC+LzZCWlInRuHjzAgpQZ8GzWm1CkiNYuHGwCxH36X0JUHl2xDSg==",
"requires": {
"classnames": "^2.2.5"
}
},
"read-cache": {
"version": "1.0.0",
"resolved": "https://registry.npmmirror.com/read-cache/-/read-cache-1.0.0.tgz",

View File

@ -27,6 +27,7 @@
"react-dom": "^18",
"react-player": "^2.16.0",
"react-redux": "^9.1.2",
"react-viewer": "^3.2.2",
"redux": "^5.0.1",
"sass": "^1.77.6"
},

BIN
public/icons/left.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.1 KiB

BIN
public/icons/right.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.2 KiB