碉堡了,基于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>
作者 | 思齐 | 蚂蚁开源社区大神,资深开发工程师