叮~来查收这份不一样的年度总结报告吧(掘金2022创作者版)


highlight: a11y-dark

前言

年底相信大家都被各种年度总结报告刷屏了吧,看了那么多年度报告,都是一屏滑过一屏,动画全是清一色淡入加淡出,难免有些审美疲劳。

我在上一篇文章 2022年终总结 的时候临时起意,于是想设计出一个交互式年度总结网页,本想为平淡的这年增添亿点别样色彩,遗憾没能抓住2022的尾巴,此番就作为回顾的篇章与你一同分享吧!新年伊始,也不算晚~

食用指南

输入你或他人掘金ID (主页URL末尾数字),点击按钮等弹窗消失后上下滑动页面即可查看报告,推荐点击上方自动播放效果会更好。

https://code.juejin.cn/pen/7178839138609659959

jcode

  • 请在 PC 端查看,移动端没做适配,头发能省几根是几根啊!需要保持横屏的比例效果较好。

  • 点击后有音乐,摸鱼时注意场合,别怪我没提醒你 ᕕ( ᐛ )ᕗ 另外因为BGM太好听了所以我就没写暂停功能(认真)。

  • 如何发弹幕 –> 报告结束时会开启弹幕,在本文中发表评论 会自动更新到网页的弹幕列表中,重要的事情我只说一遍~( ゚∀゚) ノ♡

如果2022年整一年都没发过文章,你输入id后就没反应了( ´・・)ノ(._.`),所以标题才说是创作者版~你可以输入任意你在掘金喜欢的大佬id查看😍

ok,这两天开发的玩具到这里就介绍完毕了,没人看我也要写,因为主要我自己想玩!

但作为干货区作者(自封),下面就继续展开讲讲这个交互页面的主要实现要点。

image.png

吸附滚动原理

曾经,有一位伟岸的UI设计师跟我说过:

101672745552_.pic.png

当时没文化的我只能说雀食牛逼啊朋友们,苹果官网的产品页那个炫啊,稚嫩的我在短暂体验过后心中就种下了一枚名为 滚动 的种子,虽然我做不出那么烧的效果,但也涌现出了不少灵感。

正如开头提到的,大多数网页报告交互手段都是点击切换到下一屏,然后用户就只能呆呆看着动画执行完毕才能又继续一下屏。

所以如果把每一屏的动画过程通过滚动方式交给用户去完成,是不是会更有意思一点呢!

我的设计思路很简单,把实际高度远超过屏幕高度的元素堆栈排放,每一屏的内容实际上要滑动一段距离才能到达底部,此时只需要让这个元素吸附在屏幕上就可以了,等到内容滑动到底了再解除吸附。

image.png

如何判断正在滑动的是哪一屏呢?so easy,每个元素都可以获取到 offsetTop,这就是起始位置,每一屏的高度由我们自定义,结束位置也知道了(假设高度为h,结束位置则为offsetTop+h),通过给 scroll 添加事件监听,在监听中获取到滚动距离(如:body.scrollTop),这样当滚动距离大于某元素起始位置小于结束位置时,就是在这个元素中活动。

我们把这样一个元素先称呼为“盒子”吧,在每个盒子当中的滑动进度也很容易计算出来了:

progress = (scroll - startIndex) / (endIndex - startIndex)

利用每个盒子在滑动过程中产生的 progress 来控制盒子中的动画展示从 0%100% 的过程,动画的节奏则由每一屏的高度决定,这就是我整个网页交互的核心。

image.png

现在问题只剩下如何实现吸附,这还不简单嘛,不就是绝对定位 absolute 或者 fixed咯?

虽然这些都可以实现,但我觉得还得是 position: sticky 更加合适,它的使用场景可能有点少,而且曾经连谷歌浏览器都放弃了对它的支持,因此大概比较少人关注吧,但是现在看来完全不用担心兼容性啊,一眼望去那是比青青草原还要更加生机盎然:

image.png
image.png

那么这个 position: sticky 是个什么东西呢?翻译成人话讲就是 “粘性定位”,它可以看做是相对定位与绝对定位的结合体,但本身是属于流定位的,也就是和 relative 一样,不同的是它接受top right bottom left等值的时候可以基于最近的祖先元素进行定位并牢牢地“粘”在窗口上,这种特性就使得我们很容易实现上述的效果。

我们把每一屏页面都设置为 position: sticky 而不设置偏移时,由于是流定位,此时不会形成堆叠上下文,它看起来就和 relative 没什么区别:

2023-01-04 03.11.54.gif

而当我们展示到某一页的时候,就把它设置为 top: 0 顶到页面中粘住,要注意此时它看起来虽然和绝对定位一样,但是却并没有脱离文档!我们直接就可以用这个元素把父级撑开,sticky——专为滚动而生~ヽ(゚∀゚*)ノ━━━ゥ♪

现在可以开始咱们的表演了,赶紧掏出我心爱的 Vue3 + Vite 就是一顿疯狂操作 (ノ*・ω・)ノ

2023-01-04 03.25.26.gif

实现效果如下所示:

2023-01-04 03.38.44.gif

另外我也是把这个基础组件发布到了npm,如果你也想玩玩可以自取:

npm install @palxp/scroll-wrap-vue3

在线演示和 API 文档我就放在这里了 (* ̄3 ̄)╭ scroll-wrap-vue3 组件文档

Vue父子组件通信

在这个核心组件中,数据流向主要是父传子,所以通信方式采用插槽最为合适,我们的目的是将滚动层的进度传递到子组件中,在 ScrollWrap 中默认插槽传入数据:

<slot :progress="process"></slot>

调用时在父组件上通过 v-slot 取出 props 对象,就可以拿到传递的动态响应参数了,接下来就是传入子组件的 props 中控制动画,页面中部分代码展示如下:

<ScrollWrap v-slot="props" :long="wh">
    <Text :value="'你好,' + user.name" :progress="props.progress" />
</ScrollWrap>

<ScrollWrap v-slot="props" :long="1.2 * wh">
    <Text value="时光飞逝,一弹指顷" :destroy="true" :progress="props.progress" />
</ScrollWrap>

<ScrollWrap v-slot="props" :long="wh * 2">
    <Text value="请查收你的专属回忆🌹" :destroy="true" :progress="props.progress" />
    <Hello :progress="props.progress" />
</ScrollWrap>

插槽内的子组件都是些动画部分的代码,大部分成熟的动画库都有 timeline 功能,以 animejs 为例:

2023-01-04 15.14.20.gif

最后

完整项目开源地址:https://github.com/palxiao/juejin-nzzj

猫喜欢吃鱼,却不能下水,鱼喜欢吃蚯蚓,却不能上岸。人生也是一边拥有,一边失去;一边选择,一边放弃。

不知不觉就过了这一年,偶尔停下,跟自己说两句话,第一句:看下吧,毕竟一年过去了;第二句:忘了吧,前面还有路呢。

image.png

以上就是文章的全部内容,感谢看到这里!本人知识水平有限,如有错误望不吝指正,如果觉得写得不错,对你有所帮助或启发,可以点赞收藏支持一下,也欢迎关注,我会更新更多实用的前端知识与技巧。我是茶无味de一天,希望与你共同成长~

© 版权声明
THE END
喜欢就支持一下吧
点赞6 分享
评论 抢沙发
头像
欢迎您留下宝贵的见解!
提交
头像

昵称

取消
昵称表情代码图片

    暂无评论内容