前端学习|不知道学点啥好,不如搞一个学习盲盒~

Hah -
前端学习|不知道学点啥好,不如搞一个学习盲盒~

事情是这样的:昨天浏览豆瓣,看到有朋友分享了一个开盲盒学习法?

box.jpg

感觉这个办法不错呀!平时工作之余想学点东西,如果不是系统性的学习,很有可能就在【纠结学点什么好呢】的时候,纠结来纠结去就变成了【算了,下次一定】?

其实前端内容就这些:

前端知识图谱.png

在碎片时间,无所谓学什么,随机一个主题,弄懂一个相关的知识点,只要学到就是赚到。

不如给自己搞一个前端知识点盲盒【像那种抽奖转盘一样】,这样我们在碎片时间想学点东西的时候,就不用纠结学点啥好了,学习盲盒一点,学就完事了!

最终效果如下:

主要用到:vue2 + element-ui

布局

首先找几张想要学习内容的相关图片,我这里用了 grid 布局,3行3列:

<template>
  <div >
    <!-- 盲盒大转盘 -->
    <div v-for="item in contentList">
      <div
        
        :
        @click="handleClick(item.order)"
      >
        <img :src="item.content_img" alt=""  />
      </div>
    </div>
  </div>
</template>

给选中的图片加一个不同的样式类名 picked,和其他图片区分开来,我这里加了个边框和透明度(whatever u like)~

动起来

点击图片的处理逻辑是:只有点击了最中间的图片且此时转盘没有转动时,才进入后续的逻辑。后续的逻辑也比较简单,随机生成一个转动的步数,一圈一圈转就可以了,最后一两圈的时候放慢转速。

// methods
handleClick(order) {
  if (order !== 0 || this.hasStarted) return
  // 只处理中间按钮的点击事件
  this.start()
},
start() {
  // 随机生成一个步数,大概 3~6 圈
  this.totalSteps = Math.floor(Math.random() * 24) + 24
  // 已经走的步数
  let hasRun = 0
  this.move(hasRun)
},
move(hasRun) {
  const len = this.contentList.length - 1
  setTimeout(() => {
    if (hasRun <= this.totalSteps) {
      if (this.totalSteps - hasRun < 2 * len) {
        // 放慢速度
        this.speed = 300
      } else if (this.totalSteps - hasRun < len) {
        // 最后一轮,再慢一点
        this.speed = 600
      }
      // 当前选中的图片index
      this.curIndex = hasRun % len + 1
      // 步数加一
      hasRun++
      this.move(hasRun)
    } else {
      // 抽到了!初始化数据
      this.speed = 100
      this.hasStarted = false
      this.pickedIndex = this.curIndex
      // 获取抽到的内容,用于弹窗提示
      this.contentList.forEach(item => {
        if (item.order === this.pickedIndex) {
          this.pickedContent = item.name
        }
      })
      // 弹窗通知
      this.$alert(`今天可以学一学 ${this.pickedContent} 哦!`, {
        confirmButtonText: '知道啦',
        type: 'success',
        callback: () => {
          this.curIndex = 1
        }
      });
    }
  }, this.speed)
}

没啥复杂的,写着玩玩哈哈!~~~

全部代码
<template>
  <div >
    <!-- 盲盒大转盘 -->
    <div v-for="item in contentList">
      <div
        
        :
        @click="handleClick(item.order)"
      >
        <img :src="item.content_img" alt=""  />
      </div>
    </div>
  </div>
</template>

<script>
import jsBook from '../assets/imgs/jsBook.jpeg'
import vue from '../assets/imgs/vue.webp'
import react from '../assets/imgs/react.webp'
import css from '../assets/imgs/css.webp'
import perf from '../assets/imgs/perf.webp'
import node from '../assets/imgs/node.png'
import alg from '../assets/imgs/alg.webp'
import build from '../assets/imgs/build.webp'
import box from '../assets/imgs/box.png'

export default {
  name: "Box",
  data() {
    return {
      // 学习内容列表
      contentList: [
        {
          name: 'JS 红宝书',
          content_img: jsBook,
          content_id: 'jsBook',
          order: 1,
          isPicked: true,
        },
        {
          name: 'Vue',
          content_img: vue,
          content_id: 'vue',
          order: 2,
          isPicked: false,
        },
        {
          name: 'React',
          content_img: react,
          content_id: 'react',
          order: 3,
          isPicked: false,
        },
        {
          name: 'CSS',
          content_img: css,
          content_id: 'css',
          order: 8,
          isPicked: false,
        },
        {
          name: '抽取学习盲盒',
          content_img: box,
          content_id: 'box',
          order: 0,
          isPicked: false,
        },
        {
          name: '前端性能或安全',
          content_img: perf,
          content_id: 'perf',
          order: 4,
          isPicked: false,
        },
        {
          name: '前端工程化',
          content_img: build,
          content_id: 'build',
          order: 7,
          isPicked: false,
        },
        {
          name: 'Node',
          content_img: node,
          content_id: 'node',
          order: 6,
          isPicked: false,
        },
        {
          name: '算法',
          content_img: alg,
          content_id: 'alg',
          order: 5,
          isPicked: false,
        },
      ],
      // 选中的内容
      pickedContent: '',
      // 选中的内容index
      pickedIndex: 1,
      // 当前的内容
      curIndex: 1,
      speed: 100,
      totalSteps: 0,
      hasStarted: false
    };
  },
  methods: {
    handleClick(order) {
      if (order !== 0 || this.hasStarted) return
      // 只处理中间按钮的点击事件
      this.start()
    },
    start() {
      // 随机生成一个步数,大概3~6圈
      this.totalSteps = Math.floor(Math.random() * 24) + 24
      // 已经走的步数
      let hasRun = 0
      this.move(hasRun)
    },
    move(hasRun) {
      const len = this.contentList.length - 1
      setTimeout(() => {
        if (hasRun <= this.totalSteps) {
          if (this.totalSteps - hasRun < 2 * len) {
            // 放慢速度
            this.speed = 300
          } else if (this.totalSteps - hasRun < len) {
            // 最后一轮,再慢一点
            this.speed = 600
          }
          this.curIndex = hasRun % len + 1
          hasRun++
          this.move(hasRun)
        } else {
          // 抽到了!
          this.speed = 100
          this.hasStarted = false
          this.pickedIndex = this.curIndex
          // 获取抽到的内容,用于弹窗提示
          this.contentList.forEach(item => {
            if (item.order === this.pickedIndex) {
              this.pickedContent = item.name
            }
          })
          // 弹窗通知
          this.$alert(`今天可以学一学 ${this.pickedContent} 哦!`, {
            confirmButtonText: '知道啦',
            type: 'success',
            callback: () => {
              this.curIndex = 1
            }
          });
        }
      }, this.speed)
    }
  }
}
</script>

<style scoped>
.box-wrapper {
  width: 500px;
  height: 500px;
  margin: 0 auto;
  margin-top: 100px;
  overflow-y: hidden;
  display: grid;
  grid-template-columns: 1fr 1fr 1fr;
  grid-template-rows: 1fr 1fr 1fr;
}
.content-item {
  border-radius: 2px;
  width: 150px;
  height: 150px;
  border: 4px solid transparent;
  cursor: pointer;
}
.content-img {
  width: 150px;
  height: 150px;
  object-fit: cover;
}
.picked {
  border: 4px solid rgb(224, 216, 106);
  opacity: 0.8;
}
</style>
特别申明:本文内容来源网络,版权归原作者所有,如有侵权请立即与我们联系(cy198701067573@163.com),我们将及时处理。

Tags 标签

react.jsvue.jsnode.js

扩展阅读

加个好友,技术交流

1628738909466805.jpg