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

写了一小段,试试


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. 【NOI P模拟赛】混凝土粉末(整体二分)

    题面 样例输入 5 8 1 1 4 2 2 3 1 2 3 3 1 2 5 1 2 3 3 2 5 2 2 1 2 2 1 3 样例输出 1 0 4 0 1 0 样例解释 题解 比这道题简单了不知多少 ...

  2. Spring5中JdbcTemplate

    JdbcTemplate是什么 JdbcTemplate 类提供了很多便利的方法解决诸如把数据库数据转变成基本数据类型或对象,执行写好的或可调用的数据库操作语句,提供自定义的数据错误处理. 在spri ...

  3. 关于 Math.random()生成指定范围内的随机数的公式推导

    关于 Math.random()生成指定范围内的随机数的公式推导 在 java 中,用于生成随机数的 Math 方法 random()只能生成 0-1 之间的随机数,而对于生成指定区间,例如 a-b ...

  4. 如何高效解决 C++内存问题,Apache Doris 实践之路|技术解析

    导读:Apache Doris 使用 C++ 语言实现了执行引擎,C++ 开发过程中,影响开发效率的一个重要因素是指针的使用,包括非法访问.泄露.强制类型转换等.本文将会通过对 Sanitizer 和 ...

  5. electron 起步

    electron 起步 为什么要学 Electron,因为公司需要调试 electron 的应用. Electron 是 node 和 chromium 的结合体,可以使用 JavaScript,HT ...

  6. Python数据科学手册-机器学习: 支持向量机

    support vector machine SVM 是非常强大. 灵活的有监督学习算法, 可以用于分类和回归. 贝叶斯分类器,对每个类进行了随机分布的假设,用生成的模型估计 新数据点 的标签.是属于 ...

  7. Kubernetes Operator: Operator

    Operator 就可以看成是 CRD 和 Controller 的一种组合特例,Operator 是一种思想,它结合了特定领域知识并通过 CRD 机制扩展了 Kubernetes API 资源,使用 ...

  8. MinIO管理员完整指南

    官方文档地址:http://docs.minio.org.cn/docs/master/minio-admin-complete-guide MinIO Client(mc)提供了" adm ...

  9. 使用国内镜像源安装kubelet kubeadm kubectl

    由于官网未开放同步方式, 可能会有索引gpg检查失败的情况, 这时请用 yum install -y --nogpgcheck kubelet kubeadm kubectl 安装 Debian / ...

  10. Alertmanager配置概述

    Alertmanager主要负责对Prometheus产生的告警进行统一处理,因此在Alertmanager配置中一般会包含以下几个主要部分: 全局配置(global):用于定义一些全局的公共参数,如 ...