zoukankan      html  css  js  c++  java
  • 前端小功能: 绘制多边形,并判断某个点是否在区域内

    canvas 绘制不规则多边形,包涵里面的元素不能超出多边形。

    canvas绘制多边形,并且判断某个点是否在区域内。

    涉及canvas画点,画线,成面。

    x,y坐标系,斜率,js拖拽等。

    斜率: k=(y2-y1)/(x2-x1);

    canvas画点,画线,成面:

      // 绘制连接的折线
      this.cxt.beginPath();
      this.cxt.strokeStyle='#666';
      this.cxt.lineWidth = 1;
      this.cxt.moveTo(maxXyArr[0].x,maxXyArr[0].y );
      for(let i=1,len=maxXyArr.length;i<len;i++){
          this.cxt.lineTo(maxXyArr[i].x,maxXyArr[i].y);
      }
      this.cxt.closePath(); //虽然我们只绘制了两条线段,但是closePath会closePath,仍然是一个3角形
      this.cxt.stroke(); // 描边。stroke不会自动closePath()            
    maxXyArr,就是坐标点。录入三个以上坐标就能成面。
    demo坐标例子maxXyArr:[{x:100,y:100},{x:100,y:400},{x:400,y:400},{x:400,y:100}],
    当然这个是一个规矩的四边形,判断某个点是否在区域内,可以是任意图形。

    判断某个点在多边形内部

    问题假设:有一个点P,有一个多边形A,我们要判断A是否包含P。

    基础知识–光线投射法

    原理:

    1、从点P出发,任意引一条射线(模拟光线)。

    2、记录该条射线与多边形A的边相交点的个数。

    3、判断交点的个数,若为偶数表示在图形外,若为奇数表示在图像内。

    光线投射法【升级版】

    原理:

    1、从点P出发,任意引一条射线(模拟光线)。

    2、该条射线与多边形A的边相交时,若射线从边的左侧贯穿记录leftCount加1,若射线从边的右侧贯穿记录rightCount加1。

    3、若leftCount-rightCount等于0表示在图形外部,若不等于0表示图形内部。

    /**
    * @param  dot {{x,y}} 需要判断的点
    * @param  coordinates {{x,y}[]} 多边形点坐标的数组,为保证图形能够闭合,起点和终点必须相等。
    *        比如三角形需要四个点表示,第一个点和最后一个点必须相同。 
    * @param noneZeroMode 对不规则图形进行判断
    */ function judge(dot,coordinates,noneZeroMode) {   // 默认启动none zero mode   noneZeroMode=noneZeroMode||1;   var x = dot.x,y=dot.y;   var crossNum = 0; // 点在线段的左侧数目 var leftCount = 0; // 点在线段的右侧数目 var rightCount = 0; for(var i=0;i<coordinates.length-1;i++){ var start = coordinates[i]; var end = coordinates[i+1]; // 起点、终点斜率不存在的情况 if(start.x===end.x) { // 因为射线向右水平,此处说明不相交 if(x>start.x) continue; // 从左侧贯穿 if((end.y>start.y&&y>=start.y && y<=end.y)){ leftCount++; crossNum++; } // 从右侧贯穿 if((end.y<start.y&&y>=end.y && y<=start.y)) { rightCount++; crossNum++; } continue; } // 斜率存在的情况,计算斜率 var k=(end.y-start.y)/(end.x-start.x); // 交点的x坐标 var x0 = (y-start.y)/k+start.x; // 因为射线向右水平,此处说明不相交 if(x>x0) continue; if((end.x>start.x&&x0>=start.x && x0<=end.x)){ crossNum++; if(k>=0) leftCount++; else rightCount++; } if((end.x<start.x&&x0>=end.x && x0<=start.x)) { crossNum++; if(k>=0) rightCount++; else leftCount++; } } return noneZeroMode===1?leftCount-rightCount!==0:crossNum%2===1; },

    通过获取点击的坐标点进行判断,于canvas画矩形

    let dot = {x: e.offsetX, y: e.offsetY}
    let maxArray = JSON.parse(JSON.stringify(maxXyArr))
    maxArray.push(coordinates[0])
    let flag = judge(dot,maxArray)
    console.log(flag)

    完成。

    这样的不规则图形UI才能很方便的响应舞台的事件。

    没有终点,没有彼岸,坚持就好,愿岁月如初

    smallbore,world
  • 相关阅读:
    WebSocket connection to 'ws://192.168.3.195:9527/sockjs-node/564/fjaw2vh2/websocket' failed: Invalid frame header
    审核警告:“data-custom”太新,无法在此检查的页面上运行以及cannot declare a const variable twice 'n'解决。
    react中如何使用iconfont
    重视工作质量,对自己的代码负责
    提醒自己不要浮躁
    结果重要同样过程也同样重要,享受过程
    访问链表节点的时候,需要判断链表节点是否可以访问
    遇到问题或者线上问题不要急,冷静分析,沉着处理
    注意运算符的运算优先级别
    对每一个IO操作的返回都要进行判断
  • 原文地址:https://www.cnblogs.com/bore/p/11427860.html
Copyright © 2011-2022 走看看