Browse Source

css update

master
jiannibang 6 years ago
parent
commit
973c0c0249
  1. 3
      package.json
  2. 52
      src/App.js
  3. 39
      src/App.scss
  4. 158
      src/components/shop.js
  5. 86
      src/components/shop.scss
  6. 4
      src/data/Shops.js
  7. BIN
      src/images/bg.jpg
  8. 19
      src/models/Wall.js
  9. BIN
      src/touch.png

3
package.json

@ -2,6 +2,7 @@
"name": "diw", "name": "diw",
"version": "0.1.0", "version": "0.1.0",
"private": true, "private": true,
"homepage": "https://lg-cjdqwkbo-1256266248.cos.ap-shanghai.myqcloud.com/diw/",
"dependencies": { "dependencies": {
"@tensorflow-models/posenet": "^2.2.1", "@tensorflow-models/posenet": "^2.2.1",
"@tensorflow/tfjs": "^1.7.2", "@tensorflow/tfjs": "^1.7.2",
@ -22,7 +23,7 @@
}, },
"scripts": { "scripts": {
"start": "react-scripts start", "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", "test": "react-scripts test",
"eject": "react-scripts eject" "eject": "react-scripts eject"
}, },

52
src/App.js

@ -1,17 +1,18 @@
import React, { useState, useEffect } from "react"; import React, { useState, useEffect } from "react";
import * as posenet from "@tensorflow-models/posenet"; import * as posenet from "@tensorflow-models/posenet";
import Wall from "./models/Wall";
import Wall, { easeIn } from "./models/Wall";
import Sphere from "./models/Sphere"; import Sphere from "./models/Sphere";
import createTouches from "touches"; import createTouches from "touches";
import "./App.scss"; import "./App.scss";
import shops from "./data/Shops"; import shops from "./data/Shops";
import Shop from "./components/shop"; import Shop from "./components/shop";
import touchIcon from "./touch.png";
const videoWidth = 600; const videoWidth = 600;
const videoHeight = 500; const videoHeight = 500;
const width = window.innerWidth; const width = window.innerWidth;
const height = window.innerHeight; const height = window.innerHeight;
const radius = 412;
const displacement = 600;
const radius = 450;
const displacement = 400;
const POSENET_URL = const POSENET_URL =
"https://lg-cjdqwkbo-1256266248.cos.ap-shanghai.myqcloud.com/mobile-net/50/model-stride16.json"; "https://lg-cjdqwkbo-1256266248.cos.ap-shanghai.myqcloud.com/mobile-net/50/model-stride16.json";
@ -160,24 +161,39 @@ const App = () => {
<div className="App"> <div className="App">
{list.map(([key, el]) => ( {list.map(([key, el]) => (
<div <div
className="block"
key={key}
style={el.style}
onClick={(e) => {
setItem({ dom: e.target, item: el.data, shop });
}}
></div>
className="block-wrapper"
style={{ ...el.style, backgroundImage: "nonde" }}
>
<div
className="block"
key={key}
style={{ backgroundImage: el.style.backgroundImage }}
onClick={(e) => {
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 });
}}
></div>
</div>
))} ))}
{sphere && ( {sphere && (
<div className="mist" style={sphere.style}>
<div className="ball"></div>
<div
className={"mist" + (itemData ? "" : " inactive")}
style={sphere.style}
>
<div className={"ball" + (!itemData ? " small" : "")}></div>
{itemData && <Shop data={itemData}></Shop>} {itemData && <Shop data={itemData}></Shop>}
{!itemData && (
<div className="text">
touch <br />
item
</div>
)}
{!itemData && <img className="touch-icon" src={touchIcon}></img>}
</div> </div>
)} )}
</div> </div>

39
src/App.scss

@ -6,7 +6,8 @@
width: 100vw; width: 100vw;
height: 100vh; height: 100vh;
text-align: center; text-align: center;
background: #f8f8f8;
background: #f6f8f9;
// background-image: url(./images/bg.jpg);
display: flex; display: flex;
flex-direction: column; flex-direction: column;
overflow: hidden; overflow: hidden;
@ -18,29 +19,51 @@
height: 100vh; height: 100vh;
z-index: 1; z-index: 1;
} }
.block {
background-size: cover;
background-position: center;
opacity: 1;
.block-wrapper {
position: absolute; position: absolute;
border: 1px solid rgb(224, 224, 224); 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 { .mist {
position: absolute; position: absolute;
z-index: 100; z-index: 100;
display: flex; display: flex;
flex-direction: column; flex-direction: column;
align-items: center; align-items: center;
&.inactive {
pointer-events: none;
}
.ball { .ball {
position: absolute; 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); filter: blur(50px);
border-radius: 50%; border-radius: 50%;
background: rgba(255, 255, 255, 0.8); background: rgba(255, 255, 255, 0.8);
pointer-events: none; pointer-events: none;
} }
.text {
.touch-icon {
width: 200px;
height: 200px;
text-align: center; text-align: center;
color: #000; color: #000;
font-size: 60px; font-size: 60px;

158
src/components/shop.js

@ -1,9 +1,10 @@
import React, { useState, useEffect } from "react"; import React, { useState, useEffect } from "react";
import { Swipeable } from "react-swipeable"; import { Swipeable } from "react-swipeable";
import "./shop.scss"; import "./shop.scss";
const itemVh = 380;
const itemVh = 530;
const Shop = ({ data }) => { const Shop = ({ data }) => {
const { item, shop } = data;
const { item, shop, dom } = data;
const { url } = item;
const { name, items, imgWidth, imgHeight, categoryLogoMap } = shop; const { name, items, imgWidth, imgHeight, categoryLogoMap } = shop;
const categoryUrl = categoryLogoMap[item.category]; const categoryUrl = categoryLogoMap[item.category];
const list = items.filter(({ category }) => category === item.category); const list = items.filter(({ category }) => category === item.category);
@ -13,128 +14,89 @@ const Shop = ({ data }) => {
const [stage, setStage] = useState(null); const [stage, setStage] = useState(null);
const [phStyle, setPhStyle] = 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(() => { useEffect(() => {
if (stage !== null && stage !== 2) return;
const { dom, item } = data; const { dom, item } = data;
const { width, height, left, top } = dom.getBoundingClientRect(); 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(() => { 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); 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]); }, [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 pre = () => setIndex((index - 1 + list.length) % list.length);
const nxt = () => setIndex((index + 1 + list.length) % list.length); const nxt = () => setIndex((index + 1 + list.length) % list.length);
return ( 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 && ( {stage >= 1 && (
<div className="shop"> <div className="shop">
<div className="up">
<div className="title">{name}</div>
</div>
<div className="middle"> <div className="middle">
<div className="arrow left" onClick={pre}> <div className="arrow left" onClick={pre}>
{"<"} {"<"}
</div> </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> </Swipeable>
<div className="arrow right" onClick={nxt}> <div className="arrow right" onClick={nxt}>
{">"} {">"}
</div> </div>
</div> </div>
<div className="down"> <div className="down">
<div className="avatar-wrapper">
<div
className="avatar"
style={{ backgroundImage: `url(${categoryUrl})` }}
></div>
</div>
<div className="texts"> <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> </div>
</div> </div>

86
src/components/shop.scss

@ -2,10 +2,8 @@
z-index: 1; z-index: 1;
width: 100%; width: 100%;
height: 100%; height: 100%;
display: flex;
flex-direction: column;
box-sizing: border-box; box-sizing: border-box;
padding: 100px;
padding-top: 77px;
@keyframes fadeIn { @keyframes fadeIn {
from { from {
opacity: 0; opacity: 0;
@ -14,34 +12,69 @@
opacity: 1; opacity: 1;
} }
} }
.up,
.down { .down {
flex: 1;
display: flex;
flex-direction: column;
position: relative;
animation: fadeIn 0.5s ease-in-out; 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 { .texts {
margin: auto; 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 { .middle {
position: relative; position: relative;
flex: 0 0 380px;
padding: 0 40px;
text-align: center;
padding: 0 100px;
.arrow { .arrow {
position: absolute; position: absolute;
top: 0; top: 0;
bottom: 0; bottom: 0;
margin: auto; margin: auto;
width: 40px; width: 40px;
line-height: 40px;
height: 40px;
font-size: 40px;
line-height: 60px;
height: 60px;
font-size: 60px;
font-weight: bold; font-weight: bold;
color: #dadbdd;
transform-origin: center;
transform: scaleY(2);
&.left { &.left {
left: 0; left: 0;
} }
@ -49,17 +82,18 @@
right: 0; 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 { .img {
transition: width 1s, height 1s, top 1s, left 1s;
position: absolute;
width: 100%;
height: 100%;
background-size: cover; background-size: cover;
background-position: center; background-position: center;
margin: auto; margin: auto;
border: 1px solid rgb(224, 224, 224);
} }
} }
} }
@ -69,5 +103,11 @@
transition: all 1s ease-out; transition: all 1s ease-out;
background-position: center; background-position: center;
background-size: cover; background-size: cover;
border: 1px solid rgb(224, 224, 224);
background: #fff;
.img {
width: 100%;
height: 100%;
background-size: cover;
background-position: center;
}
} }

4
src/data/Shops.js

@ -373,8 +373,8 @@ const shops = [
price: Math.floor(Math.random() * 100) + 100, price: Math.floor(Math.random() * 100) + 100,
}, },
], ],
imgWidth: 100,
imgHeight: 90,
imgWidth: 160,
imgHeight: 120,
}, },
{ {
name: "UNIQLO", name: "UNIQLO",

BIN
src/images/bg.jpg

Binary file not shown.

After

Width:  |  Height:  |  Size: 20 KiB

19
src/models/Wall.js

@ -1,9 +1,10 @@
import { Vector3 } from "three"; import { Vector3 } from "three";
import BezierEasing from "bezier-easing"; 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 enterDuration = 3000;
const exitDuration = 5000; const exitDuration = 5000;
const margin = 30;
class El { class El {
constructor(seed) { constructor(seed) {
const { data, row, wall, key, index } = seed; const { data, row, wall, key, index } = seed;
@ -50,7 +51,8 @@ class Row {
t1; t1;
t2; t2;
constructor({ wall, index }) { 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; const offsetY = initY - wall.containerHeight - wall.blockHeight;
Object.assign(this, { Object.assign(this, {
wall, wall,
@ -128,7 +130,6 @@ class Row {
this.update(); this.update();
} }
} }
export default class Wall { export default class Wall {
#rafID = null; #rafID = null;
#lastTime; #lastTime;
@ -148,12 +149,13 @@ export default class Wall {
speed, speed,
onListChange, 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 elNum = items.length;
const ratioSpeed = speed / (containerWidth / colNum); const ratioSpeed = speed / (containerWidth / colNum);
const blockWidth = containerWidth / colNum;
const blockHeight = containerHeight / rowNum;
const marginTop = (containerHeight - rowNum * blockHeight) / 2;
const elMap = new Map(); const elMap = new Map();
Object.assign(this, { Object.assign(this, {
items, items,
@ -167,6 +169,7 @@ export default class Wall {
ratioSpeed, ratioSpeed,
blockWidth, blockWidth,
blockHeight, blockHeight,
marginTop,
elMap, elMap,
onListChange, onListChange,
}); });

BIN
src/touch.png

Binary file not shown.

After

Width:  |  Height:  |  Size: 56 KiB

Loading…
Cancel
Save