最近收到一个需求,根据角度在平面上画出对应的区域,实际就是 以固定的原点,根据起始角度和结束角度和半径,画出他的区域。
写了一小段,试试
export class Draw {
constructor(domId) {
let canvas = document.getElementById(domId);
this.initLoad = false
this.storeName = ""
this.canvas = canvas;
this.context = canvas.getContext('2d'); //创建在画布上绘图的环境
}
init(x,y,offset=0) {
// 圆心坐标 x, y . 起始角度的偏差值 offset
this.initLoad = true
this.cx = x;
this.cy = y;
this.offset = offset
}
mousemoveInit(callback) {
let _this = this
this.canvas.addEventListener("mousemove", function __handler__(evt) {
if (!_this.initLoad) return
var x = evt.clientX;
var y = evt.clientY;
var rect = _this.canvas.getBoundingClientRect(); //返回元素的大小及其相对于视口的位置
x -= rect.left;
y -= rect.top;
let xl = Math.abs(x-_this.cx) //取绝对值
let yl = Math.abs(y-_this.cy)
let hl = _this.findHypotenuse(xl,yl) //根据直角边,求斜边的长度
if (hl<200){
let ang = _this.getAngle(xl,yl,x,y) // 获取点相对圆心的角度, 0 度在横轴x 上
let offsetAng = _this.getOffsetAngle(ang)
callback(x, y,offsetAng)
// console.log(x, y,offsetAng); // (x, y) 就是鼠标在 canvas 单击时的坐标 ang 是角度
}else{
callback(0, 0,500)
}
});
}
getOffsetAngle(ang) {
// 根据计算的标准角度 返回用户需要的偏差角度
return ang>90?ang-this.offset:ang+270
}
getAngle(x, y,ox,oy) {
// 根据直角边 求角度
var radian = Math.atan(y / x);//弧度 (y / x)为直线的斜率
var angle = Math.floor(180 / (Math.PI / radian));//弧度转角度
if (x < 0) {//x小于0的时候加上180°,即实际角度
angle = angle + 180;
}
if (ox>=this.cx && oy>= this.cy) {
return angle;
} else if (ox <= this.cx && oy>= this.cy) {
return 180-angle
}else if (ox <= this.cx && oy<= this.cy) {
return 180+angle
}else if (ox>=this.cx && oy<= this.cy) {
return 360-angle
}
}
findHypotenuse (base,perpendicular) {
// 根据直角边 求斜边的长度
const bSquare = base ** 2;
const pSquare = perpendicular ** 2;
const sum = bSquare + pSquare;
const hypotenuse = Math.sqrt(sum); //返回一个数的平方根
return Math.floor(hypotenuse);
}
mathAngle(angle,r) {
// 根据角度求 坐标
let angObj = {
x: '',
y: ''
}
var angles = 0;
var radian = 0;
if (angle<=90) {
angles = 90-angle
}else if (angle>90 && angle <=180) {
angles = angle-90
}else if (angle>180 && angle <=270) {
angles = 270- angle
}else if (angle>270 && angle <=360) {
angles = angle-270
}
radian = angles * Math.PI / 180
let xlen = Math.floor(Math.sin(radian)*r)
let ylen = Math.floor(Math.cos(radian)*r)
if (angle<=90) {
angObj.x = this.cx+xlen
angObj.y = this.cy+ylen
}else if (angle>90 && angle <=180) {
angObj.x = this.cx-xlen
angObj.y = this.cy+ylen
}else if (angle>180 && angle <=270) {
angObj.x = this.cx-xlen
angObj.y = this.cy-ylen
}else if (angle>270 && angle <=360) {
angObj.x = this.cx+xlen
angObj.y = this.cy-ylen
}
return angObj
}
clearRect () {
// 清除画布
this.context.clearRect(0,0,this.cx*2,this.cy*2);
}
lines (x1,y1,x2,y2,color,width=5) {
// 画直线
this.context.beginPath();
this.context.lineWidth = width;
this.context.moveTo(x1,y1);
this.context.lineTo(x2,y2);
this.context.strokeStyle = color;
this.context.stroke();
}
pieChart(r,sAngle,eAngle,color,flag=true) {
// 画扇形
let startAngle = 2*sAngle/360
let endAngle = 2*eAngle/360
this.context.beginPath();
this.context.lineWidth = 1;
this.context.moveTo(this.cx,this.cy);
this.context.strokeStyle = "white";
this.context.fillStyle = color;
this.context.arc(this.cx,this.cy,r,startAngle*Math.PI,endAngle*Math.PI);
this.context.fill();
this.context.closePath();
this.context.stroke();
}
pieName(x,y,color,name) {
//文字绘制到扇形旁边
this.context.fillText(name,x,y);
}
}
export class Angle extends Draw {
correct (ang) {
// 将传入的角度按照偏差值 进行纠正
return ang+this.offset<=360?ang+this.offset:ang+this.offset-360
}
correctM (sAngle,eAngle) {
// 取俩角度中间值
if (sAngle > eAngle) {
let ang = sAngle + 1/2*(360-sAngle+eAngle);
return ang>360?ang-360:ang
}
return sAngle + 1/2*(eAngle-sAngle);
}
drawAir (r,sAngle,eAngle,color,name) {
// 画分区的扇形
sAngle = this.correct(sAngle)
eAngle = this.correct(eAngle)
this.pieChart(r,sAngle,eAngle,color,name)
}
drawName (r,sAngle,eAngle,color,name) {
// 画分区的名字
sAngle = this.correct(sAngle)
eAngle = this.correct(eAngle)
//计算文字要放的角度
var txtAngle = this.correctM(sAngle,eAngle)
this.context.textAlign = 'center';
if(txtAngle>95 && txtAngle<260){
this.context.textAlign = 'end';
}
if(txtAngle<85 && txtAngle>5){
this.context.textAlign = 'left';
}
if(txtAngle<350 && txtAngle>275){
this.context.textAlign = 'left';
}
var x,y;
x=this.cx+Math.cos(txtAngle*Math.PI/180)*(r+20);
y=this.cy+Math.sin(txtAngle*Math.PI/180)*(r+20);
this.pieName(x,y,color,name)
}
drawMachine(r,angle,color) {
// 画机器的位置
this.lines(this.cx,this.cy,40,140,"#ff0")
}
}
<template>
<canvas id="can" width="600" height="600"></canvas>
</template>
<script>
import {onMounted} from 'vue'
import {Draw} from './draw.js'
export default {
setup(){
function pageLoad(){
let draw = new Draw('can')
draw.init(300,300)
draw.airAngle(200,20,90,'#ff0',false)
draw.airAngle(200,150,290,'#ff8',false)
draw.mousemoveInit((x, y,ang)=>{
console.log(x, y,ang)
})
}
onMounted(() =>{
pageLoad()
})
} }
</script>
得到了这样的效果
鼠标滑到 对应的区域,将返回该点的坐标 和角度