[Uni-app] 微信小程序的圆环进度条

效果图:

组件完整代码如下:

<template>
  <view class="base-style"
    :style="'position: relative;width: ' + diameter + 'px;height: ' + diameter + 'px;display: flex;flex-direction: row;background-color: ' + bgColor + ';'">
    <!-- 左半圆和右半圆都要经历下面的5步:
    [第1步]第1层限定区域; 
    [第2步]第2层决定显示一个整圆的左半边还是右半边; 
    [第3步]第3层先使用激活颜色绘制一个圆环, 再添加一个同级且宽度为区域一半的盒子A;
    [第4步]在盒子A中再使用圆环底色绘制一个圆环, 此时整个圆环是 '左一半是激活颜色、右一半是圆环底色', 但这个圆环同时只能被看到一半;
    [第5步]旋转第2层。 -->

    <!-- 左半圆 -->
    <view class="base-style" :style="firstLayerViewStyle">
      <view :style="secondLayerViewStyle + secondLayerForLeft">
        <!-- 使用激活颜色绘制一个圆环。 -->
        <view :style="thirdLayerStyle">
        </view>
        <!-- 再使用背景色遮盖同级圆环的一半。 -->
        <view class="base-style" :style="thirdLayerStyleForBg">
          <view :style="fourthLayerStyleForBg" />
        </view>
        <view v-if="0 < ePercent && ePercent < 0.5" :style="endPointStyle + endPointStyleForLeft" />
      </view>
    </view>

    <!-- 右半圆 -->
    <view class="base-style" :style="firstLayerViewStyle">
      <!-- 适配:为了避免右侧遮盖显示不全 此处向左多移动了1px -->
      <view :style="secondLayerViewStyle + 'left: ' + (- diameter / 2 - 1) + 'px;' + secondLayerForRight">
        <!-- 使用激活颜色绘制一个圆环。 -->
        <view :style="thirdLayerStyle">
        </view>
        <!-- 再使用背景色遮盖同级圆环的一半。 -->
        <view class="base-style" :style="thirdLayerStyleForBg">
          <view :style="fourthLayerStyleForBg" />
        </view>
        <view v-if="ePercent > 0.5" :style="endPointStyle + endPointStyleForRight" />
      </view>
    </view>

    <view v-if="0.5 == ePercent" :style="endPointStyle + 'background-color: ' + this.hoopBgColor + ';'" />
    <!-- #ifdef APP-PLUS -->
    <!-- 处理现象: 安卓App的顶部和底部会有一个小白点。 -->
    <!-- <view v-if="ePercent > 0.5" :style="'position: absolute;top: 0;' + repairPointStyle" /> -->
    <!-- <view v-if="1.0 == ePercent" :style="'position: absolute;bottom: 0;' + repairPointStyle" /> -->
    <!-- #endif -->
  </view>
</template>

<!-- 组件名称: 圆环进度条。
     启发地址: https://www.cnblogs.com/jr1993/p/4677921.html 。
     编者信息: 867003077@qq.com 。 -->
<script>
  export default {
    name: 'progressCircle',
    props: {
      // 背景色(不宜设置为透明 否则 需要 在 左thirdLayer 的外面 再嵌套一个盒子)。
      bgColor: {
        type: String,
        default: '#FFFFFF'
      },
      // 圆环的外直径(单位px)。
      diameter: {
        type: Number,
        default: 250
      },
      // 圆环线条的厚度(单位px)。
      hoopThickness: {
        type: Number,
        default: 8
      },
      // 圆环底色(灰色的圆环)。
      hoopBgColor: {
        type: String,
        // default: 'transparent'
        default: '#F3F3F3'
      },
      // 圆环激活部分的颜色。
      hoopColor: {
        type: String,
        default: '#FF4C20'
      },
      // 圆环进度百分比值(其值范围在0到1之间)。
      percent: {
        type: [Number, String],
        default: 0,
        validator: val => {
          return val >= 0 && val <= 1;
        },
      },
      animate: {
        type: Boolean,
        default: false,
      },
    },
    data() {
      return {
        targetPercent: 0,
        ePercent: 0,
        showTimer: undefined,
      };
    },
    watch: {
      percent: {
        handler: function() {
          console.log('progressCircle_watch_percent', this.percent);
          this.loadData();
        },
      },
    },
    computed: {
      firstLayerViewStyle() {
        return 'position: relative;width: ' + (this.diameter / 2) +
          'px;height: ' + this.diameter + 'px;';
      },
      secondLayerViewStyle() {
        return 'box-sizing: border-box;position: absolute;top: 0;width: ' + this.diameter +
          'px;height: ' + this.diameter + 'px;';
      },
      thirdLayerStyle() {
        return 'box-sizing: border-box;width: ' + this.diameter + 'px;height: ' + this.diameter +
          'px;border-radius: ' + (this.diameter / 2) +
          'px;border-width: ' + this.hoopThickness +
          'px;border-style: solid;border-color: ' + this.hoopColor + ';';
      },
      thirdLayerStyleForBg() {
        return 'box-sizing: border-box;position: absolute;top: 0;left: ' + (this.diameter / 2) + 'px;width: ' +
          this.diameter + 'px;height: ' + this.diameter + 'px;background-color: ' + this.bgColor + ';';
      },
      fourthLayerStyleForBg() {
        return 'box-sizing: border-box;margin-left: ' + (-this.diameter / 2) + 'px;width: ' + this.diameter +
          'px;height: ' +
          this.diameter + 'px;border-radius: ' + (this.diameter / 2) + 'px;border-width: ' +
          this.hoopThickness + 'px;border-style: solid;border-color: ' + this.hoopBgColor + ';';
      },
      secondLayerForLeft() {
        let angle = 0;
        if (this.ePercent < 0.5) {
          angle += (180 * (this.ePercent - 0.5) / 0.5);
        }
        // #ifdef APP-PLUS
        return 'left: 0;transform: rotate(' + angle + 'deg);';
        // #endif
        // #ifdef MP-WEIXIN
        return 'left: 0;transform: rotate(' + angle + 'deg);-webkit-transform: rotate(' + angle + 'deg);';
        // #endif
      },
      secondLayerForRight() {
        let angle = 0;
        if (this.ePercent > 0.5) {
          angle += (180 * (this.ePercent - 0.5) / 0.5);
        }
        // #ifdef APP-PLUS
        return 'right: 0;transform: rotate(' + angle + 'deg);';
        // #endif
        // #ifdef MP-WEIXIN
        return 'right: 0;transform: rotate(' + angle + 'deg);-webkit-transform: rotate(' + angle + 'deg);';
        // #endif
      },
      // repairPointStyle() {
      // 	return 'left: ' + (this.diameter - this.hoopThickness) / 2 + 'px;width: ' +
      // 		this.hoopThickness + 'px;height: ' + this.hoopThickness + 'px;border-radius: ' +
      // 		this.hoopThickness / 2 + 'px;background-color: ' + this.hoopColor + ';';
      // },
      endPointStyle() {
        // 结束点圆心圈直径。
        const _circleCenterRadius = 2;
        return 'box-sizing: border-box;position: absolute;top: 0;left: ' + (this.diameter - this.hoopThickness) / 2 +
          'px;width: ' +
          this.hoopThickness + 'px;height: ' + this.hoopThickness + 'px;border-radius: ' + (this.hoopThickness / 2) +
          'px;border-width: ' + (this.hoopThickness / 2 - _circleCenterRadius) +
          'px;border-style: solid;border-color: ' +
          this.hoopColor + ';';
      },
      endPointStyleForLeft() {
        return 'background-color: ' + ((this.ePercent > 0.5) ? this.hoopColor : this.hoopBgColor) + ';';
      },
      endPointStyleForRight() {
        return 'background-color: ' + ((1 == this.ePercent) ? this.hoopColor : this.hoopBgColor) + ';';
      },
    },
    mounted() {
      console.log('progressCircle_mounted');
      this.loadData();
    },
    methods: {
      loadData() {
        this.targetPercent = parseFloat(this.percent);
        console.log('progressCircle_loadData');
        if (!this.animate) {
          this.ePercent = this.targetPercent;
        } else {
          let _this = this;
          this.ePercent = 0;
          this.showTimer && clearInterval(this.showTimer);
          this.showTimer = setInterval(() => {
            let tempPercent = _this.ePercent + 0.1;
            if (tempPercent < _this.targetPercent) {
              _this.ePercent = tempPercent;
              return;
            };
            _this.ePercent = _this.targetPercent;
            clearInterval(_this.showTimer);
          }, 200);
        }
      }
    }
  }
</script>

<style scoped>
  .base-style {
    box-sizing: border-box;
    /* 溢出隐藏 */
    overflow: hidden;
  }
</style>

调用页面:

<template>
  <view class="my-page-container" :style="{ 'height': pageBoxH + 'px' }" @click="currentPercent=0.8">
    <progress-circle class="mine-member-level-progress" :diameter="180" :hoopThickness="10" :hoopColor="'orange'"
      :percent="currentPercent" :animate="true" />
  </view>
</template>

<script>
  /** 演示页面 */
  import progressCircle from "@/components/progress-circle/index.vue";
  // import {
  //   queryDetail,
  // } from '@/api/mine.js';
  export default {
    name: 'myDemo',
    components: {
      progressCircle,
    },
    data() {
      return {
        pageBoxH: 1000,
        currentPercent: 0.25,
      };
    },
    beforeCreate() {
      console.log('beforeCreate enter');
    },
    created() {
      console.log('created enter');
    },
    mounted() {
      console.log('mounted enter');
    },
    onLoad(option) {
      console.log('onLoad enter');
    },
    onReady() {},
    methods: {},
  }
</script>

<style scoped>
  .my-page-container {
    background-color: white;
    box-sizing: border-box;
    padding: 10px 10px 50px 10px;
    display: flex;
    flex-direction: column;
  }
</style>

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.kler.cn/a/274851.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

web前端之多种方式实现switch滑块功能、动态设置css变量、after伪元素、选择器、has伪类

MENU 效果图htmlcsshtmlcssJS 效果图 htmlcss html <div class"s"><input type"checkbox" id"si" class"si"><label for"si" class"sl"></label> </div>style * {margin: 0;pad…

iPhone迎AI大革命:谷歌、OpenAI助苹果重塑智能巅峰

近日&#xff0c;有媒体报道称&#xff0c;苹果正积极寻求与谷歌和OpenAI展开合作&#xff0c;计划将这两家在全球人工智能领域具有领先地位的公司的大模型技术应用于iPhone的AI功能。这一合作将为iPhone带来革命性的智能体验&#xff0c;开启AI手机新篇章。 AI-321 | 专注于AI…

室友打团太吵?一条命令断掉它的WiFi

「作者主页」&#xff1a;士别三日wyx 「作者简介」&#xff1a;CSDN top100、阿里云博客专家、华为云享专家、网络安全领域优质创作者 「推荐专栏」&#xff1a;更多干货&#xff0c;请关注专栏《网络安全自学教程》 ARP欺骗原理 1、arpspoof实现ARP欺骗1.1、主机探测1.2、欺骗…

论文浅尝 | GPT-RE:基于大语言模型针对关系抽取的上下文学习

笔记整理&#xff1a;张廉臣&#xff0c;东南大学硕士&#xff0c;研究方向为自然语言处理、信息抽取 链接&#xff1a;https://arxiv.org/pdf/2305.02105.pdf 1、动机 在很多自然语言处理任务中&#xff0c;上下文学习的性能已经媲美甚至超过了全资源微调的方法。但是&#xf…

SpringMVC04 实现简单的留言墙功能

前言 我们之前实现的前端留言墙功能的缺陷是不能持久化,刷新一下页面就直接没有了,实际上我们应该将数据存储到数据库中做一个硬盘上的持久化,现在我们先做一个简单的前后端交互,使用一个ArrayList来存储,在内存中保存,这样刷新页面也不会导致数据丢失的情况 但是我们一旦刷新…

远程安全访问JumpServer:使用cpolar内网穿透搭建固定公网地址

文章目录 前言1. 安装Jump server2. 本地访问jump server3. 安装 cpolar内网穿透软件4. 配置Jump server公网访问地址5. 公网远程访问Jump server6. 固定Jump server公网地址 前言 JumpServer 是广受欢迎的开源堡垒机&#xff0c;是符合 4A 规范的专业运维安全审计系统。JumpS…

反射与串扰

一、 反射 原因&#xff1a;由于AD采集端与传感器端和双绞线的阻抗不匹配而导致待测信号在AD处反射叠加&#xff1b; 解决办法&#xff1a;1、对AD采集端和炮榄传感器端进行合适于炮榄的阻抗匹配。具体来说可 以在AD采集端并联一个匹配电阻&#xff0c;电阻的阻值需要和传输线…

Gin框架 源码解析

https://zhuanlan.zhihu.com/p/136253346 https://www.cnblogs.com/randysun/category/2071204.html 这个博客里其他go的内容也讲的很好 启动 因为 gin 的安装教程已经到处都有了&#xff0c;所以这里省略如何安装&#xff0c; 建议直接去 github 官方地址的 README 中浏览安装…

图神经网络实战(5)——常用图数据集

图神经网络实战&#xff08;5&#xff09;——常用图数据集 0. 前言0. 图数据集介绍2. Cora 数据集3. Facebook Page-Page 数据集小结系列链接 0. 前言 图数据集往往比单纯的连接集合更丰富&#xff0c;节点和边也可以具有表示分数、颜色、单词等的特征。在输入数据中包含这些…

计算机毕业设计-基于python的旅游信息爬取以及数据分析

概要 随着计算机网络技术的发展&#xff0c;近年来&#xff0c;新的编程语言层出不穷&#xff0c;python语言就是近些年来最为火爆的一门语言&#xff0c;python语言&#xff0c;相对于其他高级语言而言&#xff0c;python有着更加便捷实用的模块以及库&#xff0c;具有语法简单…

【web世界探险家】HTML5 探索与实践

&#x1f4da;博客主页&#xff1a;爱敲代码的小杨. ✨专栏&#xff1a;《Java SE语法》 | 《数据结构与算法》 | 《C生万物》 |《MySQL探索之旅》 ❤️感谢大家点赞&#x1f44d;&#x1f3fb;收藏⭐评论✍&#x1f3fb;&#xff0c;您的三连就是我持续更新的动力❤️ &…

【SpringBoot3+MyBatis-Plus】头条新闻项目实现CRUD登录注册

文章目录 一、头条案例介绍二、技术栈介绍三、前端搭建四、基于SpringBoot搭建项目基础架构4.1 数据库脚本执行4.2 搭建SprintBoot工程4.2.1 导入依赖:4.2.2 编写配置4.2.3 工具类准备 4.3 MybatisX逆向工程 五、后台功能开发5.1 用户模块开发5.1.1 jwt 和 token 介绍5.1.2 jwt…

webpack5零基础入门-12搭建开发服务器

1.目的 每次写完代码都需要手动输入指令才能编译代码&#xff0c;太麻烦了&#xff0c;我们希望一切自动化 2.安装相关包 npm install --save-dev webpack-dev-server 3.添加配置 在webpack.config.js中添加devServer相关配置 /**开发服务器 */devServer: {host: localhos…

Docker 从0安装 nacos集群

前提条件 Docker支持一下的CentOs版本 Centos7(64-bit)&#xff0c;系统内核版本为 3.10 以上Centos6.5(64-bit) 或者更高版本&#xff0c;系统内核版本为 2.6.32-431 或者更高版本 安装步骤 使用 yum 安装&#xff08;CentOS 7下&#xff09; 通过 uname -r 命令查看你当…

Linux文件 profile、bashrc、bash_profile区别

Linux系统中&#xff0c;有三种文件 出现的非常频繁&#xff0c;那就是 profile、bash_profile、bashrc 文件。 1、profile 作用 profile&#xff0c;路径&#xff1a;/etc/profile&#xff0c;用于设置系统级的环境变量和启动程序&#xff0c;在这个文件下配置会对所有用户…

vivado 物理优化约束、交互式物理优化

物理优化约束 Vivado Design Suite在物理优化过程中尊重DONT_TOUCH特性。它不在具有这些属性的网络或小区上执行物理优化。要加快网络选择过程中&#xff0c;具有DONT_TOUCH属性的网络经过预过滤&#xff0c;不被考虑用于物理优化。此外&#xff0c;还遵守Pblock分配&#xff…

嵌入式学习41-数据结构2

今天学习了链表的增删改查 &#xff08;暂定&#xff01;&#xff01;后续再补内容&#xff09; 高内聚 &#xff1a;一个函数只实现一个功能 …

Java学习笔记:异常处理

Java学习笔记&#xff1a;异常处理 什么是异常异常体系结构&#xff1a;Error、Exception自定义异常 ​ **2024/3/19** 什么是异常 异常体系结构&#xff1a;Error、Exception 自定义异常

UE5 GAS开发p30 创建UI HUD 血条

新建AuraUserWidget,AuraWidgetController,AuraHUD 首先设置AuraWidgetController.h // Fill out your copyright notice in the Description page of Project Settings. #pragma once #include "CoreMinimal.h" #include "AbilitySystemComponent.h" #in…

风丘电动汽车高压测试方案 助您高效应对车辆试验难题

针对电动汽车道路试验的要求&#xff0c;风丘科技携手德国IPETRONIK共同推出了电动汽车高压测试方案。电动汽车测试通常有两种测量手段&#xff1a;第一种是测量模拟量信号&#xff0c;包括电压、电流、温度和高压&#xff1b;第二种是使用数据记录仪或CAN卡从车辆总线读取数据…
最新文章