让你的菜单图标跟随内容滚动~动起来!

377 阅读1分钟

持续创作,加速成长!这是我参与「掘金日新计划 · 10 月更文挑战」的第3天,点击查看活动详情

一、前言

前些阵子写了一个联动的动画效果,就是要实现左侧菜单栏上的图标,跟随右侧的内容滚动而转动。一个简单的用户交互动画功能。如下图所示

291891492291361822022-10-13_19.58.45.gif

二、实现方案

1.使用技术

此功能实现主要是利用css的transform属性和javascript监听dom的滚动事件scroll,通过窗体高度与内容高度以及dom的scrollTop来计算转动角度百分比。

2.具体实现

这里咱们说下实现的逻辑,分为以下几个步骤

  1. 界面分成两部分,左侧为需要转动的图标,右侧为内容数据流。
  2. 动态为左侧需要转动的图标添加样式,transform:rotate(${workBlock}deg)动态修改workBlock,来改变图标的转动角度。
  3. 获取右侧dom窗口的高度,再获取dom窗口下所有子元素的高度,即内容的高度,总高度。
  4. 计算百分滚动时当前高度所占总高度的百分比:percentage = 当前滚动高度/(总高度-窗口高度)

总体代码如下

<script setup lang="ts">
import { ref, onMounted } from 'vue';
  const data = [{
    label: 'Name',
    value: 'Socrates',
  }, {
    label: 'Mobile',
    value: '123-1234-1234',
  }, {
    label: 'Residence',
    value: 'Beijing'
  }, {
    label: 'Hometown',
    value: 'Beijing',
  }, {
    label: 'Address',
    value: 'Yingdu Building, Zhichun Road, Beijing'
  }]
  let workBlock = ref(0)
  // 动画监听方法
  const workAnimate = () => {
    const workList = document.getElementById('scroll')
    let workListHeight = 0
    if (workList) {
      // 循环获取所有窗口下子元素的高度,来计算总内容高度
      workList.childNodes.forEach((item) => {
        if (item.nodeType === 1) {
          let domRect = (item as HTMLElement).getBoundingClientRect() as DOMRect
          workListHeight = workListHeight + domRect.height
        }
      })
      workListHeight = workListHeight - (workList as HTMLElement).getBoundingClientRect().height
      workList.addEventListener('scroll', () => {
        const percentage = workList.scrollTop / workListHeight
        workBlock.value = 360 * percentage
      })
    }
  }
  onMounted(() =>{
    workAnimate()
  })
</script>
<template>
  <main>
    <ul class="left">
      <li>
        <img src="../../assets/windmill.svg" :style="`transform:rotate(${workBlock}deg)`">
        <div>首页</div>
      </li>
    </ul>
    <div class="right" id="scroll">
      <a-space v-for="i in 20" direction="vertical" size="large" fill>
        <a-descriptions :data="data" title="User Info" layout="inline-horizontal"/>
        <a-descriptions :data="data" title="User Info" :column="{xs:1, md:3, lg:4}">
          <a-descriptions-item v-for="item of data" :label="item.label">
            <a-tag>{{ item.value }}</a-tag>
          </a-descriptions-item>
        </a-descriptions>
      </a-space>
    </div>
  </main>
</template>
<style lang="less" scoped>
main {
  width: 100%;
  height: 100%;
  display: flex;
  .left {
    width: 300px;
    height: 100%;

    li {
      display: flex;
      align-items: center;
    }
  }
  .right {
    flex: 1;
    overflow: auto;
  }
}
</style>

以上 我们就实现了图标与内容间的滚动交互。用我们产品的话来讲就是用户能够更沉浸的体验产品的一个小小设计。

三、后记

这个只是利用了简单的原理实现的一个用户交互功能。觉得很有意思,跟大家分享下。

本篇完结! 撒花! 感谢观看! 希望能帮助到你!