uniapp?實現(xiàn)自定義縮略滾動條效果
更新時間:2024年08月08日 10:14:40 作者:清云隨筆
這篇文章主要介紹了uniapp?實現(xiàn)自定義縮略滾動條,本文通過示例代碼給大家介紹的非常詳細,對大家的學習或工作具有一定的參考借鑒價值,需要的朋友參考下吧

<template>
<view class="container-scroll">
<!-- 文字導航 -->
<scroll-view class="scroll-view-text" scroll-x="true" v-if="type === 1">
<navigator
:url="item.url"
class="scroll-view-item"
:style="`width:${itemWidth}px`"
v-for="(item, index) in tarbarList"
:key="index"
>
<!-- 必須得多包一層 -->
<view class="text-container" :style="`width:${itemWidth}px`">
<view class="text-nav">
{{ item.title }}
</view>
</view>
</navigator>
</scroll-view>
<!-- 圖文導航 -->
<scroll-view
class="img-scroll-view"
scroll-x="true"
@scroll="handleScroll"
ref="scrollView"
v-if="type === 2"
>
<view class="scroll-view-container">
<navigator
:url="item.url"
class="scroll-view-item"
:style="`width:${itemWidth}px`"
v-for="(item, index) in tarbarList"
:key="index"
>
<view class="nav-item">
<view class="image-container" :style="imageStyle">
<image
class="image"
:src="item.image"
mode="widthFix"
lazy-load="false"
:style="imageStyle"
>
</image>
</view>
<view class="text-title">
{{ item.title }}
</view>
</view>
</navigator>
</view>
</scroll-view>
</view>
<!-- 圖文導航自定義滾動條 -->
<view
class="custom-scroll-container"
v-if="type === 2 && showNumber < tarbarList.length"
>
<view class="custom-scroll">
<view
class="scroll"
:style="`transform:translateX(${translateXValue}px)`"
/>
</view>
</view>
</template>
<script setup name="imageTextNavigator">
import { onMounted, ref, getCurrentInstance, computed } from "vue";
const props = defineProps({
type: {
// 1 圖文導航 2 文字導航
type: Number,
default: 2,
},
// 首屏展示數(shù)量
showNumber: {
type: Number,
default: 4,
}, // 一屏顯示的數(shù)量
tarbarList: {
type: Array,
default: () => [
{
title: "導航導航導航導航",
image: "",
url: "",
},
{
title: "導航導航導航導航",
image: "",
url: "",
},
{
title: "導航導航導航導航",
image: "",
url: "",
},
{
title: "導航導航導航導航",
image: "",
url: "",
},
{
title: "導航5",
image: "",
url: "",
},
{
title: "導航6",
image: "",
url: "",
},
],
},
});
const instance = getCurrentInstance();
// 活動距離
const translateXValue = ref(0);
const itemWidth = ref(0);
// 計算滾動距離
function handleScroll(event) {
// 30 滑塊父盒子的寬度
// 8 滑塊的寬度
// scrollLeft 是 scroll-view 滾動的距離
const scrollLeft = event.detail.scrollLeft; // 獲取scroll-view滾動的距離
const scrollWidth = event.detail.scrollWidth; // 獲取scroll-view內(nèi)容的總寬度
const viewWidth = 375; // scroll-view的視口寬度
// 滑塊父容器的寬度為30,滑塊的寬度為8,計算出滑塊可移動的最大距離
const maxTranslateX = 30 - 8; // 最大滑動距離 22
// 計算滾動條的移動比例,將內(nèi)容滾動的比例映射到滑塊的移動范圍內(nèi)
const moveRatio = maxTranslateX / (scrollWidth - viewWidth); // 滑塊能夠移動距離 比上 大容器能夠滑動的距離,映射出 比率,最高就是 100% 嘛,等比換算
// 計算滑塊的實際位置,確保不會超過最大移動距離
translateXValue.value = Math.min(scrollLeft * moveRatio, maxTranslateX);
}
// 圖片樣式
const imageStyle = computed(() => {
return {
width: props.showNumber === 4 ? `44px` : `36px`,
height: props.showNumber === 4 ? `44px` : `36px`,
};
});
function getElementInfo(id, context) {
return new Promise((resolve, reject) => {
let query = uni.createSelectorQuery().in(context);
query
.select(id)
.boundingClientRect((rect) => {
if (rect) {
// 獲取的元素都是 px 需要乘以 2
resolve(rect);
} else {
reject();
}
})
.exec();
});
}
async function setNavItemWidth() {
const eleInfo = await getElementInfo(".container-scroll", instance);
const phoneWidth = eleInfo.width;
itemWidth.value = phoneWidth / props.showNumber;
}
onMounted(async () => {
await setNavItemWidth();
});
</script>
<style lang="scss" scoped>
.container-scroll {
width: 750rpx;
position: relative;
.scroll-view-text {
white-space: nowrap;
width: 750rpx;
display: flex;
.scroll-view-item {
display: inline-block;
background: #ffffff;
.text-container {
width: 150rpx;
height: 100%;
display: flex;
justify-content: center;
align-items: center;
.text-nav {
width: 112rpx;
font-weight: 400;
font-size: 28rpx;
color: #b2945e;
line-height: 28rpx;
font-style: normal;
text-transform: none;
white-space: break-spaces;
}
}
}
}
.img-scroll-view {
display: flex;
flex-wrap: nowrap;
white-space: nowrap;
box-sizing: border-box;
width: 750rpx;
.scroll-view-container {
// padding-left: 64rpx;
display: inline-block;
.scroll-view-item {
display: inline-block;
min-height: 154rpx;
background: #ffffff;
text-align: center;
.nav-item {
width: 100%;
height: 100%;
display: flex;
justify-content: center;
align-items: center;
flex-direction: column;
.text-title {
width: 112rpx;
font-weight: 400;
font-size: 28rpx;
color: #333333;
line-height: 28rpx;
white-space: break-spaces;
margin-top: 24rpx;
}
.image-container {
display: flex;
justify-content: center;
align-items: center;
.image {
background: #f3f3f3;
border-radius: 0px 0px 0px 0px;
}
}
}
}
}
}
}
// 兩種方案 絕對定位 \ 使用translateX
.custom-scroll-container {
width: 100%;
display: flex;
justify-content: center;
align-items: center;
padding-top: 24rpx;
.custom-scroll {
width: 60rpx;
overflow: hidden;
height: 6rpx;
background: #f3f3f3;
border-radius: 4px 4px 4px 4px;
position: relative;
.scroll {
width: 16rpx;
height: 6rpx;
background: #b2945e;
border-radius: 4px 4px 4px 4px;
/* 初始位置 */
transform: translateX(0rpx);
}
}
}
</style>補充:Vue3 通過 axios 獲取項目本地圖片文件進行上傳
<template>
<input
type="file"
ref="imageInput"
style="display: none"
@change="uploadImage"
/>
</template>
<script lang="tsx" setup>
import axios from 'axios'
import { ref, defineExpose, reactive } from 'vue'
import { ElMessage } from 'element-plus'
const imageInput = ref<any>(null)
// 1、項目本地實現(xiàn)上傳 方法
async function localUplaod() {
const imageUrl = require('@/assets/wxapp-icon/test.png') // 本地項目的路徑
const file = await getLocalImageAsFile(imageUrl)
const response = await uploadAPI(file)
}
// 2、模擬點擊事件,實現(xiàn) 本地電腦選擇讓圖片上傳
function handleClick(e) {
imageInput.value && imageInput.value.click()
}
// 自定義圖片上傳
async function uploadImage(event) {
const files = event.target.files
if (files.length === 0) {
ElMessage.error('沒有選擇文件')
return
}
// 讀取第一個文件(假設(shè)用戶只選擇一個文件)
const file = files[0]
if (!file.type.match('image/*')) {
ElMessage.error('請選擇一個圖片文件')
return
}
// 調(diào)用上傳API函數(shù)
try {
const response = await uploadAPI(file)
console.log('上傳成功', response)
ElMessage.success('上傳成功')
close()
} catch (error) {
console.log('error', error)
ElMessage.error('上傳失敗')
}
}
// 獲取本地圖片
async function getLocalImageAsFile(imagePath) {
try {
const response = await axios.get(imagePath, {
responseType: 'blob' // 指定響應(yīng)類型為blob
})
if (response.status === 200) {
// 使用 Blob 創(chuàng)建 File 對象
const file = new File([response.data], 'image.png', { type: 'image/png' })
return file
}
} catch (error) {
console.error('獲取圖片文件失敗:', error)
throw error
}
}
// 上傳API
function uploadAPI(dataFile) {
const file = dataFile
// 組裝成文件格式進行上傳
const formDatas = new FormData()
formDatas.append('file', file)
return new Promise((resolve, reject) => {
axios
.post<any, any>({
url: `xxx/xxx/xxx/xxx/xxx/xxx 上傳地址`,
data: formDatas,
headers: { 'Content-Type': 'multipart/form-data' }
})
.then((res) => {
resolve(res.data)
})
.catch((err) => {
reject(err)
})
})
}
defineExpose({
open,
close
})
</script>
<style lang="scss" scoped></style>到此這篇關(guān)于uniapp 實現(xiàn)自定義縮略滾動條的文章就介紹到這了,更多相關(guān)uniapp滾動條內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
使用bootstrap-paginator.js 分頁來進行ajax 異步分頁請求示例
本篇文章主要介紹了使用bootstrap-paginator.js 分頁來進行ajax 異步分頁請求示例,具有一定的參考價值,感興趣的小伙伴們可以參考一下。2017-03-03
JavaScript知識點總結(jié)(十一)之js中的Object類詳解
這篇文章主要介紹了JavaScript知識點總結(jié)(十一)之js中的Object類詳解的相關(guān)資料,需要的朋友可以參考下2016-05-05
input輸入框限制只能輸入數(shù)字的方法實例(個人認為最好的)
在很多業(yè)務(wù)中需要對輸入框進行字符限制,比如金額輸入框、手機號碼輸入框等,下面這篇文章主要給大家介紹了關(guān)于input輸入框限制只能輸入數(shù)字的相關(guān)資料,文中介紹的方法個人認為最好的,需要的朋友可以參考下2022-10-10
ionic在開發(fā)ios系統(tǒng)微信時鍵盤擋住輸入框的解決方法(鍵盤彈出問題)
在使用ionic開發(fā)ios系統(tǒng)微信的時候遇到一個bug,在填寫表單的時候鍵盤會擋住輸入框。下面小編給大家?guī)砹薸onic在開發(fā)ios系統(tǒng)微信時鍵盤擋住輸入框的解決方法(鍵盤彈出問題),非常不錯,有需要的朋友參考下吧2016-09-09
《JavaScript DOM 編程藝術(shù)》讀書筆記之JavaScript 圖片庫
這篇文章主要介紹了《JavaScript DOM 編程藝術(shù)》讀書筆記之JavaScript 圖片庫,需要的朋友可以參考下2015-01-01

