PC端横向滚动之回到指定位置---Vue3


PC端横向滚动之回到指定位置—Vue3

步骤

1.页面加载就需要指定到指定的位置

大盒子的ref.value.scrollLeft = 小盒子ref数组.value[指定位置的索引].offsetLeft - 小盒子ref数组.value[第0项].offsetLeft;
因为第0项一般都会距离左侧还有一部分需要剪掉,不要把减去的写死了,因为在不同分辨率的电脑下的距离也是不一样的

2.绑定回到某个位置的按钮,这个自己绑定一个点击事件,触发第一点即可

3.监听与销毁视图变化,视图变大或变小,都会影响你指定的位置变化,因为你的没位置未能跟着一起变化,记得销毁

onMounted(function () {
    window.addEventListener('resize', ()=>{第一点});  //缩放即会将原有的位置出现偏移,因此监听视图变化
});
onBeforeUnmount(() => {
    window.removeEventListener('resize',()=>{
            第一点
    })  //销毁事件
})

示例

<template>
    <div class="UserHome box-border">
        <a-row :gutter="[0, 20]">
            <a-col :span="24" :order="1">
                <div class="BoxBorder px-[20rem] pt-[20rem] pb-[10rem] min-h-[272rem] box-border">
                    <div style="display: flex;justify-content: space-between;">
                      <div class="FontBlack pb-[13rem]">糖尿病服务方案</div>
                      <app-button @click="goToday">回到今日</app-button>
                    </div>
                    <div class="flex box" @mousedown="startDrag" @mousemove="onDrag" @mouseup="mouseup" @mouseleave="stopDrag">
                        <div class="flex scrollBox" ref="scrollContent" v-show="newData?.length">
                            <div class="flex mr-[30px]" v-for="(item, index) in newData" :ref="(item:any) => setItemRef(item,index)" :key="index">
                             <!--......每一项-->
                            </div>
                        </div>
                        <div class="flex justify-center flex-1" v-if="!newData?.length">
                            <a-empty description="暂无数据" />
                        </div>
                    </div>
                </div>
            </a-col>
        </a-row>
    </div>
</template>

<script lang="ts" setup>
import { ref, onMounted, watch, shallowRef, computed, nextTick, onBeforeUnmount } from "vue";
import { defineComponent } from "vue";
import diseaseLable from "./disease-lable.vue";
import { throttle } from "lodash";
import { getNewUserHealthPathExecuteList, getHistoryUserHealthPathExecuteList } from "@/services/api/360";
import { useRoute } from "vue-router";

const route = useRoute();

onMounted(async function () {
    await getNewList(true);
    await getOldList(true);
    tableList();
    window.addEventListener('resize', onSizeMt);  //缩放即会将原有的位置出现偏移,因此监听视图变化
});
onBeforeUnmount(() => {
    window.removeEventListener('resize', onSizeMt)  //销毁事件
})
    
defineComponent({
    components: {
        diseaseLable,
    },
    props: {
        data: {
            type: Object,
            default: () => new Object(),
        },
    },
});
// 整个大盒子的ref初始化
const scrollContent = ref();
// 判断是否松开鼠标按键
let isDragging = false;
// 事件对象的x轴距离减去大盒子距离左部的距离
let startX = 0;
// 距离左边
let scrollLeft = 0;
// 左滑右滑
let startZY = ref(0);
let startSX = ref(0);
// 判断是否左滑还是右滑
let swipeDirection = ref();
    
const dataFlag = ref(true);

const oldPageIndex = ref(1);
const oldPageSize = ref(1000);
const dataOldFlag = ref(true);

// 定位数据长度
const nowIndex = ref(0)

// 新数据
const newData = shallowRef<any[]>([]);

const pageIndex = ref(1);
const pageSize = ref(1000);
// 鼠标按下
const startDrag = (e: any) => {
    //console.dir(scrollContent.value.offsetLeft);
    //console.log(e);
    isDragging = true;
    startX = e.pageX - scrollContent.value.offsetLeft;
    scrollLeft = scrollContent.value.scrollLeft;

    // startZY.value = e.clientX;
    // startSX.value = e.clientY;
};

// 定位到指定的位置
const onSizeMt = () => {
    scrollContent.value.scrollLeft = itemRefs.value[nowIndex.value]?.offsetLeft - itemRefs.value[0]?.offsetLeft;

}
// 鼠标移动
const onDrag = (e: any) => {
    if (!isDragging) return;  //如果没按下鼠标就移动,则失效
    e.preventDefault();
    const x = e.pageX - scrollContent.value.offsetLeft;
    const walk = (x - startX) * 3; // Scroll-fast
    scrollContent.value.scrollLeft = scrollLeft - walk;
    
   /* 
   const currentX = e.clientX;
    const currentY = e.clientY;
    const diffX = startZY.value - currentX;
    const diffY = startSX.value - currentY;
   if (Math.abs(diffX) > Math.abs(diffY)) {
        swipeDirection.value = diffX > 0 ? "Right" : "Left";
    } 这里是监听左滑右滑,不用管*/ 
};
    
// 鼠标抬起
const mouseup = throttle(() => {
    if (!isDragging) return;
    nextTick(() => {
        isDragging = false;
    });
}, 500);
// 鼠标离开
const stopDrag = () => {
    isDragging = false;
};
// 新列表
const getNewList = (flag?: boolean) => {
    getNewUserHealthPathExecuteList({
        pageIndex: pageIndex.value,
        pageSize: pageSize.value,
        userIdentityId: route.query.userIdentityId as string,
    }).then((res: any) => {
        if (!res.data) return;
        if (res.data?.data.length === 0) {
            dataFlag.value = false;
        }
        res.data?.data.forEach((item: any) => {
            item.items.forEach((row: any) => {
                if (row.status === 0 || row.status === 1) {
                    row.img = require("../images/img3.png");
                } else if (row.status === 2) {
                    row.img = require("../images/img4.png");
                }
            });
        });
        if (flag) {
            newData.value = [...newData.value, ...res.data?.data];
        }
    });
};
const itemRefs = ref<any[]>([]); // ref数组
// 动态绑定ref
const setItemRef = (item: any, index: number) => {
    if (item) {
        itemRefs.value[index] = item;
    }
};
// 历史数据接口
const getOldList = (flag?: boolean) => {
    getHistoryUserHealthPathExecuteList({
        pageIndex: oldPageIndex.value,
        pageSize: oldPageSize.value,
        userIdentityId: route.query.userIdentityId as string,
    }).then((res: any) => {
        if (!res?.data || res.data?.data.length === 0) {
            dataOldFlag.value = false;
            return
        }
        res.data?.data.forEach((item: any) => {
            item.items.forEach((row: any) => {
                if (row.status === 99) {
                    row.img = require("../images/img2.png");
                }
            });
        });
        newData.value = [...res.data?.data, ...newData.value];  // 合并新老数据
        nowIndex.value = res.data?.data.length   //拿到回到新数据的第一条,即老数据的长度
        if (flag && itemRefs.value.length) {
            nextTick(() => {
                scrollContent.value.scrollLeft = itemRefs.value[res.data?.data.length].offsetLeft - itemRefs.value[0].offsetLeft;
                
            });
            console.log(itemRefs.value[0].offsetLeft)
        }
    });
};
//  回到指定位置
const goToday = ()=>{
  scrollContent.value.scrollLeft = itemRefs.value[nowIndex.value].offsetLeft - itemRefs.value[0].offsetLeft;
}

</script>

文章作者: 冷杨威
版权声明: 本博客所有文章除特別声明外,均采用 CC BY 4.0 许可协议。转载请注明来源 冷杨威 !
  目录
-->