import { Component, createRef, useRef, useEffect } from "react"; import gsap from "gsap"; import PropTypes from "prop-types"; import { Action } from "../action"; import { css } from "@emotion/react"; import styled from "@emotion/styled"; import { Style } from "../style/section"; export function TimeLineTransText(props) { const containerRef = useRef(); const from = props.from || { autoAlpha: 0, y: 100, }; const start = props.start || "top bottom"; const end = props.end || "top center+=10%"; useEffect(() => { gsap.from( containerRef.current, Object.assign( from, {}, { scrollTrigger: { scrub: 0.2, trigger: containerRef.current, start: start, end: end, }, } ) ); }); return
{props.children}
; } TimeLineTransText.propTypes = { start: PropTypes.string, end: PropTypes.string, from: PropTypes.object, children: PropTypes.any, }; export function ButtonText(props) { const containerRef = useRef(); const contentRef = useRef(); const ButtonRef = useRef(); let isOpen = false; useEffect(() => { gsap.set(contentRef.current, { autoAlpha: 0, }); }); const handlerClick = () => { if (!isOpen) { gsap.to(contentRef.current, { autoAlpha: 1, }); isOpen = true; ButtonRef.current.classList.add("open"); ButtonRef.current.innerText = "x"; } else { gsap.to(contentRef.current, { autoAlpha: 0, }); isOpen = false; ButtonRef.current.innerText = "+"; ButtonRef.current.classList.remove("open"); } }; const Warpper = styled.div` display: flex; position: relative; align-items: center; margin-top: 12px; z-index: 10; `; const ButtonWrapper = styled.button` appearance: none; position: relative; font-size: 10px; border: none; margin: 0; align-self: start; outline: none; padding: 0; color: #000; background-color: transparent; height: 20px; width: 20px; min-width: 20px; border-radius: 2px; cursor: pointer; opacity: 1; pointer-events: all; &:before, &:after { content: ""; position: absolute; background-color: hsla(0, 0%, 100%, 0.8); transition: transform 0.25s ease-out; } &.open { &:before { transform: rotate(90deg); } &:after { transform: rotate(180deg); } } &:after { top: 50%; left: 0; width: 100%; height: 4px; margin-top: -2px; } &:before { top: 0; left: 50%; width: 4px; height: 100%; margin-left: -2px; } `; const TextWrapper = styled.div` margin-left: 10px; margin-right: 10px; font-size: 12px; `; return ( + {props.children} ); } ButtonText.propTypes = { content: PropTypes.string, children: PropTypes.any, }; export function TimeLineLabelText(props) { 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 trigger = props.trigger || Action.scrubPin; const keyframes = [ 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-TimeLineLabelText", keyframes); return (
{props.children}
); } export function TimeLineWallText(props) { const progressPosition = void 0 !== props.progressPosition ? props.progressPosition : 0.5; const fade = props.fade || 0.025; const duration = props.duration || 0.05; const verticalOffset = props.verticalOffset || "46.5vh"; const trigger = props.trigger || Action.scrubPin; const keyframes = [ Object.assign({}, Action.fadeIn, { start: progressPosition, end: progressPosition + fade, }), Object.assign({}, Action.fadeOut, { start: progressPosition + duration + fade, end: progressPosition + duration + fade + fade, }), ]; // console.log("keyframes-TimeLineWallText", keyframes); return ( {props.children} ); } export function TimeLineTitleText(props) { const verticalOffset = props.verticalOffset || "100vh"; const trigger = props.trigger || Action.scrubPin; return ( ); } class TimeLineText extends Component { constructor(props) { super(); this.containerRef = createRef(); this.timeline = null; this.top = 0; this.progress = 0; this.keyframes = []; this.trigger = false; this.init(props); } init(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) { this.timeline.kill(true); this.timeline = false; } } componentDidMount() { if (this.props.keyframes && this.props.trigger) { this.createTimeLine(); } } setTop(height) { const parentHeight = parseFloat(this.props.parentHeight); const lastHeight = ((height * window.innerHeight * ((parentHeight - 100) / 100)) / ((window.innerHeight * parentHeight) / 100)) * 100; 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; const lastStart = this.props.keyframes[this.props.keyframes.length - 1].start; const lastEnd = this.props.keyframes[this.props.keyframes.length - 1].end; const lDif = lastEnd - lastStart; const gapDiff = lastStart - end; const timeRes = (lastEnd - start) * (parseFloat(this.props.parentHeight) - 100); const flag = `+=${timeRes}%`; console.log("timeRes", flag); this.timeline = gsap.timeline({ scrollTrigger: Object.assign( { trigger: this.containerRef.current, start: "top top", end: flag, }, this.props.trigger ), }); for (var i = 0; i < this.props.keyframes.length; i += 1) { const cFrame = this.props.keyframes[i]; if (1 === i && gapDiff > 0.001) { this.timeline.to(this.containerRef.current, { duration: gapDiff, }); } if (cFrame.type === "set") { this.timeline.set( this.containerRef.current, Object.assign({}, cFrame.animation) ); } if (cFrame.type === "from") { this.timeline.from( this.containerRef.current, Object.assign({}, cFrame.animation, { duration: dif, }) ); } if (cFrame.type === "to") { this.timeline.to( this.containerRef.current, Object.assign(cFrame.animation, { duration: lDif, }) ); } } } } render() { const marginTop = "calc(var(--vh, 1vh) *" + parseFloat(this.props.verticalOffset) + ")"; return (
{this.props.children}
); } } TimeLineText.propTypes = { verticalOffset: PropTypes.string, children: PropTypes.any, trigger: PropTypes.object, parentHeight: PropTypes.string, keyframes: PropTypes.arrayOf(PropTypes.object), progressPosition: PropTypes.number, }; TimeLineText.defaultProps = { verticalOffset: "100vh", }; TimeLineTitleText.propTypes = { ...TimeLineText.propTypes, }; TimeLineLabelText.propTypes = { ...TimeLineText.propTypes, }; TimeLineWallText.propTypes = { ...TimeLineText.propTypes, };