Touch события
Доброго времени суток.
Суть в том, что у нас есть возможность отлавливать touch события, но в то же время, не могу понять, как просто можно понять, что палец, ушел с конкретного дом элемента. Сначала на нем срабатывает touch start, при видении пальца внутри элемента отрабатывает touch move, как только я выхожу из элемента, touch move продолжает работать (проверенно на последнем Chrome), touch end возникает в момент как палец был поднят с экрана. Если простая возможность, как с движением мыши (mouseover, mouseout)? |
У TouchEvent's есть свойство touches, которое хранит список Touch'ей.
Каждый Touch хранит координаты и элемент, на котором произошло событие. <div class="outside"> <div class="inside"></div> </div> <style>.inside { max-width:30%; min-height: 30vh; margin: auto; background-color: gray; }</style> <script>(() => { const inside = document.querySelector('.inside'); const styles = getComputedStyle(inside, null); const coordinates = { x: [ inside.offsetLeft, inside.offsetLeft + parseFloat(styles.width.replace('px', '')) ], y: [ inside.offsetTop, inside.offsetTop + parseFloat(styles.height.replace('px', '')) ] }; document.addEventListener('touchmove', function (event) { const hovered = [].some.call(event.touches, touch => { const xInside = touch.clientX >= coordinates.x[0] && touch.clientX <= coordinates.x[1]; const yInside = touch.clientY >= coordinates.y[0] && touch.clientY <= coordinates.y[1]; return xInside && yInside; }); inside.style.backgroundColor = hovered ? 'green' : 'red'; }); })()</script> |
Nexus,
что-то у меня координаты не совпадают. предложу такой вариант ... <!DOCTYPE html> <html> <head> <title>Untitled</title> <meta charset="utf-8"> </head> <body> <div class="outside"> <div class="inside"></div> </div> <style> html{ height: 1800px; width: 1800px; } .outside { padding: 8px; background-color: #FFD700; } .inside { max-width:30%; min-height: 30vh; margin: auto; background-color: gray; }</style> <script> (() => { const inside = document.querySelector('.inside'); document.addEventListener('touchmove', function (event) { const box = inside.getBoundingClientRect(); const coordinates = { x: [ box.left, box.left + box.width ], y: [ box.top, box.top + box.height ] }; const hovered = [...event.touches].some(touch => { console.log(touch) const xInside = touch.clientX >= coordinates.x[0] && touch.clientX <= coordinates.x[1]; const yInside = touch.clientY >= coordinates.y[0] && touch.clientY <= coordinates.y[1]; return xInside && yInside; }); inside.style.backgroundColor = hovered ? 'green' : 'red'; }); })()</script> </body> </html> |
Цитата:
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <style> html { background: black; color: white; } section#images { display: grid; grid-template: repeat(3, 200px) / repeat(3, 200px); } @media(max-width: 620px) { section#images { grid-template-columns: repeat(auto-fit, minmax(200px, 1fr)); grid-auto-rows: 200px; } } section#images > img { width: 100%; height: 100%; object-fit: cover; filter: grayscale(1) opacity(0.5); transition: 300ms filter; } section#images > img.focus { filter: none; } </style> </head> <body> <section id="images"> <img src="https://picsum.photos/id/237/400/400"> <img src="https://picsum.photos/id/238/400/400"> <img src="https://picsum.photos/id/239/400/400"> <img src="https://picsum.photos/id/247/400/400"> <img src="https://picsum.photos/id/248/400/400"> <img src="https://picsum.photos/id/249/400/400"> <img src="https://picsum.photos/id/257/400/400"> <img src="https://picsum.photos/id/258/400/400"> <img src="https://picsum.photos/id/259/400/400"> </section> <button onclick=" this.textContent = document.fullscreenElement ? '↗️ View Fullscreen' : '↙️ Exit Fullscreen'; document.fullscreenElement ? document.exitFullscreen() : document.documentElement.requestFullscreen(); ">↗️ View Fullscreen</button> <script> addEventListener("mouseover", function(event) { event.target.classList.add("focus"); }); addEventListener("mouseout", function(event) { event.target.classList.remove("focus"); }); /* dispatch `mouseover` and `mouseout` events for touch device */ { function dispatchMouseEventAtTarget(type, node, eventInitDict = {}) { return dispatchEvent(Object.defineProperties(new MouseEvent(type, eventInitDict), { target: { value: node } })); } const map = new Map(); for(const type of ["start", "move", "end", "cancel"]) addEventListener("touch" + type, function(event) { if(event instanceof TouchEvent) { for(const touch of event.changedTouches) { if(event.type === "touchstart") { map.set(touch.identifier, touch.target); dispatchMouseEventAtTarget("mouseover", event.target); } else if(event.type === "touchmove") { const currentTarget = map.get(touch.identifier); const x = touch.pageX - window.pageXOffset; const y = touch.pageY - window.pageYOffset; const target = document.elementFromPoint(x, y); if(currentTarget !== target) { if(currentTarget) dispatchMouseEventAtTarget("mouseout", currentTarget); if(target) dispatchMouseEventAtTarget("mouseover", target); map.set(touch.identifier, target); } } else { const currentTarget = map.get(touch.identifier); if(currentTarget) setTimeout(dispatchMouseEventAtTarget, 40, "mouseout", currentTarget); map.delete(touch.identifier); } } } }); } </script> </body> </html> |
Цитата:
|
Цитата:
На стр. 61-95 находится код, который переводит события прикосновения в события mouseover и mouseout. Цитата:
|
Цитата:
|
Malleys,
хром, консоль, режим эмуляции, увожу курсор с картинки за пределы "устройства". возникает ошибка. |
Цитата:
|
Мой нынешний вариант реализации через elementFromPoint, при touch move я проверяю не вышел ли я с элемента.
На данный момент, подводных камней не обнаружил. По уходу с элемента убиваю touch move и жду снова touch start. зы Очень похож на то, что было предложено Nexus и рони, но без ручного счета. зыы Надеялся, что, все таки, есть более простые вариант, как с мышью, но, оказалось, что нет - это расстроило. |
Часовой пояс GMT +3, время: 12:17. |