Получить дочерний элемент по координатам клика.
Суть такая, есть блок (контейнер), внутри него есть n блоков, так вот, по клику на контейнер в любом месте, нужно получить подходящий элемент.
структура примерно такая: --------------------------- | 0 | | 1 | | 2 | | 3 | --------------------------- Решил я это такм способом. [].filter.call(this.children, function(item) { return item.getBoundingClientRect().left <= event.clientX; }).pop(); Собственно, код работает, но, что-то мне подсказывает, что хоть способ и рабочий, фильтровать массив и вытаскивать с него последний элемент не лучший способ.. Есть у кого-то идеи? Вот полный код. <style> div { display: flex; justify-content: space-between; padding: 30px; background-color: #fff; border: 1px solid #999; cursor: pointer; } span { width: 100px; height: 100px; background-color: tomato; color: #fff; text-align: center; font-size: 80px; -moz-user-select: none; /* fucking double click :D */ } </style> <div> <span></span> <span></span> <span></span> <span></span> <span></span> </div> <script> 'use strict'; const div = document.querySelector('div'); div.addEventListener('click', handleClick); function getPos(item) { return item.getBoundingClientRect().left; } function handleClick(e) { const items = Array.from(this.children); const filtredItems = items.filter(item => item.getBoundingClientRect().left <= e.clientX ); const item = filtredItems.pop() || items[0]; // clear items items.forEach(item => { item.innerHTML = ''; }); // active item item.innerHTML = '+'; } </script> |
Lemme,
решение http://javascript.ru/forum/misc/6102...tml#post405988 ... чуть добавить фильтр |
рони, спасибо, интересно=)
|
Через offsetLeft никак? А потом через array.some найти нужный. Будет работать быстрее, т.к. не придется по всем элементам массива бегать.
var x = e.clientX; var span = document.querySelectorAll('span'); var temp = span[0]; [].some.call(span, function (elem) { if (elem.offsetLeft > x) { return true; } temp = elem; }) |
Ближайший элемент от места клика
Lemme,
<!DOCTYPE HTML> <html> <head> <title>Untitled</title> <meta charset="utf-8"> <style> div { display: flex; justify-content: space-between; padding: 30px; background-color: #fff; border: 1px solid #999; cursor: pointer; } span { width: 100px; height: 100px; background-color: tomato; color: #fff; text-align: center; font-size: 80px; -moz-user-select: none; /* fucking double click :D */ } </style> </head> <body> <div> <span></span> <span></span> <span></span> <span></span> <span></span> </div> <script> window.addEventListener("DOMContentLoaded", function() { var b = document.querySelector("div"), d = b.querySelectorAll("span"), c; b.addEventListener("click", function(b) { c = [].map.call(d, function(a) { var e = a.getBoundingClientRect(), c = e.left + a.offsetWidth / 2 - b.clientX; a = e.top + a.offsetHeight / 2 - b.clientY; return Math.sqrt(c * c + a * a) }); var f = Math.min.apply(null, c); [].forEach.call(d, function(a, b) { a.innerHTML = c[b] > f ? "" : "+" }) }) }); </script> </body> </html> |
<style> div { display: flex; justify-content: space-between; padding: 30px; background-color: #fff; border: 1px solid #999; cursor: pointer; } span { width: 100px; height: 100px; background-color: tomato; color: #fff; text-align: center; font-size: 80px; -moz-user-select: none; /* fucking double click :D */ } </style> <div> <span></span> <span></span> <span></span> <span></span> <span></span> </div> <script> var div = document.querySelector('div'); div.addEventListener('click', function (e) { var x = e.clientX; var span = document.querySelectorAll('span'); var temp = span[0]; [].some.call(span, function (elem, i) { if (elem.offsetLeft > x) { return true; } temp = elem; }); [].forEach.call(span,function(elem){ (elem == temp) ? elem.innerHTML = '+' : elem.innerHTML = ''; }) }) </script> |
Lemme,
вопрос только - можно кликнуть так что минимальное растояние будет одинаковое для нескольких элементов, тогда как? |
destus,
не работает если брать минимальное растояние -- ваш вариант для ближайшего слева |
Цитата:
|
Цитата:
|
:) Окей. Для горизонтали.
<style> div { display: flex; justify-content: space-between; padding: 30px; background-color: #fff; border: 1px solid #999; cursor: pointer; } span { width: 100px; height: 100px; background-color: tomato; color: #fff; text-align: center; font-size: 80px; -moz-user-select: none; /* fucking double click :D */ } </style> <div> <span></span> <span></span> <span></span> <span></span> <span></span> </div> <script> var div = document.querySelector('div'); div.addEventListener('click', function (e) { var x = e.clientX; var span = document.querySelectorAll('span'); var temp = span[0]; [].some.call(span, function (elem) { if (elem.offsetLeft > x) { var rightCoordBlock = temp.offsetLeft + temp.offsetWidth; var lenBetweenBlock = elem.offsetLeft - (rightCoordBlock); if ((rightCoordBlock + parseInt(lenBetweenBlock / 2)) < x) temp = elem; return true; } temp = elem; }); [].forEach.call(span,function(elem){ (elem == temp) ? elem.innerHTML = '+' : elem.innerHTML = ''; }) }) </script> |
Оптимальнее будет вычислять растояния от центра каждого блока до точки (e.clientX, e.clientY). Минимальное расстояние из всех прямых и будет ответом в задаче.
Или, например, так как все блоки имеют одинаковую ширину и отступы между, то можно вычислить ширину, которую занимает такой элемент на странице (ширина блока + правый отступ). Далее целочисленно делим e.clientX на эту ширину и получаем сколько блоков нам нужно пропустить, чтобы получить нужный. Вариантов вагон :D |
Цитата:
|
Цитата:
|
Цитата:
|
Даже 5 пост можно немного оптимизировать. Не записывать всё в новый массив и находить минимум, а использовать Array.reduce.
|
Цитата:
Разная может быть ширина блоков и высота контейнера. <style> .container { padding: 50px 0; display: flex; background-color: #fff; border: 1px solid #999; } .block { height: 50px; background-color: tomato; border: 1px solid #333; } </style> <div class="container"> <div class="block" style="width: 35%"></div> <div class="block" style="width: 45%"></div> <div class="block" style="width: 20%"></div> </div> |
Lemme, ближайший блок к клику дубль 2
<!DOCTYPE HTML> <html> <head> <title>Untitled</title> <meta charset="utf-8"> </head> <body> <style> .container { padding: 50px 0; display: flex; background-color: #fff; border: 1px solid #999; } .block { height: 50px; background-color: tomato; border: 1px solid #333; } </style> <div class="container"> <div class="block" style="width: 35%"></div> <div class="block" style="width: 45%"></div> <div class="block" style="width: 20%"></div> </div> <script> window.addEventListener("DOMContentLoaded", function() { var d = document.querySelector(".container"), e = d.querySelectorAll(".block"), c; d.addEventListener("click", function(b) { c = [].map.call(e, function(a) { a = a.getBoundingClientRect(); c = a.left > b.clientX ? a.left : a.right < b.clientX ? a.right : b.clientX; c -= b.clientX; a = a.top > b.clientY ? a.top : a.bottom < b.clientY ? a.bottom : b.clientY; a -= b.clientY; return Math.sqrt(c * c + a * a) }); var d = Math.min.apply(null, c); [].forEach.call(e, function(a, b) { a.innerHTML = c[b] > d ? "" : "+" }) }) }); </script> </body> </html> |
рони, круто, универсально, но, ад =)))
p.s может какие-то книжки с подобнымыми манипуляциями кто-то всречал?=) |
Цитата:
|
рони,круто,спасибо=)
Блин, зачем эти лимиты на плюсы ставить=) |
Визуализация работы скрипта ближайший от клика
Lemme,
кликая можно увидеть какой блок скрипт выбрал ближайшим и какое место на этом блоке ближе всего к точке клика :) <!DOCTYPE HTML> <html> <head> <title>Untitled</title> <meta charset="utf-8"> </head> <body> <style> .container { display: flex; justify-content: space-between; padding: 120px; background-color: #FF8C00; border: 1px solid #999; cursor: pointer; } span { cursor: default; padding: 0; width: 100px; height: 100px; background-color: #32CD32; color: #fff; text-align: center; font-size: 80px; -webkit-user-select: none; user-select: none; -moz-user-select: none; /* fucking double click :D */ } .arrow { -webkit-transform-origin: 0; -moz-transform-origin: 0; -o-transform-origin: 0; transform-origin: 0; position: absolute; } .arrow:before, .arrow:after { content: ""; display: block; position: absolute; width: 0; height: 0; border: 40px solid transparent; border-right: 0; } .arrow { width: 0px; height: 2px; background: #0000CD; } .arrow:after { top: -5px; right: 0px; border-left-color: #0000CD; border-width: 6px 0 6px 30px; } .arrow.replay:before, .arrow.replay:after { display: none; } .arrow.replay { border-radius: 50%; border: 2px solid #F0FFF0; width: 30px; height: 30px; margin-left: -15px; margin-top: -15px; background-color: transparent ; -webkit-animation: ripple 2s ease-in-out infinite; -moz-animation: ripple 2s ease-in-out infinite; -o-animation: ripple 2s ease-in-out infinite; animation: ripple 2s ease-in-out infinite; } @keyframes ripple { 0% { opacity: 0; -webkit-transform: scale(0); -ms-transform: scale(0); -o-transform: scale(0); -moz-transform: scale(0); transform: scale(0); margin-left: 0px; } 100% { margin-left: -15px; opacity: 1; -webkit-transform: scale(1); -ms-transform: scale(1); -o-transform: scale(1); -moz-transform: scale(1); transform: scale(1); } } @-webkit-keyframes ripple { 0% { opacity: 0; -webkit-transform: scale(0); -ms-transform: scale(0); -o-transform: scale(0); -moz-transform: scale(0); transform: scale(0); } 100% { opacity: 1; -webkit-transform: scale(1); -ms-transform: scale(1); -o-transform: scale(1); -moz-transform: scale(1); transform: scale(1); } }</style> <div class="container"> <span></span> <span></span> <span></span> </div> <div class="arrow"></div> <script> window.addEventListener("DOMContentLoaded", function() { var e = document.querySelector(".container"), h = e.querySelectorAll("span"), d = document.querySelector(".arrow"), c; e.addEventListener("click", function(b) { var g = []; c = [].map.call(h, function(a) { a = a.getBoundingClientRect(); c = a.left > b.clientX ? a.left : a.right < b.clientX ? a.right : b.clientX; c -= b.clientX; a = a.top > b.clientY ? a.top : a.bottom < b.clientY ? a.bottom : b.clientY; a -= b.clientY; g.push(360 - 180 / Math.PI * Math.atan2(a, c)); return Math.sqrt(c * c + a * a) }); var f = Math.min.apply(null,c), e = c.indexOf(f); d.style.left = b.clientX + "px"; d.style.top = b.clientY + "px"; d.style.width = (f ? f : 30) + "px"; f ? (d.classList.remove("replay"), d.style.transform = "rotate(-" + g[e] + "deg)", d.style.webkitTransform = "rotate(-" + g[e] + "deg)") : d.classList.add("replay") }) }); </script> </body> </html> |
рони, это великолепно, карл!! =)
Пост в закладки!! =) p.s нужно учить математику=))) Пошел снова тыкать плюсик в оффтопик=))). |
Часовой пояс GMT +3, время: 19:20. |