uniapp 实现自定义缩略滚动条

news2024/11/26 17:47:56

<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,
  },
  // 首屏展示数量
  showNumber: {
    type: Number,
    default: 4,
  }, // 一屏显示的数量
  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内容的总宽度
  const viewWidth = 375; // scroll-view的视口宽度

  // 滑块父容器的宽度为30,滑块的宽度为8,计算出滑块可移动的最大距离
  const maxTranslateX = 30 - 8; // 最大滑动距离 22

  // 计算滚动条的移动比例,将内容滚动的比例映射到滑块的移动范围内
  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>

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1985673.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

LE-50821F/FA激光扫描传感器|360°避障雷达之功能与连接使用说明

LE-50821F/FA激光扫描传感器|360避障雷达广泛应用于工业自动化、移动机器人应用场景中的环境感知、高精度定位&#xff08;如建图、扫描、避障、防护等&#xff09; LE-50xxxF系列升级扫描频率最高可达600KHz​​​​。 本文重点介绍LE-50821F/FA激光扫描传感器|360避障雷达之…

【C++】二维数组 数组名

二维数组名用途 1、查看所占内存空间 2、查看二维数组首地址 针对第一种用途&#xff0c;还可以计算数组有多少行、多少列、多少元素 针对第二种用途&#xff0c;数组元素、行数、列数都是连续的&#xff0c;且相差地址是有规律的 下面是一个实例 #include<iostream&g…

FreeRTOS基础入门——FreeRTOS的系统配置(三)

个人名片&#xff1a; ​ &#x1f393;作者简介&#xff1a;嵌入式领域优质创作者&#x1f310;个人主页&#xff1a;妄北y &#x1f4de;个人QQ&#xff1a;2061314755 &#x1f48c;个人邮箱&#xff1a;[mailto:2061314755qq.com] &#x1f4f1;个人微信&#xff1a;Vir202…

基于大模型的Agent

2023年&#xff0c;对于所有的人工智能领域只有一个共同的主题——大模型。大模型的受关注程度与发展速度可谓前所未有。其中&#xff0c;基于大模型的Agent又是最近几个月大模型领域的热点。这不开始研究没有几个月&#xff0c;综述文章都出来了&#xff0c;你说快不快&#x…

FashionAI比赛-服饰属性标签识别比赛赛后总结(来自 Top14 Team)

关联比赛: FashionAI全球挑战赛—服饰属性标签识别 推荐大家看本篇博客之前&#xff0c;看一下数据集制作的方法&#xff0c;如何做一个实用的图像数据集 PS&#xff1a;我是参加完比赛之后才看的&#xff0c;看完之后&#xff0c;万马奔腾.....&#xff0c;因为发现比赛中还…

62 函数参数——传递参数时的序列解包

与可变长度的参数相反&#xff0c;这里的序列解包是指实参&#xff0c;同样也有 * 和 ** 两种形式。 ① 调用含有多个位置参数的函数时&#xff0c;可以使用 Python 列表、元组、集合、字典以及其他可迭代对象作为实参&#xff0c;并在实参名称前加一个星号&#xff0c;Python …

element-ui/plus使用el-date-picker周 选择器返回时间范围处理案例

element-ui/plus使用el-date-picker周 选择器返回时间范围处理案例 如图所示 <el-date-pickerchange"changeTime":picker-options"{ firstDayOfWeek: 1 }"v-model"value1"type"week"format"YYYY年 第ww周"placeholder&…

C++初学者指南-5.标准库(第二部分)--数值运算算法

C初学者指南-5.标准库(第二部分)–数值运算算法 文章目录 C初学者指南-5.标准库(第二部分)--数值运算算法iota (注意不是itoa函数)Reductions reduce transform_reduce遗留操作&#xff08;无法并行执行&#xff09;accumulate (≈ reduce) C98inner_product (≈ transform_r…

sanger序列拼接--一次错误示范

文章目录 目的实现步骤 目的 NGS得到了很多的reads&#xff0c;其中有一些paired reads我想根据overlap 搭建起来&#xff0c;因为我对序列的ID做了删减&#xff0c;所以再pandaseq那里跑不通。 总结来说&#xff0c;目的很简单&#xff0c;就是把 有重叠区域的 reads 搭起来…

【学习笔记】A2X通信的协议(二)- A2X配置参数

目录 5. A2X配置参数 5.1 一般说明 5.2 A2X配置参数的配置和优先级 5.2.1 一般说明 5.2.2 A2X配置参数的优先级 5.2.3 通过PC5进行的A2X通信的配置参数 5.2.4 广播远程ID&#xff08;BRID&#xff09;的配置参数 5.2.5 直接检测和避免&#xff08;DDAA&#xff09;的配…

解决 Beyond Compare 30天过期问题

解决 Beyond Compare 30天过期的步骤如下&#xff1a; 1、使用快捷键WinR打开运行窗口&#xff0c;输入regedit并回车&#xff0c;打开注册表编辑器。 2、在注册表编辑器中&#xff0c;找到Beyond Compare的注册表位置&#xff0c;路径通常是HKEY_CURRENT_USER\Software\Scoot…

【redis】springboot 用redis stream实现MQ消息队列 考虑异常ack重试场景

redis stream是redis5引入的特性&#xff0c;一定程度上借鉴了kafka等MQ的设计&#xff0c;部署的redis版本必须 > 5 本文主要讲的是思路&#xff0c;结合简单的源码分析&#xff08;放心&#xff0c;无需深入大量源码&#xff09;&#xff1b;讲述在redis stream文档缺乏&a…

港科夜闻 | 香港科大,中大,港大及国大获旭日慈善基金捐款港币五千万元,支持基础数学研究及人才发展...

关注并星标 每周阅读港科夜闻 建立新视野 开启新思维 1、香港科大、中大、港大及国大获旭日慈善基金捐款港币五千万元&#xff0c;支持基础数学研究及人才发展。香港科大校长叶玉如教授在会上代表四所大学&#xff0c;就旭日慈善基金会对推动高等教育及基础研究发展的慷慨支持&…

探索智谱AI的视频生成神器:CogVideoX完全指南

引言 在当今数字化和内容创作高度发达的时代&#xff0c;视频已经成为信息传播和营销的重要工具。然而&#xff0c;对于许多缺乏视频制作经验或资源的个人和企业而言&#xff0c;如何快速、高效地创建吸引人的视频仍然是一个挑战。智谱AI推出的CogVideoX&#xff0c;作为一款先…

PuerTS和HybridCLR哪个更适合开发微信小游戏

1&#xff09;PuerTS和HybridCLR哪个更适合开发微信小游戏 2&#xff09;使用了Play Asset Delivery提交版本被Google报错 3&#xff09;怎样设置normalize来改变摄像机位置 4&#xff09;如何禁用增强型输入法中除某些输入操作之外的输入操作 这是第397篇UWA技术知识分享的推送…

CodeWave常用功能

1、CodeWave添加H5或PC端 CodeWave在左侧侧边栏&#xff0c;可通过“”按钮&#xff0c;直接添加PC端或H5端&#xff0c;或添加页面。 2、修改主题颜色 CodeWave左侧栏对应端的更多按钮中&#xff0c;可对权限及主题色进行修改。 在主题样式修改页面&#xff0c;右侧提供了预…

视频监控汇聚平台LntonCVS视频监控管理平台解决方案和常见的接入方式

一、视频融合平台 LntonCVS是一款支持多种协议和设备接入的视频汇聚流媒体平台。它能够统一管理和整合不同品牌、不同协议的视频资源&#xff0c;构建视频数据资源池&#xff0c;并通过视频资源目录为各类业务场景提供丰富、实时、高清的视频资源。 二、接入方式 1. 前端设备…

成都跃享未来教育咨询抖音小店共绘未来发展

在数字经济的浪潮中&#xff0c;教育行业正经历着前所未有的变革与升级。成都&#xff0c;这座历史悠久而又充满活力的城市&#xff0c;正以其独特的地理位置、深厚的文化底蕴和前瞻性的发展战略&#xff0c;孕育着教育创新的新篇章。其中&#xff0c;成都跃享未来教育咨询抖音…

水域救援设备,保护水域安全_鼎跃安全

季作为一年中最炎热的季节&#xff0c;不仅带来了难耐的高温&#xff0c;也悄然间加剧了水域安全问题的严峻性。这一时期&#xff0c;正值学生群体享受悠长暑假的宝贵时光&#xff0c;他们往往倾向于寻找清凉之地以解酷暑&#xff0c;水域因此成为了不少学生的首选之地。然而&a…

Linux(CentOS)环境搭建Gitea做私有的git服务器

基本分三大步骤&#xff0c;1.安装Gitea&#xff0c;2.安装MySQL&#xff08;或者SQlite等其中一款数据库&#xff09;3.安装Git 一.Gitea Gitea文档地址&#xff1a;文档 - Docs (gitea.io) Gitea的官网&#xff1a;https://gitea.io Gitea最新版本的下载地址&#xff1a;…