最近需要搞一个仪表盘动态更新的功能,新改版风格的UI表盘都不适用只有自己画了。
先上效果图:
- 补充几个知识
canvas坐标系:左上角的点为0.0 右下角的点为 width,height, 与之前我们学习的坐标系不同
cans.arc(x,y,r,0,Math.PI,1);
圆的中心的 x 坐标。
y 圆的中心的 y 坐标。
r 圆的半径。
sAngle 起始角,以弧度计。(弧的圆形的三点钟位置是 0 度)。
eAngle 结束角,以弧度计。
counterclockwise 可选。规定应该逆时针还是顺时针绘图。False = 顺时针,true = 逆时针。
ctx.fillText("textAlign=center",150,120); 实心字体
ctx.strokeText("Sample String", x0-text.width/2, y0-30) 空心字体
2.如何画一个半圆?
思路就是:其实角度为Math.PI ,结束角度为0,或者2Math.PI ,效果都是一样的,确定好了开始结束角度就能简单的画一个半圆
3.如何画一个指针的尖尖的三角?
思路就是先画一个宽一点的线段,根据线宽的一半来确定上下浮动的角度。
一个圆周是360.周长是2*Math.PI*R ,所以确定上下的浮动角度=2*Math.PI*R *360*线宽/2
再根据起始角度的不同算出来不同的坐标,先左下,在lineto到顶点,linto到第二点就可以实现
4.
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<meta http-equiv="X-UA-Compatible" content="ie=edge">
<title>Document</title>
</head>
<body>
<canvas id="mycanvas" class="mycanvas" width="338" height="168"></canvas>
</body>
<script>
/**
* 圆的中心的 x 坐标。
y 圆的中心的 y 坐标。
r 圆的半径。
sAngle 起始角,以弧度计。(弧的圆形的三点钟位置是 0 度)。
eAngle 结束角,以弧度计。
counterclockwise 可选。规定应该逆时针还是顺时针绘图。False = 顺时针,true = 逆时针。
ctx.lineTo(lineEndX,lineEndY);
ctx.lineTo(angEndX,angEndY);
ctx.fill();
// 线条末端线帽的设置为圆形
ctx.lineCap = 'round';
let differ = 4.6/2/Math.PI/ange3*360
ctx.fillText("textAlign=center",150,120); 实心字体
ctx.strokeText("Sample String", x0-text.width/2, y0-30) 空心字体
* @type {number}
*/
var canvas = document.getElementById('mycanvas');
const x0 = canvas.width/2; // 圆心坐标
const y0 = canvas.height; // 圆心坐标
const r1 = (x0 / 2 - 16) * 2 // 外圆半径
const r2 = (x0 / 2 - 30) * 2 // 内圆半径
const ange3 = (x0 / 2 - 20) * 2 // 线段终止的地方
const startAng = 180; // 起始角度
const curSpeedTex ="实时速率(Mbps)";
let curSpeed = Math.floor(Math.random() *3500);
const maxSpeed =3500;
let targetAng = curSpeed/maxSpeed*180+startAng; // 起始角度
function getPointX(r, ao) {
return x0 + r * Math.cos(ao * Math.PI / 180)
}
function getPointY(r, ao) {
return y0 + r * Math.sin(ao * Math.PI / 180)
}
var ctx = canvas.getContext("2d");
ctx.beginPath();
var img = new Image();//创建img元素
img.onload = function(){
// 参数 1:要绘制的 img 参数 2、3:绘制的 img 在 canvas 中的坐标 参数4,5是width,height
console.log("img.width="+img.width+",img1.height="+img.height);
ctx.drawImage(img,0,0,img.width,img.height);
}
img.src = 'yibiaopan.png';//设置图片源地址
ctx.fillStyle="#FEB95A";
// 获取大圆上的点 与 边界圆交点
let lineStartX = this.getPointX(r2, targetAng);
let lineStartY = this.getPointY(r2, targetAng);
// 获取小圆上的点 与 边界圆交点
let lineEndX = this.getPointX(r1, targetAng);
let lineEndY = this.getPointY(r1, targetAng);
let angX = this.getPointX(ange3, targetAng);
let angY = this.getPointY(ange3, targetAng);
ctx.beginPath();
ctx.moveTo(lineStartX, lineStartY);
ctx.lineWidth = 5;
ctx.lineCap = 'round';
ctx.strokeStyle = '#FEB95A';
ctx.lineTo(angX,angY);
ctx.stroke();
// 根据线的宽度确定小三角的开始坐标的偏移角度
let differ = 2.8/2/Math.PI/ange3*360
// 确定左下的坐标
let angStartX = this.getPointX(ange3, targetAng-differ);
let angStartY = this.getPointY(ange3, targetAng-differ);;
let angEndX = this.getPointX(ange3, targetAng+differ);
let angEndY = this.getPointY(ange3, targetAng+differ) ;
ctx.moveTo(angStartX, angStartY);
ctx.lineWidth = 1;
ctx.lineTo(lineEndX,lineEndY);
ctx.lineTo(angEndX,angEndY);
ctx.fill();
ctx.stroke();
ctx.strokeStyle = '#FEB95A';
ctx.save();
ctx.fillStyle="#00FFDC";
// 写文字
ctx.font = "28px Verdana"
// 确定文字长度,文字一半的位置刚好可以居中
var text = ctx.measureText(curSpeed)
console.log("text="+text.width+",text.height"+text.height);
ctx.fillText(curSpeed,x0-text.width/2, y0-45);
ctx.restore();
ctx.fillStyle="#FFF";
ctx.font = "16px Verdana"
// 实时速率的文字
var curspeed_text = ctx.measureText(curSpeedTex);
ctx.fillText(curSpeedTex,x0-curspeed_text.width/2, y0-14);
ctx.closePath();
</script>
<style>
.mycanvas{
background-color:#232228;
}
</style>
</html>