前言
今天为大家制作一个动若脱兔的转换视差效果,当鼠标在目标上左右移动时除了背景产生的位移视差效果外,里面的兔子也会跟着鼠标的位置来作出不同的动作
实现效果:
图片处理
先准备好四个不同动作兔子的图片和背景图
打开 ps 将新建一个 1920 * 500 的图层,将背景图拖进去铺满,然后分别将四个兔子放在指定的位置保存,最后就得到了四张带有背景和兔子的图片
实现效果
html 部分加入 section 标签,在里面分别加入弄好的图片设置不同的 class,并用一个 div 标签将图片都包起来
<section> <div class="view"> <img src="https://p3-juejin.byteimg.com/tos-cn-i-k3u1fbpfcp/a5c8e6a91c4641fab1cb04f1769ca09e~tplv-k3u1fbpfcp-zoom-1.image" class="sleep" alt=""> <img src="https://p3-juejin.byteimg.com/tos-cn-i-k3u1fbpfcp/407c35ce4b78485d9226e42a822911ee~tplv-k3u1fbpfcp-zoom-1.image" class="look" alt="">
<img src="https://p3-juejin.byteimg.com/tos-cn-i-k3u1fbpfcp/b698b8b66e6448a69611d4b31a7079cf~tplv-k3u1fbpfcp-zoom-1.image" class="jump" alt=""> <img src="https://p3-juejin.byteimg.com/tos-cn-i-k3u1fbpfcp/032fbcb3beae4d04aaab7f269568c98e~tplv-k3u1fbpfcp-zoom-1.image" class="stop" alt=""> </div></section>
复制代码
然后来到 css 部分,为 body 标签设置内外边距为 0,最小高度 100vh,将里面的元素垂直居中
body { margin: 0; padding: 0; min-height: 100vh; display: flex; align-items: center; background-color: #fffefa;}
复制代码
加入 section 选择器,宽度设为 100vw,高 300px,设置相对定位,overflow 设为 hidden
然后加入 section .view 选择器,设置绝对定位,上下左右都为 0,display 设定为 flex,justify-content 和 align-items 都设为 center
再将里面的图片重叠,display 设为 block,为了鼠标移动所产生的位移将图片宽度设大一点为 120%,高度设为 100%,但是图片比例不对,加入 object-fit: cover 图片就会按比例放大填满
section { width: 100vw; height: 300px; position: relative; overflow: hidden;}section .view{ position: absolute; top: 0; right: 0; bottom: 0; left: 0; display: flex; justify-content: center; align-items: center;}section img{ position: absolute; display: block; width: 120%; height: 100%; object-fit: cover;}
复制代码
然后调整图片的前后排序,当鼠标从左至右移动时候,兔子会由睡觉,转换为站立张望,再转换跳跃,最后结束,所以 class 为 sleep 的图片在最顶,其他的依次排序
section .sleep { z-index: 9;}
section .look { z-index: 8;}
section .jump { z-index: 7;}
section .stop { z-index: 6;}
复制代码
然后来到 js 部分,定义一个常量将 section 获取回来,为 section 新增 mousemove 监听鼠标移动的事件,在事件里将鼠标 X 的位置 e.clientX 除以浏览器视窗的宽度 window.outerWidth 的结果保存到变量 percentage 里,这样鼠标移到最左的时候 percentage 是 0,最右是 1,然后将 percentage 的值写到 css 中
const section = document.querySelector('section')section.addEventListener('mousemove', (e) => { let percentage = e.clientX / window.outerWidth section.style.setProperty('--percentage', percentage)})
复制代码
首先处理背景图的位移效果,section .view 选择器设置属性 transform,设定值为水平移动 translatex(),通过 calc()计算,将 percentage * 100px,即位移最大距离为 100px
section .view { transform: translatex(calc(var(--percentage) * 100px));}
复制代码
下一步处理图片的变化了,只需调整透明度就可以达到想要的效果了
一开始四张图片都是显示的,只是 section .sleep 的层级比较高所以显示在最上面,例如 section .sleep 这张图片,当鼠标越往右移动的时候 opacity 的值就越小,percentage 值为 0.1 及以上的时候,section .sleep 这张图片就变透明了,就显示出 section .look 的图片,最后一张照片 opacity 只需设置为 calc(1 + var(--percentage))就行了
section .sleep { z-index: 9; opacity: calc(1 - (var(--percentage) - 0.1 ) / 0.1); //percentage为0.1+时逐渐变透明}
section .look { z-index: 8; opacity: calc(1 - (var(--percentage) - 0.25 ) / 0.25);//percentage为0.25+时逐渐变透明}
section .jump { z-index: 7; opacity: calc(1 - (var(--percentage) - 0.4 ) / 0.4);//percentage为0.4+时逐渐变透明}
section .stop { z-index: 6; opacity: calc(1 + var(--percentage)); //一直显示}
复制代码
当鼠标移出的时候会回复到原来的位置,新增一个 mouseout 事件,设置 percentage 为 0.1,这样鼠标移出的时候就会复原
但是移出的时候比较生硬,需要加点动画过渡,为 section 里的每一个元素都添加 transition 过渡,但是会影响位移的效果,需要在鼠标移动的时候不套用过渡效果
所以得新增一个 mouseenter 事件,当鼠标进入的时候为 section 添加一个 moving 的 class,在 mouseout 事件中再将 moving 移除,当 section 标签有 moving 的时候里面的元素都设置 transition 为 none,就不会影响位移的效果了,完整的转换视差效果就完成了
section.addEventListener('mouseenter', (e) => { section.classList.add('moving')})
section.addEventListener('mouseout', (e) => { section.classList.remove('moving') section.style.setProperty('--percentage', 0.1)})
复制代码
section .view,section .sleep,section .look,section .jump,section .stop { transition: .2s all ease-in;}
section.moving .view,section.moving .sleep,section.moving .look,section.moving .jump,section.moving .stop { transition: none;}
复制代码
评论