向我展示 webkitConvertPointFromPageToNode 的 Javascript 实现 [英] Show me a Javascript implementation of webkitConvertPointFromPageToNode

查看:30
本文介绍了向我展示 webkitConvertPointFromPageToNode 的 Javascript 实现的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

webkitConvertPointFromPageToNode(in Node node, in WebKitPoint p) 方法很棒;给它一个 DOM 节点和页面坐标中的一个点(比如鼠标光标位置),它会在该节点的本地坐标系中返回一个坐标.不幸的是,它目前

解决方案

这似乎是一个了不起的问题,但这里有一个几乎重复的问题:如何获取具有 CSS3 变换的元素的 MouseEvent 坐标? 但没有人在看我在那里的回答似乎更笼统,所以我会在这里再次发布,并进行一些修改以使其更加清晰:

基本上,它的工作原理是:将您要为其查找相对坐标的元素拆分,然后将其拆分为 9 个较小的元素.使用 document.elementFromPoint 查找坐标是否在该迷你元素上.如果是,将该元素拆分为另外 9 个元素,并继续执行此操作,直到可以获得非常准确的坐标.然后使用 getBoundingClientRect 查找该迷你元素的屏幕坐标.轰隆隆!

jsfiddle:http://jsfiddle.net/markasoftware/rA27K/8/

这是 JavaScript 函数:

function convertPointFromPageToNode(elt,coords){///元素的原始innerHTMLvar origHTML=elt.innerHTML;//现在清除它elt.innerHTML='';//现在保存并清除不良样式var origPadding=elt.style.padding=='0px'?'':elt.style.padding;var origMargin=elt.style.margin=='0px'?'':elt.style.margin;elt.style.padding=0;elt.style.margin=0;//确保事件在给定的元素中if(document.elementFromPoint(coords.x,coords.y)!==elt){//重置元素elt.innerHTML=origHTML;//和样式elt.style.padding=origPadding;elt.style.margin=origMargin;//我们没有什么可显示的,所以返回null返回空;}//矩形的所有位置的数组var rectPlaces=['topleft','topcenter','topright','centerleft','centercenter','centerright','bottomleft','bottomcenter','bottomright'];//向元素添加9个矩形的函数函数 addChildren(elt){//遍历所有地方以获得 rectsrectPlaces.forEach(function(curRect){//为这个矩形创建元素var curElt=document.createElement('div');//添加类和idcurElt.setAttribute('class','offsetrect');curElt.setAttribute('id',curRect+'offset');//将其添加到元素elt.appendChild(curElt);});//获取元素表单点及其样式var eltFromPoint=document.elementFromPoint(coords.x,coords.y);var eltFromPointStyle=getComputedStyle(eltFromPoint);//要么返回事件所在的小于1像素的元素,要么递归直到找到它,然后返回递归的结果return Math.max(parseFloat(eltFromPointStyle.getPropertyValue('height')),parseFloat(eltFromPointStyle.getPropertyValue('width')))<=1?eltFromPoint:addChildren(eltFromPoint);}//这是最里面的元素var CorrectElt=addChildren(elt);//通过遍历其所有父元素并将值相加,找到元素的顶部和左侧值,因为顶部和左侧是相对于父元素的,但我们想要相对于墙for(var curElt=correctElt,correctTop=0,correctLeft=0;curElt!==elt;curElt=curElt.parentNode){//获取当前元素的样式var curEltStyle=getComputedStyle(curElt);//将当前元素的顶部和左侧添加到总数中rightTop+=parseFloat(curEltStyle.getPropertyValue('top'));rightLeft+=parseFloat(curEltStyle.getPropertyValue('left'));}//重置元素elt.innerHTML=origHTML;//恢复元素样式elt.style.padding=origPadding;elt.style.margin=origMargin;//返回的对象var returnObj={x:正确左,y:正确顶部}返回 returnObj;}

重要!!!您还必须包含此 CSS 才能使其正常工作:

.offsetrect{位置:绝对;不透明度:0;高度:33.333%;宽度:33.333%;}#topleftoffset{顶部:0;左:0;}#topcenteroffset{顶部:0;左:33.333%;}#toprightoffset{顶部:0;左:66.666%;}#centerleftoffset{最高:33.333%;左:0;}#centercenteroffset{最高:33.333%;左:33.333%;}#centerrightoffset{最高:33.333%;左:66.666%;}#bottomleftoffset{最高:66.666%;左:0;}#bottomcenteroffset{最高:66.666%;左:33.333%;}#bottomrightoffset{最高:66.666%;左:66.666%;}

另外:我修改了你的一些 css,给祖父"div 一个 id 并在你的 css 中使用 #div1 而不是 div 引用它,因为我的代码生成 div,而您的 div 样式也适用于我的代码使用的样式并将其弄乱

最后一件事:我不知道 CoffeeScript,所以我调整了您的代码,使其成为纯 JavaScript.很抱歉.

The webkitConvertPointFromPageToNode(in Node node, in WebKitPoint p) method is awesome; give it a DOM node and a point in page-coordinates (say, the mouse cursor position) and it will give a coordinate back to you in that node's local coordinate system. Unfortunately, it's currently only available in webkit.

# Choose a node into which we'll map the mouse coordinates
node = $('#subjectElement').get(0)

handleMouseMove = (e) ->
  # Convert the mouse position to a Point
  mousePoint = new WebKitPoint(e.pageX, e.pageY)

  # Convert the mouse point into node coordinates using WebKit
  nodeCoords = webkitConvertPointFromPageToNode(node, mousePoint)

# Attach a handler to track the mouse position
$(document).on 'mousemove', handleMouseMove    

I've thrown my entire math-brain at the problem, but no matter how close I get, my implementation falls apart with one extra level of composition, or the application of 3D perspective.

It's time for a convertPointFromPageToNode polyfill that works as well as the WebKit implementation, in 3D. @4esn0k gave one a shot, but it only solves the 2D case.

Can you write one that makes this JSFiddle work?

http://jsfiddle.net/steveluscher/rA27K/

解决方案

This seems like an amazing question, but there is an ALMOST duplicate right here: How to get the MouseEvent coordinates for an element that has CSS3 Transform? but nobody is looking at my answer there and this seems to be much more general so I'll post it again here, with a few modifications to make it more clear:

Basically, it works by doing this: split the element you are trying to find relative coordinates for, and split it into 9 smaller elements. Use document.elementFromPoint to find if the coordinate is over that mini-element. If it is, split that element into 9 more elements, and keep doing this until a pretty accurate coordinate is possible. Then use getBoundingClientRect to find the on-screen coordinates of that mini-element. BOOM!

jsfiddle: http://jsfiddle.net/markasoftware/rA27K/8/

Here is the JavaScript function:

function convertPointFromPageToNode(elt,coords){
    ///the original innerHTML of the element
    var origHTML=elt.innerHTML;
    //now clear it
    elt.innerHTML='';
    //now save and clear bad styles
    var origPadding=elt.style.padding=='0px'?'':elt.style.padding;
    var origMargin=elt.style.margin=='0px'?'':elt.style.margin;
    elt.style.padding=0;
    elt.style.margin=0;
    //make sure the event is in the element given
    if(document.elementFromPoint(coords.x,coords.y)!==elt){
        //reset the element
        elt.innerHTML=origHTML;
        //and styles
        elt.style.padding=origPadding;
        elt.style.margin=origMargin;
        //we've got nothing to show, so return null
        return null;
    }
    //array of all places for rects
    var rectPlaces=['topleft','topcenter','topright','centerleft','centercenter','centerright','bottomleft','bottomcenter','bottomright'];
    //function that adds 9 rects to element
    function addChildren(elt){
        //loop through all places for rects
        rectPlaces.forEach(function(curRect){
            //create the element for this rect
            var curElt=document.createElement('div');
            //add class and id
            curElt.setAttribute('class','offsetrect');
            curElt.setAttribute('id',curRect+'offset');
            //add it to element
            elt.appendChild(curElt);
        });
        //get the element form point and its styling
        var eltFromPoint=document.elementFromPoint(coords.x,coords.y);
        var eltFromPointStyle=getComputedStyle(eltFromPoint);
        //Either return the element smaller than 1 pixel that the event was in, or recurse until we do find it, and return the result of the recursement
        return Math.max(parseFloat(eltFromPointStyle.getPropertyValue('height')),parseFloat(eltFromPointStyle.getPropertyValue('width')))<=1?eltFromPoint:addChildren(eltFromPoint);
    }
    //this is the innermost element
    var correctElt=addChildren(elt);
    //find the element's top and left value by going through all of its parents and adding up the values, as top and left are relative to the parent but we want relative to teh wall
    for(var curElt=correctElt,correctTop=0,correctLeft=0;curElt!==elt;curElt=curElt.parentNode){
        //get the style for the current element
        var curEltStyle=getComputedStyle(curElt);
        //add the top and left for the current element to the total
        correctTop+=parseFloat(curEltStyle.getPropertyValue('top'));
        correctLeft+=parseFloat(curEltStyle.getPropertyValue('left'));
    }
    //reset the element
    elt.innerHTML=origHTML;
    //restore element styles
    elt.style.padding=origPadding;
    elt.style.margin=origMargin;
    //the returned object
    var returnObj={
        x: correctLeft,
        y: correctTop
    }
    return returnObj;
}

IMPORTANT!!! You must also include this CSS for it to work:

.offsetrect{
    position: absolute;
    opacity: 0;
    height: 33.333%;
    width: 33.333%;
}
#topleftoffset{
    top: 0;
    left: 0;
}
#topcenteroffset{
    top: 0;
    left: 33.333%;
}
#toprightoffset{
    top: 0;
    left: 66.666%;
}
#centerleftoffset{
    top: 33.333%;
    left: 0;
}
#centercenteroffset{
    top: 33.333%;
    left: 33.333%;
}
#centerrightoffset{
    top: 33.333%;
    left: 66.666%;
}
#bottomleftoffset{
    top: 66.666%;
    left: 0;
}
#bottomcenteroffset{
    top: 66.666%;
    left: 33.333%;
}
#bottomrightoffset{
    top: 66.666%;
    left: 66.666%;
}

ALSO: I modified a little of your css by giving the "grandfather" div an id and referencing to it in your css using #div1 instead of div because my code generates divs, and your div styles were also applying to the ones my code uses and messed it up

ONE LAST THING: I don't know CoffeeScript so I adjusted your code to make it pure JavaScript. Sorry about that.

这篇关于向我展示 webkitConvertPointFromPageToNode 的 Javascript 实现的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

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