Tắt cuộn phím mũi tên trong trình duyệt của người dùng


87

Tôi đang tạo trò chơi bằng canvas và javascript.

Khi trang dài hơn màn hình (nhận xét, v.v.), nhấn mũi tên xuống sẽ cuộn trang xuống và khiến trò chơi không thể chơi được.

Tôi có thể làm gì để ngăn cửa sổ cuộn khi người chơi chỉ muốn di chuyển xuống?

Tôi đoán với các trò chơi Java, và như vậy, đây không phải là vấn đề, miễn là người dùng nhấp vào trò chơi.

Tôi đã thử giải pháp từ: Cách vô hiệu hóa cuộn trang trong FF bằng các phím mũi tên , nhưng tôi không thể làm cho nó hoạt động.

Câu trả lời:


164

Tóm lược

Chỉ cần ngăn hành động mặc định của trình duyệt:

window.addEventListener("keydown", function(e) {
    // space and arrow keys
    if([32, 37, 38, 39, 40].indexOf(e.keyCode) > -1) {
        e.preventDefault();
    }
}, false);

Câu trả lời ban đầu

Tôi đã sử dụng chức năng sau trong trò chơi của riêng mình:

var keys = {};
window.addEventListener("keydown",
    function(e){
        keys[e.keyCode] = true;
        switch(e.keyCode){
            case 37: case 39: case 38:  case 40: // Arrow keys
            case 32: e.preventDefault(); break; // Space
            default: break; // do not block other keys
        }
    },
false);
window.addEventListener('keyup',
    function(e){
        keys[e.keyCode] = false;
    },
false);

Điều kỳ diệu xảy ra trong e.preventDefault();. Điều này sẽ chặn hành động mặc định của sự kiện, trong trường hợp này là di chuyển quan điểm của trình duyệt.

Nếu bạn không cần các trạng thái nút hiện tại, bạn có thể chỉ cần thả keysvà chỉ cần loại bỏ hành động mặc định trên các phím mũi tên:

var arrow_keys_handler = function(e) {
    switch(e.keyCode){
        case 37: case 39: case 38:  case 40: // Arrow keys
        case 32: e.preventDefault(); break; // Space
        default: break; // do not block other keys
    }
};
window.addEventListener("keydown", arrow_keys_handler, false);

Lưu ý rằng phương pháp này cũng cho phép bạn xóa trình xử lý sự kiện sau này nếu bạn cần bật lại thao tác cuộn phím mũi tên:

window.removeEventListener("keydown", arrow_keys_handler, false);

Người giới thiệu


8
Tôi thực sự thích giải pháp này, nhưng nó không có vẻ làm việc trong chrome = /
Kaninepete

1
@Kaninepete: Đã xảy ra lỗi cú pháp, tôi đã sử dụng lC.keysthay vì keystrong trình nghe keyup. Đã sửa lỗi này và thử nghiệm nó trên Firefox và Chrome. Chú ý rằng tất cả các thay đổi keyslà không bắt buộc, nhưng kể từ khi bạn đang xây dựng một trò chơi ...
Zeta

trong một số trình duyệt (di động) lớn tuổi, có vẻ như các phím mũi tên thậm chí không cháy, sự kiện quan trọng ... :-(
Michael

1
Nếu bạn làm điều này và bạn có bất kỳ đầu vào trường nào trên trang web của mình thì bạn sẽ không thể sử dụng phím cách hoặc các phím mũi tên để điều hướng văn bản. Nhược điểm lớn tôi tìm thấy.
Thực thể độc thân

9
Lưu ý rằng bạn thực sự cần sử dụng keydownvà không keyup.
Ludder

4

Để có thể bảo trì, tôi sẽ đính kèm trình xử lý "chặn" trên chính phần tử (trong trường hợp của bạn là canvas).

theCanvas.onkeydown = function (e) {
    if (e.key === 'ArrowUp' || e.key === 'ArrowDown') {
        e.view.event.preventDefault();
    }
}

Tại sao không chỉ đơn giản là làm window.event.preventDefault()? MDN tuyên bố:

window.eventlà một thuộc tính Microsoft Internet Explorer độc quyền chỉ khả dụng khi trình xử lý sự kiện DOM đang được gọi. Giá trị của nó là đối tượng Sự kiện hiện đang được xử lý.

Đọc thêm:


0

Tôi đã thử các cách khác nhau để chặn cuộn khi các phím mũi tên được nhấn, cả jQuery và Javascript gốc - tất cả chúng đều hoạt động tốt trong Firefox, nhưng không hoạt động trong các phiên bản Chrome gần đây.
Ngay cả thuộc tính rõ ràng {passive: false}cho window.addEventListener, được khuyến nghị là giải pháp hoạt động duy nhất, chẳng hạn ở đây .

Cuối cùng, sau nhiều lần thử, tôi đã tìm thấy một cách phù hợp với mình trên cả Firefox và Chrome:

window.addEventListener('keydown', (e) => {
    if (e.target.localName != 'input') {   // if you need to filter <input> elements
        switch (e.keyCode) {
            case 37: // left
            case 39: // right
                e.preventDefault();
                break;
            case 38: // up
            case 40: // down
                e.preventDefault();
                break;
            default:
                break;
        }
    }
}, {
    capture: true,   // this disables arrow key scrolling in modern Chrome
    passive: false   // this is optional, my code works without it
});

Trích dẫn EventTarget.addEventListener()từ MDN

tùy chọn Tùy chọn
   Một đối tượng tùy chọn chỉ định các đặc điểm về trình nghe sự kiện. Các tùy chọn có sẵn là:

capture
   A Booleancho biết rằng các sự kiện thuộc loại này sẽ được gửi đến người đã đăng ký listenertrước khi được gửi đến bất kỳ sự kiện nào EventTargetbên dưới nó trong cây DOM.
một khi
   ...
bị động
   A Boolean, nếu đúng, chỉ ra rằng hàm được chỉ định bởi listenersẽ không bao giờ gọi preventDefault(). Nếu một người nghe thụ động thực hiện cuộc gọi preventDefault(), tác nhân người dùng sẽ không làm gì khác hơn là tạo một cảnh báo trên bảng điều khiển. ...

Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.