vue怎么实现 【水波纹进度条】 组件封装,以及动画样式的效果

需求:一组数据中,多条数据都需要 “水波纹进度条” 的情况,封装成组件即可

一、创建组件 WaterRipple.vue

<template>
    <div class="water_progress" :style="'top:'+size.top+';left:'+size.left+';'">
        <div id="num">{{numTxt}}</div>
        <div class="water">
            <div class="water_bg"></div>
        </div>
        <div class="water-mask" :id="id"></div>
    </div>
</template>
<script>
export default {
  props: {
    size: {
      type: Object,
      default: () => {}
    },
    id: {
      type: String,
      default: ''
    },
    proNum: {
      type: Number,
      default: 0
    },
    isTodo: {
      type: Boolean,
      default: false
    }
  },
  data () {
    return {
      numTxt: 0,
      timerRef: null,
      progress: 50
    }
  },
  created () {
    setTimeout(() => {
      this.loadBtn()
    }, 2000)
  },
  methods: {
    loadBtn () {
      this.progress = this.proNum
      this.numTxt = this.progress >= 100 ? 100 : this.progress.toFixed(2) + '%'
      let waterEle = document.getElementById(this.id)
      waterEle.style.top = (100 - this.progress) + '%'
    }
  }
}
</script>
<style lang="scss" scoped>
@keyframes spin {
    50% {
        transform: translate(-50%, -101%) rotate(500deg);
    }
    100% {
        transform: translate(-50%, -101%) rotate(1000deg);
    }
}

.water_progress {
    width: 100px;
    height: 100px;
    border-radius: 50%;
    background: #ffffff;
    overflow: hidden;
    position: relative;
}
.water_active{
    background: url('../../assets/home/more_bg1.png') !important;
    background-size: 100% 100% !important;
}
.water_bg_active{
    background: url('../../assets/home/kong_bg1.png') !important;
    background-size: 100% 100% !important;
}
.water {
    position: relative;
    width: 100%;
    height: 100%;
    background: url('../../assets/home/more_bg.png');
    background-size: 100% 100%;
    border-radius: 50%;
    .water_bg{
        background: url('../../assets/home/kong_bg.png');
        background-size: 100% 100%;
        position: absolute;
        z-index: 100;
        width: 100%;
        height: 100%;
    }
}

.water-mask {
    position: absolute;
    width: 200%;
    height: 200%;
    top: 0;
    left: 50%;
    border-radius: 40%;
    transform: translate(-50%, -101%) rotate(0);
    animation: spin 30s linear;
    z-index: 20;
    background: #05204c;
}

#num {
    position: absolute;
    width: 100%;
    height: 100%;
    color: #fff;
    font-size: 16px;
    line-height: 100px;
    font-weight: bold;
    text-align: center;
    z-index: 100;
}
</style>

二、页面调用

<template>
<div>
  <div v-for="(task, taIndex) of taskDetailList" :key="taIndex">
    // 引入
    <WaterRipple :size="{top:'-190px',left:'106px'}" :proNum="task.finishNum" :isTodo="task.isTodo" :id="taIndex"></WaterRipple>
  </div>
</div>
</template>
<script>
import WaterRipple from '@/components/WaterRipple/index'
export default {
  components: { WaterRipple },
  data () {
    return {
      taskDetailList: [
        {id: 1, typeid: 1, finishNum: 10, name: '1三角函数原理', status: '未完成', isTodo: true}]
    }
  }
}
</script>

示例:

<template>
  <div class="learn_page">
    <div class="learn_list">
      <div class="learn_scroll">
        <div class="learn_item" v-for="(task, taIndex) of taskDetailList" :key="taIndex">
          <div v-if="task.typeid==checkIndex" class="l_item">
              <div class="item_point" :class="taIndex!==0?'':'hidden'">
                <div class="po_img"></div>
              </div>
              <div class="item_cont">
                  <img class="item_img" src="@/assets/home/item_points.png" alt="">
                   // 引入
                  <WaterRipple :size="{top:'-190px',left:'106px'}" :proNum="task.finishNum" :isTodo="task.isTodo" :id="taIndex"></WaterRipple>
                  <div class="item_cont_txt">
                    <div class="txt_name">{{task.name}}</div>
                    <div class="txt_btn" v-if="task.status!=='已完成'||!task.isTodo">已掌握,跳过</div>
                  </div>
              </div>
          </div>
        </div>
      </div>
    </div>
  </div>
</template>
<script>
import WaterRipple from '@/components/WaterRipple/index'
export default {
  components: { WaterRipple },
  data () {
    return {
      checkIndex: 1,
      taskDetailList: [
        {id: 1, typeid: 1, finishNum: 10, name: '1三角函数原理', status: '未完成', isTodo: true},
        {id: 2, typeid: 1, finishNum: 50, name: '1三角函数原理', status: '已完成', isTodo: false},
        {id: 3, typeid: 1, finishNum: 100, name: '1三角函数原理', status: '已完成', isTodo: true},
        {id: 4, typeid: 1, finishNum: 80, name: '1三角函数原理', status: '未完成', isTodo: false},
        {id: 5, typeid: 1, finishNum: 60, name: '1三角函数原理', status: '未完成', isTodo: true}
      ]
    }
  }
}
</script>

<style lang="scss" scoped>
.learn_page {
  background: url('../../assets/home/tasks_bg.png');
  background-size: 100% 100%;
  height: 100vh;
  width: 100%;
  color: #fff;
  // 内容
  .learn_list{
    background:url('../../assets/home/task_lis_bg.png') no-repeat;
    background-size: 100% 100%;
    margin: 20px 90px;
    height: 905px;
    padding: 40px 85px 0px 55px;
    user-select: none;
    .learn_scroll::-webkit-scrollbar{
      width: 0;
    }
    .learn_scroll{
      width: 100%;
      height: 830px;
      overflow-x: scroll;
      display: flex;
      -webkit-overflow-scrolling: touch;
    }
    .learn_item:first-child{
      margin-left: 40px;
    }
    // 偶数
    .learn_item:nth-child(even){
      margin-top: 470px;
      .po_img{
        position: absolute;
        top: -100px;
        left: -45px;
        width: 65px;
        height: 67px;
        background: url('../../assets/home/task_left.png');
        background-size: 100% 100%;
      }
      .po_left{
        background: url('../../assets/home/task_left_active.gif') !important;
        background-size: 100% 100% !important;
      }
      .l_item{
        margin-left: -45px;
      }
    }
    // 奇数
    .learn_item:nth-child(odd){
      .po_img{
        position: absolute;
        top: 370px;
        left: 0px;
        width: 65px;
        height: 67px;
        background: url('../../assets/home/task_right.png');
        background-size: 100% 100%;
      }
      .po_right{
        background: url('../../assets/home/task_right_active.gif') !important;
        background-size: 100% 100% !important;
      }
      .l_item{
        margin-left: -45px;
      }
    }
    .learn_item {
      position: relative;
      width: 18.6%;
      .l_item{
        display: flex;
        align-items: center;
        .item_cont{
          align-items: center;
          position: relative;
          img{
            width: 393px;
            height: 251px;
            margin-top: 15px;
          }
          .item_cont_txt{
            margin-top: -110px;
            .txt_name{
              color: #0378D2;
              font-size: 28px;
              text-shadow: 0px 4px 2px rgba(0, 0, 0, 0.58);
            }
            .txt_btn{
              margin: 0 auto;
              width: 237px;
              height: 42px;
              line-height: 42px;
              font-size: 22px;
              margin-top: 10px;
              background: url('../../assets/home/task_btns.png');
              background-size: 100% 100%;
            }
          }
        }
      }
    }
  }
}
.hidden{
  display: none;
}
</style>

      希望我的愚见能够帮助你哦~,若有不足之处,还望指出,你们有更好的解决方法,欢迎大家在评论区下方留言支持,大家一起相互学习参考呀~

  • 3
    点赞
  • 7
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
Vue实现文件上传进度条可以通过使用axios库来发送文件请求,并结合HTML5的FormData对象来实现。以下是一个简单的示例代码: 首先,在你的Vue组件中,引入axios库: ```javascript import axios from 'axios'; ``` 然后,创建一个data属性来存储上传进度相关的数据: ```javascript data() { return { file: null, // 保存要上传的文件 progress: 0, // 上传进度 }; }, ``` 接下来,创建一个方法来处理文件上传: ```javascript methods: { handleFileUpload(event) { this.file = event.target.files[0]; // 获取要上传的文件 // 创建FormData对象 let formData = new FormData(); formData.append('file', this.file); // 发送文件请求 axios.post('/upload', formData, { headers: { 'Content-Type': 'multipart/form-data', }, onUploadProgress: progressEvent => { this.progress = Math.round( (progressEvent.loaded * 100) / progressEvent.total ); // 更新上传进度 }, }) .then(response => { // 处理上传成功的响应 }) .catch(error => { // 处理上传失败的错误 }); }, }, ``` 最后,在模板中添加文件上传的input元素和进度条: ```html <template> <div> <input type="file" @change="handleFileUpload" /> <div>{{ progress }}%</div> <div class="progress-bar"> <div class="progress-bar-inner" :style="{ width: progress + '%' }"></div> </div> </div> </template> <style> .progress-bar { width: 200px; height: 20px; border: 1px solid #ccc; } .progress-bar-inner { height: 100%; background-color: #00a0e9; } </style> ``` 这样,当用户选择文件后,文件将被上传到服务器,并且进度条会实时更新上传进度。注意要将`/upload`替换为你的服务器端接收文件上传的URL。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值