Как сделать так, чтобы сохраненные координаты кликов можно было переместить в одно и то же место, даже если изменился макет страницы?
Я сохраняю координаты кликов в своей базе данных, а затем перезагружаю их позже и показываю их на сайте, где произошел клик, как мне убедиться, что он загружается в том же месте?
Сохранение координат щелчка, очевидно, является простым шагом, но если они у меня есть, если пользователь возвращается и их окно меньше или больше, координаты неверны. Я поступаю неправильно, должен ли я хранить ссылку на элемент id / dom или что-то в этом роде.
Кроме того, этот скрипт будет запускаться на разных сайтах с более чем одним макетом. Есть ли способ сделать это, когда макет не зависит от того, как хранятся координаты?
5 ответов
Да, существует множество способов изменить макет страницы между загрузками. Разные размеры окон, разные размеры шрифтов, разная доступность шрифтов, разные браузеры / настройки (даже небольшое изменение в разметке или предпочтениях шрифта может привести к отказу от переноса). Сохранение относительных координат страницы вряд ли будет полезным, если ваша страница почти не содержит изображений фиксированного размера.
Вы можете попытаться найти предков выбранного элемента, чтобы найти ближайший легко идентифицируемый элемент, а затем построить график от этого элемента до нужного элемента, основываясь на том, какой это дочерний номер.
Пример использования простого синтаксиса 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/
Я предпочитаю не использовать селектор идентификатора и просто идти рекурсивно.
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. Вам нужно точное местоположение в элементе X? Затем сохраните эту координату с началом координат слева вверху от самого элемента. Таким образом, когда элемент перемещается относительно другого содержимого на странице, позиция в элементе остается действительной.
Я надеялся, что у кого-то будет гораздо более блестящее решение этой проблемы, но мои оригинальные мысли должны быть единственным способом эффективно сделать это.
- Каждый веб-сайт должен иметь описанную базовую настройку (например, [Центрированная разметка, 960px] или [Разметка жидкости, Col1: 25%, Col2: 60%, Col3: 15%]
- Координаты кликов должны быть записаны относительно экрана:x/scroll:y вместе с координатами экрана.
- По возвращении координаты клика будут смотреть на сохраненный макет, текущий размер экрана и рассчитывать на основе этого.
Я делаю нечто подобное здесь, где мне нужно записать, где элемент был перетащен на страницу. Я могу сохранить некоторые данные о месте падения в базе данных, чтобы вытащить его и вернуть элемент туда, где он был сброшен. Единственное требование - я хочу, чтобы отброшенный элемент был как можно ближе к элементу, на котором он был сброшен, на всех размерах экрана.
Из-за адаптивного характера современной сети элементы могут перемещаться в совершенно разные места в зависимости от размера экрана.
Мое решение состоит в том, чтобы игнорировать все селекторы DOM и вместо этого просто записывать, где элемент находится в дереве DOM, записывая дочерний индекс на каждом "слое" DOM, вплоть до рассматриваемого элемента.
Я делаю это, просматривая дерево DOM из
event.target
элемент, глядя на
currentNode.parentNode.children
чтобы найти, какой ребенок индексирует мой
currentNode
населяет. Я записываю это в массив, который затем могу использовать для индексации вниз по дереву DOM, чтобы найти свой элемент. Я также сохраняю смещение отброшенных элементов в процентах на случай, если элемент dropzone изменил размер пикселя.
Вот мой сокращенный код:
var rect = mouseEvent.target.getBoundingClientRect()
// get position of mouseEvent in target as a percentage so we can be ok if it changes size
var xpos = Math.floor(mouseEvent.offsetX / rect.width * 100)
var ypos = Math.floor(mouseEvent.offsetY / rect.height * 100)
// traverse backwards up the dom tree, recording this 'branch' of it as we go:
var curEl = mouseEvent.target
var tree = []
while(curEl.parentNode){
for( var i = 0; i < curEl.parentNode.children.length; i ++ ){
var curChild = curEl.parentNode.children[i]
if( curChild === curEl ){ // i is our child index
tree.unshift(i) // unshift to push to the front of the array
break
}
}
curEl = curEl.parentNode
}
А затем, чтобы снова найти свой узел, я просто возвращаюсь вниз по dom:
var curEl = document
for(var i = 0; i < tree.length; i ++){
curEl = curEl.children[tree[i]]
}
Все, что я сохраняю в базе данных, - это
tree
array (плоский массив целых чисел - как можно уменьшить размер?) и мои смещения по осям x и y!