æééå® APIï¼Pointer Lock APIï¼ä»¥åå«å Mouse Lock APIï¼æä¾äºä¸ç§åºäºé¼ æ éçæ¶é´æ¨ç§»ï¼ä¹å°±æ¯å¢éï¼çè¿å¨çè¾å ¥æ¹æ³ï¼èä¸ä» æ¯é¼ æ å æ å¨è§å£ä¸çç»å¯¹ä½ç½®ãéè¿å®å¯ä»¥è®¿é®åå§çé¼ æ è¿å¨ï¼æé¼ æ äºä»¶çç®æ éå®å°ä¸ä¸ªåç¬çå ç´ ï¼è¿å°±æ¶é¤äºé¼ æ å¨ä¸ä¸ªåç¬çæ¹åä¸å°åºå¯ä»¥ç§»å¨å¤è¿è¿æ¹é¢çéå¶ï¼å¹¶ä»è§å¾ä¸å å»å æ ãä¾å¦ï¼å®æ¯ç¬¬ä¸äººç§° 3D 游æççæ³éæ©ã
ä¸ä» 妿¤ï¼è¯¥ API 对äºéè¦å¤§éé¼ æ è¾å ¥æ¥æ§å¶ç§»å¨ãæè½¬å¯¹è±¡åæ´æ¹æ¡ç®çä»»ä½åºç¨ç¨åºé½é常æç¨ï¼ä¾å¦ï¼å è®¸ç¨æ·éè¿ç§»å¨é¼ æ æ¥æ§å¶è§è§ï¼èæ éåå»ä»»ä½æé®ãç¶åéæ¾æé®ä»¥æ§è¡å ¶ä»æä½ãå ¶ä»ç¤ºä¾å æ¬ç¨äºæ¥çå°å¾æå«æå¾åçåºç¨ç¨åºã
æééå®è®©ä½ å³ä½¿å æ è¶ åºæµè§å¨æå±å¹çè¾¹çä¹è½è®¿é®é¼ æ äºä»¶ãä¾å¦ï¼ä½ çç¨æ·å¯ä»¥éè¿æ 伿¢å°ç§»å¨é¼ æ æ¥ç»§ç»æè½¬ææä½ 3D 模åãå¦ææ²¡ææééå®ï¼æè½¬ææä½ä¼å¨æéå°è¾¾æµè§å¨æå±å¹çè¾¹ç¼æ¶åæ¢ã游æç©å®¶ç°å¨å¯ä»¥ç¹å»æé®å¹¶æ¥åæ»å¨é¼ æ å æ ï¼èä¸å¿ æ å¿ç¦»å¼æ¸¸æåºåå¹¶æå¤ç¹å»å¦ä¸ä¸ªåºç¨ç¨åºè导è´é¼ æ ç¦ç¹ä»æ¸¸æä¸ç§»å¼ã
åºæ¬æ¦å¿µæééå®åæéæè·æå ³ãæéæè·å¨é¼ æ è¢«ææ³æ¶å¯ä»¥åä¸ä¸ªç®æ å ç´ æç»ä¼ éæå ³äºä»¶ï¼ä½æ¯å½é¼ æ æé®è¢«æ¾å¼æ¶å°±ä¼åæ¢ãæééå®åæéæè·å¨ä»¥ä¸æ¹é¢ææä¸åï¼
æ¬å°è坹䏿ééå®è§èç¸å ³çæ¯ä¸ªå±æ§åæ¹æ³è¿è¡äºç®è¦è¯´æã
requestPointerLock()æééå® API ä¸å
¨å± API 类似ï¼éè¿æ·»å æ°æ¹æ³ reââquestPointerLock()
æ¥æ©å± DOM å
ç´ ã以ä¸ç¤ºä¾è¯·æ±å¯¹ <canvas>
å
ç´ è¿è¡æééå®ï¼
canvas.addEventListener("click", async () => {
await canvas.requestPointerLock();
});
夿³¨ï¼ å¦æç¨æ·éè¿é»è®¤è§£éæå¿éåºæééå®ï¼æè
ä¹åæªä¸ºæ¤ææ¡£è¾å
¥æééå®ï¼åææ¡£å¿
é¡»æ¶å°å䏿å¿çæçäºä»¶ï¼requestPointerLock
æä¼æåãï¼æ¥èª https://w3c.github.io/pointerlock/#extensions-to-the-element-interfaceï¼
æä½ç³»ç»é»è®¤å¯ç¨é¼ æ å éï¼è¿å¨ä½ ææ¶æ³è¦ç¼æ ¢ç²¾ç¡®ç§»å¨ï¼æ³æ³ä½ å¯è½ä¼ä½¿ç¨å¾å½¢å ï¼æ¶å¾æç¨ï¼ä½ä¹å¸æéè¿æ´å¿«çé¼ æ ç§»å¨ç§»å¨å¾è¿çè·ç¦»ï¼æ³æ³æ»å¨åéæ©å¤ä¸ªæä»¶ï¼ãç¶èï¼å¯¹äºä¸äºç¬¬ä¸äººç§°è§è§æ¸¸æï¼åå§é¼ æ è¾å ¥æ°æ®æ´éåç¨äºæ§å¶ç¸æºæè½¬ââç¸åè·ç¦»çç§»å¨ï¼æ è®ºå¿«ææ ¢ï¼é½ä¼å¯¼è´ç¸åçæè½¬ãä¸ä¸æ¸¸æç©å®¶è¡¨ç¤ºï¼è¿ä¼å¸¦æ¥æ´å¥½ç游æä½éªåæ´é«çå确度ã
è¦ç¦ç¨æä½ç³»ç»çº§é¼ æ å é并访é®åå§é¼ æ è¾å
¥ï¼ä½ å¯ä»¥å° unadjustedMovement
设置为 true
ï¼
canvas.addEventListener("click", async () => {
await canvas.requestPointerLock({
unadjustedMovement: true,
});
});
å¤ç requestPointerLock() ç promise çæ¬åé promise çæ¬
ä¸è¿°ä»£ç çæ®µå¨ä¸æ¯æåºäº promise ç requestPointerLock()
çæ¬æ unadjustedMovement
éé¡¹çæµè§å¨ä¸ä»å¯æ£å¸¸å·¥ä½ââå
许å¨ä¸è¿å promise ç彿°åé¢ä½¿ç¨ await
è¿ç®ç¬¦ï¼å¹¶ä¸é项对象å°å¨ä¸æ¯æçæµè§å¨ä¸è¢«å¿½ç¥ã
使¯ï¼è¿å¯è½ä¼é ææ··æ·ï¼å¹¶ä¸æå
¶ä»æ½å¨çå¯ä½ç¨ï¼ä¾å¦ï¼å°è¯ä½¿ç¨ requestPointerLock().then()
ä¼å¨ä¸æ¯æçæµè§å¨ä¸å¼åé误ï¼ï¼å æ¤ä½ å¯è½éè¦ä½¿ç¨ä»¥ä¸ä»£ç æç¡®å¤çæ¤é®é¢ï¼
function requestPointerLockWithUnadjustedMovement() {
const promise = myTargetElement.requestPointerLock({
unadjustedMovement: true,
});
if (!promise) {
console.log("䏿¯æç¦ç¨é¼ æ å é");
return;
}
return promise
.then(() => console.log("æé被éå®"))
.catch((error) => {
if (error.name === "NotSupportedError") {
// æäºå¹³å°å¯è½ä¸æ¯ææªè°æ´çç§»å¨ãä½ å¯ä»¥éæ°è¯·æ±å¸¸è§æééå®ã
return myTargetElement.requestPointerLock();
}
});
}
pointerLockElement å exitPointerLock()
æééå® API è¿æ©å±äº Document
æ¥å£ï¼æ·»å äºä¸ä¸ªæ°å±æ§åä¸ä¸ªæ°æ¹æ³ï¼
pointerLockElement
ç¨äºè®¿é®å½åéå®çå
ç´ ï¼å¦ææï¼ãexitPointerLock()
ç¨äºéåºæééå®ãpointerLockElement
屿§å¯ç¨äºç¡®å®ä»»ä½å
ç´ å½åæ¯å¦è¢«æééå®ï¼ä¾å¦ï¼è¿è¡å¸å°æ£æ¥ï¼ï¼ä¹å¯ç¨äºè·å对éå®å
ç´ çå¼ç¨ï¼å¦ææï¼ã
以䏿¯ä½¿ç¨ pointerLockElement
ç示ä¾ï¼
if (document.pointerLockElement === canvas) {
console.log("æééå®ç¶æç°å·²éå®");
} else {
console.log("æééå®ç¶æç°å·²è§£é");
}
Document.exitPointerLock()
æ¹æ³ç¨äºéåºæééå®ï¼ä¸ reââquestPointerLock
䏿 ·ï¼ä½¿ç¨ pointerlockchange
å pointerlockerror
äºä»¶å¼æ¥è¿è¡ï¼ä½ å°å¨ä¸é¢çå°æ´å¤ç¸å
³å
容ã
document.exitPointerLock();
pointerlockchange äºä»¶
彿ééå®ç¶ææ¹åæ¶ââä¾å¦ï¼å½è°ç¨ requestPointerLock()
æ exitPointerLock()
ï¼ç¨æ·æä¸ ESC é®ï¼ççââpointerlockchange
äºä»¶å¨ document
ä¸è§¦åãè¿æ¯ä¸ä¸ªä¸å
å«ä»»ä½çé¢å¤æ°æ®çç®åäºä»¶ã
document.addEventListener("pointerlockchange", lockChangeAlert, false);
function lockChangeAlert() {
if (document.pointerLockElement === canvas) {
console.log("æééå®ç¶æç°å·²éå®");
// åä¸äºæç¨çäºæ
ä½ä¸ºååº
} else {
console.log("æééå®ç¶æç°å·²è§£é");
// åä¸äºæç¨çäºæ
ä½ä¸ºååº
}
}
pointerlockerror äºä»¶
å½è°ç¨ requestPointerLock()
æ exitPointerLock()
èå¼åé误æ¶ï¼ pointerlockerror
äºä»¶å¨ document
ä¸è§¦åãè¿æ¯ä¸ä¸ªç®åäºä»¶æä»¥ä¸å
å«ä»»ä½çé¢å¤æ°æ®ã
document.addEventListener("pointerlockerror", lockError, false);
function lockError(e) {
alert("æééå®å¤±è´¥");
}
é¼ æ äºä»¶çæ©å±
æééå® API æ©å±äºæ®éç MouseEvent
æ¥å£ï¼ä½¿å
¶å
·æ movement 屿§ãé¼ æ äºä»¶ç两个æ°å±æ§ââmovementX
å movementY
ââæä¾é¼ æ ä½ç½®çååãåæ°çå¼ä¸ MouseEvent
屿§å¼ screenX
å screenY
ä¹é´çå·®å¼ç¸åï¼å®ä»¬åå¨å¨ä¸¤ä¸ªåç» mousemove
äºä»¶ eNow
å ePrevious
ä¸ãæ¢å¥è¯è¯´ï¼æééå®åæ° movementX = eNow.screenX - ePrevious.screenX
ã
彿ééå®è¢«å¯å¨ä¹åï¼æ åç MouseEvent
屿§ clientX
ãclientY
ãscreenX
å screenY
屿§ä¿æä¸åï¼å°±åé¼ æ æªç§»å¨ä¸æ ·ãmovementX
å movementY
屿§ç»§ç»æä¾é¼ æ çä½ç½®ååãå¦æé¼ æ æç»æä¸ä¸ªæ¹åç§»å¨ï¼å movementX
å movementY
å¼ä¸åéå¶ãé¼ æ å
æ çæ¦å¿µä¸åå¨ï¼å¹¶ä¸å
æ ä¸è½ç§»åºçªå£æè¢«å±å¹è¾¹ç¼å¤¹ä½ã
æ è®ºé¼ æ æ¯å¦å¤äºéå®ç¶æï¼åæ° movementX
å movementY
åææï¼å¹¶ä¸å³ä½¿é¼ æ è§£éåä¹å¯ç¨ï¼ä»¥æ¹ä¾¿ä½¿ç¨ã
å½é¼ æ è§£éæ¶ï¼ç³»ç»å
æ å¯ä»¥éåºå¹¶éæ°è¿å
¥æµè§å¨çªå£ã妿åçè¿ç§æ
åµï¼å¯ä»¥å° movementX
å movementY
设置为é¶ã
æä»¬ç¼åäºä¸ä¸ªæéé宿¼ç¤ºï¼æ¥çæºä»£ç ï¼ï¼åä½ å±ç¤ºå¦ä½ä½¿ç¨å®æ¥è®¾ç½®ä¸ä¸ªç®åçæ§å¶ç³»ç»ãæ¤æ¼ç¤ºä½¿ç¨ JavaScript å¨ <canvas>
å
ç´ ä¸ç»å¶ä¸ä¸ªçãå½ä½ åå»ç»å¸æ¶ï¼æééå®å°ç¨äºç§»é¤é¼ æ æéï¼å¹¶å
è®¸ä½ ç´æ¥ä½¿ç¨é¼ æ ç§»å¨çã让æä»¬çç宿¯å¦ä½å·¥ä½çã
æä»¬å¨ç»å¸ä¸è®¾ç½® x å y çåå§ä½ç½®ï¼
æ¥ä¸æ¥ï¼æä»¬è®¾ç½®ä¸ä¸ªäºä»¶çå¬å¨ï¼å½åå»ç»å¸æ¶ï¼å¨ç»å¸ä¸è¿è¡ requestPointerLock()
æ¹æ³ï¼ä»èå¯å¨æééå®ãdocument.pointerLockElement
æ£æ¥æ¯ä¸ºäºæ¥çæ¯å¦å·²ç»æä¸ä¸ªæ´»å¨çæééå®ââå¦æå·²ç»ææééå®ï¼æä»¬ä¸æ³æ¯æ¬¡åå»ç»å¸æ¶é½ç»§ç»è°ç¨ requestPointerLock()
ã
canvas.addEventListener("click", async () => {
if (!document.pointerLockElement) {
await canvas.requestPointerLock({
unadjustedMovement: true,
});
}
});
夿³¨ï¼ ä¸è¿°ä»£ç çæ®µå¨ä¸æ¯æ requestPointerLock()
ç promise çæ¬çæµè§å¨ä¸ææã请åé
å¤ç requestPointerLock() ç promise çæ¬åé promise çæ¬äºè§£è¯¦ç»è¯´æã
ç°å¨æ¥ççä¸ç¨çæééå®äºä»¶çå¬å¨ï¼pointerlockchange
ãå½è¿ç§æ
åµåçæ¶ï¼æä»¬è¿è¡ä¸ä¸ªå为 lockChangeAlert()
ç彿°æ¥å¤çååã
document.addEventListener("pointerlockchange", lockChangeAlert, false);
æ¤å½æ°æ£æ¥ pointerLockElement
屿§ä»¥æ¥ç宿¯å¦æ¯æä»¬çç»å¸ã妿æ¯ï¼å®ä¼éå ä¸ä¸ªäºä»¶ä¾¦å¬å¨ï¼ä»¥ä½¿ç¨ updatePosition()
彿°å¤çé¼ æ ç§»å¨ã妿䏿¯ï¼å®ä¼å次å é¤äºä»¶ä¾¦å¬å¨ã
function lockChangeAlert() {
if (document.pointerLockElement === canvas) {
console.log("æééå®ç¶æç°å·²éå®");
document.addEventListener("mousemove", updatePosition, false);
} else {
console.log("æééå®ç¶æç°å·²è§£é");
document.removeEventListener("mousemove", updatePosition, false);
}
}
updatePosition()
彿°ä¼æ´æ°çå¨ç»å¸ä¸çä½ç½®ï¼x
å y
ï¼ï¼åæ¶è¿å
å« if ()
è¯å¥ï¼ç¨äºæ£æ¥çæ¯å¦å·²ç»è¶
åºç»å¸çè¾¹ç¼ã妿è¶
åºï¼å让çç»å°å¦ä¸ä¾§çè¾¹ç¼ãå®è¿ä¼æ£æ¥ä¹åæ¯å¦å·²è°ç¨ requestAnimationFrame()
ï¼å¦æå·²è°ç¨ï¼åæ ¹æ®éè¦å次è°ç¨ï¼å¹¶è°ç¨ canvasDraw()
彿°æ¥æ´æ°ç»å¸åºæ¯ãè¿è®¾ç½®äºä¸ä¸ªè·è¸ªå¨ï¼ç¨äºå° X å Y å¼åå
¥å±å¹ï¼ä»¥ä¾åèã
const tracker = document.getElementById("tracker");
let animation;
function updatePosition(e) {
x += e.movementX;
y += e.movementY;
if (x > canvas.width + RADIUS) {
x = -RADIUS;
}
if (y > canvas.height + RADIUS) {
y = -RADIUS;
}
if (x < -RADIUS) {
x = canvas.width + RADIUS;
}
if (y < -RADIUS) {
y = canvas.height + RADIUS;
}
tracker.textContent = `X åæ ï¼${x}ï¼Y åæ ï¼${y}`;
if (!animation) {
animation = requestAnimationFrame(() => {
animation = null;
canvasDraw();
});
}
}
canvasDraw()
彿°å¨å½å x
å y
ä½ç½®ç»å¶åï¼
function canvasDraw() {
ctx.fillStyle = "black";
ctx.fillRect(0, 0, canvas.width, canvas.height);
ctx.fillStyle = "#f00";
ctx.beginPath();
ctx.arc(x, y, RADIUS, 0, degToRad(360), true);
ctx.fill();
}
iframe çéå¶
æééå®ä¸æ¬¡åªè½éå®ä¸ä¸ª <iframe>
ãå¦æä½ éå®ä¸ä¸ª <iframe>
ï¼åæ æ³éå®å¦ä¸ä¸ªå¹¶å°ç®æ 转移å°å®ï¼æââééå®å°åºéãè¦é¿å
æ¤éå¶ï¼è¯·å
è§£éå·²éå®ç <iframe>
ï¼ç¶åéå®å¦ä¸ä¸ªã
è½ç¶ <iframe>
é»è®¤å·¥ä½ï¼ä½âæ²çåâç <iframe>
ä¼é»æ¢æééå®ãè¦é¿å
æ¤éå¶ï¼è¯·ä½¿ç¨ <iframe sandbox="allow-pointer-lock">
ã
RetroSearch is an open source project built by @garambo | Open a GitHub Issue
Search and Browse the WWW like it's 1997 | Search results from DuckDuckGo
HTML:
3.2
| Encoding:
UTF-8
| Version:
0.7.4