js:使用canvas画一个半圆
背景
需求需要画一个半圆,或者多半圆,其实一下子就能想到 canvas 中的圆弧,核心使用 context.arc
context.arc(x,y,r,sAngle,eAngle,counterclockwise)


接下来我们看看示例
例一
<!DOCTYPE html>
<html lang="en">
<head><meta charset="UTF-8"><meta name="viewport" content="width=device-width, initial-scale=1.0">
</head>
<body><canvas id="myCanvas" width="400" height="400"></canvas><script>const canvas = document.getElementById('myCanvas');const context = canvas.getContext('2d');const width = canvas.width;const height = canvas.height;const angle = 50; // 你的角度值const score = 50; // 你的分数值// 外层圆环context.beginPath();context.arc(width / 2, height - 20, width / 2 - 30, 1 * Math.PI, 2 * Math.PI);context.lineWidth = 4;context.lineCap = 'round';context.strokeStyle = '#DEDEDE';context.stroke();// 外层进度圆环context.beginPath();context.arc(width / 2, height - 20, width / 2 - 30, 1 * Math.PI, (1 + angle / 100) * Math.PI);context.lineWidth = 4;context.lineCap = 'round';const gnt1 = context.createLinearGradient(0, 0, 180, 0);gnt1.addColorStop(0, '#8ce459');gnt1.addColorStop(1, '#62af35');context.strokeStyle = gnt1;context.stroke();// 指示器const xAxis = Math.cos(Math.PI * 2 / 360 * (1.8 * (100 + angle))) * (width / 2 - 30);const yAxis = Math.sin(Math.PI * 2 / 360 * (1.8 * (100 + angle))) * (width / 2 - 30);context.beginPath();context.arc(width / 2 + xAxis, height - 20 + yAxis, 5, 0, 2 * Math.PI);context.fillStyle = '#5EAD35';context.fill();// 文本const textY = Math.sin(Math.PI * 2 / 360 * (1.8 * (100 + 15))) * (width / 2 - 30);context.fillStyle = '#168C66';context.font = '40px Arial';context.textAlign = 'center';context.textBaseline = 'middle';context.fillText(score, width / 2 - 5, height + 10 + textY);context.fillStyle = '#62AF35';context.font = '14px Arial';context.fillText('分', width / 2 + 30, height + 18 + textY);// 内层圆环context.beginPath();context.arc(width / 2, height - 20, width / 2 - 40, 1 * Math.PI, 2 * Math.PI);context.lineWidth = 2;context.setLineDash([1, 4]);context.lineCap = 'round';context.strokeStyle = '#A2BCC3';context.stroke();
</script></body>
</html>

例二
<!DOCTYPE html>
<html lang="en">
<head><meta charset="UTF-8"><meta name="viewport" content="width=device-width, initial-scale=1.0"><style>.canvas-main {width: 400px;height: 400px;position: relative;}.main-text {width: 100%;height: 100%;display: flex;align-items: center;justify-content: center;position: absolute;top: 0;left: 0;}</style>
</head>
<body>
<div class="canvas-main"><canvas id="main-canvas" width="400" height="400"></canvas><div class="main-text">10分</div>
</div><script>const canvas = document.getElementById('main-canvas');const context = canvas.getContext('2d');const width = canvas.width;const height = canvas.height;const score = 50; // 你的分数值const totalScore = 100; // 总分const scorePercentage = score / totalScore; // 你的分数值占总分的百分比// 外层圆环context.beginPath();context.arc(width / 2, height / 2, width / 2 - 30, 0.75 * Math.PI, 2.25 * Math.PI, false);context.lineWidth = 14;context.lineCap = 'round';context.strokeStyle = '#f5edfc';context.stroke();// 外层进度圆环context.beginPath();// 最小-最大:0.75 * Math.PI 到 2.25 * Math.PI 2.25 - 0.75 = 1.5context.arc(width / 2, height / 2, width / 2 - 30, 0.75 * Math.PI, (0.75 + 1.5 * scorePercentage) * Math.PI, false);context.lineWidth = 14;context.lineCap = 'round';const gnt1 = context.createLinearGradient(0, 0, 180, 0);gnt1.addColorStop(0, '#f5edfc');gnt1.addColorStop(1, '#9c4ce3');context.strokeStyle = gnt1;context.stroke();// 指示器const indicatorAngle = 0.75 + 1.5 * scorePercentage;const indicatorRadius = width / 2 - 30;const indicatorX = width / 2 + Math.cos(indicatorAngle * Math.PI) * indicatorRadius;const indicatorY = height / 2 + Math.sin(indicatorAngle * Math.PI) * indicatorRadius;context.beginPath();context.arc(indicatorX, indicatorY, 10, 0, 2 * Math.PI); // 外圈半径设置为 10context.fillStyle = '#fff';context.strokeStyle = '#fff'; // 外圈线颜色也为白色context.lineWidth = 2; // 设置线宽,增加外圈线的宽度context.fill();context.stroke();// 指示器内部填充红色context.beginPath();context.arc(indicatorX, indicatorY, 6, 0, 2 * Math.PI);context.fillStyle = '#9c4ce3';context.fill();
</script></body>
</html>

小程序
如果是小程序的话,把 api 换一下
<canvas id="ring" canvas-id="ring" class="progress-canvas"></canvas>
Component({/*** 组件的属性列表*/properties: {score: {type: Number},totalScore: {type: Number}},observers: {score: function(data) {if (data || data === 0) {this.init()}}},/*** 组件的方法列表*/methods: {init() {const query = this.createSelectorQuery()query.select('#ring').boundingClientRect(res => {this.drawRing('ring',res.width,res.height,this.data.score,this.data.totalScore)}).exec()},drawRing: function(canvasId, width, height, score, totalScore) {var context = wx.createCanvasContext(canvasId, this)// const score = 50 // 你的分数值// const totalScore = 100 // 总分const scorePercentage = score / totalScore // 你的分数值占总分的百分比// 外层圆环context.beginPath()context.arc(width / 2,height / 2,width / 2 - 30,0.75 * Math.PI,2.25 * Math.PI,false)context.lineWidth = 14context.lineCap = 'round'context.strokeStyle = '#f5edfc'context.stroke()// 外层进度圆环context.beginPath()context.arc(width / 2,height / 2,width / 2 - 30,0.75 * Math.PI,(0.75 + 1.5 * scorePercentage) * Math.PI,false)context.lineWidth = 14context.lineCap = 'round'const gnt1 = context.createLinearGradient(0, 0, 180, 0)gnt1.addColorStop(0, '#f5edfc')gnt1.addColorStop(1, '#9c4ce3')context.strokeStyle = gnt1context.stroke()// 指示器const indicatorAngle = 0.75 + 1.5 * scorePercentageconst indicatorRadius = width / 2 - 30const indicatorX =width / 2 + Math.cos(indicatorAngle * Math.PI) * indicatorRadiusconst indicatorY =height / 2 + Math.sin(indicatorAngle * Math.PI) * indicatorRadius// 指示器外圈context.beginPath()context.arc(indicatorX, indicatorY, 10, 0, 2 * Math.PI) // 外圈半径设置为 10context.setFillStyle('#fff')context.setStrokeStyle('#fff') // 外圈线颜色也为白色context.setLineWidth(2) // 设置线宽,增加外圈线的宽度context.fill()context.stroke()// 指示器内部填充红色context.beginPath()context.arc(indicatorX, indicatorY, 6, 0, 2 * Math.PI)context.setFillStyle('#9c4ce3')context.fill()context.draw()}}
})相关文章:
js:使用canvas画一个半圆
背景 需求需要画一个半圆,或者多半圆,其实一下子就能想到 canvas 中的圆弧,核心使用 context.arc context.arc(x,y,r,sAngle,eAngle,counterclockwise)接下来我们看看示例 例一 <!DOCTYPE html> <html lang"en"> &…...
1.框架介绍项目环境配置与项目启动!
目录 1.框架开发方向:2.项目启动与环境搭建 1.框架开发方向: 1.前后端分离项目 2.纯后端项目 3.移动端开发uni-app(ios、Android、H5、微信小程序) 4.内容管理系统2.项目启动与环境搭建 1.安装node.js 下载地址可以用nvm安装 便于运行前端项目https://juejin.cn/post/7094576…...
LeetCode算法题解:螺旋矩阵
LeetCode算法题解:螺旋矩阵 题目描述 给定一个 m x n 的矩阵,按照螺旋顺序返回矩阵中的所有元素。 解题思路 1. 初始化变量 我们首先定义四个边界变量来跟踪螺旋遍历的边界:top、bottom、left 和 right。 2. 螺旋遍历 开始从左到右遍历…...
【Java 设计模式】设计原则之开放封闭原则
文章目录 1. 定义2. 好处3. 应用4. 示例结语 在软件开发中,设计原则是创建灵活、可维护和可扩展软件的基础。 这些原则为我们提供了指导方针,帮助我们构建高质量、易理解的代码。 ✨单一职责原则(SRP) ✨开放/封闭原则(…...
数据分析求职-知识脑图
今天和大家聊聊数据分析求职常见面试题,这是这个系列的第一篇文章,但是我不想开始就直接罗列题目,因为这样的文章实在太多了,同学们的兴趣程度肯定一般。所以,我想先和大家聊聊在准备面试题时候通常遇到的困扰…...
SQL-修改数据
🎉欢迎您来到我的MySQL基础复习专栏 ☆* o(≧▽≦)o *☆哈喽~我是小小恶斯法克🍹 ✨博客主页:小小恶斯法克的博客 🎈该系列文章专栏:重拾MySQL 🍹文章作者技术和水平很有限,如果文中出现错误&am…...
Rockchip | FIQ-Debugger调试工具
FIQ-Debugger fiq debugger是集成到内核中的一种系统调试手段。 FIQ在arm架构中相当于nmi中断,fiq debugger把串口注册成fiq中断,在串口fiq中断服务程序中集成了一些系统调试命令。 一般情况下串口是普通的console模式,在串口工具下键盘输入…...
第二百六十三回 给geolocator插件提交问题
文章目录 1. 知识回顾2. 问题描述与解决2.1 问题描述2.2 问题解决 3. 心得与感受 1. 知识回顾 我们在前面章回中介绍过如何获取位置信息,主要介绍的是geolocator这个三方包,不过在最近使用时却发现了问题,尝试搜索解决,但是没有结…...
分组背包问题
题目来源:9. 分组背包问题 - AcWing题库 题目: 有 N 组物品和一个容量是 V 的背包。 每组物品有若干个,同一组内的物品最多只能选一个。 每件物品的体积是 vij,价值是 wij,其中 i 是组号,j 是组内编号。 …...
WinForm 中Label自动换行 解决方法
Label自动换行 1.单行完全显示:Label.AutoSize true; 2.换行显示:Label. AutoSize false;(Label框高度用户指定)。 3.多行显示 根据字数自动控制高度:Label.AutoSize true;Label.MaximumSize new Size(w,0); …...
【蓝桥杯软件赛 零基础备赛20周】第7周——二叉树
文章目录 1 二叉树概念2 二叉树的存储和编码2.1 二叉树的存储方法2.2 二叉树存储的编码实现2.3 二叉树的极简存储方法 3 例题4 习题 前面介绍的数据结构数组、队列、栈,都是线性的,它们存储数据的方式是把相同类型的数据按顺序一个接一个串在一起。简单的…...
SpringBoot+SSM项目实战 苍穹外卖(12) Apache POI
继续上一节的内容,本节是苍穹外卖后端开发的最后一节,本节学习Apache POI,完成工作台、数据导出功能。 目录 工作台Apache POI入门案例 导出运营数据Excel报表 工作台 工作台是系统运营的数据看板,并提供快捷操作入口,…...
Maven 基础总结篇
Maven 基础总结篇 Maven是专门用于管理和构建Java项目的工具,它的主要功能有: 提供了一套标准化的项目结构:用于解决不同IDE(例如eclipse与IDEA)不同的项目结构的问题 提供了一套标准化的构建流程(编译&…...
MySQL的导入导出及备份
一.准备导入之前 二.navicat导入导出 编辑 三.MySQLdump命令导入导出 四.load data file命令的导入导出 五.远程备份 六. 思维导图 一.准备导入之前 需要注意: 在导出和导入之前,确保你有足够的权限。在进行导入操作之前,确保目标数据…...
【机器学习】常见算法详解第2篇:K近邻算法各种距离度量(已分享,附代码)
本系列文章md笔记(已分享)主要讨论机器学习算法相关知识。机器学习算法文章笔记以算法、案例为驱动的学习,伴随浅显易懂的数学知识,让大家掌握机器学习常见算法原理,应用Scikit-learn实现机器学习算法的应用࿰…...
@KafkaListener指定kafka集群
基于KafkaListener注解的kafka监听代码可以手动指定要消费的kafka集群,这对于需要访问多套kafka集群的程序来说,是有效的解决方案。这里需要注意的是,此时的消费者配置信息需使用原生kafka的配置信息格式(如:ConsumerC…...
什么是算法的空间复杂度?
一、问题 常常⽤算法的空间复杂度来评价算法的性能,那么什么是算法的空间复杂度呢? 二、解答 算法的空间复杂度是指在算法的执⾏过程中,需要的辅助空间数量。 辅助空间数量指的不是程序指令、常数、指针等所需要的存储空间,也不是…...
WebDav协议相关软件@简单配置局域网内的http和WebDav服务器和传输系统
文章目录 相关软件windows自带第三方软件 chfs(CuteHttpFileServer)下载软件GUI方案 补充命令行方案命令行程序定位简单创建服务站点使用配置文件配置细节 使用软连接或符号链接等手段将向共享站点的根目录添加文件开机自启服务包装nssm包装使用powershell包装 服务启动chfs服务…...
自定义数据实现SA3D
SA3D:Segment Anything in 3D with NeRFs 实现了3D目标分割 原理是利用SAM(segment anything) 模型和Nerf分割渲染3D目标, SAM只能分块,是没有语义标签的,如何做到语义连续? SA3D中用了self-prompt, 根据前一帧的mask…...
设计模式基础概念:探索设计模式的魅力
设计模式是软件开发中的一种指导性概念,它提供了一套被广泛接受的解决方案,用于常见的设计问题。设计模式有助于提高软件的可重用性、可扩展性和可维护性,并促进团队之间的沟通。 以下是一些常见的设计模式: 创建型模式࿱…...
Spark 之 入门讲解详细版(1)
1、简介 1.1 Spark简介 Spark是加州大学伯克利分校AMP实验室(Algorithms, Machines, and People Lab)开发通用内存并行计算框架。Spark在2013年6月进入Apache成为孵化项目,8个月后成为Apache顶级项目,速度之快足见过人之处&…...
电脑插入多块移动硬盘后经常出现卡顿和蓝屏
当电脑在插入多块移动硬盘后频繁出现卡顿和蓝屏问题时,可能涉及硬件资源冲突、驱动兼容性、供电不足或系统设置等多方面原因。以下是逐步排查和解决方案: 1. 检查电源供电问题 问题原因:多块移动硬盘同时运行可能导致USB接口供电不足&#x…...
鱼香ros docker配置镜像报错:https://registry-1.docker.io/v2/
使用鱼香ros一件安装docker时的https://registry-1.docker.io/v2/问题 一键安装指令 wget http://fishros.com/install -O fishros && . fishros出现问题:docker pull 失败 网络不同,需要使用镜像源 按照如下步骤操作 sudo vi /etc/docker/dae…...
招商蛇口 | 执笔CID,启幕低密生活新境
作为中国城市生长的力量,招商蛇口以“美好生活承载者”为使命,深耕全球111座城市,以央企担当匠造时代理想人居。从深圳湾的开拓基因到西安高新CID的战略落子,招商蛇口始终与城市发展同频共振,以建筑诠释对土地与生活的…...
【无标题】路径问题的革命性重构:基于二维拓扑收缩色动力学模型的零点隧穿理论
路径问题的革命性重构:基于二维拓扑收缩色动力学模型的零点隧穿理论 一、传统路径模型的根本缺陷 在经典正方形路径问题中(图1): mermaid graph LR A((A)) --- B((B)) B --- C((C)) C --- D((D)) D --- A A -.- C[无直接路径] B -…...
4. TypeScript 类型推断与类型组合
一、类型推断 (一) 什么是类型推断 TypeScript 的类型推断会根据变量、函数返回值、对象和数组的赋值和使用方式,自动确定它们的类型。 这一特性减少了显式类型注解的需要,在保持类型安全的同时简化了代码。通过分析上下文和初始值,TypeSc…...
【 java 虚拟机知识 第一篇 】
目录 1.内存模型 1.1.JVM内存模型的介绍 1.2.堆和栈的区别 1.3.栈的存储细节 1.4.堆的部分 1.5.程序计数器的作用 1.6.方法区的内容 1.7.字符串池 1.8.引用类型 1.9.内存泄漏与内存溢出 1.10.会出现内存溢出的结构 1.内存模型 1.1.JVM内存模型的介绍 内存模型主要分…...
MySQL 索引底层结构揭秘:B-Tree 与 B+Tree 的区别与应用
文章目录 一、背景知识:什么是 B-Tree 和 BTree? B-Tree(平衡多路查找树) BTree(B-Tree 的变种) 二、结构对比:一张图看懂 三、为什么 MySQL InnoDB 选择 BTree? 1. 范围查询更快 2…...
django blank 与 null的区别
1.blank blank控制表单验证时是否允许字段为空 2.null null控制数据库层面是否为空 但是,要注意以下几点: Django的表单验证与null无关:null参数控制的是数据库层面字段是否可以为NULL,而blank参数控制的是Django表单验证时字…...
6.9-QT模拟计算器
源码: 头文件: widget.h #ifndef WIDGET_H #define WIDGET_H#include <QWidget> #include <QMouseEvent>QT_BEGIN_NAMESPACE namespace Ui { class Widget; } QT_END_NAMESPACEclass Widget : public QWidget {Q_OBJECTpublic:Widget(QWidget *parent nullptr);…...
