記錄--你還在用傳統輪播組件嗎?來看看遮罩輪播組件

来源:https://www.cnblogs.com/smileZAZ/archive/2023/07/19/17566449.html
-Advertisement-
Play Games

這裡給大家分享我在網上總結出來的一些知識,希望對大家有所幫助 背景 最近有一個頁面改版的需求,在UI走查階段,設計師說原來的輪播組件和新版頁面UI整體風格不搭,所以要換掉。 這裡就涉及到兩種輪播組件,一種是傳統的輪播組件,一種是設計師要的那種。 傳統的輪播組件,大家都見過,原理也清楚,就是把要輪播的 ...


這裡給大家分享我在網上總結出來的一些知識,希望對大家有所幫助

 

背景

最近有一個頁面改版的需求,在UI走查階段,設計師說原來的輪播組件和新版頁面UI整體風格不搭,所以要換掉。

這裡就涉及到兩種輪播組件,一種是傳統的輪播組件,一種是設計師要的那種。

傳統的輪播組件,大家都見過,原理也清楚,就是把要輪播的圖片橫向排成一個隊列,把他們當成一個整體,每次輪換,其實是把這個隊列整體往左平移X像素,這裡的X通常就是一個圖片的寬度。 這種效果可以參見vant組件庫里的swipe組件

而我們設計師要的輪播效果是另外一種,因為我利用端午假期已經做好了一個雛形,所以大家可以直接看Demo

當然你也可以直接打開 騰訊視頻APP 首頁,頂部的輪播,就是我們設計師要的效果。

需求分析

新式輪播,涉及要兩個知識點:

  • 圖片層疊
  • 揭開效果

與傳統輪播效果一個最明顯的不同是,新的輪播效果需要把N張待輪播的圖片在Z軸上重疊放置,每次揭開其中的一張,下一張是自然漏出來的。這裡的實現方式也有多種,但最先想到的還是用zindex的方案。

第二個問題是如何實現揭開的效果。這裡就要使用到css3的新屬性mask。 mask是一系列css的簡化屬性。包括mask-image, mask-position等。 因為mask的系列屬性還有一定的相容性,所以一部分瀏覽器需要帶上-webkit-首碼才能生效。

還有少數瀏覽器不支持mask屬性,退化的情況是輪播必須有效,但是沒有輪換的動效。

實現

有了以上的分析,就可以把效果做出來了。核心代碼如下:

<script setup lang="ts">
 import { ref, onMounted, watch } from "vue";
 // 定義屬性
const props = defineProps([
  'imgList',
  'duration', 
  'transitionDuration',
  'maskPositionFrom', 
  'maskPositionTo',
  'maskImageUrl'
]);
 // 定義響應式變數
const currentIndex = ref(0);
const oldCurrentIndex = ref(0);
const imgList = ref([...props.imgList, props.imgList[0]]);
const getInitZindex = () => {
  const arr = [1];
  for (let i = imgList.value.length - 1; i >= 1; i--) {
    arr.unshift(arr[0] + 1);
  }
  return arr;
}
const zIndexArr = ref([...getInitZindex()]);
const maskPosition = ref(props.maskPositionFrom || 'left');
const transition = ref(`all ${props.transitionDuration || 1}s`);
 // 設置動畫參數
const transitionDuration = props.transitionDuration || 1000;
const duration = props.duration || 3000;

 // 監聽currentIndex變化
watch(currentIndex, () => {
  if (currentIndex.value === 0) {
    zIndexArr.value = [...getInitZindex()];
  }
  maskPosition.value = props.maskPositionFrom || 'left';
  transition.value = 'none';
})
 // 執行動畫
const execAnimation = () => {
  transition.value = `all ${props.transitionDuration || 1}s`;
  maskPosition.value = props.maskPositionFrom || 'left';
  maskPosition.value = props.maskPositionTo || 'right';
  oldCurrentIndex.value = (currentIndex.value + 1) % (imgList.value.length - 1);
   setTimeout(() => {
    zIndexArr.value[currentIndex.value] = 1;
    currentIndex.value = (currentIndex.value + 1) % (imgList.value.length - 1);
  }, 1000)
}
 // 掛載時執行動畫
onMounted(() => {
  const firstDelay = duration - transitionDuration;
  function animate() {
    execAnimation();
    setTimeout(animate, duration);
  }
  setTimeout(animate, firstDelay);
})
 </script>
 <template>
  <div class="fly-swipe-container">
    <div class="swipe-item"
         :class="{'swipe-item-mask': index === currentIndex}"
         v-for="(url, index) in imgList"
         :key="index"
         :style="{ zIndex: zIndexArr[index],
         'transition': index === currentIndex ? transition : 'none',
         'mask-image': index === currentIndex ? `url(${maskImageUrl})` : '',
         '-webkit-mask-image': index === currentIndex ? `url(${maskImageUrl})`: '',
         'mask-position':  index === currentIndex ? maskPosition: '',
         '-webkit-mask-position':  index === currentIndex ? maskPosition: '' }">
      <img :src="url" alt="">
    </div>
    <div class="fly-indicator">
      <div class="fly-indicator-item"
           :class="{'fly-indicator-item-active': index === oldCurrentIndex}"
           v-for="(_, index) in imgList.slice(0, imgList.length - 1)"
           :key="index"></div>
    </div>
  </div>
</template>
 <style lang="less" scoped>
.fly-swipe-container {
  position: relative;
  overflow: hidden;
  width: 100%;
  height: inherit;
   .swipe-item:first-child {
    position: relative;
  }
  .swipe-item {
    position: absolute;
    width: 100%;
    top: 0;
    left: 0;
     img {
      display: block;
      width: 100%;
      object-fit: cover;
    }
  }
   .swipe-item-mask {
    mask-repeat: no-repeat;
    -webkit-mask-repeat: no-repeat;
    mask-size: cover;
    -webkit-mask-size: cover;
  }
   .fly-indicator {
    display: flex;
    justify-content: center;
    align-items: center;
    z-index: 666;
    position: relative;
    top: -20px;
    .fly-indicator-item {
      margin: 0 5px;
      width: 10px;
      height: 10px;
      border-radius: 50%;
      background: gray;
    }
    .fly-indicator-item-active {
      background: #fff;
    }
  }
}
</style>

這是一個使用 Vue 3 構建的圖片輪播組件。在這個組件中,我們可以通過傳入一組圖片列表、切換動畫的持續時間、過渡動畫的持續時間、遮罩層的起始位置、遮罩層的結束位置以及遮罩層的圖片 URL 來自定義輪播效果。

組件首先通過 defineProps 定義了一系列的屬性,並使用 ref 創建了一些響應式變數,如 currentIndexoldCurrentIndeximgListzIndexArr 等。

onMounted 鉤子函數中,我們設置了一個定時器,用於每隔一段時間執行一次輪播動畫。 在模板部分,我們使用了一個 v-for 指令來遍歷圖片列表,並根據當前圖片的索引值為每個圖片元素設置相應的樣式。同時,我們還為每個圖片元素添加了遮罩層,以實現輪播動畫的效果。

在樣式部分,我們定義了一些基本的樣式,如輪播容器的大小、圖片元素的位置等。此外,我們還為遮罩層設置了一些樣式,包括遮罩圖片的 URL、遮罩層的位置等。

總之,這是一個功能豐富的圖片輪播組件,可以根據傳入的參數自定義輪播效果。

後續

因為mask可以做的效果還有很多,後續該組件可以封裝更多輪播效果,比如從多個方向的揭開效果,各種漸變方式揭開效果。歡迎使用和提建議。

倉庫地址:github.com/cunzaizhuyi…

本文轉載於:

https://juejin.cn/post/7251564871510163512

如果對您有所幫助,歡迎您點個關註,我會定時更新技術文檔,大家一起討論學習,一起進步。

 


您的分享是我們最大的動力!

-Advertisement-
Play Games
更多相關文章
  • 對於GaussDB來說,在今天引入數據壓縮,究竟能夠給客戶帶來什麼不一樣的價值,是過去一段時間我們一直在思考的問題。 ...
  • ## 背景概述 在一次客戶的資料庫實例連接不上了,需要我們排查一下原因,通過查看資料庫實例進程已經不存在了,在錯誤日誌中沒有發現其他報錯信息,發現有`shutdown`的字樣出現,懷疑是某個用戶手動關閉了實例。我們通過以下測試,發現是由於用戶關閉了主機所導致的。 ## 問題復現 本次測試基於`Gre ...
  • 原文: [Android 妙用TextView實現左邊文字,右邊圖片 - Stars-One的雜貨小窩](https://stars-one.site/2023/07/19/android-tv-and-right-img) 有時候,需要文字在左邊,右邊有個箭頭,我個人之前會有兩種做法: > 使用線 ...
  • 鏈接(URL):https://www.hygrey.com/burpsuite-can-not-capture-https-packet-in-android7.html 來源(Source):渡緣人 渡緣人大佬的教程詳細的列出來Android 7 配置bp抓包的流程,也可以一同參考下麵的鏈接 h ...
  • > 原文地址: [Android LinearLayout快速設置每個item間隔](https://stars-one.site/2023/07/19/android-linearlayout-item-margin) 平常使用LinearLayout的時候,有時候會需要對每個item設置間距,但 ...
  • 博客推行版本更新,成果積累制度,已經寫過的博客還會再次更新,不斷地琢磨,高質量高數量都是要追求的,工匠精神是學習必不可少的精神。因此,大家有何建議歡迎在評論區踴躍發言,你們的支持是我最大的動力,你們敢投,我就敢肝 ...
  • 文件流下載轉Blob時類型匹配,例如: ```javascript let blob = new Blob([data], {type: 'audio/mpeg'}); ``` Blob配置類型如下表所示,[詳細介紹](https://developer.mozilla.org/zh-CN/docs ...
  • Vue文件解析 什麼是<template/>標簽 template是html5新元素,主要用於保存客戶端中的內容,表現為瀏覽器解析該內容但不渲染出來,可以將一個模板視為正在被存儲以供隨後在文檔中使用的一個內容片段。 關於單文件組件 vue的單文件相當於一個頁面中的組件,包含了關於該組件的html-c ...
一周排行
    -Advertisement-
    Play Games
  • 移動開發(一):使用.NET MAUI開發第一個安卓APP 對於工作多年的C#程式員來說,近來想嘗試開發一款安卓APP,考慮了很久最終選擇使用.NET MAUI這個微軟官方的框架來嘗試體驗開發安卓APP,畢竟是使用Visual Studio開發工具,使用起來也比較的順手,結合微軟官方的教程進行了安卓 ...
  • 前言 QuestPDF 是一個開源 .NET 庫,用於生成 PDF 文檔。使用了C# Fluent API方式可簡化開發、減少錯誤並提高工作效率。利用它可以輕鬆生成 PDF 報告、發票、導出文件等。 項目介紹 QuestPDF 是一個革命性的開源 .NET 庫,它徹底改變了我們生成 PDF 文檔的方 ...
  • 項目地址 項目後端地址: https://github.com/ZyPLJ/ZYTteeHole 項目前端頁面地址: ZyPLJ/TreeHoleVue (github.com) https://github.com/ZyPLJ/TreeHoleVue 目前項目測試訪問地址: http://tree ...
  • 話不多說,直接開乾 一.下載 1.官方鏈接下載: https://www.microsoft.com/zh-cn/sql-server/sql-server-downloads 2.在下載目錄中找到下麵這個小的安裝包 SQL2022-SSEI-Dev.exe,運行開始下載SQL server; 二. ...
  • 前言 隨著物聯網(IoT)技術的迅猛發展,MQTT(消息隊列遙測傳輸)協議憑藉其輕量級和高效性,已成為眾多物聯網應用的首選通信標準。 MQTTnet 作為一個高性能的 .NET 開源庫,為 .NET 平臺上的 MQTT 客戶端與伺服器開發提供了強大的支持。 本文將全面介紹 MQTTnet 的核心功能 ...
  • Serilog支持多種接收器用於日誌存儲,增強器用於添加屬性,LogContext管理動態屬性,支持多種輸出格式包括純文本、JSON及ExpressionTemplate。還提供了自定義格式化選項,適用於不同需求。 ...
  • 目錄簡介獲取 HTML 文檔解析 HTML 文檔測試參考文章 簡介 動態內容網站使用 JavaScript 腳本動態檢索和渲染數據,爬取信息時需要模擬瀏覽器行為,否則獲取到的源碼基本是空的。 本文使用的爬取步驟如下: 使用 Selenium 獲取渲染後的 HTML 文檔 使用 HtmlAgility ...
  • 1.前言 什麼是熱更新 游戲或者軟體更新時,無需重新下載客戶端進行安裝,而是在應用程式啟動的情況下,在內部進行資源或者代碼更新 Unity目前常用熱更新解決方案 HybridCLR,Xlua,ILRuntime等 Unity目前常用資源管理解決方案 AssetBundles,Addressable, ...
  • 本文章主要是在C# ASP.NET Core Web API框架實現向手機發送驗證碼簡訊功能。這裡我選擇是一個互億無線簡訊驗證碼平臺,其實像阿裡雲,騰訊雲上面也可以。 首先我們先去 互億無線 https://www.ihuyi.com/api/sms.html 去註冊一個賬號 註冊完成賬號後,它會送 ...
  • 通過以下方式可以高效,並保證數據同步的可靠性 1.API設計 使用RESTful設計,確保API端點明確,並使用適當的HTTP方法(如POST用於創建,PUT用於更新)。 設計清晰的請求和響應模型,以確保客戶端能夠理解預期格式。 2.數據驗證 在伺服器端進行嚴格的數據驗證,確保接收到的數據符合預期格 ...