vue+element实现双向描点 反向联动

   前端项目里经常会有锚点得操作、以及反向联动的效果

   就是一个菜单,点击会定位到一个块上,滚动的当前块的时候,菜单会出现定位的效果

 

 

差不多就是这种动起来的效果,由于不太懂之前的逻辑,今天又从重新看了下

上代码

 

html:

-----滚动的区域----------
<el-row class="panel-box part-detail" id="partdetail" :class="navClass">
--------菜单
     <ul class="nav-list">
        <li
          :class="{ current: item.value === navCurrent }"
          v-for="item in navList"
          :key="item.value"
          @click="linkTo(item.value)"
        >{{item.label}}</li>
      </ul>


---------------对应显示区域  注意id和class 后边要用
        <h5 id="scene" class="do-jump">
          应用场景
          <p class="detail-content">{{ algorithmData.brief }}</p>
        </h5>

       <h5 id="word" class="do-jump">
          使用文档
          <ul
            v-if="algorithmData.fileList && algorithmData.fileList.length > 0"
            class="detail-content"
          >
        </h5>

        <h5 id="explain" class="do-jump">
          使用说明
          <div class="detail-content">交付方式:{{ algorithmData.instruction.deliveryType }}</div>
        </h5>


</el-row>

vuejs:

 data() {
    return {
      imageLocalUrl,
      navClass: '',
      navList: [
        {
          value: 'scene',
          label: '应用场景'
        },
        {
          value: 'word',
          label: '使用文档'
        },
        {
          value: 'explain',
          label: '使用说明'
        }
      ],
      navCurrent: 'scene',
      typeMap: {},
      algorithmData: {
        instruction: {}
      },
      scrollBox: '',
      scrollFalg: true
    }
  },

---------加入监听事件

  mounted() {
    window.addEventListener('scroll', this.scrollPage)
  },

  activated() {
    window.addEventListener('scroll', this.scrollPage)
  },

  methods: {
   ------------锚点事件
   linkTo(id) {
      //点击时传值id
      this.navCurrent = id
      const el = document.querySelector(`#${id}`)
      this.$nextTick(function() {
        window.scrollTo({ 'behavior': 'smooth', 'top':el && el.offsetTop })
      })
    },

   --------------反向联动
     scrollPage() {

   ----------菜单控制样式
      if (document.querySelector('#partdetail').getBoundingClientRect().top <= 0) {
        this.navClass = 'fix-nav'
      } else {
        this.navClass = ''
      }
      /**
       * 反向联动
       */

      //获取所有锚点元素的高,并放在obj对象里     class用上了
      const navContents = document.querySelectorAll('.do-jump')
      const offsetTopArr = []
      let temp = {}
      for (let i = 0; i < navContents.length; i++) {
        const e = navContents[i]
        let temp = {
          offsetTop: e.offsetTop,
          id: e.id
        }
        offsetTopArr.push(temp)
      }
      // 获取当前文档流的滚动位置的高度 scrollTop
      const scrollTop = document.documentElement.scrollTop || document.body.scrollTop
      const domPosition = document.documentElement.scrollTop
      //console.log("滚动时当前dom:"+domPosition)
      // 定义当前点亮的导航下标
      let navIndex = 'scene'
      for (let n = 0; n < offsetTopArr.length; n++) {
        // 如果 scrollTop 大于等于第 n 个元素的 offsetTop 则说明 n-1 的内容已经完全不可见
        // 那么此时导航索引就应该是 n 了
        if (scrollTop >= offsetTopArr[n].offsetTop) {
          navIndex = offsetTopArr[n].id
        }
      }
      this.navCurrent = navIndex
      console.log('滚动到的菜单:' + this.navCurrent)
      //this.linkTo(navIndex)
      console.log('navIndex:' + navIndex + '########')
    }
  },

},
 deactivated() {
    window.removeEventListener('scroll', this.scrollPage)
  },
  destroyed() {
    window.removeEventListener('scroll', this.scrollPage)
  }


css:

.part-detail {
  margin-top: 15px;
  padding: 0;
  .nav-list {
    display: flex;
    border-bottom: 1px solid #ededed;
    font-size: 16px;
    margin: 0;
    li {
      padding: 16px 0;
      margin: 0 16px;
      cursor: pointer;
      &:first-child {
        margin-left: 46px;
      }
      &.current {
        color: #ff6400;
        border-bottom: 3px solid #ff6400;
      }
    }
  }
  &.fix-nav {
    padding-top: 54px;
    //color: red;
    .nav-list {
      position: fixed;
      background: #fff;
      top: 0;
      float: right;
      z-index: 5;
      left: 140px;
      right: 140px;
    }
  }
}

代码已基本如此

思路:

每一个区域加上相同的calss,滚动的时候获取距离,

得到菜单对应的下标(id)和距离上部元素的高度,便于滚动

得到当前滚动的高度和内容块的距离做比较,大于则菜单变动,出现效果

后记:前端刚上手,还有很多不会的,借助修改bug的机会能学到更多,这个本来的效果时这种实现的

 // 锚点跳转

    // linkTo(id) {

    //   this.navCurrent = id

    //   this.scrollFalg=false

    //   console.log('当前点击的菜单:' + this.navCurrent)

    //   // 要移动的距离登录本身减去nav-list底部位置

    //   const jump = document.querySelector(`#${id}`).getBoundingClientRect().top - document.querySelector('.nav-list').offsetHeight

    //   // 获取当前dom位置

    //   const domPosition = document.documentElement.scrollTop

    //   //console.log("点击时当前dom:"+domPosition)

 

    //   let index = 0

    //   let moveTime = null

    //   clearInterval(moveTime)

    //   moveTime = setInterval(() => {

    //     if (++index === 50) {

    //       clearInterval(moveTime)

    //       return

    //     }

    //     // 每次移动1/50,50次移动完毕

    //     document.documentElement.scrollTop = domPosition + (jump / 50) * index

    //   }, 10)

    //    //this.scrollFalg=true

    // },

这样很好,直接锚点跳到当前内容顶部,效果很好,但是在监听滚动的时候,反向联动和点击事件或冲突,无奈修改了,定位不如之前的准,到那时反向的效果有了,也希望有人看到后指教一下

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值