Matrix3d动态滚动

问题描述 投票:0回答:1

import React, { useState, useRef } from "react";
import { render } from "react-dom";
import styled from "styled-components";
import { useScrollData } from "scroll-data-hook";

const Menu = () => {
  const ref = useRef('myRef');
  const datas = ["Sao Paulo", "New-York", "Lisbonne", "Milan", "Paris"];
  const { direction } = useScrollData({
    onScrollEnd: () => {
      if (ref.current){
        Array.from(ref.current.children).forEach(el => {
        el.style.transform = `translate3d(0,0,0)`;
        el.style.transition = "transform 1s";
        })
      }
    }
  })

  const setTransformMatrix3d = ( matrix3d ) => {
    if (ref.current){
      Array.from(ref.current.children).forEach(el => {
        el.style.transition = "transform 1s";
        el.style.transform = matrix3d;
      })
    }
  };

  if (direction.y) {
    console.log(direction.y);
    let matrix =
      direction.y === "up"
        ? `matrix3d(1,0.09,0,0,0,1.1,0,0,0,0,1,0,0,0,0,1)`
        : `matrix3d(1,-0.09,0,0,0,1.1,0,0,0,0,1,0,0,0,0,1)`;
    setTransformMatrix3d({ matrix });
  }


  return (
    <Wrapper>
      <Ul ref={ref}>
        {datas.map((value, index) => (
          <Item key={index} value={value} />
        ))}
      </Ul>
    </Wrapper>
  );
};

export default Menu;

const Item = ( {...props} ) => {
  const [isHover, setIsHover] = useState(false);

  return (
    <Li>
      <Link>
        <ContainerMatrix
          onMouseOver={() => setIsHover(!isHover)}
          onMouseLeave={() => setIsHover(!isHover)}
        >
          <ContainerSpan>
            <Span isHover={isHover}>
              { props.value }
              <Mask className="mask" isHover={isHover} dataMask={props.value} />
            </Span>
          </ContainerSpan>
        </ContainerMatrix>
      </Link>
    </Li>
  );
};


const Wrapper = styled.section`
  transition: transform 100ms;
  will-change: transform;
  display: flex;
  flex-direction: column;
  justify-content: center;
  align-content: center;
  align-items: center;
  width: 100vw;
  height: 140vh;
  margin: auto;
  background-color : black;
`

const Link = styled.a`
  text-decoration: none;
  color: inherit;
  background-color: transparent;
`
const Ul = styled.ul`
  display: flex;
  flex-direction: column;
  align-items: center;
  align-content: center;
`

const ContainerMatrix = styled.div`
  transform: translate3d(0px, 0px, 0px);
  transition: transform 100ms;
  will-change: transform;
`

const Li = styled.li`
  transition: transform 2s;
  list-style: none;
  text-transform: uppercase;
`

const ContainerSpan = styled.span`
  position: relative;
  display: inline-block;
  margin: 0;
  color: hsla(0, 0%, 100%, 0.2);
  text-align: center;
  padding: 0 0.15em;
  line-height: 1.15;
  // background-color : red;
`

const Span = styled.span`
  line-height: 1.15;
  font-size: 8.5675vw;
  display: inline-block;
  transform: scaleY(${props => (props.isHover ? "1.1" : "1")}) translateY(${props => (props.isHover ? "-0.1em" : "0em")});
  transition: transform 1.25s cubic-bezier(0.23, 1, 0.32, 1),
    -webkit-transform 1.25s cubic-bezier(0.23, 1, 0.32, 1);
`

const Mask = styled.span.attrs({
  "aria-hidden": "true"
})`
    transform:  translate3d(0, ${props => (props.isHover ? "0%" : "100%")}, 0);
    display: block;
    overflow: hidden;
    transition: transform 1.5s cubic-bezier(.23,1,.32,1),opacity .75s linear,-webkit-transform 1.5s cubic-bezier(.23,1,.32,1);
    will-change: transform,opacity;
    position:absolute;  
    top: 0;
    right: 0;
    bottom: 0;
    left: 0;
    display: block;
    pointer-events: none;


    &::before{
    content: '${props => props.dataMask}';
    transform:  translate3d(0,${props => (props.isHover ? "0%" : "-100%")}, 0);
    color: #fff;
    top: 0;
    right: 0;
    bottom: 0;
    left: 0;
    display: block;
    pointer-events: none;
    transition: opacity .75s linear,-webkit-transform 1.5s cubic-bezier(.23,1,.32,1);
    transition: transform 1.5s cubic-bezier(.23,1,.32,1),opacity .75s linear;
    will-change: transform,opacity;
}
`

这是我关于stackoverflow的第一篇文章。我正在与react一起工作,并且试图在此页面上找到一种(正确的)方法来重现效果:https://www.rudolfson.com/。我已经使字体颜色显示出来了,但是我不知道如何使用在滚动时使用bindind的“ transform:matrix3d”属性在文本容器上重现“波动效果”。自3天以来我一直在努力,但我需要帮助!我认为它使用滚动速度,但我不确定。非常感谢您的回答和建议。

javascript css reactjs css-transitions
1个回答
0
投票

要使之正常工作的粗糙补丁。将变换放在每个li元素上会使事情变得更加困难。只需将其应用到我已修改的外部ul上,就容易得多。

您需要填写高度计算(并替换为-200,代码可能会更干净。但在大多数情况下,它是有效的。我使用了鲁道夫使用的matrix3d作为基础。

此处为codesandbox演示:https://codesandbox.io/s/lucid-sky-hg2of

  const setTransformMatrix3d = matrix => {
    Array.from([ref.current]).map((el, index) => {
      el.style.transition = "transform 1s";
      el.style.transform = matrix;
    });
  };

  if (direction.y) {
    console.log(direction.y);
    let matrix =
      direction.y === "up"
        ? `matrix3d(1, 0.000174533, 0, 0, -0.000174533, 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1)`
        : `matrix3d(1, 0.000174533, 0, 0, -0.000174533, 1, 0, 0, 0, 0, 1, 0, 0, -200, 0, 1)`;
    setTransformMatrix3d(matrix);
  }

  useEffect(() => {
    window.addEventListener("scroll", setTransformMatrix3d);
    return () => {
      window.removeEventListener("scroll", setTransformMatrix3d);
    };
  }, []);
© www.soinside.com 2019 - 2024. All rights reserved.