diff --git a/package.json b/package.json index 2c50d42..10b81d3 100644 --- a/package.json +++ b/package.json @@ -2,6 +2,7 @@ "name": "diw", "version": "0.1.0", "private": true, + "homepage": "https://lg-cjdqwkbo-1256266248.cos.ap-shanghai.myqcloud.com/diw/", "dependencies": { "@tensorflow-models/posenet": "^2.2.1", "@tensorflow/tfjs": "^1.7.2", @@ -22,7 +23,7 @@ }, "scripts": { "start": "react-scripts start", - "build": "react-scripts build", + "build": "react-scripts build && coscmd config -a AKIDjS6at7fjTAVgggDNCrogRiZTSL304DPR -s FPPGCXr4xgZRLKDC8tZGp7HTZXlqx0gU -b lg-cjdqwkbo-1256266248 -r ap-shanghai && coscmd delete diw -f && coscmd upload -r build diw", "test": "react-scripts test", "eject": "react-scripts eject" }, diff --git a/src/App.js b/src/App.js index f0835d5..976ea30 100644 --- a/src/App.js +++ b/src/App.js @@ -1,17 +1,18 @@ import React, { useState, useEffect } from "react"; import * as posenet from "@tensorflow-models/posenet"; -import Wall from "./models/Wall"; +import Wall, { easeIn } from "./models/Wall"; import Sphere from "./models/Sphere"; import createTouches from "touches"; import "./App.scss"; import shops from "./data/Shops"; import Shop from "./components/shop"; +import touchIcon from "./touch.png"; const videoWidth = 600; const videoHeight = 500; const width = window.innerWidth; const height = window.innerHeight; -const radius = 412; -const displacement = 600; +const radius = 450; +const displacement = 400; const POSENET_URL = "https://lg-cjdqwkbo-1256266248.cos.ap-shanghai.myqcloud.com/mobile-net/50/model-stride16.json"; @@ -160,24 +161,39 @@ const App = () => {
{list.map(([key, el]) => (
{ - setItem({ dom: e.target, item: el.data, shop }); - }} - >
+ className="block-wrapper" + style={{ ...el.style, backgroundImage: "nonde" }} + > +
{ + if (!itemData) { + let i = 0; + let interval = setInterval(() => { + i++; + let t = i / 30; + if (t > 1) { + sphere.displacement = 600; + clearInterval(interval); + } + sphere.displacement = displacement + easeIn(t) * 200; + }, 1000 / 30); + } + setItem({ dom: e.target, item: el.data, shop }); + }} + >
+
))} {sphere && ( -
-
+
+
{itemData && } - {!itemData && ( -
- touch
- item -
- )} + {!itemData && }
)}
diff --git a/src/App.scss b/src/App.scss index 5add751..8355533 100644 --- a/src/App.scss +++ b/src/App.scss @@ -6,7 +6,8 @@ width: 100vw; height: 100vh; text-align: center; - background: #f8f8f8; + background: #f6f8f9; + // background-image: url(./images/bg.jpg); display: flex; flex-direction: column; overflow: hidden; @@ -18,29 +19,51 @@ height: 100vh; z-index: 1; } - .block { - background-size: cover; - background-position: center; - opacity: 1; + .block-wrapper { position: absolute; border: 1px solid rgb(224, 224, 224); + opacity: 1; + padding: 8px 10px; + box-sizing: border-box; + background: #fff; + .block { + width: 100%; + height: 100%; + background-size: cover; + background-position: center; + } } + .mist { position: absolute; z-index: 100; display: flex; flex-direction: column; align-items: center; + &.inactive { + pointer-events: none; + } .ball { position: absolute; - width: 100%; - height: 100%; + width: 140%; + height: 140%; + left: -20%; + top: -20%; + transition: all 1s ease-in; + &.small { + width: 80%; + height: 80%; + left: 10%; + top: 10%; + } filter: blur(50px); border-radius: 50%; background: rgba(255, 255, 255, 0.8); pointer-events: none; } - .text { + .touch-icon { + width: 200px; + height: 200px; text-align: center; color: #000; font-size: 60px; diff --git a/src/components/shop.js b/src/components/shop.js index a488539..cb2fef8 100644 --- a/src/components/shop.js +++ b/src/components/shop.js @@ -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) && ( -
+ {stage === 0 && ( +
+
+
)} {stage >= 1 && (
-
-
{name}
-
{"<"}
- - {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 ( -
- ); - })} + + {list[index] && ( +
+ )}
{">"}
+
+
+
+
-
- {list[index].name} -
-
{list[index].price}元
-
{list[index].desc}
+
{list[index] && list[index].name}
+
{list[index] && list[index].price}元
+
{list[index] && list[index].desc}
diff --git a/src/components/shop.scss b/src/components/shop.scss index 726fc83..4cb290d 100644 --- a/src/components/shop.scss +++ b/src/components/shop.scss @@ -2,10 +2,8 @@ z-index: 1; width: 100%; height: 100%; - display: flex; - flex-direction: column; box-sizing: border-box; - padding: 100px; + padding-top: 77px; @keyframes fadeIn { from { opacity: 0; @@ -14,34 +12,69 @@ opacity: 1; } } - .up, .down { - flex: 1; - display: flex; - flex-direction: column; + position: relative; animation: fadeIn 0.5s ease-in-out; - .title { - font-size: 60px; - margin: auto; + margin: 40px 100px 0 100px; + padding-left: 200px; + text-align: left; + .avatar-wrapper { + position: absolute; + top: 0; + left: 0; + width: 180px; + height: 180px; + border: 1px solid #cacaca; + padding: 18px; + background: #fdfdfd; + .avatar { + width: 100%; + height: 100%; + background-position: center; + background-size: contain; + background-repeat: no-repeat; + } } .texts { margin: auto; + .name { + color: #333; + font-size: 30px; + line-height: 40px; + margin: auto; + } + .price { + color: #333; + font-size: 20px; + line-height: 20px; + } + .desc { + color: #676767; + margin-top: 25px; + font-size: 18px; + line-height: 22px; + max-height: 95px; + overflow: scroll; + } } } .middle { position: relative; - flex: 0 0 380px; - padding: 0 40px; + text-align: center; + padding: 0 100px; .arrow { position: absolute; top: 0; bottom: 0; margin: auto; width: 40px; - line-height: 40px; - height: 40px; - font-size: 40px; + line-height: 60px; + height: 60px; + font-size: 60px; font-weight: bold; + color: #dadbdd; + transform-origin: center; + transform: scaleY(2); &.left { left: 0; } @@ -49,17 +82,18 @@ right: 0; } } - .imgs { - position: relative; - width: 100%; - height: 100%; + .img-wrapper { + width: 700px; + height: 530px; + background: #fefefe; + padding: 35px 45px; + box-shadow: 0px 0px 39px 0px rgba(162, 162, 162, 0.5); .img { - transition: width 1s, height 1s, top 1s, left 1s; - position: absolute; + width: 100%; + height: 100%; background-size: cover; background-position: center; margin: auto; - border: 1px solid rgb(224, 224, 224); } } } @@ -69,5 +103,11 @@ transition: all 1s ease-out; background-position: center; background-size: cover; - border: 1px solid rgb(224, 224, 224); + background: #fff; + .img { + width: 100%; + height: 100%; + background-size: cover; + background-position: center; + } } diff --git a/src/data/Shops.js b/src/data/Shops.js index 0a4d8e5..4d7590e 100644 --- a/src/data/Shops.js +++ b/src/data/Shops.js @@ -373,8 +373,8 @@ const shops = [ price: Math.floor(Math.random() * 100) + 100, }, ], - imgWidth: 100, - imgHeight: 90, + imgWidth: 160, + imgHeight: 120, }, { name: "UNIQLO", diff --git a/src/images/bg.jpg b/src/images/bg.jpg new file mode 100644 index 0000000..a2460fd Binary files /dev/null and b/src/images/bg.jpg differ diff --git a/src/models/Wall.js b/src/models/Wall.js index 2018367..fbdcdfa 100644 --- a/src/models/Wall.js +++ b/src/models/Wall.js @@ -1,9 +1,10 @@ import { Vector3 } from "three"; import BezierEasing from "bezier-easing"; -const easeIn = BezierEasing(0.5, 0.16, 0.74, 0.38); -const easeOut = BezierEasing(0, 0, 0.58, 1); +export const easeIn = BezierEasing(0.5, 0.16, 0.74, 0.38); +export const easeOut = BezierEasing(0, 0, 0.58, 1); const enterDuration = 3000; const exitDuration = 5000; +const margin = 30; class El { constructor(seed) { const { data, row, wall, key, index } = seed; @@ -50,7 +51,8 @@ class Row { t1; t2; constructor({ wall, index }) { - const initY = index * wall.blockHeight + wall.blockHeight / 2; + const initY = + wall.marginTop + index * wall.blockHeight + wall.blockHeight / 2; const offsetY = initY - wall.containerHeight - wall.blockHeight; Object.assign(this, { wall, @@ -128,7 +130,6 @@ class Row { this.update(); } } - export default class Wall { #rafID = null; #lastTime; @@ -148,12 +149,13 @@ export default class Wall { speed, onListChange, }) { - const colNum = Math.floor(containerWidth / imgWidth) - 1; - const rowNum = Math.floor(containerHeight / imgHeight) - 1; + const blockWidth = imgWidth + margin; + const blockHeight = imgHeight + margin; + const colNum = Math.floor(containerWidth / blockWidth); + const rowNum = Math.floor(containerHeight / blockHeight); const elNum = items.length; const ratioSpeed = speed / (containerWidth / colNum); - const blockWidth = containerWidth / colNum; - const blockHeight = containerHeight / rowNum; + const marginTop = (containerHeight - rowNum * blockHeight) / 2; const elMap = new Map(); Object.assign(this, { items, @@ -167,6 +169,7 @@ export default class Wall { ratioSpeed, blockWidth, blockHeight, + marginTop, elMap, onListChange, }); diff --git a/src/touch.png b/src/touch.png new file mode 100644 index 0000000..b8e0df2 Binary files /dev/null and b/src/touch.png differ