Как переопределить сенсорный зум и панорамирование в Firefox и Chrome с событиями указателя - PullRequest
0 голосов
/ 11 февраля 2019

Это относится и к другим браузерам, но основными целями являются Firefox и Chrome.

Я зарегистрировал всех слушателей событий указателя и должен был зарегистрировать мышь вниз и moue up слушателей, чтобы получить изменения состояния кнопки (состояния кнопки всобытия указателя не являются точными или «chorded»)

Но даже если я выполняю event.preventDefault () для всех указателей: события over, enter, down, up, out и, exit (за исключением мыши pointerType длявниз, так как это отключит слушателей mousedown и mouse up) У меня есть остающиеся проблемы:

Мультитач (более одного пальца) будет перенесен и выполнит операцию масштабирования страницы, отрисовывая мультитач в моемприложение бесполезно.

Если на странице есть полосы прокрутки, операция сенсорного панорамирования / прокрутки переходит на одно касание.

Функция protectDefault () неправильно реализована в операционной системе (то есть: окна 10) и указатель вниз над моим элементом также будет генерировать искусственную мышь вниз и синтетически перемещать мышь ккоснулся локации.Я могу игнорировать синтетические события «вниз» и «вверх» с грязным кодом), но он помещает мышь в неожиданные места и предотвращает использование мыши и одновременное касание в качестве отдельных входов при желании.(исправление этого, вероятно, потребует наличия флага для самого элемента DOM, а не для каждого события, поскольку внутренняя очередь событий будет устанавливать задержку между ОС и событиями, отправляемыми браузером - я решил эту проблему в своих собственных приложениях)

Я тестирую с помощью консоли веб-разработчика, чтобы я мог регистрировать состояние - я не знаю, влияет ли это на вещи.

У меня такое же отсутствие управления панорамированием / масштабированием в Chrome.Поведение при наведении / опускании мыши в Chrome и Firefox значительно отличается, что требует отдельного пути к коду.PK

Для любителей кода - обратите внимание, что это интерфейсное устройство "front end" для движка "webasm" (игра или игра в жизнь):)

Цель состоит в том, чтобы получить «чистый необработанный» поток событий для любого указателя, входящего в элемент canvas (который не перехватывается обработчиком другого элемента). Отразите состояние всех кнопок на всех поддерживаемых устройствах с захваченными указателями, пока захват не будет потерян.Кроме того, чтобы иметь возможность использовать мышь и сенсорный экран (и любые другие поддерживаемые устройства) в качестве отдельных устройств, игнорируя все синтетические события и желая отключить все, где одно устройство, которое я слушаю, эмулируется другим устройством, которое я слушаю (поэтому они нене борись).Также, чтобы полностью контролировать, что делается с событиями, пока захват потока событий для указателя не будет потерян.Я хотел бы захватить все касания, которые исчезают после и в то время как «основное» касание отключается на нашем элементе для сенсорного устройства (планшет, панель, экран и т. Д.) И, при желании, позволяет им «проваливаться», если они не используют наш пользовательский интерфейс.

Ниже приведены обработчики событий, которые прикреплены к элементу «canvas».Они ничего не делают, но пересылают данные в приложение webasm.Конечно будет вычищен после того, как все заработает.Это код Firefox.:)

canvas.addEventListener('pointerover', this.onPeOED, false);
canvas.addEventListener('pointerenter', this.onPeOED, false);
canvas.addEventListener('pointerdown', this.onPeOED, false);

canvas.addEventListener('pointermove', this.onPeMove, false);

canvas.addEventListener('pointerup', this.onPeUOCL, false);
canvas.addEventListener('pointerout', this.onPeUOCL, false);
canvas.addEventListener('pointercancel', this.onPeUOCL, false);
canvas.addEventListener('pointerleave', this.onPeUOCL, false);

canvas.addEventListener('mousedown', this.onMouseDown, false);
canvas.addEventListener('mouseup', this.onMouseUp, false);

 onPeOED: (function(e) {
    var handled = 0;
    var code = e.type.charCodeAt(7);
    var target = e.currentTarget;
    var posX = e.clientX;
    var posY = e.clientY;

    var flags = (1 << (9 + 16)); // fPointerInside
    if(posX < 0 || posY < 0 || posX >= target.width || posY >= target.height) {
        flags = 0;
    }
    // o == over, e == enter, d == down,

    if(code == 100) { // 100 == 'd'
        flags |= (1 << (10 + 16)); // in contact << 16
    }

    target._mousePointerId_ = -1;

    switch(e.pointerType) {
        case 'mouse':
            target._mousePointerId_ = e.pointerId;
            if(code == 100) { // 100 == 'd' handled by onMouseDown
                target.setPointerCapture(e.pointerId);
                return;
            }
            flags |= 0x0100;  // UID_MOUSE << 8
            break;
        case 'pen':
            flags |= 0x0200;  // UID_STYLUS << 8
            break;
        case 'touch':
            flags |= 0x0300;  // UID_FINGER << 8
            break;
        default:
            Module.print("unknown UID");
            break;
    }

    if(code == 100) { // 100 == 'd'
        target.setPointerCapture(e.pointerId);
    }

    // Module.print("ON uid " + e.pointerType + " " + e.type + " buttons " + e.which + " inside " + ((flags & (1 << (9 + 16))) != 0));

    if(e.buttons != 0) {
        flags |= (e.buttons << 16) | (1 << (10 + 16)); // fPointerInContact
    }

    handled = ccall('onPointerFlagsOn', 'number', EngineConnector.number_11_Sig,
        //  target  type|flags    time      id     screenX  screenY   pageX    pageY   targetX  targetY  pressure
        [   target._CPPHandle_,
            (code | flags),
            e.timeStamp,
            e.pointerId,
            e.screenX,
            e.screenY,
            e.pageX,
            e.pageY,
            posX,
            posY,
            e.pressure
        ]);
    e.preventDefault();
}),

onMouseDown: (function(e) {

    var target = e.currentTarget;
    var posX = e.clientX;
    var posY = e.clientY;

    // Module.print("mouse ME down " + target._mousePointerId_);

    if(target._mousePointerId_ < 0 || posX < 0 || posY < 0 || posX >= target.width || posY >= target.height) {
        Module.print("mouse ignored");
        e.preventDefault();
        return; // ignore downs while outide element
    }
    var wentDown = (e.buttons & (~(target._mouseButtons_)));
    target._mouseButtons_ = e.buttons;

    // Module.print("mouse down " + e.buttons + " went down " + wentDown);

    handled = ccall('onPointerFlagsOn', 'number', EngineConnector.number_11_Sig,
        //  target    type    time      id     screenX  screenY   pageX    pageY   targetX  targetY  pressure
        [   target._CPPHandle_,
          // 'd'  UID_MOUSE                       fPointerInside  fPointerInContact
            (100 | 0x0100 | (1 << (9 + 16)) | (1 << (10 + 16)) | (wentDown << 16)),
            e.timeStamp,
            e.pointerId,
            e.screenX,
            e.screenY,
            e.pageX,
            e.pageY,
            posX,
            posY,
            e.pressure
        ]);
    // e.preventDefault();

}),
fireButtonUp: (function(e, buttons) {

    // Module.print("ME fire up true " + buttons );

    var ptrId = e.currentTarget._mousePointerId_;
    if(ptrId < 0) {
        return;
    }

    ccall('onPointerFlagsOff', 'number', EngineConnector.number_11_Sig,
        //  target    type    time      id     screenX  screenY   pageX    pageY   targetX  targetY  pressure
        [e.currentTarget._CPPHandle_,
            (117 | 0x0100 | (buttons << 16)),  // 117 == 'u' == 'up', 1 == UID_MOUSE
            e.timeStamp,
            ptrId,
            e.screenX,
            e.screenY,
            e.pageX,
            e.pageY,
            e.clientX,
            e.clientY,
            0,
        ]);

}),
// up/leave
onMouseUp: (function(e) {

    var target = e.currentTarget;
    var posX = e.clientX;
    var posY = e.clientY;

    if(posX < 0 || posY < 0 || posX >= target.width || posY >= target.height) {
        // we have to kill ALL the buttons
        EngineConnector.fireButtonUp(e,target._mouseButtons_ | (1 << 10));
        target._mouseButtons_ = 0;
    } else {
        var released = (target._mouseButtons_ & (~e.buttons)); // will leave the one we released
        target._mouseButtons_ = e.buttons;
        if(e.buttons == 0) {
            released |= (1 << 10); // fPointerInContact
        }
        EngineConnector.fireButtonUp(e,(released | (1 << 9)));
    }
    e.preventDefault();

}),

onPeMove: (function(e) {

    var target = e.currentTarget;
    var posX = e.clientX;
    var posY = e.clientY;

    var flags = (1 << 9);
    if(posX < 0 || posY < 0 || posX >= target.width || posY >= target.height) {
        flags = 0;
    }

    var pType =  e.pointerType.charCodeAt(0);
    if(pType == 109) { // 'm' == 109
        // MOUSE
        if(target._mousePointerId_ < 0) {
            e.preventDefault();
            return;
        }
    } else {
        Module.print("move !!!");
    }

    flags |= pType; // 'm', 'p', 't'

    handled = ccall('onPointerMove', 'number', EngineConnector.number_11_Sig,
        //  target    flags time      id     screenX  screenY   pageX    pageY   targetX  targetY  pressure
        [ target._CPPHandle_,
            flags,
            e.timeStamp,
            e.pointerId,
            e.screenX,
            e.screenY,
            e.pageX,
            e.pageY,
            posX,
            posY,
            e.pressure
        ]);
}),
onPeUOCL: (function(e) {

    var code = e.type.charCodeAt(7);
    var target = e.currentTarget;
    target._poinsePointerId_ = -1;

    switch(e.pointerType) {
        case 'mouse':
            target._poinsePointerId_ = e.pointerId;
            if(code == 117) { // 117 == 'u' mouseup handled by mouse event handler
                return;
            }
            code |= 0x0100;  // UID_MOUSE << 8
            // let leave and cancel get reported
            break;
        case 'pen':
            code |= 0x0200;  // UID_STYLUS << 8
            if(code == 117) {
                code |= ((1 << 16) << e.which);
            }
            break;
        case 'touch':
            code |= 0x0300;  // UID_FINGER << 8
            if(code == 117) {
                code |= ((1 << 16) << e.which);
            }
            break;
        default:
            Module.print("unknown UID");
            break;
    }

    var posX = e.clientX;
    var posY = e.clientY;

    if(posX >= 0 && posY >= 0 || posX < target.width || posY < target.height) {
        code |= (1 << (9 + 16));
    }

    // Module.print("off uid " + e.pointerType + " " + e.type + " buttons " + e.which + " inside " + ((code & (1 << (9 + 16))) != 0));

    var handled = 0;

    handled = ccall('onPointerFlagsOff', 'number', EngineConnector.number_11_Sig,
        //  target    type    time      id     screenX  screenY   pageX    pageY   targetX  targetY  pressure
        [e.currentTarget._CPPHandle_,
            code,
            e.timeStamp,
            e.pointerId,
            e.screenX,
            e.screenY,
            e.pageX,
            e.pageY,
            posX,
            posY,
            e.pressure,
        ]);
    e.preventDefault();
}),

Цитата от Меня, когда я работал над тем, чтобы заставить Microsoft создавать DirectX почти 30 лет назад - это снова Дежа Воус:)

«Чтобы любая система была по-настоящему гибкой, необходимо иметь возможность внедрить эту систему с нуля с помощью предоставляемых ею средств».

1 Ответ

0 голосов
/ 12 февраля 2019

Я удивлен, что никто не упомянул об этом.Решением является canvas.setAttribute ('style', 'touch-action: none');

https://developer.mozilla.org/en-US/docs/Web/CSS/touch-action

Кстати, в Chrome работает на 99% правильно.

Firefoxвсе равно будут передаваться через синтетические щелчки, которые я должен вставить в неприятный код синхронизации событий, чтобы отфильтровать.

Оба не в состоянии отключить Windows 10 Mouse от эмуляции Touch, что делает невозможным использование мыши и touch одновременно.Я не нашел способа для пользователя отключить это в Windows 10. В любом случае я не хочу отключать его в масштабе всей системы, но только при касании и касании / перетаскивании элемента canvas.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...