91超碰碰碰碰久久久久久综合_超碰av人澡人澡人澡人澡人掠_国产黄大片在线观看画质优化_txt小说免费全本

溫馨提示×

溫馨提示×

您好,登錄后才能下訂單哦!

密碼登錄×
登錄注冊×
其他方式登錄
點擊 登錄注冊 即表示同意《億速云用戶服務條款》

vue如何實現無縫滾動手摸手效果

發布時間:2023-03-06 17:14:01 來源:億速云 閱讀:106 作者:iii 欄目:開發技術

這篇文章主要講解了“vue如何實現無縫滾動手摸手效果”,文中的講解內容簡單清晰,易于學習與理解,下面請大家跟著小編的思路慢慢深入,一起來研究和學習“vue如何實現無縫滾動手摸手效果”吧!

    需求分析

    • 通過使用類似下列代碼的方式實現

    <Swiper>
        <SwiperSlide>111</SwiperSlide>
        <SwiperSlide>222</SwiperSlide>
        <SwiperSlide>333</SwiperSlide>
        <SwiperSlide>444</SwiperSlide>
    </Swiper>
    • 實現自動滾動

    • 實現無縫滾動

    • 鼠標移入暫停,鼠標移出繼續

    實現思路

    實現需求一

    首先是需要兩個組件,這里姑且把父組件稱做Scroll組件,子組件稱作ScrollSlide組件。 父組件和子組件中均需要使用插槽,子組件的插槽內容即是一個slide的內容,具體內容由使用者提供。

    實現需求二

    通過使用定時器setInteval持續讓元素向左偏移(translateX)。

    實現需求三

    通過在父組件中放置兩個<slot />將使用者傳過來的插槽復制兩遍,正如上面的例子,傳入了四個Slide,但其實父組件中渲染了八遍,稱為兩組,當向左偏移量 >= 所有子元素的寬度之和/2,說明滾動了一組,這時就可以把偏移量置為0,也就是讓他從頭開始滾動,但此時無縫銜接到第二組之后又從頭開始,視覺上看不出任何變化,這是我們也可以清除掉(clearInterval)為實現需求二而創造的定時器(setInterval)

    實現需求四

    前面都說了,使用 定時器(setInteval) 結合偏移(translateX) 實現滾動,那停止滾動,自然就執行clearInteval啦,那繼續滾動也就繼續開始執行setInteval了。

    擼起袖子開始干

    目錄規劃

    |-------------------scroll
    |
    |----------index.vue
    |
    |----------scroll-slide.vue
    • scroll/index.vue 為父組件

    • scroll/scroll-slide.vue 為子組件

    父組件的實現

    這里用的是Vue3+TypeScript,先把基礎架子搭建起來

    <script setup lang="ts">
    </script>
    <template>
      <div class="vue-scroll">
        <ul class="vue-scroll-wrap"></ul>
      </div>
    </template>
    <style lang="less" scoped>
    .vue-scroll{ 
        overflow: hidden;
        cursor: pointer;
        .vue-scroll-wrap { 
            padding:0;
            margin:0;
            white-space: nowrap;
        }
    }
    </style>

    用了vue3不用setup怎么行呢?這里就直接使用setup語法糖來實現。

    我們假設ul中有n個li,并讓他們橫向排列.vue-scroll設置了overflow:hidden;,這時你就不難發現,我們讓偏移的元素也就是ul,超出容器被隱藏。

    接下來編寫滾動函數

    <script setup lang="ts">
    import { ref, Ref } from 'vue';
    // 定時器
    const timer:Ref<null|NodeJS.Timer> = ref(null);
    // 開始滾動
    const beginScroll = () => {
      // 滾動容器
      const vueScrollWrapDom: HTMLElement | null = document.querySelector(".vue-scroll-wrap");
      // 滾動容器的寬(所有子元素的寬之和)
      const overWidth = Array.from(document.querySelectorAll(".vue-scroll-wrap .vue-scroll-slide"))
        .map(e => e.clientWidth).reduce((a,b) => a + b);
      // 定義定時器開始滾動
      if(vueScrollWrapDom){
        timer.value = setInterval(() => {
          // 獲取滾之前的滾動距離
          const translateXs = vueScrollWrapDom.style.transform.match(/translateX\((.*)px\)/);
          let oldTranslateX = translateXs ? Number(translateXs[1]) : 0;
          // 如果滾動距離大于等于總距離的1/2,也就說明滾完了第一組(總共有兩組來做無縫銜接),當第二組開始的時候讓滾動距離置為0,從頭開始
          if(Math.abs(oldTranslateX) >= (overWidth / 2)) oldTranslateX = 0;
          // 設置滾動距離
          vueScrollWrapDom.style.transform = `translateX(${oldTranslateX - 1}px)`;
        },30)
      }
    }
    </script>

    上述代碼注釋已經寫得非常詳細了,這里就不做過多解釋。接下來需要讓這個滾動函數執行,所以引入onMounted鉤子,并調用滾動方法。

    <script setup lang="ts">
    import { ref, onMounted, Ref } from 'vue';
    // ...
    onMounted(() => {
        beginScroll();
    })
    </script>

    這個時候父組件就已經實現了自動滾動,接下來要實現,鼠標移入停止滾動,鼠標移出繼續滾動。

    那首先就需要給div元素綁定鼠標移入移出事件,并在js里面編寫對應方法。

    <script setup lang="ts">
    // ...
    // 停止滾動方法
    const stopScroll = () => {
        if(timer.value) clearInterval(timer.value);
    }
    // 鼠標移入
    const onMouseEn = () => {
      beginScroll();
    }
    // 鼠標移出
    const onMouseLe = () => {
      stopScroll();
    }
    </script>
    <template>
        <div class="vue-scroll" @mouseenter="onMouseEn" @mouseleave="onMouseLe">
            <!-- ... -->
        </div>
    </template>

    這時我突發奇想,有些人就會反著來,鼠標移入開始滾動,鼠標移出停止滾動,如果要把組件面向大眾使用,確實得考慮這個問題,所以定義個boolean用來判斷是正常流程還是騷操作

    <script setup lang="ts">
    // ...
    // 行為 true(鼠標放上去暫停,移出滾動) false(鼠標放上去滾動,移出暫停)
    const behave = ref(true);
    // 修改鼠標移入移出事件
    const onMouseEn = () => {
      behave.value ? stopScroll() : beginScroll();
    }
    const onMouseLe = () => {
      behave.value ? beginScroll() : stopScroll();
    }
    </script>

    為了組件的靈活性,定義一個boolean變量autoplay,用來判斷組件是否掛載完成之后自動滾動,

    beginScroll方法中,不難發現,translateX(${oldTranslateX - n}px),n越大,滾動速度越快,這里就把n剔出去,叫做speed,由父組件傳入。

    綜上所述,父組件源碼經收拾之后就是下面這樣:

    <script setup lang="ts">
    import { ref, onMounted, Ref } from 'vue';
    // 組件接受的屬性
    const props = defineProps({
      // 是否自動播放
      autoplay:{ type:Boolean, default: true },
      // 播放速度 1-10,越大越快,為防止填錯,將處理之后的結果用來播放速度
      speed:{ type:Number, default:1 },
      // 行為 true(鼠標放上去暫停,移出滾動) false(鼠標放上去滾動,移出暫停,必須設置autoplay為false)
      behave:{ type:Boolean, default: true }
    });
    // 定時器
    const timer:Ref<null|NodeJS.Timer> = ref(null);
    // 真正的播放速度
    const realSpeed = ref(1);
    // 開始滾動
    const beginScroll = () => {
      // 滾動容器
      const vueScrollWrapDom: HTMLElement | null = document.querySelector(".vue-scroll-wrap");
      // 滾動容器的寬(所有子元素的寬之和)
      const overWidth = Array.from(document.querySelectorAll(".vue-scroll-wrap .vue-scroll-slide"))
        .map(e => e.clientWidth).reduce((a,b) => a + b);
      // 定義定時器開始滾動
      if(vueScrollWrapDom){
        timer.value = setInterval(() => {
          // 獲取滾之前的滾動距離
          const translateXs = vueScrollWrapDom.style.transform.match(/translateX\((.*)px\)/);
          let oldTranslateX = translateXs ? Number(translateXs[1]) : 0;
          // 如果滾動距離大于等于總距離的1/2,也就說明滾完了第一組(總共有兩組來做無縫銜接),當第二組開始的時候讓滾動距離置為0,從頭開始
          if(Math.abs(oldTranslateX) >= (overWidth / 2)) oldTranslateX = 0;
          // 設置滾動距離
          vueScrollWrapDom.style.transform = `translateX(${oldTranslateX - realSpeed.value}px)`;
        },30)
      }
    }
    // 停止滾動
    const stopScroll = () => {
      if(timer.value) clearInterval(timer.value);
    }
    // 處理播放速度(為防止參數輸錯做處理)
    const handleSpeed = (sped:number) => {
      if(sped < 1) return 1;
      if(sped > 10) return 10;
      return sped;
    }
    // 鼠標移入
    const onMouseEn = () => {
      props.behave ? stopScroll() : beginScroll();
    }
    // 鼠標移出
    const onMouseLe = () => {
      props.behave ? beginScroll() : stopScroll();
    }
    onMounted(() => {
      realSpeed.value = handleSpeed(props.speed);
      if(props.autoplay) beginScroll();
    })
    </script>
    <template>
      <div class="vue-scroll" @mouseenter="onMouseEn" @mouseleave="onMouseLe">
        <ul class="vue-scroll-wrap">
          <slot></slot>
          <slot></slot>
        </ul>
      </div>
    </template>
    <style lang="less" scoped>
    .vue-scroll{ overflow: hidden;cursor: pointer;
      .vue-scroll-wrap { padding:0;margin:0;white-space: nowrap;}
    }
    </style>

    子組件的實現

    父組件實現之后,子組件就很容易了。子組件只需要提供一個插槽可以放內容就夠了。

    子組件源碼如下:

    <script setup lang="ts"></script>
    <template>
      <li class="vue-scroll-slide">
        <slot></slot>
      </li>
    </template>
    <style lang="less" scoped>
    .vue-scroll-slide{ list-style: none;display:inline-block;}
    </style>

    使用方法

    父子組件都實現完成之后,接下來我們看一下怎么使用。

    <script setup lang="ts">
    // 1.首先引入兩個組件
    import vueScroll from "@/components/vue-scroll/index.vue";
    import vueScrollSlide from "@/components/vue-scroll/vue-scroll-slide.vue";
    </script>
    <template>
        <!-- 2.使用組件 -->
        <vue-scroll :autoplay="true" :speed="1" :behave="true">
          <vue-scroll-slide>111</vue-scroll-slide>
          <vue-scroll-slide>222</vue-scroll-slide>
          <vue-scroll-slide>333</vue-scroll-slide>
        </vue-scroll>
    </template>
    <style lang="less" scoped></style>

    感謝各位的閱讀,以上就是“vue如何實現無縫滾動手摸手效果”的內容了,經過本文的學習后,相信大家對vue如何實現無縫滾動手摸手效果這一問題有了更深刻的體會,具體使用情況還需要大家實踐驗證。這里是億速云,小編將為大家推送更多相關知識點的文章,歡迎關注!

    向AI問一下細節

    免責聲明:本站發布的內容(圖片、視頻和文字)以原創、轉載和分享為主,文章觀點不代表本網站立場,如果涉及侵權請聯系站長郵箱:is@yisu.com進行舉報,并提供相關證據,一經查實,將立刻刪除涉嫌侵權內容。

    vue
    AI

    克拉玛依市| 齐齐哈尔市| 大庆市| 湘乡市| 安化县| 汾阳市| 南丰县| 洪湖市| 荆门市| 巴马| 柳林县| 开封市| 南木林县| 凤凰县| 兰溪市| 朔州市| 南充市| 澜沧| 山东省| 江口县| 页游| 闽侯县| 韶关市| 辽宁省| 旬邑县| 安庆市| 罗源县| 平原县| 屏东市| 商都县| 塔河县| 太湖县| 铁岭县| 吉林省| 武邑县| 朔州市| 观塘区| 普兰县| 双牌县| 安庆市| 和政县|