最新国产好看的视频,伊人天堂AV在线,国产Aaaaaa视频,蜜臀视频在线观看一区,人妻av色图,密臀久久久精品影片,青青视频免费观看毛片,久草在线观看视,国产三级精品色情在线

基于Vue3實(shí)現(xiàn)鼠標(biāo)滑動(dòng)和滾輪控制的輪播

 更新時(shí)間:2024年02月29日 14:05:54   作者:Jiude  
在這篇文章主要為大家詳細(xì)介紹了如何一步步地實(shí)現(xiàn)一個(gè)基于?Vue?3?的輪播組件,這個(gè)組件的特點(diǎn)是可以通過(guò)鼠標(biāo)滑動(dòng)和滾輪來(lái)控制輪播圖的切換,感興趣的可以了解下

需求

實(shí)現(xiàn)一個(gè)輪播組件,這個(gè)組件應(yīng)該有以下的特性:

  • 用戶可以通過(guò)鼠標(biāo)點(diǎn)擊來(lái)切換輪播圖。
  • 用戶可以通過(guò)鼠標(biāo)滑動(dòng)來(lái)切換輪播圖。
  • 用戶可以通過(guò)鼠標(biāo)滾輪來(lái)切換輪播圖。
  • 一開(kāi)始自動(dòng)切換,用戶操作時(shí)停止自動(dòng)切換,用戶停止操作一段時(shí)間后,繼續(xù)自動(dòng)切換。

效果圖

分析與設(shè)計(jì)

數(shù)組結(jié)構(gòu):

interface ListType {
    title: string
    icon: string
    img: string
    desc: string[]
}
const list: ListType = []

輪播中有一個(gè)唯一的active項(xiàng),設(shè)置其下標(biāo)為activeIndex

<ul class="swipper-wrapper">
    <li class="swipper-item" 
        v-for="(item, index) in list" 
        :class="{ active: index === activeIndex }"
        @click="activeIndex = index"
     >
      <img class="swipper-item-icon" :src="item.icon" alt="">
      {{ item.title }}
    </li>
 </ul>
const activeIndex = ref(0)

輪播最多可以同時(shí)展示7項(xiàng),設(shè)置常量NUM默認(rèn)值為7,理論上來(lái)說(shuō)可以通過(guò)activeIndex獲取展示的這7項(xiàng)的下標(biāo)(即取距離activeIndex最近的7項(xiàng), 因?yàn)樾枰嚯x最近,所以暫定這里NUM為奇數(shù)):

const NUM = 7 // 展示的卡片數(shù)量(奇數(shù))
function getSurroundingNumbers(length: number, activeIndex: number) {
  var start = activeIndex - (NUM - 1) / 2;
  var end = activeIndex + (NUM + 1) / 2;

  if (activeIndex < (NUM - 1) / 2) {
    start = 0;
    end = NUM;
  }

  if (activeIndex > length - (NUM + 1) / 2) {
    start = length - NUM;
    end = length;
  }

  var result = [];
  for (var i = start; i < end; i++) {
    result.push(i);
  }

  return result;
}

const surroundingNumbers = computed(() => getSurroundingNumbers(list.length, activeIndex.value))

比較每一項(xiàng)的下標(biāo)和surroundingNumbers,知道他在數(shù)組的前面還是后面還是里面,從而設(shè)置相應(yīng)的樣式:

function getSwiperItemStyle(index: number) {
  // 每個(gè)卡片高度60px 間隔16px
  // 最多正常展示NUM個(gè),其余藏在后,只露出16px高度
  const HIDEH = 15,
    H = 60,
    M = 16;
  
  let y = 0,
    scaleX = 1,
    backgroundColor = '#f9fbfc',
    zIndex = 9999,
    boxShadow = '2px 2px 1px 0px rgba(0,0,0,0.04), #fff 0px -2px 0px 0px';

  if (!surroundingNumbers.value.includes(index)) {
    backgroundColor = '#EBEDF2'
    zIndex = zIndex - Math.abs(activeIndex.value - index) + 2
    scaleX = 0.98 ** (Math.abs(activeIndex.value - index) + 2)

    if (index < surroundingNumbers.value[0]) {
      // 在上面
      y = HIDEH * index
      scaleX = 0.98 ** (surroundingNumbers.value[0] - index)
      boxShadow = '2px 2px 1px 0px rgba(255, 255, 255, .3) inset';
    } else {
      // 在下面
      y = surroundingNumbers.value[0] * HIDEH + (NUM - 1) * (H + M) + (index - surroundingNumbers.value.at(-1)!) * HIDEH
      scaleX = 0.98 ** (index - surroundingNumbers.value.at(-1)!)
      boxShadow = '2px 2px 1px 0px rgba(0,0,0,0.04)';
    }
  } else {
    y = surroundingNumbers.value[0] * HIDEH + (index - surroundingNumbers.value[0]) * (H + M)
  }

  if (activeIndex.value === index) {
    boxShadow = '5px 6px 12px 0px rgba(0,0,0,0.08), #fff 0px -2px 0px 0px';
  }


  return {
    transform: 'translateY(' + y / 19.2 + 'vw) scaleX(' + scaleX + ')',
    backgroundColor,
    zIndex,
    boxShadow
  }
}
<ul class="swipper-wrapper">
    <li class="swipper-item" 
        v-for="(item, index) in list" 
        :class="{ active: index === activeIndex }"
        :style="getSwiperItemStyle(index)"
        @click="activeIndex = index"
     >
      <img class="swipper-item-icon" :src="item.icon" alt="">
      {{ item.title }}
    </li>
 </ul>

交互實(shí)現(xiàn)

鼠標(biāo)滾輪切換

綁定滾動(dòng)事件@wheel="wheel"

// 處理鼠標(biāo)滾動(dòng)
function wheel(event: WheelEvent) {
  event.preventDefault(); // 防止頁(yè)面滾動(dòng)
  if (event.deltaY < 0) {
    // 向下滾動(dòng),activeIndex減少
    activeIndex.value = Math.max(0, activeIndex.value - 1);
  } else {
    // 向上滾動(dòng),activeIndex增加
    activeIndex.value = Math.min(list.length - 1, activeIndex.value + 1);
  }
}

鼠標(biāo)滑動(dòng)切換

綁定鼠標(biāo)事件@mousedown="startSwipe" @mousemove="swipe" @mouseup="endSwipe" @mouseleave="endSwipe"

// 處理滑動(dòng)
let startY = 0; // 鼠標(biāo)按下時(shí)的y坐標(biāo)
let accumulatedDiffY = 0; // 累積的滑動(dòng)距離
let swiping = false; // 是否正在滑動(dòng)

function startSwipe(event: MouseEvent) {
  startY = event.clientY;
  swiping = true;
}

function swipe(event: MouseEvent) {
  if (!swiping) return;
  const currentY = event.clientY;
  const diffY = currentY - startY;

  // 累積滑動(dòng)距離
  accumulatedDiffY += diffY;

  // 假設(shè)每個(gè)元素的高度是100px
  const elementHeight = 84;

  // 使用累積的滑動(dòng)距離計(jì)算滑動(dòng)的元素?cái)?shù)量,向下取整
  const numItems = Math.floor(Math.abs(accumulatedDiffY) / elementHeight);

  if (accumulatedDiffY > 0) {
    // 向下滑動(dòng),activeIndex減少
    if (activeIndex.value <= 2) return
    activeIndex.value = Math.min(list.length - 3, activeIndex.value)
    activeIndex.value = Math.max(0, activeIndex.value - numItems);
    accumulatedDiffY -= numItems * elementHeight; // 更新累積的滑動(dòng)距離
  } else {
    // 向上滑動(dòng),activeIndex增加
    if (activeIndex.value >= list.length - 3) return
    activeIndex.value = Math.max(2, activeIndex.value)
    activeIndex.value = Math.min(list.length - 1, activeIndex.value + numItems);
    accumulatedDiffY += numItems * elementHeight; // 更新累積的滑動(dòng)距離
  }

  // 更新起始Y坐標(biāo)
  startY = currentY;
}

function endSwipe(event: MouseEvent) {
  swiping = false;
  accumulatedDiffY = 0; // 結(jié)束滑動(dòng)時(shí)重置累積的滑動(dòng)距離
}

自動(dòng)切換

// 自動(dòng)切換定時(shí)器
const { pause, resume } = useIntervalFn(() => {
  activeIndex.value++
  if (activeIndex.value >= list.length - 1) {
    activeIndex.value = 0
  }
}, 3000)

// 重新自動(dòng)切換的倒計(jì)時(shí)
const { start: startTimeoutFn, stop: stopTimeoutFn } = useTimeoutFn(resume, 5000)

在每個(gè)用戶操作的方法里先暫停自動(dòng)切換pause()并停止繼續(xù)切換的倒計(jì)時(shí)stopTimeoutFn,結(jié)束操作時(shí)再開(kāi)啟繼續(xù)切換的倒計(jì)時(shí)startTimeoutFn。

完整代碼

到此這篇關(guān)于基于Vue3實(shí)現(xiàn)鼠標(biāo)滑動(dòng)和滾輪控制的輪播的文章就介紹到這了,更多相關(guān)Vue3輪播內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!

相關(guān)文章

最新評(píng)論

沾化县| 清水河县| 会同县| 临武县| 深圳市| 库尔勒市| 湾仔区| 钟山县| 昌黎县| 田阳县| 天峨县| 漳平市| 临颍县| 三台县| 南涧| 襄汾县| 米泉市| 乌兰浩特市| 新化县| 嘉兴市| 辽宁省| 张掖市| 集安市| 宁强县| 阳高县| 崇仁县| 丰宁| 阳曲县| 聊城市| 会昌县| 噶尔县| 册亨县| 邢台县| 两当县| 齐齐哈尔市| 河池市| 景宁| 辽宁省| 平顶山市| 新闻| 南城县|