Показать сообщение отдельно
  #1 (permalink)  
Старый 31.12.2017, 03:00
Аспирант
Отправить личное сообщение для eugenk Посмотреть профиль Найти все сообщения от eugenk
 
Регистрация: 14.05.2013
Сообщений: 47

Чудеса с mousemove в chrome
Приветствую многоуважаемый All, с наступающим !
Дело такое. Захотел я сделать раздвижные окна, разделяемые сплитером. Всё стандартно. Наводим мышку на сплитер, жмём левую кнопку, перетаскиваем и отпускаем. Окна перестраиваются. Работает это так. Окна и сплитер это div-ы. На сплитер вешаем событие mousedown, устанавливающую в true переменную, обозначающую что сплитер захвачен. На подложку всего этого безобразия - события mousemove, по которому передвигается сплитер и mouseup, по которому сплитер отпускается и окна перестраиваются. Всё просто. Однако я наткнулся на следующее чудо. Иногда захваченный сплитер перестаёт двигаться. И начинает двигаться при отпускании кнопки мыши ! Вообще-то проект у меня на dart. Но я минимизировал эффект до 40 с небольшим строк на чистом javascript. Вот код:
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Slider</title>
</head>
<body>
<div id="root" style="position: absolute; background: #ffffff">
<!-- Тут можно закомментировать left и right -->
    <div id="left" style="position: absolute; background: #ff0000"></div>
    <div id="right" style="position: absolute; background: #0000ff"></div>
<!---->
    <div id="split" style="position: absolute; background: #000000; cursor: ew-resize"></div>
</div>
<script type="text/javascript">
    var rat=0.5;
    var gap=7;
    var drag=false;
    var W=window.innerWidth, H=window.innerHeight;
    var root=document.getElementById("root");
    var left=document.getElementById("left");
    var right=document.getElementById("right");
    var split=document.getElementById("split");
    window.onresize=resize;
    split.onmousedown=function(ev) {drag=true;}
    root.onmousemove=function (ev) {if(drag) split.style.left=px(ev.clientX);}
    root.onmouseup=function (ev) {drag=false; rat=split.offsetLeft/W; resize();}
    resize();
    function px(n){return ""+n+"px"}
    function resize() {
        W=window.innerWidth; H=window.innerHeight;
        root.style.left=px(0); root.style.top=px(0);
        root.style.width=px(W); root.style.height=px(H);
        split.style.left=px(W*rat); split.style.top=px(0);
        split.style.width=px(gap); split.style.height=px(H);
        if(left) {
            left.style.left=px(0); left.style.top=px(0);
            left.style.width=px(W*rat); left.style.height=px(H);}
        if(right) {
            right.style.left=px(W*rat+gap);right.style.top=px(0);
            right.style.width=px(W-W*rat-gap);right.style.height=px(H);}
    }
</script>
</body>
</html>


Испытывал я его в chrome и firefox. "Чудеса" происходят только в chrome. Далеко не всегда, где-то одна попытка из пяти. В firefox всё работает нормально. Если Вы закомментируете div-ы left и right, сплитер будет двигаться нормально и в chrome. Я довольно плотно поигрался с этим кодом, вставляя отладочную печать, и пришел к выводу, что в chrome события mousemove иногда почему-то "перестают проходить" через лежащие сверху элементы. Впервые обнаружил я это в dartium (50.0.2661.108 (64-bit) linux). Но этим же страдает и chrome 60.0.3112.113 (Официальная сборка), (64 бит) linux. Понятно что глюк броузера. Но я был бы очень благодарен, если бы добрые люди подсказали мне, как с этой напастью бороться. Я сам что-то совсем уже иссяк.

Хорошего всем праздника и удачи в будущем году !

Последний раз редактировалось eugenk, 31.12.2017 в 03:03.
Ответить с цитированием