即使页面布局发生变化,我如何确保保存的点击坐标可以重新加载到同一位置?

IT技术 javascript
2021-01-26 23:00:15

我将点击坐标存储在我的数据库中,然后稍后重新加载它们并在发生点击的站点上显示它们,我如何确保它在同一个地方加载?

存储点击坐标显然是一个简单的步骤,但是一旦我拥有它们,如果用户回来并且他们的窗口更小或更大,则坐标是错误的。我是否以错误的方式处理这个问题,我是否还应该存储元素 id/dom 引用或类似性质的内容。

此外,此脚本将在多个具有多个布局的不同网站上运行。有没有办法在布局与坐标存储方式无关的情况下做到这一点?

6个回答

是的,页面布局可以通过多种方式在加载之间进行更改。不同的窗口大小、不同的字体大小、不同的字体可用性、不同的浏览器/设置(即使布局或字体偏好的微小变化也可能导致包装失效)。除非您的页面几乎完全是固定大小的图像,否则存储页面相对坐标不太可能有用。

您可以尝试查找被点击元素的祖先以找到最近的易于识别的元素,然后根据它是哪个子编号绘制从该元素到您想要的元素的图。

使用简单XPath语法的示例

document.onclick= function(event) {
    if (event===undefined) event= window.event;                     // IE hack
    var target= 'target' in event? event.target : event.srcElement; // another IE hack

    var root= document.compatMode==='CSS1Compat'? document.documentElement : document.body;
    var mxy= [event.clientX+root.scrollLeft, event.clientY+root.scrollTop];

    var path= getPathTo(target);
    var txy= getPageXY(target);
    alert('Clicked element '+path+' offset '+(mxy[0]-txy[0])+', '+(mxy[1]-txy[1]));
}

function getPathTo(element) {
    if (element.id!=='')
        return 'id("'+element.id+'")';
    if (element===document.body)
        return element.tagName;

    var ix= 0;
    var siblings= element.parentNode.childNodes;
    for (var i= 0; i<siblings.length; i++) {
        var sibling= siblings[i];
        if (sibling===element)
            return getPathTo(element.parentNode)+'/'+element.tagName+'['+(ix+1)+']';
        if (sibling.nodeType===1 && sibling.tagName===element.tagName)
            ix++;
    }
}

function getPageXY(element) {
    var x= 0, y= 0;
    while (element) {
        x+= element.offsetLeft;
        y+= element.offsetTop;
        element= element.offsetParent;
    }
    return [x, y];
}

您可以使用此 JSFiddle 看到它的实际效果:http : //jsfiddle.net/luisperezphd/L8pXL/

多谢你们。我想我可能只需要以注释形式存储布局的骨架(例如 [“布局”:“居中”;“宽度”:“960”] 或 [“布局”:“流体”;“列 1”:“ 25%"; "Column2": "60%"; "Column3": "15%"]) 我可能会尝试剖析这些热图脚本之一,看看它们如何记录它们并始终正确显示它们。Jordan 可能是对的,可能必须将浏览器的大小调整为特定大小之类的。但这只会变得混乱。
2021-04-04 23:00:15

我更喜欢不使用 id 选择器而只是递归。

function getPathTo(element) {
    if (element.tagName == 'HTML')
        return '/HTML[1]';
    if (element===document.body)
        return '/HTML[1]/BODY[1]';

    var ix= 0;
    var siblings= element.parentNode.childNodes;
    for (var i= 0; i<siblings.length; i++) {
        var sibling= siblings[i];
        if (sibling===element)
            return getPathTo(element.parentNode)+'/'+element.tagName+'['+(ix+1)+']';
        if (sibling.nodeType===1 && sibling.tagName===element.tagName)
            ix++;
    }
}

您的坐标应该相对于页面内容,而不是窗口。使用 HTML 的左上角作为原点。

您需要在记录数据时进行计算以确定这一点。

我不明白为什么这被否决了。这是一种合乎逻辑的方法。使用左上角将页面宽度和当前 x:y 记录为 0:0,然后根据检索到的屏幕宽度重新计算。与乔丹在 OP 中推荐的内容相同。
2021-03-15 23:00:15
当然可以。锚点位于 HTML 的左上角,而不是 BROWSER WINDOW。无论您的页面位于视口内的哪个位置,您都可以使用左上角然后记录相对于该点的所有坐标。您需要根据页面在浏览器窗口中的位置,在记录数据和播放数据时计算新的原点。
2021-03-19 23:00:15
好的,这是 Diodeus 迄今为止最有前途的帖子。但是,您如何准确获取页面宽度以及 0,0 在哪里。如果这是一个左对齐的设计,那很容易,但如果它是居中的还是流动的呢?
2021-03-31 23:00:15
您需要一些位于设计顶角的“锚定 div”。那将成为您的新“0,0”。计算相对于该坐标的所有点。
2021-04-04 23:00:15
好吧,这不考虑布局。这是一个公平的努力,但它只是一个单一的案例修复。如果您的布局有 3 列(25%、50%、25%)并且窗口宽度为 1000 像素,并且用户在 100、100 处单击,然后用户返回并且他们的屏幕宽度为 500 像素,则单击坐标是错误的. 它将显示在 100, 100 而不是 50, 100 与布局相关的位置。我相信唯一可以实现的方法是将站点布局设置为参数并记录与之相关的坐标。
2021-04-05 23:00:15

这可能取决于点击的含义。也就是说,您是否关心用户点击了页面的哪些元素?如果是这种情况,那么我将存储相对于元素的坐标。

所以用户点击了元素 X。你需要元素 X 中的精确位置吗?然后将该坐标与元素本身左上角的原点一起存储。这样,当元素相对于页面上的其他内容移动时,元素内的位置仍然有效。

我希望有人对这个问题有更出色的解​​决方案,但我最初的想法必须是有效地做到这一点的唯一方法。

  1. 每个网站都必须描述一个基本设置(例如 [居中布局,960 像素] 或 [流体布局,Col1:25%,Col2:60%,Col3:15%]
  2. 单击坐标必须与 screen:x/scroll:y 以及屏幕坐标相关联。
  3. 返回时,单击坐标将查看存储的布局、当前屏幕大小并基于此进行计算。