手写滚轮式菜单

结果图

手写滚轮式菜单_第1张图片

实现逻辑

逻辑很简单,就是滚轮滚动这个转盘也跟着滚动,中间的大圆跟着最中间的小圆的颜色走;
代码实现也不难,如下:

const middleOne = ref(menus.value[2])
const wheelDown = (flag) => {
    if (flag) {
        let lastElement = menus.value.pop(); // 删除数组的最后一个元素并将其保存在变量中
        menus.value.unshift(lastElement); // 将保存的最后一个元素
    } else {
        let firstElement = menus.value.shift(); // 移除第一个元素并返回它
        menus.value.push(firstElement); // 将第一个元素添加到数组的末尾
    }
    middleOne.value = menus.value[2]; // 更新中间的元素
}

onMounted(() => {
    window.addEventListener('wheel', (e) => {
        if (e.wheelDelta > 0) {
            wheelDown(0)
        } else {
            wheelDown(1)
        }
    })
})

然后就是点击强行切换的功能,只能用滚轮切换难免有些僵硬,有的时候还是会想通过点击切换菜单

const clickFun = (index) => { // 点击事件
    console.log(index);
    if (index !== 2) {
        let count = index - 2;
        if (count > 0) {
            for (let i = 0; i < count; i++) {
                wheelDown(0)
            }
        } else {
            for (let i = 0; i < -count; i++) {
                wheelDown(1)
            }
        }
    }

}

有待改进(如果有空改掉了会更新)

  • 滚动没有动画,有些僵硬
  • 目前仅限五个菜单,css样式是写死的

实现代码

<template>
    <div class="wheelMenu">
        <div>
            <div class="menuItem" v-for="(item, index) in menus" :key="index" :style="'background:' + item.color"
                @click="clickFun(index)">
            </div>
            <div class="circle" :style="'background:' + middleOne.color">
                <div class="innerContent">
                    {{ middleOne.name }}
                </div>
            </div>
        </div>
    </div>
</template>
<script setup>
import { onMounted, ref } from 'vue';

const menus = ref([
    {
        name: '前端',
        color: 'lightgreen',
    }, {
        name: '后端',
        color: 'lightyellow',
    }, {
        name: 'UE4',
        color: 'lightblue',
    }, {
        name: '其他语言',
        color: 'lightpink',
    }, {
        name: '随笔',
        color: 'lightsalmon',
    }])
const middleOne = ref(menus.value[2])
const wheelDown = (flag) => {
    if (flag) {
        let lastElement = menus.value.pop(); // 删除数组的最后一个元素并将其保存在变量中
        menus.value.unshift(lastElement); // 将保存的最后一个元素
    } else {
        let firstElement = menus.value.shift(); // 移除第一个元素并返回它
        menus.value.push(firstElement); // 将第一个元素添加到数组的末尾
    }
    middleOne.value = menus.value[2]; // 更新中间的元素
}

const clickFun = (index) => { // 点击事件
    console.log(index);
    if (index !== 2) {
        let count = index - 2;
        if (count > 0) {
            for (let i = 0; i < count; i++) {
                wheelDown(0)
            }
        } else {
            for (let i = 0; i < -count; i++) {
                wheelDown(1)
            }
        }
    }

}

onMounted(() => {
    window.addEventListener('wheel', (e) => {
        if (e.wheelDelta > 0) {
            wheelDown(0)
        } else {
            wheelDown(1)
        }
    })
})

</script>
<style>
.wheelMenu {
    width: 400px;
    height: 200px;
    position: fixed;
    bottom: 0;
    left: 50%;
    transform: translate(-50%, 0);
    /*水平居中*/

}

.circle {
    position: absolute;
    width: 200px;
    height: 200px;
    bottom: -100px;
    left: 100px;
    background-color: lightblue;
    border-radius: 50%;
}

.innerContent {
    line-height: 100px;
    margin: auto;
    font-size: larger;
    font-weight: bolder;
    color: black;
}

.menuItem {
    position: absolute;
    width: 40px;
    height: 40px;
    box-shadow: 0px 0px 15px #ffffff;
    border-radius: 50%;
}

.menuItem:nth-child(1) {
    right: 20px;
    bottom: 20px;
}

.menuItem:nth-child(2) {
    right: 53px;
    bottom: 127px;
}

.menuItem:nth-child(3) {
    right: 180px;
    bottom: 180px;

}

/* 下面的小箭头 */
.menuItem:nth-child(3)::after {
    content: "";
    position: absolute;
    bottom: -15px;
    right: 12px;
    left: 12px;
    width: 0;
    height: 0;
    border-style: solid;
    border-width: 0px 8px 8px 8px;
    border-color: transparent transparent white transparent;
}

.menuItem:nth-child(3):active:after {
    border-color: transparent transparent rgb(255, 166, 0) transparent;
}

.menuItem:nth-child(4) {
    left: 53px;
    bottom: 127px;

}

.menuItem:nth-child(5) {
    left: 20px;
    bottom: 20px;

}
</style>


你可能感兴趣的:(web技术,前端vue,自定义组件,前端)