Vue:写一个可配置内容的的随机转盘(今天吃什么)

在线预览地址: 

今天吃什么https://jujubefoxx.github.io/WhatDoWeHaveToEat-/

代码: https://github.com/jujubefoxx/WhatDoWeHaveToEat-https://github.com/jujubefoxx/WhatDoWeHaveToEat- 效果图:

下面是代码

HTML

<div id="toEat">
    <div class="wrapper">
        <div :class=['light',onRotation?'light-twinkling':''] v-for="light in foodList"></div>
        <div class="panel">
            <div class="sector" v-for="food in foodList">
                <div class="sector-inner">
                    <span>{{ food }}</span>
                </div>
            </div>
            <div :class=["pointer",onRotation?'pointer-trans':''] @transitionend="afterTransitionend"
                 @click="handleClick">吃什么呢
            </div>
        </div>
    </div>
    <div class="result">{{ result }}</div>
    <div class="button" @click="showEdit=true">编辑配置</div>
    <div v-if="showEdit" id="popBox">
        <div class="close">
            <a href="javascript:void(0)" @click="showEdit=false">关闭</a>
        </div>
        <div class="content">
            <div class="content-title">
                当前配置
            </div>
            <div>
                <ul>
                    <li class="popBox-list" v-for="(food,index) in foodList">
                        {{ food }}
                        <a class="edit-button" href="javascript:void(0)" @click="handleEdit(index)">修改</a>
                    </li>
                </ul>
            </div>
        </div>
    </div>
</div>

样式部分参考自https://www.cnblogs.com/wenruo/p/9732704.html 包括下面JS中旋转的方法

   /* 样式参考自https://www.cnblogs.com/wenruo/p/9732704.html*/
        * { /* 重置默认样式 */
            margin: 0;
            padding: 0;
            border: none;
            outline: none;
            user-select: none;
        }

        .wrapper {
            position: relative;
            height: 200px;
            width: 200px;
            padding: 20px;
            background-color: #ff5555;
            box-shadow: #000000 0px 0px 10px;
            border-radius: 50%;
            margin: 20px auto;

        }

        .light {
            position: absolute;
            height: 10px;
            width: 10px;
            border-radius: 50%;
            top: 5px;
            left: 115px;
            transform-origin: 5px 115px;
        }

        .light-twinkling {
            animation: 1s twinkling 3, 100ms 3s twinkling 3;
        }

        .light:nth-child(2n) {
            background-color: #fafce7;
        }

        .light:nth-child(2n+1) {
            background-color: #ffe58b;
        }

        .light:nth-child(2) {
            transform: rotate(36deg);
        }

        .light:nth-child(3) {
            transform: rotate(72deg);
        }

        .light:nth-child(4) {
            transform: rotate(108deg);
        }

        .light:nth-child(5) {
            transform: rotate(144deg);
        }

        .light:nth-child(6) {
            transform: rotate(180deg);
        }

        .light:nth-child(7) {
            transform: rotate(216deg);
        }

        .light:nth-child(8) {
            transform: rotate(252deg);
        }

        .light:nth-child(9) {
            transform: rotate(288deg);
        }

        .light:nth-child(10) {
            transform: rotate(324deg);
        }

        .panel {
            position: relative;
            height: 200px;
            width: 200px;
            background-color: #b7b7b7;
            border-radius: 100px;
        }

        .sector {
            position: absolute;
            left: 100px;
            top: 0px;
            width: 100px;
            height: 200px;
            font-size: 14px;
            border-radius: 0px 100px 100px 0;
            overflow: hidden;
            transform-origin: left center;
        }

        .sector:nth-child(1) {
            transform: rotate(-18deg);
        }

        .sector:nth-child(2) {
            transform: rotate(18deg);
        }

        .sector:nth-child(3) {
            transform: rotate(54deg);
        }

        .sector:nth-child(4) {
            transform: rotate(90deg);
        }

        .sector:nth-child(5) {
            transform: rotate(126deg);
        }

        .sector:nth-child(6) {
            transform: rotate(162deg);
        }

        .sector:nth-child(7) {
            transform: rotate(198deg);
        }

        .sector:nth-child(8) {
            transform: rotate(234deg);
        }

        .sector:nth-child(9) {
            transform: rotate(270deg);
        }

        .sector:nth-child(10) {
            transform: rotate(306deg);
        }

        .sector:nth-child(2n+1) .sector-inner {
            background: #fef6e0;
        }

        .sector:nth-child(2n) .sector-inner {
            background: #ffffff;
        }

        .sector-inner {
            text-align: center;
            display: block;
            width: 40px;
            padding: 5px 3px 0 57px;
            height: 195px;
            transform: translateX(-100px) rotate(36deg);
            transform-origin: right center;
            border-radius: 100px 0 0 100px;
        }

        .sector-inner span {
            display: block;
            transform-origin: center;
            transform: rotate(-19deg);
            color: #d46854;
        }

        .pointer-trans {
            transition: transform 3s cubic-bezier(.2, .93, .43, 1);
        }

        .pointer {
            position: absolute;
            left: 79px;
            top: 79px;
            z-index: 10;
            height: 30px;
            width: 30px;
            padding: 6px;
            color: #fff899;
            line-height: 15px;
            font-size: 12px;
            text-align: center;
            background-color: #ff5350;
            border-radius: 50%;
            border: 1px solid #ff5350;

        }

        .pointer::after {
            content: '';
            position: absolute;
            left: 14px;
            top: -24px;
            border-width: 12px 6px;
            border-style: solid;
            border-color: transparent;
            border-bottom-color: #ff5350;
            transform-origin: center;
        }

        .button {
            cursor: pointer;
            padding: 5px;
            margin: 20px auto;
            width: 100px;
            background-color: #d46854;
            color: #fff;
            text-align: center;
            border-radius: 4px;
        }

        .result {
            height: 50px;
            line-height: 50px;
            text-align: center;
            /*margin: 20px 60px;*/
            margin: 0 auto;

        }

        /*背景层*/
        #popLayer {
            display: none;
            background-color: #B3B3B3;
            position: absolute;
            top: 0;
            right: 0;
            bottom: 0;
            left: 0;
            z-index: 10;
            -moz-opacity: 0.8;
            opacity: .80;
            filter: alpha(opacity=80); /* 只支持IE6、7、8、9 */
        }

        #popBox {
            background-color: #FFFFFF;
            z-index: 11;
            position: fixed;
            top: 50%;
            left: 50%;
            transform: translate(-50%, -50%);
            border-radius: 8px;
            overflow: hidden;
            box-shadow: 3px 3px 5px #2D2C3B;
        }

        #popBox .content {
            padding: 15px;
            font-size: 14px;
            text-align: left;
            line-height: 25px;
        }

        #popBox .close {
            text-align: right;
            margin-right: 5px;
            font-size: 12px;
            height: 25px;
            line-height: 25px;
            background-color: #F8F8F8;
        }

        /*关闭按钮*/
        #popBox .close a {
            color: #2D2C3B;
        }

        a {
            text-decoration: none;
        }

        .content-title {
            font-weight: 600;
            margin-bottom: 10px;
        }

        .popBox-list {
            display: flex;
            justify-content: space-between;
            align-items: center;
            margin: 10px 0;
        }

        .edit-button {
            height: 20px;
            font-size: 12px;
            line-height: 20px;
            margin-left: 50px;
            background: #d46854;
            color: #f2f2f2;
            padding: 3px;
            font-family: 微软雅黑, 宋体, Arial, Helvetica, Verdana, sans-serif;
            border-radius: 3px;
            -webkit-transition: all linear 0.30s;
            -moz-transition: all linear 0.30s;
            transition: all linear 0.30s;
        }

        .edit-button:hover {
            background: #385f9e;
        }

        @keyframes twinkling {
            50% {
                background: transparent;
            }
        }

JS部分

<!--引入cdn-->
<script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js"></script>
<script>
    const toEat = new Vue({
        //挂载
        el: "#toEat",
        data() {
            return {
                foodList: ["北京烤鸭", "烧鸡", "快餐", "麻辣烫", "炒饭", "面", "寿司", "烤肉", "火锅", "饺子"],//食物列表
                onRotation: false, // 记录当前是否正在旋转,如果正在旋转,就不能继续点击了
                result: '点击中间按钮看看今天吃啥',//结果文案
                nextStatus: {},//转盘的下一个状态
                showEdit: false //是否处于编辑状态
            }
        },
        methods: {
            afterTransitionend() {
                const {nextStatus} = this;
                setTimeout(() => { // 等闪烁三下结束
                    this.onRotation = false; //结束旋转状态
                    this.result = nextStatus.text; //更新结果文案为下一步状态的文案
                }, 300);
            },
            //获得当前结果
            getReward() {
                let getEle = document.getElementsByClassName.bind(document);
                let pointer = getEle('pointer')[0]; //获取指针元素
                let currentDeg = this.nextStatus.deg ? this.nextStatus.deg : 0; //如果当前已有角度则获取角度 无则为0
                // 转三圈到四圈
                let rotateDeg = Math.random() * 360 + 1080;
                currentDeg += rotateDeg; //加上旋转的随机角度
                let rewardText = this.foodList[Math.floor((currentDeg + 18) % 360 / 36)] //获取结果位置的食物
                this.nextStatus = {
                    deg: currentDeg,
                    text: `就决定是你了!${rewardText}`
                } //更新下一步状态
                pointer.style.transform = `rotateZ(${this.nextStatus.deg}deg)`; //旋转+动画
            },
            //重置
            reset() {
                this.onRotation = false; //关闭旋转状态
                this.result = '   '; //结果清空
            },
            // 功能1:转动转盘
            // 1.点击中间按钮转动转盘
            // 2.获得结果并显示
            // 3.制作灯闪效果
            handleClick() {
                if (this.onRotation) return; //如果在旋转 不执行

                this.reset(); //重置
                this.onRotation = true; //开启旋转状态 禁止点击事件
                this.getReward();//获取结果
            },
            handleEdit(index) {
                const value = prompt(`请输入需要替换${this.foodList[index]}的事物`);  //弹出输入框
                if (value) {
                    Vue.set(this.foodList, index, value) //更新新的值
                }
            }
        }
    });
</script>

  • 2
    点赞
  • 23
    收藏
    觉得还不错? 一键收藏
  • 2
    评论
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值