最近收到一个需求,根据角度在平面上画出对应的区域,实际就是 以固定的原点,根据起始角度和结束角度和半径,画出他的区域。

写了一小段,试试


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>

得到了这样的效果

鼠标滑到 对应的区域,将返回该点的坐标 和角度

使用canvas 根据角度画圆弧的更多相关文章

  1. 有趣html5(两)----使用canvas结合剧本画在画布上的简单图(html5另一个强大)

    请珍惜劳动小编成果,这篇文章是原来小编,转载请注明出处. 于html5中能够使用canvas标签在画布上绘图,先直接上代码,这篇文章先简介一下canvas的用法.简单画几个圆,矩形,三角形,写字. 在 ...

  2. UIBezierPath画圆弧的记录

    UIBezierPath通过 - (void)addArcWithCenter:(CGPoint)center radius:(CGFloat)radius startAngle:(CGFloat)s ...

  3. Canvas中如何画一条清晰的线宽为奇数(如1px逻辑像素)的线?

    我在开发中使用canvas的机会不是很多,但是第一次实际使用中就遇到了问题,"很久很久以前,我自己画了一个雷达图,线宽都是1像素,但是显示效果不如期望,这才发现canvas中的画线还是有坑的 ...

  4. IOS 绘制基本图形( 画圆、画线、画圆弧、绘制三角形、绘制四边形)

    // 当自定义view第一次显示出来的时候就会调用drawRect方法- (void)drawRect:(CGRect)rect { // 1.获取上下文 CGContextRef ctx = UIG ...

  5. KiCad EDA 画圆弧

    KiCad EDA 画圆弧 看起来像是成功了. KiCad 画圆弧一直没有完善解决,但是 KiCad 一直有在努力.

  6. 关于 KiCad 画圆弧走线

    关于 KiCad 画圆弧走线 有很多关于 关于 KiCad 画圆弧走线的帖子. 最新进展是 V6 在开发中. 但是因为关于 DRC 问题,开发好像有难度. https://bugs.launchpad ...

  7. canvas入门(画圆)

    1.想在H5上画一个canvas,必须在页面上你需要的地方添加canvas标签, <canvas id="myCanvas"></canvas>   接着需 ...

  8. Html5新特性 &lt;canvas&gt;画板画直线

     以下样例为用canvas标签画多条直线 <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" & ...

  9. 用HTML5 Canvas做一个画图板

    使用HTML5可以非常简单地在canvas上实现画图应用,用支持html5的浏览器便可在下面的区域进行绘画,要看到演示效果,请确保你的浏览器支持HTML5: 功能很简单,原理其实和拖放是类似的,主要是 ...

随机推荐

  1. OpenJ_Bailian - 3424 Candies (差分约束)

    题面 During the kindergarten days, flymouse was the monitor of his class. Occasionally the head-teache ...

  2. 1.6_HTML基础属性

    name 属性 name 属性用于指定标签元素的名称. <a> 标签内必须提供 href 或 name 属性. <a name="value"> id 属性 ...

  3. 青源Talk第8期|苗旺:因果推断,观察性研究和2021年诺贝尔经济学奖

    biobank 英国的基金数据因果推断和不同的研究互相论证,而非一个研究得到的接了就行.数据融合,data fusion,同一个因果问题不同数据不同结论,以及历史上的数据,来共同得到更稳健.更高效的推 ...

  4. 【Java】学习路径53-InetAdress获取服务器ip

    InetAdress如何使用? import java.net.*; public class InetAdress { public static void main(String[] args) ...

  5. 第八十八篇:Vue keep-alive的使用 让组件"活下去""

    好家伙, 1.关于keep-alive 这是一个用于阻止组件自行销毁的插件 <!-- keep-alive可以把内部组件进行缓存,而不是销毁组件 --> 那么我们什么时候会用到他呢? 举个 ...

  6. 在安装Windows时手动创建分区

    目前硬件都已经支持UEFI模式启动了,而且硬盘容量普遍大于MBR磁盘能支持的最大2TB的容量.所以在安装Windows系统的时候优先选用UEFI启用,并将磁盘配置为GPT模式以支持更大的容量.而且Wi ...

  7. PostgreSQL逻辑复制解密

    在数字化时代的今天,我们都认同数据会创造价值.为了最大化数据的价值,我们不停的建立着数据迁移的管道,从同构到异构,从关系型到非关系型,从云下到云上,从数仓到数据湖,试图在各种场景挖掘数据的价值.而在这 ...

  8. Kubernetes的kubectl常用命令速记

    文章转载自:https://mp.weixin.qq.com/s/0kqQzeA-MzCOhPMkmiR4_A kubectl是用来管理Kubernetes集群的命令行工具. kubectl默认在&q ...

  9. 使用Prometheus和Grafana监控emqx集群

    以 Prometheus为例: emqx_prometheus 支持将数据推送至 Pushgateway 中,然后再由 Promethues Server 拉取进行存储. 注意:emqx_promet ...

  10. 监控Redis集群,有两种方法

    前提条件 redis集群:已搭建三主三从(三台主机) prometheus.grafana已安装 三台主机ip: 192.168.0.39,192.168.0.164,192.168.0.68 第一种 ...