实现上滑列表图片放大进入,缩小放大后隐藏效果

el/2023/9/24 23:10:25

讲解:

HTML 的部分

打开 CodePen 编辑器,在 HTML 的部份加入标题。由于它有一个副标题,所以我会用 <p>标签去装着它。然后加入一个 <div>id 名为 iphone,里面新增两个 <div>id 分别是 hardware 和 uihardware 会用来显示 iPhone 的机身和边框,而 ui 则会显示画面里面的内容。

图片

CSS 的部分

先定义一些 CSS,让我们更加清楚知道在做什么。加入 :root 选择器,定义一些变量和样式:

  • --device-width 是 770px

  • --device-height 是 1336px

  • --ui-width 是 640px

  • 基础文字大小是 15px

然后加入 #iphone 选择器,设定 position 是 relative,宽度和高度的值从变量中获取。

图片

再加入 #hardware 选择器,设定宽度和高度是 100%,然后背景图片,载入 iPhone 的机身图片,为了支援 Retina Display 高清屏幕,这张图片的尺寸是两倍大小,所以设定 background-size,宽度和高度同样等于变量的设定值。

好了,在这里想介绍一个图片遮罩的 CSS 属性,大家会发现现在 iPhone 的四周,圆型边框背后有个黑色背景:

图片

而我发现 Apple 特地准备了一张遮罩图片,画出了 iPhone 的外型,用白色填充,而圆型边框的四周是透明的:

图片

我们可以通过 mask-image 这个属性将遮罩图片套用上去。由于这个 CSS 属性还在试验阶段,所以要加上 -webkit 前缀的版本,与背景图片一样,图片是两倍大小,所以同样需要将遮罩的大小设定一下,将 mask-size 设定为变量的值,并且加上 -webkit 前缀的版本。

图片

现在可以看到遮罩已经成功套用上,iPhone 的黑色背景不见了。至于为何 Apple 不直接将 iPhone 图片的背景设定为透明?我估计是为了优化图片的大小,因为透明底的图片需要用到 PNG 格式,而这么大张的彩色 PNG 图片容量上比起 JPG 会大不少,所以 Apple 就采用了高压缩比的 JPG 格式作为 iPhone 图片,再准备一张只有单色的 PNG 图片来做遮罩,这样的确可以省下不少网络频宽。

好了,介绍完这个属性,可以加入 body 选择器,将背景颜色设定为黑色,margin 设定为 0,然后将网页的内容上下左右置中:

  • display 设定为 flex

  • flex-direction 设定为 column

  • justify-content 设定为 center

  • align-items 设定为 center

  • min-height 设定为 100vh

字体设定为 Helvetica,再加入一些 padding,设定上下是 4rem,左右是 0

图片

再设定一下标题的样式,加入 h2 选择器,文字颜色设定为灰色,text-align 设定为 center 将它置中,文字大小设定为 4.5rem,文字粗度是 600。然后 margin 设定为上下 6rem,左右 0

加入 h2 p 选择器,设定副标题的样式,margin 设定为 0,文字颜色设定为白色就可以了。

图片

框架大置上设定好了,下一步就设定 iPhone 画面的内容。

在 #ui 里面加入一张图片,是画面顶部的 UI,然后就是每一行资料的图片,我会用 <ul>列表去建构它,加入 <li>,内容是一张图片,总共有 7 行。

图片

回到 CSS 的部份,加入 #ui 选择器,position 设定为 absolutetop 设定为 0。然后要将它左右置中,先将 left 设定为 50%,再将 transform 设定为 translateX(-50%)就可以了。

加入 #ui .top-ui 选择器,设定顶部 UI 图片的定位。display 设定为 block,宽度从变量中获取,高度是 auto,然后 margin,设定上方是 70px,左右是 auto,下方是 0。再加一点 padding-bottom,设定为 30px,以及一条下边框线。

图片

来到列表的部份,加入 #ui ul 选择器,将 list-style 设定为 none,取消列表的样式,margin 和 padding 设定为 0

再设定里面的图片的样式,加入 #ui ul li img 选择器,设定 display 是 block,宽度从变量中获取,高度是 automargin 设定为上下 10px,左右 autopadding-bottom 是 10px,然后再加一条下边框线。

图片

现在界面基本上已设定好了,接下来处理动画的部份。

动画的部分

我们先了解一下这个动画的原理,它是在页面卷动的时候,一行一行的由大至小滑入至列表中,先试试在 CSS 中将效果实现出来。

加入 #ui ul li img:hover 选择器,设定 transform 为 scale(1.8),然后 opacity 设定为 0。在 #ui ul li img 选择器内加入 transition: .25s transform ease-in-out;,现在试试将游标移至其中一行,就可以实现将图片由放大至缩小,回到列表中的效果。

图片

再加一些位移,例如 translateY() 设定为 -60px,效果大致上是这样:

图片

不过这个动画并不是由游标触发,是随着页面卷动时触发,并且可以通过卷动控制动画的进度,所以我会通过 JavaScript 计算目前页面卷动了多少,然后再设定对应行数的 transform和 opacity

为了简化 JavaScript 对 CSS 样式的设定,我想先在 CSS 这边做一个设定值,用来控制一行动画的进度。

先将 hover 和 transition 的设定值移除,然后在 HTML 里面,在第一个 li 那里加入 style,设定 --progress 是 0.5

图片

--progress 是我自己定义的 CSS 变量,我想在它的设定值为 0 时将 scale() 设定为 1.8,以及 opacity 设定为 0;而在它的设定值为 1 的时候,将 scale() 设定为 1opacity 设定为 1。做到像是一个动画的开关的功能,那么我们在 JavaScript 那边,只需要调整这个 --progress 就可以控制动画。

在 #ui ul li img 里面,加入 transform,先设定 scale(),将 1.8 减去 0.8 * var(--progress),这样在 --progress 为 1 的时候,scale 就是 1;而 --progress 为 0 的时候,scale 就是 1.8 了。

再来 translateY(),将 -60px 乘以 1 \- var(--progress),这样在 --progress 为 1时,translateY 就是 0;而 --progress 为 0 的时候,translateY 就是 -60px

再将 opacity 直接设定为 --progress 的值,0 的时候会将它隐藏,1 的时候它就会显示。试试调整一下 --progress 的值,大家就可以看到这个设定值的具体作用了。

图片

然后将 <li> 上的设定值移除,在 #ui ul 里将 --progress 初始化为 0 就可以了。

图片

图片

JavaScript 的部分

最后,就是用 JavaScript 控制动画。

首先定义一个名为 rows 的常量,将每一个 <li> 获取回来,再定义一个名为 html 的常量,赋值为 document.documentElement,因为稍后会有几次引用 document.documentElement 的。

加入 document.addEventListener,监听 scroll 页面卷动,定义一个变量,scrolled 等于 html.scrollTop 除以 html.scrollHeight 减去 html.clientHeight

这样会得出一个由 0 至 1 之间的值,页面卷动到最顶时是 0,卷动到最底时是 1

图片

接下来要将每一个 <li>,一个接着一个,将 --progress 设定为 1

新增一个 for of 回圈,将每一个 <li> 获取出来,由于动画是一个接着一个,而页面卷动了多少可以经由 scrolled 获取,所以我们要计算每一个 <li> 在 0 至 1 之间的所属区间。

定义一个名为 total 的变量,将 1 除以 <li> 的总数,然后计算两个值,一个是 start,将 total 乘以 index,另一个是 end,将 total 乘以 index 加 1,通过 console.log(),将每一个 <li> 的区间输出一下看看。

图片

有了这些资料,我们可以计算每一个 <li> 的 --progress 的值了。定义变量 progress,将 scrolled 减 start 除以 end 减 start;然后如果 progress 大于等于 1 的话,将 progress 设定为 1;少于等于 0 的话,就设定为 0

最后,将 progress 的值通过 setProperty 设定到 <li> 上。

图片

html

<div id="iphone"><div id="hardware"></div><div id="ui"><img src="https://assets.codepen.io/2002878/iphone12-5g_top_ui.jpg" class="top-ui" alt=""><ul><li><img src="https://assets.codepen.io/2002878/iphone12-5g_show_01.jpg" /></li><li><img src="https://assets.codepen.io/2002878/iphone12-5g_show_02.jpg" /></li><li><img src="https://assets.codepen.io/2002878/iphone12-5g_show_03.jpg" /></li><li><img src="https://assets.codepen.io/2002878/iphone12-5g_show_04.jpg" /></li><li><img src="https://assets.codepen.io/2002878/iphone12-5g_show_05.jpg" /></li><li><img src="https://assets.codepen.io/2002878/iphone12-5g_show_06.jpg" /></li><li><img src="https://assets.codepen.io/2002878/iphone12-5g_show_07.jpg" /></li></ul></div>
</div>

CSS

:root {--device-width: 770px;--device-height: 1336px;--ui-width: 640px;font-size: 15px;
}body {background-color: #000;margin: 0;display: flex;flex-direction: column;justify-content: center;align-items: center;min-height: 100vh;font-family: Helvetica;padding: 4rem 0;
}h2 {color: #6e6e73;text-align: center;font-size: 4.5rem;font-weight: 600;margin: 6rem 0;
}h2 p {margin: 0;color: #fff;
}#iphone {position: relative;width: var(--device-width);height: var(--device-height);
}#hardware {width: 100%;height: 100%;background-image: url(https://assets.codepen.io/2002878/iphone12-5g_on_phone.jpg);background-size: var(--device-width) var(--device-height);mask-image: url(https://assets.codepen.io/2002878/iphone12-5g_on_phone_mask.png);-webkit-mask-image: url(https://assets.codepen.io/2002878/iphone12-5g_on_phone_mask.png);mask-size: var(--device-width) var(--device-height);-webkit-mask-size: var(--device-width) var(--device-height);}#ui {position: absolute;top: 0;left: 50%;transform: translateX(-50%);
}#ui .top-ui {display: block;width: var(--ui-width);height: auto;margin: 70px auto 0;padding-bottom: 30px;border-bottom: 1px solid #222;
}#ui ul {list-style: none;margin: 0;padding: 0;--progress: 0;
}#ui ul li img {display: block;width: var(--ui-width);height: auto;margin: 10px auto;padding-bottom: 10px;border-bottom: 1px solid #222;transform: scale(calc(1.8 - (0.8 * var(--progress)))) translateY(calc(-60px * (1 - var(--progress))));opacity: var(--progress);
}

JS

const rows = document.querySelectorAll('#ui ul li')
const html = document.documentElementdocument.addEventListener('scroll', (e) => {let scrolled = html.scrollTop / (html.scrollHeight - html.clientHeight)let total =  1 / rows.lengthfor (let [index, row] of rows.entries()) {let start = total * indexlet end = total * (index + 1)let progress = (scrolled - start) / (end - start)if (progress >= 1) progress = 1if (progress <= 0) progress = 0row.style.setProperty('--progress', progress)}
})


http://www.ngui.cc/el/3419117.html

相关文章

解决uniapp的checkBox取消选中

<checkbox-group change"selectUniverSity" checked><checkbox v-for"(item,index) in universityTypes" class"m-2":key"item.typeId":value"item.typeId" <!--每次触发一次多选则向checkUnType追加一次&#…

uniApp设置安卓手机真机调试

use连接手机&#xff0c;会出现相关USB相关设置需要选择MIDI模式或其他带M的模式&#xff0c; 之后选择手机设置中的关于手机&#xff0c;多次点击手机版本&#xff0c;出现已打开开发者模式选项 在设置中找到开发这选项&#xff0c;选择USB调试即可

十几个CSS高级常见技巧汇总(placeholder,虚线框、三角形、优惠券卡券、滚动条、多行溢出...)

设置input的placeholder的字体样式 单行和多行文本超出省略号 负边距使用技巧 定位同时设置方位情况 相邻兄弟选择器之常用场景 outline属性的妙用技巧 隐藏滚动条或更改滚动条样式 纯CSS绘制三角形 虚线框绘制技巧 卡券效果制作 隐藏文本的常用两种方法 表格边框合…

uniapp中使用百度API实现全景地图(仅支持H5)

首先需要新建一个js bMap.js export function map(()>{ //由于要执行引入的script加载&#xff0c;所以要执行init每次引用次方法都触发 window.init(()>{ //传入使用当前方法&#xff0c;resolve执行成功返回结果then向下执行 resolve(map); }) return new Promise(()&g…

ajax上传文件及监听进度 PC端或H5

if(this.loadingStep!0){uni.showToast({icon:none,title:上一张图片暂未完成})return false;} var input document.createElement(input);input.type file;input.acceptimage/*; document.getElementById(upFile).appendChild(input);// this.$refs.input.appendChild(inp…

uniapp打包H5相关配置

在pages.json页如果tabBar设置的icon是png不是字体图标则从app切换h5打包后需要修改图片path路径&#xff1a; app的iconPath或selectedIconPath是获取当前项目文件下&#xff1a;static/images/tab/mine.png h5使用的时候需要改为外部链接地址图片&#xff1a;http://xxx/xx…

uniapp配置权限

在登录的时候后端接口查出当前用户可进入页面路由的数组 let dataList[{name:first,uri:/1},{name:second,uri:/2},{name:third,uri:/3},{name:four,uri:/4} ] 前端在每个页面的详情页执行验证&#xff0c;如果当前的路由不包含返回的数组中的内容则出现蒙板 前端获取当前页…

uniapp后端配置升级

升级选择原生app制作wgt生成wgt文件后上传到OSS,后端数据库修改url及version即可&#xff0c;将status改为上线

用一行CSS分别实现10种现代布局

01、超级小中 在没有和flex grid之前&#xff0c;垂直居中一直不能很优雅的实现。而现在&#xff0c;可以结合我们grid和place-items优雅的实现同时水平居中和垂直居中。 <div class"parent blue" > <div class"box coral" contenteditable>…