美文网首页
LayaBox:工具类HitArea(绘制可视区域)

LayaBox:工具类HitArea(绘制可视区域)

作者: 一眼就认出你 | 来源:发表于2020-10-13 10:17 被阅读0次

    代码:

    package laya.utils {
        import laya.display.Graphics;
        import laya.maths.Point;
        import laya.maths.Rectangle;
        import laya.renders.Render;
        import laya.renders.RenderContext;
        
        /**
         * 鼠标点击区域,可以设置绘制一系列矢量图作为点击区域和非点击区域(目前只支持圆形,矩形,多边形)
         */
        public class HitArea {
            
            /**@private */
            private static var _cmds:Array = [];
            /**@private */
            private static var _rec:Rectangle = new Rectangle();
            /**@private */
            private static var _ptPoint:Point = new Point();
            /**@private */
            private var _hit:Graphics;
            /**@private */
            private var _unHit:Graphics;
            
            /**
             * 是否包含某个点
             * @param x x坐标
             * @param y y坐标
             * @return 是否点击到
             */
            public function isHit(x:Number, y:Number):Boolean {
                if (!isHitGraphic(x, y, hit)) return false;
                return !isHitGraphic(x, y, unHit);
            }
            
            /**
             * 检测对象是否包含指定的点。
             * @param   x   点的 X 轴坐标值(水平位置)。
             * @param   y   点的 Y 轴坐标值(垂直位置)。
             * @return  如果包含指定的点,则值为 true;否则为 false。
             */
            public function contains(x:Number, y:Number):Boolean {
                return isHit(x, y);
            }
            
            /**
             * @private
             * 是否击中Graphic
             */
            public static function isHitGraphic(x:Number, y:Number, graphic:Graphics):Boolean {
                if (!graphic) return false;
                var cmds:Array;
                cmds = graphic.cmds;
                if (!cmds && graphic._one) {
                    cmds = _cmds;
                    cmds.length = 1;
                    cmds[0] = graphic._one;
                    
                }
                if (!cmds) return false;
                var i:int, len:int;
                len = cmds.length;
                var cmd:Array;
                for (i = 0; i < len; i++) {
                    cmd = cmds[i];
                    if (!cmd) continue;
                    var context:RenderContext = Render._context;
                    switch (cmd.callee) {
                    
                    case context._translate: 
                    case 6://translate
                        x -= cmd[0];
                        y -= cmd[1];
                    default:
                        
                    }
                    if (isHitCmd(x, y, cmd)) return true;
                }
                return false;
            }
            
            /**
             * @private
             * 是否击中绘图指令
             */
            public static function isHitCmd(x:Number, y:Number, cmd:Array):Boolean {
                if (!cmd) return false;
                var context:RenderContext = Render._context;
                var rst:Boolean = false;
                switch (cmd["callee"]) {
                
                case context._drawRect: 
                case 13://case context._drawRect:
                    _rec.setTo(cmd[0], cmd[1], cmd[2], cmd[3]);
                    rst = _rec.contains(x, y);
                    break;
                case context._drawCircle: 
                case context._fillCircle: 
                case 14://case context._drawCircle
                    var d:Number;
                    x -= cmd[0];
                    y -= cmd[1];
                    d = x * x + y * y;
                    rst = d < cmd[2] * cmd[2];
                    break;
                
                case context._drawPoly: 
                case 18://drawpoly
                    x -= cmd[0];
                    y -= cmd[1];
                    rst = ptInPolygon(x, y, cmd[2]);
                    break;
                default: 
                    break;
                }
                return rst;
            }
            
            /**
             * @private
             * 坐标是否在多边形内
             */
            public static function ptInPolygon(x:Number, y:Number, areaPoints:Array):Boolean {
                var p:Point;
                p = _ptPoint;
                p.setTo(x, y);
                // 交点个数
                var nCross:int = 0;
                var p1x:Number, p1y:Number, p2x:Number, p2y:Number;
                var len:int;
                len = areaPoints.length;
                for (var i:int = 0; i < len; i += 2) {
                    p1x = areaPoints[i];
                    p1y = areaPoints[i + 1];
                    p2x = areaPoints[(i + 2) % len];
                    p2y = areaPoints[(i + 3) % len];
                    //var p1:Point = areaPoints[i];
                    //var p2:Point = areaPoints[(i + 1) % areaPoints.length]; // 最后一个点与第一个点连线
                    if (p1y == p2y)
                        continue;
                    if (p.y < Math.min(p1y, p2y))
                        continue;
                    if (p.y >= Math.max(p1y, p2y))
                        continue;
                    // 求交点的x坐标
                    var tx:Number = (p.y - p1y) * (p2x - p1x) / (p2y - p1y) + p1x;
                    // 只统计p1p2与p向右射线的交点
                    if (tx > p.x) {
                        nCross++;
                    }
                }
                // 交点为偶数,点在多边形之外
                return (nCross % 2 == 1);
            }
            
            /**
             * 可点击区域,可以设置绘制一系列矢量图作为点击区域(目前只支持圆形,矩形,多边形)
             */
            public function get hit():Graphics {
                if (!_hit) _hit = new Graphics();
                return _hit;
            }
            
            public function set hit(value:Graphics):void {
                _hit = value;
            }
            
            /**
             * 不可点击区域,可以设置绘制一系列矢量图作为非点击区域(目前只支持圆形,矩形,多边形)
             */
            public function get unHit():Graphics {
                if (!_unHit) _unHit = new Graphics();
                return _unHit;
            }
            
            public function set unHit(value:Graphics):void {
                _unHit = value;
            }
        }
    }
    
    

    相关文章

      网友评论

          本文标题:LayaBox:工具类HitArea(绘制可视区域)

          本文链接:https://www.haomeiwen.com/subject/oeizjctx.html