微信小程序进度条cavans

1.组件

c 复制代码
<template>
  <view class="circle-progress-container">
    <!-- 画布容器 -->
    <view class="canvas-wrapper">
      <canvas canvas-id="bgCanvas" class="progress-canvas" :style="{ width: size + 'px', height: size + 'px' }"></canvas>
      <canvas canvas-id="progressCanvas" class="progress-canvas"
        :style="{ width: size + 'px', height: size + 'px' }"></canvas>
    </view>

    <!-- 修正后的文字容器 -->
    <view class="text-wrapper" :style="{
      width: size + 'px',
      height: size + 'px'
    }">
      <view class="text-content">
        <view class="score-line">
          <text class="current-value">{{ currentValue.toFixed(1) }}</text>
          <text class="max-value">/{{ maxValue }}</text>
        </view>
        <text class="progress-label">总成绩</text>
      </view>
    </view>
  </view>
</template>

<script lang="ts">
import { Vue, Component, Prop, Watch } from 'vue-property-decorator'

@Component
export default class CircleProgress extends Vue {
  @Prop({ default: 504.5 }) readonly currentValue!: number
  @Prop({ default: 750 }) readonly maxValue!: number
  @Prop({ default: 200 }) readonly size!: number
  @Prop({ default: 12 }) readonly strokeWidth!: number
  @Prop({ default: '#4CAF50' }) readonly progressColor!: string
  @Prop({ default: '#e0f7e0' }) readonly bgColor!: string

  private ctxBg: UniApp.CanvasContext | null = null
  private ctxProgress: UniApp.CanvasContext | null = null

  mounted() {
    this.$nextTick(() => {
      this.initCanvas()
    })
  }

  @Watch('currentValue')
  onValueChange() {
    this.drawProgress()
  }

  private initCanvas() {
    this.ctxBg = uni.createCanvasContext('bgCanvas', this)
    this.ctxProgress = uni.createCanvasContext('progressCanvas', this)
    this.drawBackground()
    this.drawProgress()
  }

  private drawBackground() {
    if (!this.ctxBg) return

    const center = this.size / 2
    const radius = center - this.strokeWidth / 2

    this.ctxBg.beginPath()
    this.ctxBg.setLineWidth(this.strokeWidth)
    this.ctxBg.setStrokeStyle(this.bgColor)
    this.ctxBg.arc(center, center, radius, 0, 2 * Math.PI)
    this.ctxBg.stroke()
    this.ctxBg.draw()
  }

  private drawProgress() {
    if (!this.ctxProgress) return

    const center = this.size / 2
    const radius = center - this.strokeWidth / 2
    const endAngle = (2 * Math.PI * this.currentValue) / this.maxValue - Math.PI / 2

    this.ctxProgress.clearRect(0, 0, this.size, this.size)
    this.ctxProgress.beginPath()
    this.ctxProgress.setLineWidth(this.strokeWidth)
    this.ctxProgress.setStrokeStyle(this.progressColor)
    this.ctxProgress.setLineCap('round')
    this.ctxProgress.arc(center, center, radius, -Math.PI / 2, endAngle)
    this.ctxProgress.stroke()
    this.ctxProgress.draw()
  }
}
</script>

<style lang="less" scoped>
.circle-progress-container {
  position: relative;
  display: inline-block;
  /* 改为inline-block避免flex影响 */

  .canvas-wrapper {
    position: relative;
    width: 100%;
    height: 100%;

    .progress-canvas {
      position: absolute;
      left: 0;
      top: 0;
    }
  }

  /* 修正后的文字容器样式 */
  .text-wrapper {
    position: absolute;
    top: 0;
    left: 0;
    display: flex;
    flex-direction: column;
    justify-content: center;
    align-items: center;
    text-align: center;

    .text-content {
      display: flex;
      flex-direction: column;
      align-items: center;
      transform: translateY(-5px);
      /* 微调垂直居中 */

      .score-line {
        display: flex;
        align-items: baseline;

        .current-value {
          font-size: 24px;
          font-weight: bold;
          color: #000;
        }

        .max-value {
          font-size: 16px;
          color: #999;
        }
      }

      .progress-label {
        font-size: 16px;
        color: #4CAF50;
        margin-top: 4px;
      }
    }
  }
}
</style>

2、使用

c 复制代码
<view :style="'width: ' + windowHeight + 'rpx; height: ' + windowHeight + 'rpx;'">
      <circle-pr :current-value="elseScore" :size="windowHeight / 2" :max-value="750"
        progress-color="#4CAF50"></circle-pr>
    </view>


<script lang="ts">
import CirclePr from '../components/circlePro.vue';
@Component({
  components: {
    CirclePr
  }
})
elseScore: number = 200
  windowHeight = 600
   onLoad() {
    var that = this
    wx.getSystemInfo({
      success: function (res: any) {
        // 屏幕宽度、高度
        // 高度,宽度 单位为px

        that.windowHeight = (res.windowHeight - 60) / 2;
        console.log(that.windowHeight + '获取宽度')
      },
    });
    this.elseScore = 504.5
  }
相关推荐
海纳百川·纳海川11 小时前
数字化升级,让废品回收更简单高效
大数据·微信小程序·小程序
2601_9567436817 小时前
上海小程序开发公司技术路径全解:从架构选型到工程落地的核心判断
小程序·架构·开发经验·上海
VX_bysjlw98517 小时前
基于微信小程序的宠物用品商城系统-后端74346-计算机毕设原创(免费领源码+带部署教程)
java·redis·微信小程序·eclipse·mybatis·idea·微信开发者工具
mykj155118 小时前
灵感石这个手链DIY小程序,简直是手作人的福音
小程序·灵感石小程序开发·手串diy小程序
一只昀21 小时前
基于微信小程序的咖啡店点餐小程序
微信小程序·小程序
2501_915918411 天前
深入对比iOS开发中常用性能监控工具的底层原理与优缺点分析
android·ios·小程序·https·uni-app·iphone·webview
黄华SJ520it2 天前
连锁多门店超市小程序:单品牌多家门店,总部统一管理、门店独立接单、线上到店/配送商超系统设计与实现
小程序·系统开发
2301_810313182 天前
社交APP定制开发:海外交友app开发婚礼聊天直播交友系统源码搭建
小程序·团队开发·软件需求·交友
mykj15512 天前
消费积分抵扣物业费小程序商城开发
小程序·积分商城抵扣物业费·积分商城小程序开发
云迈科技-软件定制开发3 天前
2026年湖南长沙软件定制开发公司怎么选?本地企业做APP、小程序、管理系统的合作参考
小程序