04.10.2019, 16:03
|
|
Аспирант
|
|
Регистрация: 30.12.2015
Сообщений: 49
|
|
Touch события
Доброго времени суток.
Суть в том, что у нас есть возможность отлавливать touch события, но в то же время, не могу понять, как просто можно понять, что палец, ушел с конкретного дом элемента.
Сначала на нем срабатывает touch start, при видении пальца внутри элемента отрабатывает touch move, как только я выхожу из элемента, touch move продолжает работать (проверенно на последнем Chrome), touch end возникает в момент как палец был поднят с экрана.
Если простая возможность, как с движением мыши (mouseover, mouseout)?
|
|
05.10.2019, 13:45
|
Профессор
|
|
Регистрация: 04.12.2012
Сообщений: 3,791
|
|
У 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>
|
|
05.10.2019, 16:26
|
|
Профессор
|
|
Регистрация: 27.05.2010
Сообщений: 33,105
|
|
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>
|
|
06.10.2019, 20:51
|
|
Профессор
|
|
Регистрация: 20.12.2009
Сообщений: 1,714
|
|
Сообщение от Spirtikys
|
Есть ли... возможность, как с движением мыши (mouseover, mouseout)?
|
Вы можете описáть, как должны обрабатываться события mouseover и mouseout. Затем добавить обобщённый код, который переводит прикосновения к этим событиям.
<!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>
Последний раз редактировалось Malleys, 06.10.2019 в 22:40.
|
|
06.10.2019, 21:23
|
|
Профессор
|
|
Регистрация: 27.05.2010
Сообщений: 33,105
|
|
Сообщение от Malleys
|
Вы можете описать как должны обрабатываться события mouseover и mouseout.
|
а можно пример или это есть уже в коде?
|
|
06.10.2019, 21:45
|
|
Профессор
|
|
Регистрация: 20.12.2009
Сообщений: 1,714
|
|
Сообщение от рони
|
а можно пример или это есть уже в коде?
|
Да, в коде идет пример, в котором добавляется класс focus при наведении мыши, и удаляется при отведении мыши. Смотрите стр. 53-59 в примере выше.
На стр. 61-95 находится код, который переводит события прикосновения в события mouseover и mouseout.
Сообщение от рони
|
а можно пример или это есть уже в коде?
|
Это так непонятно, если пропустить запятую! Наверное, лучше так: Вы можете описáть, как должны обрабатываться события mouseover и mouseout. Затем...
|
|
06.10.2019, 22:01
|
|
Профессор
|
|
Регистрация: 27.05.2010
Сообщений: 33,105
|
|
Сообщение от Malleys
|
Это так непонятно
|
у меня лезет null в строке 88, идёт ошибка Cannot read property 'classList' of null.
|
|
06.10.2019, 22:19
|
|
Профессор
|
|
Регистрация: 27.05.2010
Сообщений: 33,105
|
|
Malleys,
хром, консоль, режим эмуляции, увожу курсор с картинки за пределы "устройства". возникает ошибка.
|
|
06.10.2019, 22:40
|
|
Профессор
|
|
Регистрация: 20.12.2009
Сообщений: 1,714
|
|
Сообщение от рони
|
хром, консоль, режим эмуляции, увожу курсор с картинки за пределы "устройства".
|
А такое, а то я думал, что это вообще не работает! Тогда добавил ещё проверку на наличие элементов!
|
|
07.10.2019, 14:05
|
|
Аспирант
|
|
Регистрация: 30.12.2015
Сообщений: 49
|
|
Мой нынешний вариант реализации через elementFromPoint, при touch move я проверяю не вышел ли я с элемента.
На данный момент, подводных камней не обнаружил. По уходу с элемента убиваю touch move и жду снова touch start.
зы Очень похож на то, что было предложено Nexus и рони, но без ручного счета.
зыы Надеялся, что, все таки, есть более простые вариант, как с мышью, но, оказалось, что нет - это расстроило.
Последний раз редактировалось Spirtikys, 07.10.2019 в 15:53.
|
|
|
|