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

写了一小段,试试


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. javaweb-thymeleaf,加载jar包---视图基础

    1.加载完thymeleaf的jar包 将thymeleaf的jar包复制到项目下lib文件夹中 右击lib文件夹,点击Add as librarb... 打开Project Structure,找到 ...

  2. VS2019 Community社区版登录提示:我们无法刷新此账户的凭证 解决方法

    最正确的方式: 1.点击 帮助-->发送反馈-->报告问题 2.点击 检查新的许可证 ,即可登陆成功 3.如果提示:无法下载或者下载失败. 4.那么就需要在左边 账户选项 中将 嵌入式We ...

  3. 函数索引引用的函数必须是immutable类型

    用户在使用中,可能会用到基于函数的索引,但是函数是非 immutable 类型的,导致函数索引无法创建.如: test=# create index ind_t1 on t1(to_char(crea ...

  4. Elasticsearch7.6.2 RestHighLevelClient查询用法 must should(and or 关系)

    1. 引入jar <dependency> <groupId>org.elasticsearch.client</groupId> <artifactId&g ...

  5. 为什么最近每份 Android 简历都说 “熟悉 MQTT 协议”?

    请点赞关注,你的支持对我意义重大. Hi,我是小彭.本文已收录到 GitHub · AndroidFamily 中.这里有 Android 进阶成长知识体系,有志同道合的朋友,关注公众号 [彭旭锐] ...

  6. 腾讯云实验室 Gitea 互动教程上线啦

    如果你想学习.体验或是向他人演示开源的 Gitea 代码托管方案,那么接下来给你推荐一款神器. 使用腾讯云实验室免费获得 Gitea 实验环境,直接通过浏览器就可在 Ubuntu Server 20. ...

  7. Django CSRF验证失败. 请求被中断.

    当页面中form使用POST方式向后台提交时,报如下错误: 禁止访问 (403) CSRF验证失败. 请求被中断. Help Reason given for failure: ​ CSRF toke ...

  8. 云原生分布式文件存储 MinIO 教程

    文章转载自:https://mp.weixin.qq.com/s/_52kZ5jil1Cec98P5oozoA MinIO 提供开源.高性能.兼容 s3 的对象存储,为每个公共云.每个 Kuberne ...

  9. 使用nginx反向代理RabbitMQ的web界面

    直接贴nginx的conf配置: server { listen 80; server_name www.xxxxx.com; location / { client_body_buffer_size ...

  10. filebeat测试output连通性

    在默认的情况下,直接运行filebeat的话,它选择的默认的配置文件是当前目录下的filebeat.yml文件. filebeat.yml文件内容 filebeat.inputs: - type: l ...