碉堡了,基于HTML5 WebGL的图像扭曲变形动画开源特效

  • 2019 年 10 月 6 日
  • 筆記

简要说明

这是一款基于HTML5 WebGL的图像扭曲变形动画特效。该特效中,通过Three.js来制作从一幅缩略图,扭曲变形为全屏大图的动画特效,共有6种炫酷的动画效果。

该特效提供了一个控制面板来控制图像扭曲的动画,你可以自行调节效果。

实现方法

HTML结构

<div id="app"></div>  <div id="itemsWrapper">      <figure class="grid__item">          <img class="grid__item-img" src="img/1.jpg" alt="An image" />          <img class="grid__item-img grid__item-img--large" src="img/1_large.jpg" />          <figcaption class="grid__item-caption">              <h2 class="grid__item-title">Our Item Title</h2>              <p class="grid__item-text">                  Our Item Description              </p>          </figcaption>      </figure>      ...  </div>

引入base.css

#cdawrap .carbon-text {      --cda-text-color: #aba1a6;      padding: 0.25rem 0 0.75rem;      display: block;      line-height: 1.4;      font-weight: 700;      font-weight: var(--cda-text-weight);      text-decoration: none;      text-transform: none;      letter-spacing: 0px;      border: 0;  }    body #cdawrap {          --cda-left: 2rem;      --cda-right: auto;      --cda-top: auto;      --cda-bottom: 6rem;      z-index: 1;  }    *,  *::after,  *::before {          box-sizing: border-box;  }    :root {          font-size: 15px;  }    body {          margin: 0;          --color-text: #615d5d;      --color-bg: #121217;      --color-link: #aba1a6;      --color-link-hover: #fff;      --color-info: #f58a4e;          color: var(--color-text);          background-color: var(--color-bg);          font-family: -apple-system, BlinkMacSystemFont, Segoe UI, Helvetica, Arial, sans-serif;          font-weight: 600;          -webkit-font-smoothing: antialiased;          -moz-osx-font-smoothing: grayscale;          overflow: hidden;  }    .dg .title {      transition: background-color 300ms ease-out;  }    .shine {          transition: background-color 100ms ease-out !important;      background-color: #fff !important;  }    #app {          top: 0;          left: 0;          position: fixed;          width: 100vw;          height: 100vh;          overflow: hidden;  }    #app:hover {          cursor: pointer;  }    .dg.ac {          z-index: 99999 !important;  }    /* Page Loader */  .js .loading::before {          content: '';          position: fixed;          z-index: 100000;          top: 0;          left: 0;          width: 100%;          height: 100%;          background: var(--color-bg);  }    .js .loading::after {          content: '';          position: fixed;          z-index: 100000;          top: 50%;          left: 50%;          width: 60px;          height: 60px;          margin: -30px 0 0 -30px;          pointer-events: none;          border-radius: 50%;          opacity: 0.4;          background: var(--color-link);          animation: loaderAnim 0.7s linear infinite alternate forwards;  }    @keyframes loaderAnim {          to {                  opacity: 1;                  transform: scale3d(0.5,0.5,1);          }  }    a {          text-decoration: none;          color: var(--color-link);          outline: none;  }    a:hover,  a:focus {          color: var(--color-link-hover);          outline: none;  }    .frame {          padding: 3rem 5vw;          text-align: center;          position: relative;          z-index: 1000;  }    .frame__title {          font-size: 1rem;          margin: 0 0 1rem;  }    .frame__tagline {          color: var(--color-info);  }    .frame__links {          display: inline;  }    .frame a {          text-transform: lowercase;  }    .frame__links a:not(:last-child),  .frame__demos a:not(:last-child) {          margin-right: 1rem;  }    .frame__demos {          margin: 1rem 0;  }    .frame__demo--current,  .frame__demo--current:hover {          color: var(--color-text);  }    .content {          display: flex;          flex-direction: column;          width: 100vw;          height: calc(100vh - 13rem);          position: relative;          justify-content: flex-start;          align-items: center;  }    .content__img {          width: 500px;          max-width: 100%;          display: block;          cursor: pointer;  }    .content__img--large {          pointer-events: none;          position: fixed;          opacity: 0;  }    @media screen and (min-width: 53em) {          .frame {                  position: fixed;                  text-align: left;                  z-index: 10000;                  top: 0;                  left: 0;                  display: grid;                  align-content: space-between;                  width: 100%;                  max-width: none;                  height: 100vh;                  padding: 3rem;                  pointer-events: none;                  grid-template-columns: 50% 50%;                  grid-template-rows: auto auto auto;                  grid-template-areas: 'title ...'                                                          '... ...'                                                          'links demos';          }          .frame__title-wrap {                  grid-area: title;                  display: flex;          }          .frame__title {                  margin: 0;          }          .frame__tagline {                  position: relative;                  margin: 0 0 0 1rem;                  padding: 0 0 0 1rem;                  opacity: 0.5;          }          .frame__demos {                  margin: 0;                  grid-area: demos;                  justify-self: end;          }          .frame__links {                  grid-area: links;                  padding: 0;                  justify-self: start;          }          .frame a {                  pointer-events: auto;          }          .content {                  height: 100vh;                  justify-content: center;          }  }

引入javascript

 <script src="js/imagesloaded.pkgd.min.js"></script>   <script src="js/three.min.js"></script>   <script src="js/TweenLite.min.js"></script>   <script src="js/CSSPlugin.min.js"></script>   <script src="js/EasePack.min.js"></script>   <script src="js/dat-gui.min.js"></script>   <script src="js/Configurator.js"></script>   <script src="js/GridToFullscreenEffect.js"></script>   <script src="js/basicDemo.js"></script>    <script>                          const itemsWrapper = document.getElementById('items-wrap');                            const configurator = createDemoConfigurator({                                  activation: { type: "side", props: { top: true, bottom: true} },                                  timing: {                                          type: "sections",                                          props: {                                                  sections: 4,                                          }                                  },                                  transformation: {type: 'simplex'},                                  duration: 1.8,                                  easings: {                                          toFullscreen: Cubic.easeInOut,                                          toGrid: Cubic.easeInOut                                  }                            })                  imagesLoaded(document.querySelectorAll("img"), instance => {                            //https://www.techrepublic.com/article/preloading-and-the-javascript-image-object/                          document.body.classList.remove("loading");                          let images = [];                                  for (var i = 0, imageSet = {}; i < instance.elements.length; i++) {                                          let image = {                                                  element: instance.elements[i],                                                  image: instance.images[i].isLoaded ? instance.images[i].img : null                                          };                                          if (i % 2 === 0) {                                                  imageSet = {};                                                  imageSet.small = image;                                          }                                            if (i % 2 === 1) {                                                  imageSet.large = image;                                                  images.push(imageSet);                                          }                                  }                                  configurator.effect.createTextures(images);                          });  </script>

作者 | 思齐 | 蚂蚁开源社区大神,资深开发工程师