如何在给定鼠标坐标的情况下检测重叠(旋转)的DOM元素? [英] How to detect overlapping (rotated) DOM elements given mouse coordinate?

查看:76
本文介绍了如何在给定鼠标坐标的情况下检测重叠(旋转)的DOM元素?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我使用以下脚本来获取鼠标单击坐标处的重叠DIV元素的列表.

I use the following script in order to get a list of overlapping DIV elements at mouse click coordinates.

在此示例中,如果未旋转DIV,脚本可以正常工作:

In this example script works fine if the DIV are not rotated:

http://jsfiddle.net/eyxt2tt1/2/

如果我在DIV上应用旋转,然后用户单击(在此示例中,红色标记附近)

If I apply a rotation on a DIV and user click (near red mark in this example)

http://jsfiddle.net/eyxt2tt1/3/

当脚本只考虑一个DIV时,它将始终返回两个DIV.

The script will always return two DIV when instead it should consider only one.

我需要知道:

  • 如何在计算中考虑轮换?
  • 您知道更好的方法/替代方法吗?

注意:

  • 我无法使用Document.elementFromPoint()
  • 在SO上它们是类似的问题,但是我认为这是不同的,因为我需要特别解决轮换问题".
  • 非常感谢您在jsfiddle中提出的想法
$(document).click(function (e) {
    var hitElements = getHitElements(e);
    var output = $('#output');
    output.html('');
    for (var i = 0; i < hitElements.length; ++i) {
        output.html(output.html() + '<br />' + hitElements[i][0].tagName + ' ' + hitElements[i][0].id);

    };

});

var getHitElements = function (e) {
    var x = e.pageX;
    var y = e.pageY;
    var hitElements = [];
    $(':visible').each(function () {
        console.log($(this).attr("id"), $(this).outerWidth());
        var offset = $(this).offset();
        console.log('+++++++++++++++++++++');
        console.log('pageX: ' + x);
        console.log('pageY: ' + y);
        console.log($(this).attr("id"), $(this).offset());
        console.log('+++++++++++++++++++++');
        if (offset.left < x && (offset.left + $(this).outerWidth() > x) && (offset.top < y && (offset.top + $(this).outerHeight() > y))) {
            console.log('included: ', $(this).attr("id"));
            console.log('from 0p far x: ', $(this).attr("id"), offset.left + $(this).outerWidth());
            console.log('from 0p far y: ', $(this).attr("id"), offset.top + $(this).outerHeight());
            hitElements.push($(this));
        }
    });

    return hitElements;

}

推荐答案

您必须使用线性代数.

我修改了您的小提琴- http://jsfiddle.net/pcdk2s0g/

I've modified your fiddle - http://jsfiddle.net/pcdk2s0g/

var getHitElements = function (e) {
    var mx = e.pageX;
    var my = e.pageY;
    var hitElements = [];

    $(':visible').each(function () {

        //Parse CSS matrix
        var matrix = [];
        var matrixVal = $(this).css('transform');

        if(matrixVal != "none"){
            var matrixParsed = matrixVal.substr(7, matrixVal.length - 8).split(',');
            for(var i in matrixParsed) matrix[i] = parseFloat(matrixParsed[i]);
        } else {
            matrix = [1, 0, 0, 1, 0, 0];
        }

        var hW = this.offsetWidth / 2; //Half of width
        var hH = this.offsetHeight / 2; //Half of height
        var o = { x: this.offsetLeft + hW, y: this.offsetTop + this.offsetHeight / 2} //Transform origin

        //Define shape points and transform by matrix
        var p1 = {
            x: o.x + matrix[0] * -hW + matrix[2] * -hH + matrix[4],
            y: o.y + matrix[1] * -hW + matrix[3] * -hH + matrix[5]
        }; //Left top

        var p2 = {
            x: o.x + matrix[0] * +hW + matrix[2] * -hH + matrix[4],
            y: o.y + matrix[1] * +hW + matrix[3] * -hH + matrix[5]
        }; //Right top

        var p3 = {
            x: o.x + matrix[0] * +hW + matrix[2] * +hH + matrix[4],
            y: o.y + matrix[1] * +hW + matrix[3] * +hH + matrix[5]
        }; //Right bottom

        var p4 = {
            x: o.x + matrix[0] * -hW + matrix[2] * +hH + matrix[4],
            y: o.y + matrix[1] * -hW + matrix[3] * +hH + matrix[5]
        }; //Left bottom

        //Calculate edge normal vectors & C vars
        var v1 = { x: -(p2.y - p1.y), y: (p2.x - p1.x) }; //Top
        var v2 = { x: -(p3.y - p2.y), y: (p3.x - p2.x) }; //Right
        var v3 = { x: -(p4.y - p3.y), y: (p4.x - p3.x) }; //Bottom
        var v4 = { x: -(p1.y - p4.y), y: (p1.x - p4.x) }; //Left

        var c1 = -(v1.x * p1.x + v1.y * p1.y);
        var c2 = -(v2.x * p2.x + v2.y * p2.y);
        var c3 = -(v3.x * p3.x + v3.y * p3.y);
        var c4 = -(v4.x * p4.x + v4.y * p4.y);

        //Check cursor distance from edge using general line quation: ax + by + c = 0
        var isInner = function(v, c, x, y){
            return (v.x * x + v.y * y + c) / Math.sqrt( v.x*v.x + v.y*v.y )  > 0;
        }

        //Check if mouse point is in shape coords using general line equation
        if(isInner(v1, c1, mx, my) && isInner(v2, c2, mx, my) && isInner(v3, c3, mx, my) && isInner(v4, c4, mx, my))        
            hitElements.push($(this));

    });

    return hitElements;

}

它使用CSS转换属性,该属性由浏览器转换为CSS矩阵.

It uses CSS transform property which is translated to CSS matrix by browser.

代码解析CSS矩阵,计算新的边缘点,并检查光标是否在翻译的元素中.

Code parses CSS matrix, calculates new edge points and checks if cursor is in translated element.

它可以与任何角度或CSS转换一起使用.

It works with any angle or CSS transformation.

代码可以改进,例如,您也可以解析CSS transform-origin属性.

Code can be improved, for example you can parse CSS transform-origin property too.

这篇关于如何在给定鼠标坐标的情况下检测重叠(旋转)的DOM元素?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
相关文章
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆