gsap 基本使用及各种效果

这里的html样式都是基于tailwindcss上的样式,但是大概大家都能明白咋回事儿,不懂随时给我留言,欢迎大家互相交流学习,最近时间比较紧,有时间把例子都整到codepen上,大家看着就更方便了,gsap真是个好框架,大家一起学习吧

gsap.registerEffect

文字生成器演示1

html

<h1 class="text-6xl pb-5 opacity-0">开始懂了</h1>
<h2 class="text-2xl opacity-0">快乐是选择</h2>

js

gsap.registerEffect({
  name: 'tweenText',
  // 集成到timeline上
  extendTimeline: true,
  // 默认参数
  defaults: {
    y: -100,
    opacity: 0,
    colors: ['blue', 'pink', 'green']
  },
  effect: (targets: any, config: any) => {
    let split = new SplitText(targets, {type: 'chars'});
    let chars = split.chars;
    // 初始设为可视
    gsap.set(targets, {opacity: 1});
    return gsap.timeline().from(chars, {
      opacity: config.opacity,
      y: config.y,
      stagger: 0.05,
      duration: .5,
    }).to(chars, {
      color: gsap.utils.wrap([...config.colors])
    }, 0);
  }
});

// 调用方法
gsap.timeline().tweenText('h1').tweenText('h2', {y: 50}, 0);

其他文字的一些效果整理

文字生成器演示2
文字生成器演示3
文字生成器演示4
文字生成器演示5

gsap.registerEffect({
  name: 'slideIn',
  extendTimeline: true,
  defaults: {
    y: 0,
    x: 0,
    duration: 1,
    ease: 'power1'
  },
  effect: (targets: any, config: any) => {
    gsap.set(config.parent, {perspective: 300});
    let tl: gsap.core.Timeline = gsap.timeline()
        .from(targets, {duration: config.duration, x: config.x, y: config.y, transformOrigin: config.transformOrigin, ease: config.ease, stagger: {each: 0.03, ease: 'power1'}})
        .from(targets, {duration: config.duration, opacity: 0, ease: 'none', stagger: {each: 0.03, ease: 'power2' }}, 0)
    return tl;
  }
});
gsap.registerEffect({
  name: 'slideOut',
  extendTimeline: true,
  defaults: {
    y: 0,
    x: 0,
    duration: 0.5,
    ease: 'power1.in'
  },
  effect: (targets: any, config: any) => {
    gsap.set(config.parent, {perspective: 300});
    let tl: gsap.core.Timeline = gsap.timeline()
        .to(targets, {duration: config.duration, x: config.x, y: config.y, transformOrigin: config.transformOrigin, ease: config.ease, stagger: {each: 0.03, ease: 'power1'}})
        .to(targets, {duration: config.duration, opacity: 0, ease: 'none', stagger: {each: 0.01, ease: 'power2' }}, 0)
    return tl;
  }
});

gsap.registerEffect({
  name: 'twistIn',
  extendTimeline: true,
  defaults: {
    duration: 1,
    rotationX: 0,
    rotationY: 0,
    transformOrigin: '50% 50%',
    ease: 'back',
    parent: 'body'
  },
  effect: (targets: any, config: any) => {
    // gsap.set(targets, {transformPerspective: 300});
    gsap.set(config.parent, {perspective: 300});
    let tl: gsap.core.Timeline = gsap.timeline()
        .from(targets, {duration: config.duration, rotationX: config.rotationX, rotationY: config.rotationY, transformOrigin: config.transformOrigin, ease: config.ease, stagger: {each: 0.05}})
        .from(targets, {duration: 0.4, opacity: 0, ease: 'none', stagger: {each: 0.05 }}, 0)
    return tl;
  }
});

gsap.registerEffect({
  name: 'twistOut',
  extendTimeline: true,
  defaults: {
    rotationX: 0,
    rotationY: 0,
    transformOrigin: '50% 50%',
    ease: 'power1.in',
    parent: 'body'
  },
  effect: (targets: any, config: any) => {
    gsap.set(config.parent, {perspective: 300});
    let tl: gsap.core.Timeline = gsap.timeline()
        .to(targets, {duration: 0.5, rotationX: config.rotationX, rotationY: config.rotationY, transformOrigin: config.transformOrigin, ease: config.ease, stagger: {each: 0.01}})
        .to(targets, {duration: 0.3 , opacity: 0, ease: 'none', stagger: {each: 0.01 }}, '-=0.2')
    return tl;
  }
});


gsap.registerEffect({
  name: 'in',
  extendTimeline: true,
  defaults: {
    duration: 0.5,
    fade: 0.5,
    y: 0,
    x: 0,
    rotationX: 0,
    rotationY: 0,
    scale: 1,
    transformOrigin: '50% 50%',
    perspective: 400,
    ease: 'power1',
    each: 0.05,
    staggerEase: 'power1.in',
    from: 'start'
  },
  effect: (targets: any, config: any) => {
    if (config.rotationX != 0 || config.rotationY != 0) {
      let currentNode = targets[0];
      gsap.set(currentNode.parentNode, {
        perspective: config.perspective
      });
    }

    let tl: gsap.core.Timeline = gsap.timeline()
        .from(targets, {
          duration: config.duration,
          ease: config.ease,
          x: config.x,
          y: config.y,
          scale: config.scale,
          transformOrigin: config.transformOrigin,
          rotationY: config.rotationY,
          rotationX: config.rotationX,
          stagger: {
            each: config.each,
            ease: config.staggerEase,
            from: config.from
          }
        })
        .from(targets, {
          duration: config.fade,
          opacity: 0,
          ease: 'none',
          stagger: {
            each: config.each,
            ease: config.staggerEase,
            from: config.from
          }
        }, 0 )
    return tl;
  }
});
gsap.registerEffect({
  name: 'out',
  extendTimeline: true,
  defaults: {
    duration: 0.5,
    fade: 0.5,
    y: 0,
    x: 0,
    rotationX: 0,
    rotationY: 0,
    scale: 1,
    transformOrigin: '50% 50%',
    perspective: 400,
    ease: 'power1',
    each: 0.05,
    staggerEase: 'power1.in',
    from: 'start'
  },
  effect: (targets: any, config: any) => {
    if (config.rotationX != 0 || config.rotationY != 0) {
      let currentNode = targets[0];
      gsap.set(currentNode.parentNode, {
        perspective: config.perspective
      });
    }
    let tl: gsap.core.Timeline = gsap.timeline()
        .to(targets, {
          duration: config.duration,
          ease: config.ease,
          x: config.x,
          y: config.y,
          scale: config.scale,
          transformOrigin: config.transformOrigin,
          rotationY: config.rotationY,
          rotationX: config.rotationX,
          stagger: {
            each: config.each,
            ease: config.staggerEase,
            from: config.from
          }
        })
        .to(targets, {
          duration: config.fade,
          opacity: 0,
          ease: 'none',
          stagger: {
            each: config.each,
            ease: config.staggerEase,
            from: config.from
          }
        }, 0 )
    return tl;
  }
});


gsap.registerEffect({
  name: 'jelly',
  extendTimeline: true,
  defaults: {
    stagger: 0.03,
    duration: 0.8
  },
  effect: (target: any, config: any) => {
    gsap.set(target, {transformOrigin: '50% 50%'})
    let tl:gsap.core.Timeline = gsap.timeline({delay: 0.5})
        .from(target, {scale: 0.8, duration: config.duration, stagger: config.stagger, ease: 'elastic'})
        .from(target, {opacity: 0, duration: 0.01, stagger: config.stagger}, 0)
    return tl;
  }
});

gsap.registerEffect({
  name: 'burnIn',
  extendTimeline: true,
  defaults: {
    x: 0,
    y: 0,
    duration: 0.5,
    ease: 'none'
  },
  effect: (targets: any, config: any) => {
    gsap.set(targets, {filter: 'blur(0px) brightness(1)'})
    let tl: gsap.core.Timeline = gsap.timeline()
        .from(targets, {filter: 'blur(20px) brightness(8)', scale: 0.8, rotation: -10, duration: config.duration, ease: config.ease, x: config.x, y: config.y, clearProps: 'filter', stagger: {each: 0.02, ease: 'none'}})
        .from(targets, {duration: 0.1, opacity: 0, ease: 'none', stagger: {each: 0.02, ease: 'power2'}}, 0);
    return tl;
  }
});

gsap.registerEffect({
  name: 'burnOut',
  extendTimeline: true,
  defaults: {
    x: 0,
    y: 0,
    duration: 0.3,
    ease: 'none'
  },
  effect: (targets: any, config: any) => {
    gsap.set(targets, {filter: 'blur(0px) brightness(1)'})
    let tl: gsap.core.Timeline = gsap.timeline()
        .to(targets, {filter: 'blur(20px) brightness(8)', scale: 0.3, rotation: 10, duration: config.duration, ease: config.ease, x: config.x, y: config.y, clearProps: 'filter', stagger: {each: 0.01, ease: 'none'}})
        .to(targets, {duration: .2, opacity: 0, ease: 'none', stagger: {each: 0.01, ease: 'power2'}}, 0);
    return tl;
  }
});

// 参数配置out
gsap.registerEffect({
  name: 'randomFade',
  extendTimeline: true,
  defaults: {
    x: 0,
    y: 0,
    duration: 1,
    ease: 'power1',
    scale: 1,
    direction: 'in'
  },
  effect: (targets: any, config: any) => {
    let tl = gsap.timeline();
    if (config.direction === 'in') {
      tl.from(targets, {opacity: 0, duration: config.duration, ease: config.ease, x: config.x, y: config.y, scale: config.scale, stagger: {each: 0.01, from: 'random'}})
    } else {
       tl.to(targets, {opacity: 0, duration: 0.5, ease: config.ease, x: config.x, y: config.y, scale: config.scale, stagger: {each: 0.01, from: 'random'}})
    }
    return tl;
  }
});

3d双面翻转

双面翻转效果演示

html

/**
* transform-style: preserve-3d; 3d元素的子元素保留3d空间
* backface-visibility: hidden;设置完上面这句就有效了
*/

<div class="trans w-10 bg-red-800 h-10 relative" style="transform-style: preserve-3d;">
    <div class="bg-green-400 absolute inset-0" style="backface-visibility: hidden;"></div>
</div>

js

  let animation = gsap.timeline();
  gsap.set('.trans', {
    transformPerspective: 200 // 设置后才能有3d效果,非常重要
  });
  animation.to('.trans', {
    rotateY: 360,
    duration: 1,
    stagger: 0.2
  });

gsap.utils.distribute()

html

<div class="bg-black flex justify-between items-end h-96">
  <div class="bg-green-800 w-2 h-96 bar trans"></div>
  <div class="bg-green-800 w-2 h-96 bar trans"></div>
  <div class="bg-green-800 w-2 h-96 bar trans"></div>
  ******
  <div class="bg-green-800 w-2 h-96 bar trans"></div>
  <div class="bg-green-800 w-2 h-96 bar trans"></div>
  <div class="bg-green-800 w-2 h-96 bar trans"></div>
</div>

js

  gsap.set('.bar', {
    transformOrigin: '50% 100%'
  })
  gsap.set('.bar', {
    scaleY: gsap.utils.distribute({
      base: -1,
      amount: 2,
      ease: 'power4',
      // from: 'edges'
    })
  })

胶囊文字效果

html

<div class="text-center pt-20">
      <span class="myEnglish text-2xl">abcdefghijklmnopqrst</span>
    </div>

js

let split = new SplitText('.myEnglish', {type: 'chars'});
let chars = split.chars;

let animation = gsap.timeline();
animation.from(chars, {
    opacity: 0,
    scale:gsap.utils.distribute({
        base: 0.2,
        amount: 4,
        ease: 'power',
        from: 'center'
    }),
    x: gsap.utils.distribute({// [-200,-199, ... 199, 200]
        base: -200,
        amount: 400,
    }),
    stagger: {
        each: 0.01,
        from: 'center'
    },
    yoyo: true,
    repeat: -1
});

3D翻转文字效果

html

<div class="hasText bg-gray-200 h-80 text-2xl relative opacity-0 font-extrabold w-96">
  <div class="absolute w-full text-center left-0 top-32">我爱上让我奋不顾身的一个人</div>
  <div class="absolute w-full text-center left-0 top-32">我以为这就是我所追求的世界</div>
  <div class="absolute w-full text-center left-0 top-32">然而横冲直撞</div>
  <div class="absolute w-full text-center left-0 top-32">被误解被骗</div>
  <div class="absolute w-full text-center left-0 top-32">是否成人的世界背后总有残缺</div>
</div>

js 连贯翻转无缝隙


const textArray = ['我爱上让我奋不顾身的一个人', '我以为这就是我所追求的世界', '然而横冲直撞', '被误解被骗', '是否成人的世界背后总有残缺'];

onMounted(() => {
  let duration = 0.5;
  let delay = 2;
  let stagger = duration + delay;
  let allDelay = (textArray.length - 1) * stagger + delay;
  textTransTop(duration);
  function textTransTop(duration: number) {
    let animation = gsap.timeline();
    
    gsap.set('.hasText', {
      // transformPerspective:200,
      perspective: 200,
      autoAlpha: 1
    });
    gsap.set('.hasText div', {
      transformOrigin: '50% 50% -50'
    });
    animation.from('.hasText div', {
      rotationX: -90,
      rotationY: -45,
      y: 30,
      duration: duration,
      opacity: 0,
      stagger: {
        each: stagger,
        repeat: -1,
        repeatDelay: allDelay
      }
    }).to('.hasText div', {
      rotationX: 90,
      rotationY: 45,
      y: -30,
      opacity: 0,
      duration: duration,
      stagger: {
        each: stagger,
        repeat: -1,
        repeatDelay: allDelay
      }
    }, stagger);

    GSDevTools.create({animation})
  }

});

stagger交错运动

html

    <div class="border-2 bg-gray-50 w-96 h-96 flex justify-around rollBall">
      <div class="w-10 h-10 rounded-full bg-emerald-900"></div>
      <div class="w-10 h-10 rounded-full bg-red-800"></div>
      <div class="w-10 h-10 rounded-full bg-emerald-900"></div>
      <div class="w-10 h-10 rounded-full bg-red-800"></div>
      <div class="w-10 h-10 rounded-full bg-emerald-900"></div>
      <div class="w-10 h-10 rounded-full bg-red-800"></div>
      <div class="w-10 h-10 rounded-full bg-emerald-900"></div>
      <div class="w-10 h-10 rounded-full bg-red-800"></div>
    </div>

js

  gsap.to('.rollBall div', {
    y: 80,
    stagger: {
      each: .5,
      yoyo: true,
      repeat: -1
    }
  })

labels

html

    <div class="bg-black py-10 flex justify-around">
      <div class="box b0 red w-20 h-20 bg-red-800">1</div>
      <div class="box b1 red w-20 h-20 bg-green-400">2</div>
      <div class="box b2 red w-20 h-20 bg-amber-200">3</div>
      <div class="box b3 red w-20 h-20 bg-pink-900">4</div>
    </div>
    <div class="dotNav bg-gray-800 py-10 flex justify-around">
      <div v-for="(item, key) in dots" :key="key" class="dot w-5 h-5 cursor-pointer rounded-full bg-fuchsia-500 border-4 border-amber-800" @click="playTlFn(item.name)"></div>
    </div>
    <div class="nav text-center pt-10">
      <button id="prev" class="px-8 py-4 rounded-xl bg-pink-900 mr-5 text-white">prev</button>
      <button id="next" class="px-8 py-4 rounded-xl bg-pink-900 mr-5 text-white">next</button>
    </div>

js

type BaseObject = {name: string, time: number};
let dots = ref<BaseObject[]>([]);
let playTlFn;

onMounted(() => {
  let tl = gsap.timeline({paused: false, repeat: -1, defaults: {rotation: 180, opacity: 0, duration: 0.4}});
  tl
      .add('b0')
      .from('.b0', {
        rotation: -180})
      .addPause()
      .to('.b0', {})
      .add('b1')
      .from('.b1', {
        rotation: -180
      })
      .addPause()
      .to('.b1', {})
      .add('b2')
      .from('.b2', {
        rotation: -180
      })
      .addPause()
      .to('.b2', {})
      .add('b3')
      .from('.b3', {
        rotation: -180
      })
      .addPause()
      .to('.b3', {});
  // tl.tweenFromTo('b3', 'b0');

  console.log(tl.labels);
  const getLabelsArray = (tl: gsap.core.Timeline) => Object.keys(tl.labels).map(v => ({name: v, time: tl.labels[v]})).sort((a, b) => (a.time - b.time));
  const labels = getLabelsArray(tl);
  dots.value.push(...labels);
  console.log(labels);
  playTlFn = (name: string) => {
    tl.play(name);
  }

  next.addEventListener('click', () => tl.play());
  prev.addEventListener('click', () => tl.reverse());
});

时间线、tweenTo、 tweenFromTo

html

    <div class="bg-black py-10 flex justify-around h-80 relative">
      <div class="box0 b0 red w-20 h-20 bg-red-800">1</div>
      <div class="box1 b1 red w-20 h-20 bg-green-400">2</div>
      <div class="box2 b2 red w-20 h-20 bg-amber-200">3</div>
      <div class="bot flex items-center justify-center h-20 absolute left-0 w-full bottom-0 text-white">
        <div class="botSub0 text-6xl pr-4">
          <Icon name="logos:airtable"/>
        </div>
        <div class="botSub1 text-2xl whitespace-nowrap">asdfasdf</div>
      </div>
    </div>

js

function midTl(text: string):gsap.core.Timeline {
  gsap.set(['.botSub0', '.botSub1'], {
    y: 100
  });
  let tl = gsap.timeline()
      .set('.botSub1',{
        innerText: text
      })
      .to(['.botSub0', '.botSub1'], {
        y: 0,
        yoyo: true,
        repeat: 1,
        stagger: .2
      })
  return tl;
}

onMounted(() => {
  let redAni = gsap.timeline()
      .to('.box0', {y: 100})
      .to('.box0', {rotation: 360})
      .to('.box0', {y: 0});
  let greenAni = gsap.timeline()
      .to('.box1', {y: -100})
      .to('.box1', {rotation: 360})
      .to('.box1', {y: 0});
  let amberAni = gsap.timeline()
      .to('.box2', {scale: 2})
      .to('.box2', {rotation: 360})
      .to('.box2', {scale: 1});

  let master = gsap.timeline()
      // redAni 执行2次
      .add(redAni.tweenTo(redAni.duration(), {repeat: 1}))
      .add(midTl('什么情况!'))
      .add(greenAni)
      .add(midTl('想多了!'))
      .add(amberAni)
      .add(midTl('redAni 再执行1次!'))
      // 再次执行要用fromTo
      .add(redAni.tweenFromTo(0, redAni.duration()))

});

曲线轮播效果

html

    <div class="bg-black flex relative w-72 h-72">
      <div class="panel panel1 flex flex-col items-center w-72 h-72 justify-center absolute opacity-0">
        <Icon name="logos:webstorm" class="text-6xl icon" />
        <h4 class="text-2xl pt-10 text-cyan-500"><span class="text-amber-500 leftText inline-block relative">logos</span><span class="textRight pl-4 inline-block relative">webstorm</span></h4>
      </div>
      <div class="panel panel2 flex flex-col items-center w-72 h-72 justify-center absolute opacity-0">
        <Icon name="logos:intellij-idea" class="text-6xl icon" />
        <h4 class="text-2xl pt-10 text-cyan-500"><span class="text-amber-500 leftText inline-block relative">logos</span><span class="textRight inline-block relative pl-4">intellij-idea</span></h4>
      </div>
      <div class="panel panel3 flex flex-col items-center w-72 h-72 justify-center absolute opacity-0">
        <Icon name="logos:clion" class="text-6xl icon" />
        <h4 class="text-2xl pt-10 text-cyan-500"><span class="text-amber-500 leftText inline-block relative">logos</span><span class="textRight inline-block relative pl-4">clion</span></h4>
      </div>
      <div class="panel panel4 flex flex-col items-center w-72 h-72 justify-center absolute opacity-0">
        <svg width="126px" height="120px" viewBox="0 0 126 120" version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
          <polygon id="down" fill="#FFFFFF" points="63 0 125.76973 45.6048784 101.793827 119.395122 24.2061733 119.395122 0.230269925 45.6048784"></polygon>
          <polygon id="up" fill="#EE4242" points="63.2129032 44.283871 102.697088 72.9708106 87.6154716 119.387254 38.8103348 119.387254 23.7287182 72.9708106"></polygon>
        </svg>
        <h4 class="panelText text-2xl top-24 text-cyan-500 ts w-full absolute text-center"><span class="text-amber-500 leftText inline-block relative">down</span><span class="textRight inline-block relative"> ####</span></h4>
      </div>
    </div>

js

function commonAnimate(panel: string) {
  let tl:gsap.core.Timeline = gsap.timeline()
      .set(panel, {opacity: 1})
      .from(`${panel} .icon`, {x: -180})
      .from(`${panel} .icon`, {
        y: 50,
        ease: 'power1.out'
      }, '<')
      .from(`${panel} .icon`, {
        opacity: 0,
        duration: .2
      }, '<')
      .from(`${panel} .leftText`, {
        x: -100,
        duration: 0.3
      },'-=0.3')
      .from(`${panel} .textRight`, {
        x: 100,
        duration: 0.3
      },'-=0.3')
      .from([`${panel} .leftText`, `${panel} .textRight`], {
        opacity: 0,
        duration: 0.2
      },'-=0.3')
      .to(`${panel} .icon`, {x: 180, delay: 1})
      .to(`${panel} .icon`, {
        y: 50,
        ease: 'power1.in'
      }, '<')
      .to(`${panel} .icon`, {
        opacity: 0,
        duration: .2
      }, '-=0.2')
      .to([`${panel} .leftText`, `${panel} .textRight`], {
        opacity: 0,
        y: 50,
        duration: 0.2
      },'-=0.3')
  return tl;
}
onMounted(() => {
  const downAni = gsap.timeline()
      .set('.panel4', {
        opacity: 1,
      })
      .from('.panel4 .panelText', {
        y: -124,
        ease: 'power1.in'
      })
      .to('#down', {
        attr: {
          points: '63.2129032 44.283871 102.697088 72.9708106 87.6154716 119.387254 38.8103348 119.387254 23.7287182 72.9708106'
        },
        ease: 'power1.in',
        duration: 0.2
      }, '-=0.2');

  let master = gsap.timeline({repeat: -1, repeatDelay: 2})
      .add(commonAnimate('.panel1'))
      .add(commonAnimate('.panel2'), '-=.2')
      .add(commonAnimate('.panel3'), '-=.2')
      // .add('myLabel')
      .add(downAni);
  // master.play('myLabel')

  // GSDevTools.create({animation: master})
});

keyframes 关键帧

html

    <div class="p-20 bg-black flex justify-evenly">
      <div class="ball w-10 h-10 rounded-full bg-green-400"></div>
      <div class="ball w-10 h-10 rounded-full bg-red-400"></div>
      <div class="ball w-10 h-10 rounded-full bg-green-400"></div>
      <div class="ball w-10 h-10 rounded-full bg-red-400"></div>
      <div class="ball w-10 h-10 rounded-full bg-green-400"></div>
    </div>

js

let animation = gsap.timeline({defaults: {duration: .5, ease: 'none', repeat: -1}});
animation.to('.ball', {
keyframes: [
  {y: gsap.utils.wrap([100, -100])},
  {y: gsap.utils.wrap([-100, 100]), duration: 1},
  {y: 0}
]
})
  • 12
    点赞
  • 7
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值