问题背景
在Linux平台上,使用chromium内核的浏览器打开米哈游官方的云游戏平台(如云原神)会发现在进入游戏后鼠标无法被捕获,视角无法移动的情况.通过简单测试发现此问题与Linux内核、x、桌面环境无关,疑似是浏览器适配问题
解决方案(任选其一)
方案一:添加油猴脚本
// ==UserScript==
// @name Genshin Cloud
// @namespace http://tampermonkey.net/
// @version 0.1
// @description fix a Genshin Impact cloud game bug
// @match https://ys.mihoyo.com/cloud/*
// @grant none
// ==/UserScript==
(function () {
'use strict';
const origin = HTMLElement.prototype.requestPointerLock
HTMLElement.prototype.requestPointerLock = function () {
return origin.call(this)
}
})(); 方案二:
如果没有安装油猴插件可以在进入游戏的网页内打开调试面板,直接将上述代码复制到浏览器控制台后回车即可。
问题原因
浏览器提供了Pointer Lock API,MDN对该API描述如下
指针锁定(以前叫做鼠标锁定) 提供了一种输入方法,这种方法是基于鼠标随着时间推移的运动的(也就是,deltas),而不仅是鼠标光标的绝对位置。通过它可以访问原始的鼠标运动,把鼠标事件的目标锁定到一个单独的元素,这就消除了鼠标在一个单独的方向上到底可以移动多远这方面的限制,并从视图中删去光标。
该API用于将鼠标指针锁定于特定元素,如果该API访问执行错误将无法锁定指针。通过搜索浏览器返回的代码,发现在云原神中,使用了下面的方法调用了该API
try {
await t.value.requestPointerLock({
unadjustedMovement: !0
})
} catch (e) {} 其中unadjustedMovement若为true会关闭鼠标加速以在射击游戏中取得更好的体验,云原神也传入了该值以获取更好的游戏体验。
但通过demo模拟后发现,在Linux平台若传入了该参数会导致方法抛出错误:
The options asked for in this request are not supported on this platform.
可见在linux平台并不支持传入该参数,且传入该参数会导致方法调用异常,也就无法捕获鼠标了。
为了解决这个问题,可以通过hook html元素的requestPointerLock方法,将所有传入参数屏蔽,来避免api调用报错。上述的脚本就是通过修改了HTML元素的原型方法来避免传入unadjustedMovement的。