微信小程序 纯css画仪表盘

在这里插入图片描述

刚看到设计稿的时候第一时间想到的就是用canvas来做这个仪表盘,虽然本人的画布用的不是很好但还可以写一写😀。话不多说直接上代码。最后有纯css方法

<!--wxml-->
<canvas canvas-id="circle" class="circle" >
// js
data: {
    canvasWidth: 285, // 画布宽度
    canvasHeight: 285, // 画布高度
    value: 60, // 当前得分
},

  /*
   * 绘制仪表盘
   */
  showCanvasRing() {
    var that = this;
    var ctx = wx.createCanvasContext("circle");
    ctx.clearRect(0, 0, that.data.canvasWidth, that.data.canvasHeight); // 清除画布
    var circle_r = that.data.canvasWidth / 2; //画布的一半,用来找中心点和半径
    var scoreText = that.data.value>=100?100:that.data.value; // 当前得分 最多100分
    var descript = '良好'; // 当前描述
    var date = formatTime(new Date(),'MM-DD'); // 当前日期
    // 圆弧起点
    var startAngle = 0.8 * Math.PI;
    var endAngle = 2.2 * Math.PI;
    //定义起始点
    ctx.translate(that.data.canvasWidth / 2, that.data.canvasHeight / 2);
    // 画圆背景
    ctx.beginPath();
    ctx.setStrokeStyle("#6bb7b9");
    ctx.fillStyle="#6bb7b9";
    ctx.setLineCap("round");
    ctx.arc(0, 0, circle_r,2*Math.PI);
    ctx.fill()
    ctx.stroke();
    ctx.closePath();

    //  白半边圆弧
    ctx.beginPath();
    ctx.setStrokeStyle("#FFFFFF");
    ctx.setLineWidth(10);
    ctx.setLineCap("round");
    ctx.arc(0, 0, circle_r - 20, startAngle, endAngle, false);
    ctx.stroke();
    ctx.closePath();

    // 刻度
    for (let i = 0; i <= 10; i++) {
      let angle = startAngle + (endAngle - startAngle - 0.1) * (i * 10) / 100;
      if (angle > Math.PI * 2) {
        angle = angle - Math.PI * 2
      }
      const point = that.getPoint(0, 0, circle_r - 44, angle);
      const PI_3_2 = Math.PI * 1.5;
      const PI_1_2 = Math.PI * 0.5;
      ctx.save()
      ctx.setFillStyle("#fff");
      ctx.setFontSize(13);
      ctx.translate(point.x, point.y)
      const rotateDegrees = angle >= PI_3_2 ? (angle - PI_3_2) : (angle + PI_1_2);
      ctx.rotate(rotateDegrees)
      ctx.fillText(i * 10, 0, 0)
      ctx.restore()
    }

    // 当前得分内圆弧
    ctx.beginPath();
    ctx.setStrokeStyle("#FFA64D");
    ctx.setLineWidth(10);
    ctx.setLineCap("round");
    ctx.arc(0, 0, circle_r - 20, startAngle, startAngle + (endAngle - startAngle) * scoreText / 100, false);
    ctx.stroke();
    ctx.closePath();


    // 分数
    ctx.setTextAlign("center"); // 字体位置
    ctx.setFillStyle("#fff");
    ctx.font = "900 50px Arial"
    ctx.fillText(scoreText, 0, -20);

    // 描述
    ctx.setTextAlign("center"); // 字体位置
    ctx.font = "400 15px Arial"
    ctx.fillText(descript, 0, 15);

    // 日期
    ctx.setTextAlign("center");
    ctx.setLineWidth(8);
    ctx.setFontSize(14);
    ctx.fillText(date + ' 更新', 0, 35);

    // 绘图
    ctx.draw();
  },
  getPoint: function (x, y, r, angle) {
    const x1 = x + r * Math.cos(angle);
    const y1 = y + r * Math.sin(angle);
    return {
      x: x1,
      y: y1
    }
  },

到此仪表盘就画完了,最后需求有变动需要再仪表盘上加文本,众所周知canvas在小程序中的层级很高。但是官方说可以使用cover-view | cover-image

 <canvas canvas-id="circle" class="circle" >
 	<cover-view class="lowScore" wx-if="{{showView}}">
      目前信用分过低
    </cover-view>
 </canvas>

经过验证cover-view可以做到在canvas上悬浮,但是不能满足所有需求;
比如要悬浮scroll-view ,总不能把内容全部用画布来写吧 ~ ~。也有人说可以将绘画完成后的canvas转成图片进行显示wx.canvasToTempFilePath。我同样也试过但是会报错:canvasToTempFilePath:fail fail canvas is empty,怎么解决试了好半天,由于项目着急也没用太多时间研究了。所有最后我决定使用最原始的方法来实现。来看代码吧 ↓ ↓

 <!--wxml-->
<view class="dashboard">
  <view class="dashboard-arc">
    <view class="dashboard-scale">
      <view wx:for="{{[0,10,20,30,40,50,60,70,80,90,100]}}" wx:key="item">{{item}}</view>
    </view>
    <view class="dashboard-arc-active" style="background: conic-gradient(#FFA64D 0, #FFA64D {{(value*0.75)}}%, transparent 0, transparent);">
      <view class="dashboard-arc-active-end" style="transform: translateX(-50%) rotate({{(value/100)*270}}deg);"></view>
    </view>
  </view>
  <view class="dashboard-content">
    <view class="dashboard-content-title">{{value}}</view>
    <view class="dashboard-content-text">{{state}}</view>
    <view class="dashboard-content-desc">{{tool.formatTime(date,'MM-DD')}} 更新</view>
  </view>
  <view class="lowScore" wx-if="{{showView}}">目前信用分过低</view>
...要悬浮的内容
</view>
	/* 仪表盘 */
	.dashboard {
	    width: 750rpx;
	    height: 600rpx;
	    background: rgba(70, 165, 168, 1);
	    box-shadow: 0px 10px 20px rgba(0, 0, 0, 0.1);
	    text-align: center;
	    position: relative;
	}
	.dashboard::before{
	  content: '';
	  width: 570rpx;
	  height: 570rpx;
	  position: absolute;
	  top: 50%;
	  left: 50%;
	  transform: translate(-50%, -50%);
	  background-color: #6bb7b9;
	  border-radius: 50%;
	}
	.dashboard-arc{
	  width: 520rpx;
	  height: 520rpx;
	  position: absolute;
	  top: 50%;
	  left: 50%;
	  transform: translate(-50%, -50%);
	  transform: translate(-50%, -50%) rotate(-135deg);
	  border-radius: 50%;
	  background: conic-gradient(#fff 0, #fff 75%, transparent 0, transparent);
	}
	.dashboard-arc::before,
	.dashboard-arc::after{
	  content: "";
	  position: absolute;
	  width: 20rpx;
	  height: 20rpx;
	  border-radius: 50%;
	  background: #fff;
	}
	.dashboard-arc::before{
	  left: 50%;
	  top: 0;
	  background-color: #FFA64D;
	  transform: translateX(-50%);
	}
	.dashboard-arc::after{
	  left: 0;
	  top: 50%;
	  transform: translateY(-50%);
	}
	.dashboard-arc-active{
	  position: absolute;
	  width: 100%;
	  height: 100%;
	  border-radius: 50%;
	  top: 0;
	  left: 0;
	}
	.dashboard-arc-active-end{
	  position: absolute;
	  width: 20rpx;
	  height:100%;
	  top: 0;
	  left: 50%;
	  z-index: 1;
	}
	.dashboard-arc-active-end::before{
	  content: '';
	  width: 20rpx;
	  height: 20rpx;
	  position: absolute;
	  top: 0;
	  left: 0;
	  background: #FFA64D;
	  border-radius: 50%;
	}
	.dashboard-scale{
	  background-color: #6bb7b9;
	  width: 480rpx;
	  height: 480rpx;
	  border-radius: 50%;
	  position: relative;
	  top: 50%;
	  left: 50%;
	  z-index: 99;
	  font-size: 20rpx;
	  transform: translate(-50%, -50%);
	  color: #fff;
	}
	.dashboard-scale>view{
	  position: absolute;
	  top: 50%;
	  height:calc(100% - 10rpx);
	  left: 50%;
	  transform: translate(-50%,-50%);
	}
	.dashboard-scale>view:nth-child(2){
	  transform:translate(-50%,-50%)rotate(27deg);
	}
	.dashboard-scale>view:nth-child(3){
	  transform:translate(-50%,-50%)rotate(54deg);
	}
	.dashboard-scale>view:nth-child(4){
	  transform:translate(-50%,-50%)rotate(81deg);
	}
	.dashboard-scale>view:nth-child(5){
	  transform:translate(-50%,-50%)rotate(108deg);
	}
	.dashboard-scale>view:nth-child(6){
	  transform:translate(-50%,-50%)rotate(135deg);
	}
	.dashboard-scale>view:nth-child(7){
	  transform:translate(-50%,-50%)rotate(162deg);
	}
	.dashboard-scale>view:nth-child(8){
	  transform:translate(-50%,-50%)rotate(189deg);
	}
	.dashboard-scale>view:nth-child(9){
	  transform:translate(-50%,-50%)rotate(216deg);
	}
	.dashboard-scale>view:nth-child(10){
	  transform:translate(-50%,-50%)rotate(243deg);
	}
	.dashboard-scale>view:nth-child(11){
	  transform:translate(-50%,-50%)rotate(270deg);
	}
	.dashboard-content{
	  position: absolute;
	  width: 300rpx;
	  height: 300rpx;
	  top: 50%;
	  left: 50%;
	  transform: translate(-50%, -50%);
	  color: #fff;
	  border-radius: 50%;
	  padding: 20rpx;
	}
	.dashboard-content-title{
	  font-size: 115rpx;
	  font-weight: 900;
	}
	.dashboard-content-text{
	  font-size: 25rpx;
	}
	.dashboard-content-desc{
	  font-size: 20rpx;
	}

以上就是所有代码了,觉得对你有用的话就点个赞吧 !
最后给大家推荐一个在线题库小程序包含了阿里云认证、腾讯云认证、华为云认证、思科认证、锐捷认证、瓴羊认证、红帽认证、软考、IT认证等等
请添加图片描述

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

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

相关文章

python pyaudio显示音频波形图

python pyaudio显示音频波形图 代码如下&#xff1a; import numpy as np import matplotlib.pylab as plb import wave# 读取 wav wf wave.open("./output.wav", "rb")# 获取音频相关参数&#xff1a;声道数、量化位数、采样频率、采样帧数 nchannels,…

Java多线程 - 黑马教程

文章目录 Java 多线程一、多线程概述二、 多线程创建方式1、继承 Thread 类创建线程2、实现 Runnable 接口3、实现 Callable 接口三、Thread 常用的方法四、线程安全什么是线程安全问题?线程安全问题出现的原因程序模拟线程安全五、线程同步线程同步方式1:同步代码块线程同步…

Opencv打开图片

cv.imread() oepncv中使用cv.imread函数读取图片&#xff0c;并打开窗口显示&#xff0c;以下是示例代码 import cv2 as cv import numpy as np from matplotlib import pyplot as pltsrc cv.imread("demo.jpg")#blue, green red cv.namedWindow("input ima…

GPIO的使用--时钟使能含义--代码封装

目录 一、时钟使能的含义 1.为什么要时钟使能&#xff1f; 2.什么是时钟使能&#xff1f; 3.GPIO的使能信号&#xff1f; 二、代码封装 1.封装前完整代码 2.封装结构 封装后代码 led.c led.h key.c key.h main.c 一、时钟使能的含义 1.为什么要时钟使能&#xff1f…

vue3 vue-cropper@next 实现图片裁切功能

Vue Cropper 实现上传图片预览&#xff0c;裁切上传效果 下载 pnpm add vue-croppernext使用 <template><inputref"inputRef"class"hidden"accept".png,.jpeg,.jpg"multipletype"file"change"handleUploadChange&quo…

C#,数值计算——计算实对称矩阵所有特征值和特征向量的雅可比(Jacobi)方法与源程序

1 文本格式 using System; namespace Legalsoft.Truffer { /// <summary> /// Computes all eigenvalues and eigenvectors of /// a real symmetric matrix by Jacobis method. /// </summary> public class Jacobi { private …

CUDA简介——Grid和Block内Thread索引

1. 引言 前序博客&#xff1a; CUDA简介——基本概念CUDA简介——编程模式CUDA简介——For循环并行化 Thread Index&#xff1a; 每个Thread都有其thread index。 在Kernel中&#xff0c;可通过内置的threadIdx变量来获取其thread index。threadIdx为三维的&#xff0c;有相…

音频录制软件哪个好?帮助你找到最合适的一款

音频录制软件是日常工作、学习和创作中不可或缺的一部分。选择一个适合自己需求的录音软件对于确保音频质量和提高工作效率至关重要。可是您知道音频录制软件哪个好吗&#xff1f;本文将深入探讨两种常见的音频录制软件&#xff0c;通过详细的步骤指南&#xff0c;帮助您了解它…

记一次引入低版本包导致包冲突,表现为NoClassDefFoundError的故障

简而言之&#xff0c;因为参考别的项目处理excel的代码if(org.apache.poi.hssf.usermodel.HSSFDateUtil.isCellDateFormatted(cell)) &#xff0c;为了使用这个HSSFDateUtil类我引入了依赖&#xff1a; <dependency><groupId>org.apache.poi</groupId><a…

Python3 GUI 自制音乐播放器 图片浏览 图片轮播 PyQt5(附下载地址)

目录 Part1&#xff1a; 介绍 Part2: create window Part2: create window Adv Part4: Music Play Part5&#xff1a; 图片加载&#xff1a; Part1&#xff1a; 介绍 在这篇文章中&#xff0c;我们将学习如何使用PyQt 库创建一个基本的窗口应用程序&#xff0c;并进行一些…

【C/PTA —— 14.结构体1(课内实践)】

C/PTA —— 14.结构体1&#xff08;课内实践&#xff09; 6-1 计算两个复数之积6-2 结构体数组中查找指定编号人员6-3 综合成绩6-4 结构体数组按总分排序 6-1 计算两个复数之积 struct complex multiply(struct complex x, struct complex y) {struct complex product;product.…

1-4、调试汇编程序

语雀原文链接 文章目录 1、执行过程第一步&#xff1a;源程序第二步&#xff1a;编译连接第三步&#xff1a;执行 2、DOSBox运行程序第1步 进入EDIT.EXE第2步 编写源程序第3步 编译第4步 连接第5步 执行完整过程 3、DEBUG跟踪执行过程加载程序到内存执行程序debug和源程序数字…

Selenium 自动化高级操作与解决疑难杂症,如无法连接、使用代理等

解决 Selenium 自动化中的常见疑难杂症 这里记录一些关于 Selenium的常用操作和疑难杂症。 有一些细节的知识点就不重复介绍了&#xff0c;因为之前的文章中都有&#xff01; 如果对本文中的知识点有疑问的&#xff0c;可以先阅读我以前分享的文章&#xff01; 知识点&…

【滑动窗口】LeetCode2953:统计完全子字符串

作者推荐 [二分查找]LeetCode2040:两个有序数组的第 K 小乘积 本题其它解法 【离散差分】LeetCode2953:统计完全子字符串 题目 给你一个字符串 word 和一个整数 k 。 如果 word 的一个子字符串 s 满足以下条件&#xff0c;我们称它是 完全字符串&#xff1a; s 中每个字符…

【UGUI】sprite精灵的创建与编辑

如何切图&#xff08;sprite editor&#xff09; 有时候一张图可能包含了很多张子图&#xff0c;就需要在Unity 临时处理一下&#xff0c;切开&#xff0c;比如动画序列帧图集 虽然我们可以在PS里面逐个切成一样的尺寸导出多张&#xff0c;再放回Unity&#xff0c;但是不需要这…

通讯录管理系统(基于C语言)

模块设计 本通讯录管理系统功能模块共包括9个部分&#xff1a;1.输入数据、2.显示数据、 3.插入数据、4.删除数据、5.查看数据、6.修改数据、7.保存数据、 8.返回主菜单、9.退出系统. 一&#xff0e;总体设计 通讯录的每一条信息包括&#xff1a;姓名、性别、住址、联系电话…

[leetcode ~二叉树] 模版

文章目录 1. 左叶子之和2. 翻转二叉树 E 1. 左叶子之和 :::details 给定二叉树的根节点 root &#xff0c;返回所有左叶子之和。 示例 1&#xff1a; 输入: root [3,9,20,null,null,15,7] 输出: 24 解释: 在这个二叉树中&#xff0c;有两个左叶子&#xff0c;分别是 9 和 15&…

java生成邮件eml文件例子

提前导入javamail.jar 仓库地址 仓库服务 导入引用类方法 import javax.mail.Message; import javax.mail.Session; import javax.mail.internet.InternetAddress; import javax.mail.internet.MimeMessage; import java.io.FileOutputStream; import java.util.Properties…

10、外观模式(Facade Pattern,不常用)

外观模式&#xff08;Facade Pattern&#xff09;也叫作门面模式&#xff0c;通过一个门面&#xff08;Facade&#xff09;向客户端提供一个访问系统的统一接口&#xff0c;客户端无须关心和知晓系统内部各子模块&#xff08;系统&#xff09;之间的复杂关系&#xff0c;其主要…

利用DateFormat、Date、Calendar等相关类,编程实现如下功能

&#xff08;1&#xff09;用户输入2个日期&#xff0c;第一个日期用整数形式输入&#xff0c;把输入的整数设置为日历对象1的年月日的值。第二个日期以字符串形式输入&#xff0c;形如“2022-10-25”&#xff0c;并设置为日历对象2的年月日的值。将2个日期以“xx年xx月xx日”的…