|
|
|
@ -1,9 +1,10 @@ |
|
|
|
import React, { useState, useEffect } from "react"; |
|
|
|
import { Swipeable } from "react-swipeable"; |
|
|
|
import "./shop.scss"; |
|
|
|
const itemVh = 380; |
|
|
|
const itemVh = 530; |
|
|
|
const Shop = ({ data }) => { |
|
|
|
const { item, shop } = data; |
|
|
|
const { item, shop, dom } = data; |
|
|
|
const { url } = item; |
|
|
|
const { name, items, imgWidth, imgHeight, categoryLogoMap } = shop; |
|
|
|
const categoryUrl = categoryLogoMap[item.category]; |
|
|
|
const list = items.filter(({ category }) => category === item.category); |
|
|
|
@ -13,128 +14,89 @@ const Shop = ({ data }) => { |
|
|
|
const [stage, setStage] = useState(null); |
|
|
|
|
|
|
|
const [phStyle, setPhStyle] = useState(null); |
|
|
|
const init = () => { |
|
|
|
setPhStyle({ |
|
|
|
position: "absolute", |
|
|
|
width: itemVw + "px", |
|
|
|
height: itemVh + "px", |
|
|
|
left: 0, |
|
|
|
right: 0, |
|
|
|
top: 0, |
|
|
|
bottom: 0, |
|
|
|
margin: "auto", |
|
|
|
opacity: 1, |
|
|
|
backgroundImage: `url(${item.url})`, |
|
|
|
}); |
|
|
|
setTimeout(() => { |
|
|
|
setStage(1); |
|
|
|
}, 1000); |
|
|
|
}; |
|
|
|
const entrance = () => { |
|
|
|
setStage(2); |
|
|
|
}; |
|
|
|
useEffect(() => { |
|
|
|
if (stage !== null && stage !== 2) return; |
|
|
|
const { dom, item } = data; |
|
|
|
const { width, height, left, top } = dom.getBoundingClientRect(); |
|
|
|
setIndex(list.findIndex(({ id }) => item.id === id)); |
|
|
|
setStage(-1); |
|
|
|
setPhStyle({ |
|
|
|
position: "absolute", |
|
|
|
width: width + "px", |
|
|
|
height: height + "px", |
|
|
|
left: `calc(${left}px - ((100vw - ${itemVw}px) / 2))`, |
|
|
|
top: `calc(${top}px - ((100vh - ${itemVh}px) / 2))`, |
|
|
|
opacity: dom.style.opacity, |
|
|
|
padding: "8px 10px", |
|
|
|
border: `1px solid rgb(224, 224, 224)`, |
|
|
|
}); |
|
|
|
setTimeout(() => { |
|
|
|
setPhStyle({ |
|
|
|
position: "fixed", |
|
|
|
width: width + "px", |
|
|
|
height: height + "px", |
|
|
|
left: left + "px", |
|
|
|
top: top + "px", |
|
|
|
opacity: dom.style.opacity, |
|
|
|
backgroundImage: `url(${item.url})`, |
|
|
|
}); |
|
|
|
setStage(0); |
|
|
|
setTimeout(() => { |
|
|
|
setPhStyle({ |
|
|
|
position: "absolute", |
|
|
|
width: itemVw + "px", |
|
|
|
height: itemVh + "px", |
|
|
|
left: 0, |
|
|
|
right: 0, |
|
|
|
top: "77px", |
|
|
|
margin: "auto", |
|
|
|
opacity: 1, |
|
|
|
padding: "45px 35px", |
|
|
|
boxShadow: `0px 0px 39px 0px rgba(162,162,162,0.5)`, |
|
|
|
}); |
|
|
|
setTimeout(() => { |
|
|
|
setStage(1); |
|
|
|
}, 1000); |
|
|
|
}); |
|
|
|
}); |
|
|
|
setIndex(list.findIndex(({ id }) => item.id === id)); |
|
|
|
setStage(-1); |
|
|
|
}, [data]); |
|
|
|
useEffect(() => { |
|
|
|
switch (stage) { |
|
|
|
case 0: |
|
|
|
init(); |
|
|
|
break; |
|
|
|
case 1: |
|
|
|
entrance(); |
|
|
|
break; |
|
|
|
default: |
|
|
|
break; |
|
|
|
} |
|
|
|
}, [stage]); |
|
|
|
useEffect(() => {}, [stage]); |
|
|
|
|
|
|
|
const pre = () => setIndex((index - 1 + list.length) % list.length); |
|
|
|
const nxt = () => setIndex((index + 1 + list.length) % list.length); |
|
|
|
return ( |
|
|
|
<> |
|
|
|
{(stage === 0 || stage === 1) && ( |
|
|
|
<div className="ph" style={phStyle}></div> |
|
|
|
{stage === 0 && ( |
|
|
|
<div className="ph" style={phStyle}> |
|
|
|
<div className="img" style={{ backgroundImage: `url(${url})` }}></div> |
|
|
|
</div> |
|
|
|
)} |
|
|
|
{stage >= 1 && ( |
|
|
|
<div className="shop"> |
|
|
|
<div className="up"> |
|
|
|
<div className="title">{name}</div> |
|
|
|
</div> |
|
|
|
<div className="middle"> |
|
|
|
<div className="arrow left" onClick={pre}> |
|
|
|
{"<"} |
|
|
|
</div> |
|
|
|
<Swipeable className="imgs" onSwipedLeft={nxt} onSwipedRight={pre}> |
|
|
|
{list.map(({ url }, i) => { |
|
|
|
let leftD = index - i; |
|
|
|
let rightD = i - index; |
|
|
|
if (leftD < 0) leftD += list.length; |
|
|
|
if (rightD < 0) rightD += list.length; |
|
|
|
const isCurrent = i === index; |
|
|
|
const isLeft = leftD < rightD; |
|
|
|
const dis = isCurrent ? 0 : isLeft ? leftD : rightD; |
|
|
|
const scale = 1 - 0.25 * dis; |
|
|
|
return ( |
|
|
|
<div |
|
|
|
className={"img"} |
|
|
|
style={{ |
|
|
|
zIndex: 2 - dis, |
|
|
|
top: `${((1 - scale) / 2) * itemVh}px`, |
|
|
|
width: `${scale * itemVw}px`, |
|
|
|
height: `${scale * itemVh}px`, |
|
|
|
backgroundImage: `url(${url})`, |
|
|
|
opacity: dis <= 2 ? 1 : 0, |
|
|
|
...(isCurrent |
|
|
|
? { |
|
|
|
left: `calc(50% - ${itemVw / 2}px)`, |
|
|
|
} |
|
|
|
: isLeft |
|
|
|
? { |
|
|
|
left: |
|
|
|
dis === 2 ? 0 : `calc((100% - ${itemVw}px) / 4)`, |
|
|
|
} |
|
|
|
: { |
|
|
|
left: |
|
|
|
dis === 2 |
|
|
|
? `calc(100% - ${scale * itemVw}px)` |
|
|
|
: `calc(100% - ((100% - ${itemVw}px) / 4) - ${ |
|
|
|
scale * itemVw |
|
|
|
}px)`,
|
|
|
|
}), |
|
|
|
}} |
|
|
|
key={url} |
|
|
|
></div> |
|
|
|
); |
|
|
|
})} |
|
|
|
<Swipeable |
|
|
|
className="img-wrapper" |
|
|
|
onSwipedLeft={nxt} |
|
|
|
onSwipedRight={pre} |
|
|
|
> |
|
|
|
{list[index] && ( |
|
|
|
<div |
|
|
|
className={"img"} |
|
|
|
style={{ |
|
|
|
backgroundImage: `url(${list[index].url})`, |
|
|
|
}} |
|
|
|
></div> |
|
|
|
)} |
|
|
|
</Swipeable> |
|
|
|
<div className="arrow right" onClick={nxt}> |
|
|
|
{">"} |
|
|
|
</div> |
|
|
|
</div> |
|
|
|
<div className="down"> |
|
|
|
<div className="avatar-wrapper"> |
|
|
|
<div |
|
|
|
className="avatar" |
|
|
|
style={{ backgroundImage: `url(${categoryUrl})` }} |
|
|
|
></div> |
|
|
|
</div> |
|
|
|
|
|
|
|
<div className="texts"> |
|
|
|
<div className="name"> |
|
|
|
<img src={categoryUrl}></img> {list[index].name} |
|
|
|
</div> |
|
|
|
<div className="price">{list[index].price}元</div> |
|
|
|
<div>{list[index].desc}</div> |
|
|
|
<div className="name">{list[index] && list[index].name}</div> |
|
|
|
<div className="price">{list[index] && list[index].price}元</div> |
|
|
|
<div className="desc">{list[index] && list[index].desc}</div> |
|
|
|
</div> |
|
|
|
</div> |
|
|
|
</div> |
|
|
|
|