html5中监视canvas內部元素点一下恶性事件的3种方

日期:2021-01-20 类型:科技新闻 

关键词:小程序制作流程,抽奖小程序,微信小程序怎么开店,小程序码生成,小程序模版

canvas內部元素不可以像DOM元素1样便捷的加上互动恶性事件监视,由于canvas内不存在“元素”这个定义,她们仅仅是canvas绘图出来的图型。这针对互动开发设计来讲是1个必经阻碍,要想监视图型的点一下恶性事件思路很简易,要是监视canvas元素自身的点一下恶性事件,再分辨点一下座标坐落于哪个图型內部,就变相完成了图型点一下恶性事件。本文将详细介绍3种方式,分辨座标点是不是坐落于某个canvas图型內部。

承诺

本文详细介绍的3种方式可用于鉴别canvas内样子不规律并且部位无规律性的图型点一下恶性事件,针对样子标准或部位有规律性的情景,毫无疑问有更简单的完成,这里不做探讨。

像素法

像素检验法的思路是,将canvas中的好几个图型(假如有好几个的话)各自离屏绘图,并用 getImageData() 方式各自获得到像素数据信息储存起来。当canvas元素监视到点一下恶性事件时,根据点一下座标能够立即推算出点一下产生在canvas上的第几个像素,随后遍历前面储存的图型数据信息,看看这个像素的alpha值是否0,假如是0表明落点不在当今图型内,不然就表明点到了这个图型。

依据点一下座标获得所点一下的像素编号的方式:

像素编号 = (纵座标⑴) * canvas宽度 + 横座标

例如在宽度为 5 的画布上点一下座标 (3,3) ,依据上述公式获得像素编号是 (3⑴) * 5 + 3 = 18 ,如图所示:

由于canvas导出来的图型数据信息是将每一个像素以 rgba 的次序存成4个数据构成的数字能量数组,因此想浏览特定像素的alpha值,要是载入这个数字能量数组的第 pIndex * 4 + 3 个值便可以了,假如这个值不为0,表明该像素可见,也便是点一下到了该图型。

这个方式是我觉得思路最立即、結果最精确、并且对图型样子沒有任何规定的方式,但这个方式有1个致命的局限,当图型必须在画布上挪动时,要经常的建立数据信息缓存文件才可以确保检验結果精确,遭受画布规格和图型数量的危害, getImageData() 方式的特性会变成比较严重的短板。因此假如canvas图型是静态数据的,这个方式十分合适,不然就不合适用这个方式了。

角度法

角度分辨法的基本原理很非常容易了解,假如1个点在多边形內部,则该点与多边形全部端点两两组成的夹角,相加应当恰好等于360°。

测算全过程能够变化为下列3个流程:

1.已知多边形端点和已知座标,将座标与端点两两组成成3点序列
2. 已知3点求夹角,可使用 余玄定理
3.分辨夹角之和是不是360°

每步都很简易,完成以下:

//测算两点间距
const getDistence = function (p1, p2) {
  return Math.sqrt((p1.x - p2.x) * (p1.x - p2.x) + (p1.y - p2.y) * (p1.y - p2.y))
};
//角度法分辨点在多边形內部
const checkPointInPolyline = (point, polylinePoints) => {
    let totalA = 0;
    const A = point;
    for (let i = 0; i < polylinePoints.length; i++) {
        let B, C;
        if (i === polylinePoints.length - 1) {
            B = {
                x: polylinePoints[i][0],
                y: polylinePoints[i][1]
            };
            C = {
                x: polylinePoints[0][0],
                y: polylinePoints[0][1]
            };
        } else {
            B = {
                x: polylinePoints[i][0],
                y: polylinePoints[i][1]
            };
            C = {
                x: polylinePoints[i + 1][0],
                y: polylinePoints[i + 1][1]
            };
        }
        //测算角度
        const angleA = Math.acos((Math.pow(getDistence(A, C), 2) + Math.pow(getDistence(A, B), 2) - Math.pow(getDistence(B, C), 2)) / (2 * getDistence(A, C) * getDistence(A, B)))
        totalA += angleA
    }
    //分辨角度之和
    return totalA === 2 * Math.PI
}

这个方式有1个局限性,便是图型务必是 凸多边形 。假如并不是凸多边形必须先激光切割成凸多边形再测算,这就较为繁杂了。

相近的思路也有面积法,假如1个点在多边形內部,那末该点与多边形全部端点两两组成的3角形,面积相加应当等于多边形的面积,最先测算多边形的面积就很不便,因此这类方式能够立即pass掉。

射线法

射线法是1个我讲不清道理但十分功能强大的方式,要是分辨点与多边形1侧的交点个数为单数,则点在多边形內部。必须留意的是,要是数任何1侧的聚焦点个数便可以,例如左边。这个方式不限定多边形的种类,凸多边形、凹多边形乃至环状都可以以。

完成起来也十分简易:


 

const checkPointInPolyline = (point, polylinePoints) => {
    //射线法
  let leftSide = 0;
  const A = point;
  for (let i = 0; i < polylinePoints.length; i++) {
    let B, C;
    if (i === polylinePoints.length - 1) {
      B = {
        x: polylinePoints[i][0],
        y: polylinePoints[i][1]
      };
      C = {
        x: polylinePoints[0][0],
        y: polylinePoints[0][1]
      };
    } else {
      B = {
        x: polylinePoints[i][0],
        y: polylinePoints[i][1]
      };
      C = {
        x: polylinePoints[i + 1][0],
        y: polylinePoints[i + 1][1]
      };
    }
    //分辨左边交叉
    let sortByY = [B.y, C.y].sort((a,b) => a-b)
    if (sortByY[0] < A.y && sortByY[1] > A.y){
      if(B.x<A.x || C.x < A.x){
        leftSide++
      }
    }
  }
  return leftSide % 2 === 1
}

射线法有1种独特状况,当点在多形变的1条旁边时必须独特解决。但在工程项目中我觉得还可以不解决,由于假如客户恰好点在图型的界限上,那末程序流程觉得他沒有点到也讲的以往。

总结

以上3种方式都可以以完成canvas中不规律图型的点一下检验。在其中,像素法的优点在于不挑样子,并且在静态数据情景中有1定的特性优点;角度法应当说仅有基础理论使用价值,好用性不佳;工程项目中最好用确当属射线法,局限性小,完成简易,大部分情况下只必须了解射线法便可以了。
 

上一篇:手机微信红包作用 返回下一篇:没有了