gemercheung 1 سال پیش
والد
کامیت
e85203680a
4فایلهای تغییر یافته به همراه173 افزوده شده و 176 حذف شده
  1. 19 28
      README.md
  2. 81 93
      src/App.jsx
  3. 50 50
      src/components/TimeLineText.jsx
  4. 23 5
      src/components/Viewer.jsx

+ 19 - 28
README.md

@@ -1,29 +1,20 @@
-# React + Vite
-
-This template provides a minimal setup to get React working in Vite with HMR and some ESLint rules.
-
-Currently, two official plugins are available:
-
-- [@vitejs/plugin-react](https://github.com/vitejs/vite-plugin-react/blob/main/packages/plugin-react/README.md) uses [Babel](https://babeljs.io/) for Fast Refresh
-- [@vitejs/plugin-react-swc](https://github.com/vitejs/vite-plugin-react-swc) uses [SWC](https://swc.rs/) for Fast Refresh
-
 [
-{
-"type": "from",
-"animation": {
-"y": 75,
-"autoAlpha": 0
-},
-"start": 0.03,
-"end": 0.04
-},
-{
-"type": "to",
-"animation": {
-"y": -75,
-"autoAlpha": 0
-},
-"start": 0.0725,
-"end": 0.08249999999999999
-}
-]
+    {
+        "type": "from",
+        "animation": {
+            "y": 75,
+            "autoAlpha": 0
+        },
+        "start": 0.25,
+        "end": 0.26
+    },
+    {
+        "type": "to",
+        "animation": {
+            "y": -75,
+            "autoAlpha": 0
+        },
+        "start": 0.36,
+        "end": 0.37
+    }
+]

+ 81 - 93
src/App.jsx

@@ -73,112 +73,100 @@ function App() {
           298: 40,
         }}
       >
-        <>
-          <TimeLineText
-            trigger={Action.scrubPin}
-            parentHeight={"1300vh"}
-            verticalOffset={"33vh"}
-            keyframes={[
-              Object.assign(Action.visible, {
-                start: 0,
-                end: 0,
-              }),
-              Object.assign(Action.fadeDown, {
-                start: 0.02,
-                end: 0.03,
-              }),
-            ]}
+        <TimeLineText
+          trigger={Action.scrubPin}
+          verticalOffset={"33vh"}
+          keyframes={[
+            Object.assign(Action.visible, {
+              start: 0,
+              end: 0,
+            }),
+            Object.assign(Action.fadeDown, {
+              start: 0.02,
+              end: 0.03,
+            }),
+          ]}
+        >
+          <div
+            css={css`
+              font-weight: 300;
+              font-size: 2.75vw;
+              width: 100%;
+              text-align: center;
+            `}
           >
-            <div
-              css={css`
-                font-weight: 300;
-                font-size: 2.75vw;
-                width: 100%;
-                text-align: center;
-              `}
-            >
-              对古代美索不达米亚人来说,礼拜是日常生活的一部分。
-            </div>
-          </TimeLineText>
+            对古代美索不达米亚人来说,礼拜是日常生活的一部分。
+          </div>
+        </TimeLineText>
 
-          <TimeLinePureText
-            parentHeight={"1300vh"}
-            duration={0.0325}
-            fade={0.01}
-            progressPosition={0.03}
+        <TimeLinePureText duration={0.0325} fade={0.01} progressPosition={0.03}>
+          <div
+            css={css`
+              font-weight: 300;
+              font-size: 18px;
+              width: 50%;
+              max-width: 600px;
+              padding: 8px 12px;
+              margin-right: 20px;
+              margin-left: auto;
+              background: rgba(0, 0, 0, 0.7);
+              border-radius: 2px;
+            `}
           >
-            <div
-              css={css`
-                font-weight: 300;
-                font-size: 18px;
-                width: 50%;
-                max-width: 600px;
-                padding: 8px 12px;
-                margin-right: 20px;
-                margin-left: auto;
-                background: rgba(0, 0, 0, 0.7);
-                border-radius: 2px;
-              `}
-            >
-              各城邦的城市建筑甚至被赋予象征及宗教意义。巴比伦古城的建筑装饰即是一个鲜明例子。
-            </div>
-          </TimeLinePureText>
+            各城邦的城市建筑甚至被赋予象征及宗教意义。巴比伦古城的建筑装饰即是一个鲜明例子。
+          </div>
+        </TimeLinePureText>
 
-          <TimeLineWallText
-            className={"wall-text"}
-            parentHeight={"1300vh"}
-            progressPosition={0.125}
+        <TimeLineWallText className={"wall-text"} progressPosition={0.125}>
+          <div
+            css={css`
+              width: 35%;
+              padding-left: 32px;
+              padding-right: 32px;
+              z-index: 25;
+              font-size: 24px;
+              line-height: 1.66;
+              text-shadow: 2px 2px 6px rgba(0, 0, 0, 0.6);
+            `}
           >
             <div
               css={css`
-                width: 35%;
-                padding-left: 32px;
-                padding-right: 32px;
-                z-index: 25;
-                font-size: 24px;
-                line-height: 1.66;
-                text-shadow: 2px 2px 6px rgba(0, 0, 0, 0.6);
+                font-size: 30px;
               `}
             >
-              <div
-                css={css`
-                  font-size: 30px;
-                `}
-              >
-                迈步狮纹镶板
-              </div>
-              <div>公元前605-562年</div>
-              <div>涂釉陶瓷</div>
+              迈步狮纹镶板
             </div>
-          </TimeLineWallText>
+            <div>公元前605-562年</div>
+            <div>涂釉陶瓷</div>
+          </div>
+        </TimeLineWallText>
 
-          <TimeLinePureText
-            parentHeight={"1300vh"}
-            fade={0.01}
-            verticalOffset={"63vh"}
-            progressPosition={0.03}
+        <TimeLinePureText
+          fade={0.01}
+          verticalOffset={"63vh"}
+          progressPosition={0.25}
+        >
+          <div
+            css={css`
+              font-weight: 300;
+              font-size: 18px;
+              width: 50%;
+              max-width: 600px;
+              padding: 8px 12px;
+              margin-right: 20px;
+              margin-left: auto;
+              background: rgba(0, 0, 0, 0.7);
+              border-radius: 2px;
+            `}
           >
-            <div
-              css={css`
-                font-weight: 300;
-                font-size: 18px;
-                width: 50%;
-                max-width: 600px;
-                padding: 8px 12px;
-                margin-right: 20px;
-                margin-left: auto;
-                background: rgba(0, 0, 0, 0.7);
-                border-radius: 2px;
-              `}
-            >
-              <div>
-                在巴比伦最重要的街道Processional
-                Way两侧,排列着一百多块狮子釉砖,迈步狮纹镶板便是其中之一。这条路穿过伊什塔尔城门(Ishtar
-                Gate),连接这座城市的宫殿及主要神庙。
-              </div>
+            <div>
+              在巴比伦最重要的街道Processional
+              Way两侧,排列着一百多块狮子釉砖,迈步狮纹镶板便是其中之一。这条路穿过伊什塔尔城门(Ishtar
+              Gate),连接这座城市的宫殿及主要神庙。
+              
             </div>
-          </TimeLinePureText>
-        </>
+          </div>
+        </TimeLinePureText>
       </Viewer>
 
       <Viewer

+ 50 - 50
src/components/TimeLineText.jsx

@@ -1,27 +1,35 @@
 import { Component, createRef } from "react";
-import gsap from "gsap";
+import { gsap, ScrollTrigger } from "gsap/all";
 import PropTypes from "prop-types";
 import { Action } from "../action";
 import { css } from "@emotion/react";
 
 export function TimeLinePureText(props) {
-  const progressPosition = props.progressPosition
-    ? props.progressPosition
-    : 0.5;
+  const progressPosition =
+    void 0 !== props.progressPosition ? props.progressPosition : 0.5;
   const fade = props.fade || 0.04;
   const duration = props.duration || 0.1;
   const verticalOffset = props.verticalOffset || "50vh";
   const keyframes = [
-    Object.assign({}, Action.fadeUp, {
-      start: progressPosition,
-      end: progressPosition + fade,
-    }),
-    Object.assign({}, Action.fadeDown, {
-      start: progressPosition + duration + fade,
-      end: progressPosition + duration + fade + fade,
-    }),
+    Object.assign(
+      {},
+      Action.fadeUp,
+      {},
+      {
+        start: progressPosition,
+        end: progressPosition + fade,
+      }
+    ),
+    Object.assign(
+      {},
+      Action.fadeDown,
+      {},
+      {
+        start: progressPosition + duration + fade,
+        end: progressPosition + duration + fade + fade,
+      }
+    ),
   ];
-
   console.log("keyframes-TimeLinePureText", keyframes);
   return (
     <TimeLineText
@@ -65,7 +73,6 @@ export function TimeLineWallText(props) {
       parentHeight={props.parentHeight}
       style={props.style}
       progressPosition={props.progressPosition}
-      // {...props}
     >
       {props.children}
     </TimeLineText>
@@ -73,20 +80,30 @@ export function TimeLineWallText(props) {
 }
 
 export class TimeLineText extends Component {
-  constructor() {
+  constructor(props) {
     super();
     this.containerRef = createRef();
-    this.timeline = false;
+    this.timeline = null;
     this.top = 0;
+    this.progress = 0;
     this.keyframes = [];
     this.trigger = false;
+    this.init(props);
   }
   init(props) {
-    console.log("props", props);
+    // console.log("props", props);
+    this.props = props;
+    if (props.trigger && props.keyframes) {
+      var top = props.keyframes[0].start;
+      this.setTop(top);
+    } else {
+      if (this.props.progressPosition) {
+        this.setTop(this.props.progressPosition);
+      }
+    }
   }
   componentWillUnmount() {
     if (this.timeline) {
-      console.error("remove-timeline");
       this.timeline.kill(true);
       this.timeline = false;
     }
@@ -95,10 +112,6 @@ export class TimeLineText extends Component {
   componentDidMount() {
     if (this.props.keyframes && this.props.trigger) {
       this.createTimeLine();
-      var n = this.props.keyframes[0].start || 0;
-      this.setTop(n);
-    } else {
-      this.props.progressPosition && this.setTop(this.props.progressPosition);
     }
   }
   setTop(height) {
@@ -110,9 +123,12 @@ export class TimeLineText extends Component {
     this.top = lastHeight + "%";
     console.log("this.top", this.top);
   }
-
+  componentDidCatch(error) {
+    console.error("error", error);
+  }
   createTimeLine() {
     if (!this.timeline) {
+      console.log("createTimeLine");
       const start = this.props.keyframes[0].start;
       const end = this.props.keyframes[0].end;
       const dif = end - start;
@@ -123,41 +139,28 @@ export class TimeLineText extends Component {
       const gapDiff = lastStart - end;
       const timeRes =
         (lastEnd - start) * (parseFloat(this.props.parentHeight) - 100);
-      console.log("timeRes", timeRes);
 
-      // var t = this.props.keyframes[0].start,
-      // n = this.props.keyframes[0].end,
-      // r = n - t,
-      // a =
-      //   this.props.keyframes[this.props.keyframes.length - 1]
-      //     .start,
-      // i =
-      //   this.props.keyframes[this.props.keyframes.length - 1].end,
-      // o = i - a,
-      // l = a - n,
-      // s = (i - t) * (parseFloat(this.props.parentHeight) - 100),
-      // debugger;
+      const flag = `+=${timeRes}%`;
+      console.log("timeRes", flag);
 
       this.timeline = gsap.timeline({
         scrollTrigger: Object.assign(
           {
             trigger: this.containerRef.current,
             start: "top top",
-            end: "+=" + timeRes + "%",
-            onEnter: () => {
-              // console.warn("onEnter");
-            },
+            end: flag,
           },
           this.props.trigger
         ),
       });
       for (var i = 0; i < this.props.keyframes.length; i += 1) {
         const cFrame = this.props.keyframes[i];
-        1 === i &&
-          gapDiff > 0.001 &&
+        if (1 === i && gapDiff > 0.001) {
           this.timeline.to(this.containerRef.current, {
             duration: gapDiff,
           });
+        }
+
         if (cFrame.type === "set") {
           this.timeline.set(
             this.containerRef.current,
@@ -171,16 +174,13 @@ export class TimeLineText extends Component {
               duration: dif,
             })
           );
-        } else {
+        }
+        if (cFrame.type === "to") {
           this.timeline.to(
             this.containerRef.current,
-            Object.assign(
-              Object.assign({}, cFrame.animation),
-              {},
-              {
-                duration: lDif,
-              }
-            )
+            Object.assign(cFrame.animation, {
+              duration: lDif,
+            })
           );
         }
       }

+ 23 - 5
src/components/Viewer.jsx

@@ -1,4 +1,10 @@
-import { Component, createRef } from "react";
+import {
+  Component,
+  createRef,
+  Children,
+  isValidElement,
+  cloneElement,
+} from "react";
 import PropTypes from "prop-types";
 import { gsap, ScrollTrigger } from "gsap/all";
 import LazyLoad from "react-lazyload";
@@ -8,10 +14,21 @@ const isDebug = Number(import.meta.env.VITE_APP_DEBUG) === 1;
 
 console.log("isDebug", isDebug);
 
-export default function Viewer({ height, ...props }) {
+export default function Viewer(props) {
+  const lazyHeight = 0.01 * parseFloat(props.height) * window.innerHeight;
+  // offset={1e4}
+  var allChildren = Children.map(props.children, function (element) {
+    return isValidElement(element)
+      ? cloneElement(element, {
+          parentHeight: props.height,
+        })
+      : element;
+  });
+
+  // console.log("lazyHeight", lazyHeight);
   return (
-    <LazyLoad height={height || "500vh"}>
-      <ViewerInner height={height} {...props} />
+    <LazyLoad height={lazyHeight} offset={1e4}>
+      <ViewerInner {...props}>{allChildren}</ViewerInner>
     </LazyLoad>
   );
 }
@@ -400,7 +417,7 @@ class ViewerInner extends Component {
           css={css`
             position: fixed;
             top: calc(100vh - 4px);
-            // top: calc(var(--vh, 1vh) * 100 - 4px);
+            top: calc(var(--vh, 1vh) * 100 - 4px);
             left: 0;
             width: 100vw;
             max-width: 100%;
@@ -408,6 +425,7 @@ class ViewerInner extends Component {
             background-color: rgba(17, 17, 34, 0.6);
             height: 4px;
             z-index: 9;
+            visibility: hidden;
           `}
         >
           <div