最新消息:雨落星辰是一个专注网站SEO优化、网站SEO诊断、搜索引擎研究、网络营销推广、网站策划运营及站长类的自媒体原创博客

javascript - useMotionValueEvent not working on motion react - Stack Overflow

programmeradmin6浏览0评论

I just discovered motion for react (previously framer motion) and I just started learning it. I've gotten a hold of the basic syntax from the docs to make some simple animations. I'm working with useMotionEvent. But I'm not sure I totally get the concept, because I've been trying to replicate this "Track element scroll offset" on the docs. /docs/react-scroll-animations,

I've gotten the scrollXprogress to work, but I'm not totally getting the function with the maskimg to work. It's supposed to give a fade gradient animation to the left or right depending on whether you've scrolled to the end or start or middle of the container.
The code on the docs is mostly using typescript and I'm not familiar with that. I use reactJS

This is what I've been able to do so far.

import React, { useRef } from "react";
import {
  animate,
  motion,
  useMotionValue,
  useMotionValueEvent,
  useScroll,
} from "motion/react";

const ScrollXBox = () => {
  const left = `0%`;
  const right = `100%`;
  const leftInset = `20%`;
  const rightInset = `80%`;
  const transparent = `#0000`;
  const opaque = `#000`;

  function useScrollOverflowMask(scrollXProgress) {
    const maskImage = useMotionValue(
      `linear-gradient(90deg, ${opaque}, ${opaque} ${left}, ${opaque} ${rightInset}, ${transparent})`
    );

    useMotionValueEvent(scrollXProgress, "change", (value) => {
      if (value === 0) {
        animate(
          maskImage,
          `linear-gradient(90deg, ${opaque}, ${opaque} ${left}, ${opaque} ${rightInset}, ${transparent})`
        );
      } else if (value === 1) {
        animate(
          maskImage,
          `linear-gradient(90deg, ${transparent}, ${opaque} ${leftInset}, ${opaque} ${right}, ${opaque})`
        );
      } else if (
        scrollXProgress.getPrevious() === 0 ||
        scrollXProgress.getPrevious() === 1
      ) {
        animate(
          maskImage,
          `linear-gradient(90deg, ${transparent}, ${opaque} ${leftInset}, ${opaque} ${rightInset}, ${transparent})`
        );
      }
    });

    return maskImage;
  }

  const elements = ["A", "B", "C", "D"];
  const colors = [
    "bg-red-800",
    "bg-yellow-600",
    "bg-green-900",
    "bg-purple-900",
  ];

  const ref = useRef(null);
  const { scrollXProgress } = useScroll({ container: ref });
  const maskImage = useScrollOverflowMask(scrollXProgress);

  return (
    <div className="scroll-x h-screen flex flex-col justify-center items-center gap-4 bg-violet-400">
      <div id="example">
        <svg id="progress" width="80" height="80" viewBox="0 0 100 100">
          <circle
            cx="50"
            cy="50"
            r="40"
            pathLength="1"
            style={{ fill: "none", stroke: "red", strokeWidth: 20 }}
          />
          <motion.circle
            cx="50"
            cy="50"
            r="40"
            style={{
              fill: "none",
              stroke: "yellow",
              strokeWidth: 10,
              pathLength: scrollXProgress,
            }}
          />
        </svg>
        <div
          ref={ref}
          className="element-container overflow-x-scroll w-96 flex gap-4"
          style={{
            WebkitMaskImage: maskImage.get(),
            maskImage: maskImage.get(),
          }}
        >
          {elements.map((element, index) => (
            <motion.ul key={index} className="flex-shrink-0">
              <li>
                <div className={`${colors[index]} w-64 h-64`}></div>
              </li>
            </motion.ul>
          ))}
        </div>
      </div>
    </div>
  );
};

export default ScrollXBox;

I tried using the .get() function with the maskImg but it only gets the value declared

发布评论

评论列表(0)

  1. 暂无评论