使用canvas 根据角度画圆弧


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

写了一小段,试试

export class Draw {
  constructor(domId) {
    let canvas = document.getElementById(domId);
    this.initLoad = false
    
    this.canvas = canvas;
    this.context = canvas.getContext('2d');
  }
  init(x,y,defaultColor='#000') {
    this.initLoad = true
    this.cx = x;
    this.cy = y;
    this.defaultColor = defaultColor
  }
  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)
          callback(x, y,ang)
          console.log(x, y,ang); // (x, y) 就是鼠标在 canvas 单击时的坐标 ang 是角度
        }
        
    });
  }
  getAngle(x, y,ox,oy) {
      // 根据直角边 求角度
      var radian = Math.atan(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
  }
  lines (x1,y1,x2,y2) {
    // 画直线
    this.context.beginPath();
    this.context.moveTo(x1,y1);
    
    this.context.lineTo(x2,y2); 
    this.context.strokeStyle = this.defaultColor; 
    this.context.stroke();
  }
  triangle (x1,y1,x2,y2,x3,y3,color,type) {
    // 画三角形
    this.context.beginPath();
    this.context.moveTo(x1, y1);
    this.context.lineTo(x2, y2);
    this.context.lineTo(x3, y3);
    this.context.lineTo(x1, y1);
    this.context[type + 'Style'] = color;

    this.context[type]();
    this.context.strokeStyle = color; 
    this.context.stroke();
  }
  air(r,sAngle,eAngle,color,flag=true) {
    // 画圆弧
    // 传入的角度按照 顺时针计算  0度 对应 0*Math.PI  360度 对应 2*Math.PI
    let startAngle = 2*sAngle/360
    let endAngle = 2*eAngle/360
    this.context.beginPath();
    this.context.arc(this.cx,this.cy,r,startAngle*Math.PI,endAngle*Math.PI,flag);
    this.context.fillStyle=color;//设置填充颜色
    this.context.fill();//开始填充
    this.context.strokeStyle = this.defaultColor; 
    this.context.stroke();
  }
  airAngle (r,sAngle,eAngle,color,flag=true) {
    // 计算链接的三角形 点的坐标
    
    if ((eAngle-sAngle<=180)){
      let angObjStart = this.mathAngle(sAngle,r)
      let angObjEnd = this.mathAngle(eAngle,r)
      this.air(r,sAngle,eAngle,color,flag)
      this.triangle(this.cx,this.cy,angObjStart.x,angObjStart.y,angObjEnd.x,angObjEnd.y,color,'fill')
      // 画起始角度
      this.lines(this.cx,this.cy,angObjStart.x,angObjStart.y)

      // 画结束角度
      this.lines(this.cx,this.cy,angObjEnd.x,angObjEnd.y)
    }else {
      let angObjStart = this.mathAngle(sAngle,r)
      let angObjEnd = this.mathAngle(180,r)
      this.air(r,sAngle,180,color,flag)
      this.triangle(this.cx,this.cy,angObjStart.x,angObjStart.y,angObjEnd.x,angObjEnd.y,color,'fill')
      this.lines(this.cx,this.cy,angObjStart.x,angObjStart.y)

      let angObjStart2 = this.mathAngle(180,r)
      let angObjEnd2 = this.mathAngle(eAngle,r)
      this.air(r,180,eAngle,color,flag)
      this.triangle(this.cx,this.cy,angObjStart2.x,angObjStart2.y,angObjEnd2.x,angObjEnd2.y,color,'fill')
      this.lines(this.cx,this.cy,angObjEnd2.x,angObjEnd2.y)
    }
  }
}

得到了这样的效果

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

相关