gemer zhang 1 年之前
父节点
当前提交
a13879071d
共有 4 个文件被更改,包括 111 次插入72 次删除
  1. 13 12
      .eslintrc.cjs
  2. 36 9
      src/App.jsx
  3. 52 14
      src/components/Viewer.jsx
  4. 10 37
      src/index.css

+ 13 - 12
.eslintrc.cjs

@@ -2,20 +2,21 @@ module.exports = {
   root: true,
   env: { browser: true, es2020: true },
   extends: [
-    'eslint:recommended',
-    'plugin:react/recommended',
-    'plugin:react/jsx-runtime',
-    'plugin:react-hooks/recommended',
+    "eslint:recommended",
+    "plugin:react/recommended",
+    "plugin:react/jsx-runtime",
+    "plugin:react-hooks/recommended",
   ],
-  ignorePatterns: ['dist', '.eslintrc.cjs'],
-  parserOptions: { ecmaVersion: 'latest', sourceType: 'module' },
-  settings: { react: { version: '18.2' } },
-  plugins: ['react-refresh'],
+  ignorePatterns: ["dist", ".eslintrc.cjs"],
+  parserOptions: { ecmaVersion: "latest", sourceType: "module" },
+  settings: { react: { version: "18.2" } },
+  plugins: ["react-refresh"],
   rules: {
-    'react/jsx-no-target-blank': 'off',
-    'react-refresh/only-export-components': [
-      'warn',
+    "react/jsx-no-target-blank": "off",
+    "react/no-unknown-property": ["error", { ignore: ["css"] }],
+    "react-refresh/only-export-components": [
+      "warn",
       { allowConstantExport: true },
     ],
   },
-}
+};

+ 36 - 9
src/App.jsx

@@ -1,22 +1,46 @@
-import { useRef } from "react";
+import { useRef, useEffect } from "react";
 import LazyLoad from "react-lazyload";
 import { useGSAP } from "@gsap/react";
 import { gsap, ScrollTrigger } from "gsap/all";
 import Opening from "./components/Opening";
 import Viewer from "./components/Viewer";
-import "./App.css";
+// import "./App.css";
 gsap.registerPlugin(useGSAP);
 gsap.registerPlugin(ScrollTrigger);
+
+ScrollTrigger.config({
+  autoRefreshEvents: "visibilitychange,DOMContentLoaded,load",
+});
+
+let resizeTimer = null;
+
 function App() {
   // const [count, setCount] = useState(0);
   const container = useRef();
-  useGSAP(
-    () => {
-      // gsap code here...
-      // gsap.to(".box", { rotation: 180 }); // <-- automatically reverted
-    },
-    { scope: container }
-  ); // <-- scope for selector text (optional)
+  const handlerResize = () => {
+    clearTimeout(resizeTimer);
+    resizeTimer = setTimeout(function () {
+      var height = 0.01 * window.innerHeight;
+      var width = ((16 * window.innerHeight) / 9) * 0.01;
+      var n = 0;
+      100 * height < window.innerWidth &&
+        (n = 0.5 * (window.innerWidth - 100 * height));
+      document.documentElement.style.setProperty(
+        "--vh",
+        "".concat(height, "px")
+      ),
+        document.documentElement.style.setProperty(
+          "--cw",
+          "".concat(width, "px")
+        ),
+        document.documentElement.style.setProperty("--cl", "".concat(n, "px")),
+        ScrollTrigger.refresh();
+    }, 100);
+  };
+  useEffect(() => {
+    window.addEventListener("resize", handlerResize, false);
+    handlerResize();
+  });
 
   return (
     <div ref={container}>
@@ -27,6 +51,9 @@ function App() {
           height={"1300vh"}
           frameCount={300}
           path="lion-render-10fps-873-rev1"
+          pause={{
+            298: 40,
+          }}
         />
       </LazyLoad>
       <LazyLoad height={"400vh"}>

+ 52 - 14
src/components/Viewer.jsx

@@ -1,6 +1,8 @@
 import { Component, createRef } from "react";
 import PropTypes from "prop-types";
-import gsap from "gsap";
+import { gsap, ScrollTrigger } from "gsap/all";
+import styled from "@emotion/styled";
+import { css } from "@emotion/react";
 
 export default class Viewer extends Component {
   constructor() {
@@ -42,6 +44,7 @@ export default class Viewer extends Component {
     enterTween: PropTypes.func,
     exitTween: PropTypes.func,
     canvasSize: PropTypes.array,
+    pause: PropTypes.object,
     children: PropTypes.object,
   };
 
@@ -58,6 +61,10 @@ export default class Viewer extends Component {
       this.initializeTimeline();
       this.setTimeline();
     }
+    if (!this.enterTimeline && this.props.enterTween) {
+      this.initializeEnterTween();
+    }
+    ScrollTrigger.refresh();
   }
 
   loadImage(index) {
@@ -66,6 +73,12 @@ export default class Viewer extends Component {
     img.retried = 0;
     img.src = this.getSourcePath(index);
     img.ogSrc = img.src;
+
+    if (this.props.pause && index + "" in this.props.pause) {
+      for (var r = this.props.pause[index]; r--; ) {
+        this.sequence.push(img);
+      }
+    }
     this.sequence.push(img);
 
     img.onload = () => {
@@ -166,14 +179,16 @@ export default class Viewer extends Component {
       ease: "none",
       onUpdate: () => {
         this.frame = Math.floor(this.floatFrame);
-        if (this.lastFrame === this.frame || this.loadedRenderPool.length) {
+        if (this.lastFrame === this.frame || this.loadedRenderPool.length > 0) {
           this.renderImageToCanvas(this.frame);
         }
       },
     });
   }
 
-  initializeEnterTween() {}
+  initializeEnterTween() {
+    console.log("initializeEnterTween");
+  }
 
   poolNewFrames(index) {
     console.log("poolNewFrames", index);
@@ -214,23 +229,46 @@ export default class Viewer extends Component {
   render() {
     // process props
     this.fullFrameCount = this.props.frameCount;
+    if (this.props.pause) {
+      Object.keys(this.props.pause).forEach((index) => {
+        this.fullFrameCount += this.props.pause[index];
+      });
+    }
+    const Wrapper = styled.div({
+      position: "relative",
+      margin: "auto",
+      textAlign: "center",
+      pointerEvents: "none",
+      maxWidth: "100vw",
+    });
     return (
-      <div ref={this.containerRef}>
-        <div ref={this.viewerRef} style={{ height: this.props.height }}>
+      <>
+        <Wrapper
+          ref={this.containerRef}
+          style={{ height: this.props.height || "500vh" }}
+        >
           <div>{this.props.name}</div>
           <div className="loading-wrap" ref={this.loadingWrap}></div>
-          <div className="canvas-container" ref={this.canvasContainerRef}>
-            <canvas
-              className="sequence-canvas"
-              ref={this.canvasRef}
-              width={500}
-              height={500}
-            ></canvas>
+
+          <div ref={this.viewerRef}>
+            <div style={{ overflow: "hidden" }}>
+              <canvas
+                css={css`
+                  width: auto;
+                  margin-left: 50%;
+                  transform: translateX(-50%);
+                  height: calc(var(--vh, 1vh) * 100);
+                `}
+                ref={this.canvasRef}
+                width={this.width}
+                height={this.height}
+              ></canvas>
+            </div>
           </div>
 
           <>{this.props.children}</>
-        </div>
-      </div>
+        </Wrapper>
+      </>
     );
   }
 }

+ 10 - 37
src/index.css

@@ -5,7 +5,7 @@
 
   color-scheme: light dark;
   color: rgba(255, 255, 255, 0.87);
-  background-color: #242424;
+  background-color: #000;
 
   font-synthesis: none;
   text-rendering: optimizeLegibility;
@@ -21,48 +21,21 @@ a {
 a:hover {
   color: #535bf2;
 }
+* {
+  box-sizing: border-box;
+}
 
+html,
 body {
+  width: 100vw;
+  max-width: 100%;
+  overflow-x: hidden;
+  overflow-y: auto;
   margin: 0;
-  display: flex;
-  place-items: center;
-  min-width: 320px;
-  min-height: 100vh;
+  padding: 0;
 }
 
 h1 {
   font-size: 3.2em;
   line-height: 1.1;
 }
-
-button {
-  border-radius: 8px;
-  border: 1px solid transparent;
-  padding: 0.6em 1.2em;
-  font-size: 1em;
-  font-weight: 500;
-  font-family: inherit;
-  background-color: #1a1a1a;
-  cursor: pointer;
-  transition: border-color 0.25s;
-}
-button:hover {
-  border-color: #646cff;
-}
-button:focus,
-button:focus-visible {
-  outline: 4px auto -webkit-focus-ring-color;
-}
-
-@media (prefers-color-scheme: light) {
-  :root {
-    color: #213547;
-    background-color: #ffffff;
-  }
-  a:hover {
-    color: #747bff;
-  }
-  button {
-    background-color: #f9f9f9;
-  }
-}