CINXE.COM

Pointer Lock API - Web APIs | MDN

<!doctype html><html lang="en-US" prefix="og: https://ogp.me/ns#"><head><meta charSet="utf-8"/><meta name="viewport" content="width=device-width,initial-scale=1"/><link rel="icon" href="https://developer.mozilla.org/favicon-48x48.bc390275e955dacb2e65.png"/><link rel="apple-touch-icon" href="https://developer.mozilla.org/apple-touch-icon.528534bba673c38049c2.png"/><meta name="theme-color" content="#ffffff"/><link rel="manifest" href="https://developer.mozilla.org/manifest.f42880861b394dd4dc9b.json"/><link rel="search" type="application/opensearchdescription+xml" href="/opensearch.xml" title="MDN Web Docs"/><title>Pointer Lock API - Web APIs | MDN</title><link rel="alternate" title="Pointer Lock API" href="https://developer.mozilla.org/de/docs/Web/API/Pointer_Lock_API" hrefLang="de"/><link rel="alternate" title="API Pointer Lock" href="https://developer.mozilla.org/es/docs/Web/API/Pointer_Lock_API" hrefLang="es"/><link rel="alternate" title="Pointer Lock API" href="https://developer.mozilla.org/fr/docs/Web/API/Pointer_Lock_API" hrefLang="fr"/><link rel="alternate" title="ポインターロック API" href="https://developer.mozilla.org/ja/docs/Web/API/Pointer_Lock_API" hrefLang="ja"/><link rel="alternate" title="Pointer Lock API" href="https://developer.mozilla.org/ru/docs/Web/API/Pointer_Lock_API" hrefLang="ru"/><link rel="alternate" title="指针锁定 API" href="https://developer.mozilla.org/zh-CN/docs/Web/API/Pointer_Lock_API" hrefLang="zh"/><link rel="alternate" title="Pointer Lock API" href="https://developer.mozilla.org/zh-TW/docs/Web/API/Pointer_Lock_API" hrefLang="zh-Hant"/><link rel="alternate" title="Pointer Lock API" href="https://developer.mozilla.org/en-US/docs/Web/API/Pointer_Lock_API" hrefLang="en"/><link rel="preload" as="font" type="font/woff2" href="/static/media/Inter.var.c2fe3cb2b7c746f7966a.woff2" crossorigin=""/><link rel="alternate" type="application/rss+xml" title="MDN Blog RSS Feed" href="https://developer.mozilla.org/en-US/blog/rss.xml" hrefLang="en"/><meta name="description" content="The Pointer Lock API (formerly called Mouse Lock API) provides input methods based on the movement of the mouse over time (i.e., deltas), not just the absolute position of the mouse cursor in the viewport. It gives you access to raw mouse movement, locks the target of mouse events to a single element, eliminates limits on how far mouse movement can go in a single direction, and removes the cursor from view. It is ideal for first-person 3D games, for example."/><meta property="og:url" content="https://developer.mozilla.org/en-US/docs/Web/API/Pointer_Lock_API"/><meta property="og:title" content="Pointer Lock API - Web APIs | MDN"/><meta property="og:type" content="website"/><meta property="og:locale" content="en_US"/><meta property="og:description" content="The Pointer Lock API (formerly called Mouse Lock API) provides input methods based on the movement of the mouse over time (i.e., deltas), not just the absolute position of the mouse cursor in the viewport. It gives you access to raw mouse movement, locks the target of mouse events to a single element, eliminates limits on how far mouse movement can go in a single direction, and removes the cursor from view. It is ideal for first-person 3D games, for example."/><meta property="og:image" content="https://developer.mozilla.org/mdn-social-share.d893525a4fb5fb1f67a2.png"/><meta property="og:image:type" content="image/png"/><meta property="og:image:height" content="1080"/><meta property="og:image:width" content="1920"/><meta property="og:image:alt" content="The MDN Web Docs logo, featuring a blue accent color, displayed on a solid black background."/><meta property="og:site_name" content="MDN Web Docs"/><meta name="twitter:card" content="summary_large_image"/><meta name="twitter:creator" content="MozDevNet"/><link rel="canonical" href="https://developer.mozilla.org/en-US/docs/Web/API/Pointer_Lock_API"/><style media="print">.article-actions-container,.document-toc-container,.language-menu,.main-menu-toggle,.on-github,.page-footer,.place,.sidebar,.top-banner,.top-navigation-main,ul.prev-next{display:none!important}.main-page-content,.main-page-content pre{padding:2px}.main-page-content pre{border-left-width:2px}</style><script src="/static/js/gtag.js" defer=""></script><script defer="" src="/static/js/main.5e889624.js"></script><link href="/static/css/main.26c64ea7.css" rel="stylesheet"/></head><body><script>if(document.body.addEventListener("load",(t=>{t.target.classList.contains("interactive")&&t.target.setAttribute("data-readystate","complete")}),{capture:!0}),window&&document.documentElement){const t={light:"#ffffff",dark:"#1b1b1b"};try{const e=window.localStorage.getItem("theme");e&&(document.documentElement.className=e,document.documentElement.style.backgroundColor=t[e]);const o=window.localStorage.getItem("nop");o&&(document.documentElement.dataset.nop=o)}catch(t){console.warn("Unable to read theme from localStorage",t)}}</script><div id="root"><ul id="nav-access" class="a11y-nav"><li><a id="skip-main" href="#content">Skip to main content</a></li><li><a id="skip-search" href="#top-nav-search-input">Skip to search</a></li><li><a id="skip-select-language" href="#languages-switcher-button">Skip to select language</a></li></ul><div class="page-wrapper category-api document-page"><div class="top-banner loading"><section class="place top container"></section></div><div class="sticky-header-container"><header class="top-navigation "><div class="container "><div class="top-navigation-wrap"><a href="/en-US/" class="logo" aria-label="MDN homepage"><svg id="mdn-docs-logo" xmlns="http://www.w3.org/2000/svg" x="0" y="0" viewBox="0 0 694.9 104.4" style="enable-background:new 0 0 694.9 104.4" xml:space="preserve" role="img"><title>MDN Web Docs</title><path d="M40.3 0 11.7 92.1H0L28.5 0h11.8zm10.4 0v92.1H40.3V0h10.4zM91 0 62.5 92.1H50.8L79.3 0H91zm10.4 0v92.1H91V0h10.4z" class="logo-m"></path><path d="M627.9 95.6h67v8.8h-67v-8.8z" class="logo-_"></path><path d="M367 42h-4l-10.7 30.8h-5.5l-10.8-26h-.4l-10.5 26h-5.2L308.7 42h-3.8v-5.6H323V42h-6.5l6.8 20.4h.4l10.3-26h4.7l11.2 26h.5l5.7-20.3h-6.2v-5.6H367V42zm34.9 20c-.4 3.2-2 5.9-4.7 8.2-2.8 2.3-6.5 3.4-11.3 3.4-5.4 0-9.7-1.6-13.1-4.7-3.3-3.2-5-7.7-5-13.7 0-5.7 1.6-10.3 4.7-14s7.4-5.5 12.9-5.5c5.1 0 9.1 1.6 11.9 4.7s4.3 6.9 4.3 11.3c0 1.5-.2 3-.5 4.7h-25.6c.3 7.7 4 11.6 10.9 11.6 2.9 0 5.1-.7 6.5-2 1.5-1.4 2.5-3 3-4.9l6 .9zM394 51.3c.2-2.4-.4-4.7-1.8-6.9s-3.8-3.3-7-3.3c-3.1 0-5.3 1-6.9 3-1.5 2-2.5 4.4-2.8 7.2H394zm51 2.4c0 5-1.3 9.5-4 13.7s-6.9 6.2-12.7 6.2c-6 0-10.3-2.2-12.7-6.7-.1.4-.2 1.4-.4 2.9s-.3 2.5-.4 2.9h-7.3c.3-1.7.6-3.5.8-5.3.3-1.8.4-3.7.4-5.5V22.3h-6v-5.6H416v27c1.1-2.2 2.7-4.1 4.7-5.7 2-1.6 4.8-2.4 8.4-2.4 4.6 0 8.4 1.6 11.4 4.7 3 3.2 4.5 7.6 4.5 13.4zm-7.7.6c0-4.2-1-7.4-3-9.5-2-2.2-4.4-3.3-7.4-3.3-3.4 0-6 1.2-8 3.7-1.9 2.4-2.9 5-3 7.7V57c0 3 1 5.6 3 7.7s4.5 3.1 7.6 3.1c3.6 0 6.3-1.3 8.1-3.9 1.8-2.7 2.7-5.9 2.7-9.6zm69.2 18.5h-13.2v-7.2c-1.2 2.2-2.8 4.1-4.9 5.6-2.1 1.6-4.8 2.4-8.3 2.4-4.8 0-8.7-1.6-11.6-4.9-2.9-3.2-4.3-7.7-4.3-13.3 0-5 1.3-9.6 4-13.7 2.6-4.1 6.9-6.2 12.8-6.2 5.7 0 9.8 2.2 12.3 6.5V22.3h-8.6v-5.6h15.8v50.6h6v5.5zM493.2 56v-4.4c-.1-3-1.2-5.5-3.2-7.3s-4.4-2.8-7.2-2.8c-3.6 0-6.3 1.3-8.2 3.9-1.9 2.6-2.8 5.8-2.8 9.6 0 4.1 1 7.3 3 9.5s4.5 3.3 7.4 3.3c3.2 0 5.8-1.3 7.8-3.8 2.1-2.6 3.1-5.3 3.2-8zm53.1-1.4c0 5.6-1.8 10.2-5.3 13.7s-8.2 5.3-13.9 5.3-10.1-1.7-13.4-5.1c-3.3-3.4-5-7.9-5-13.5 0-5.3 1.6-9.9 4.7-13.7 3.2-3.8 7.9-5.7 14.2-5.7s11 1.9 14.1 5.7c3 3.7 4.6 8.1 4.6 13.3zm-7.7-.2c0-4-1-7.2-3-9.5s-4.8-3.5-8.2-3.5c-3.6 0-6.4 1.2-8.3 3.7s-2.9 5.6-2.9 9.5c0 3.7.9 6.8 2.8 9.4 1.9 2.6 4.6 3.9 8.3 3.9 3.6 0 6.4-1.3 8.4-3.8 1.9-2.6 2.9-5.8 2.9-9.7zm45 5.8c-.4 3.2-1.9 6.3-4.4 9.1-2.5 2.9-6.4 4.3-11.8 4.3-5.2 0-9.4-1.6-12.6-4.8-3.2-3.2-4.8-7.7-4.8-13.7 0-5.5 1.6-10.1 4.7-13.9 3.2-3.8 7.6-5.7 13.2-5.7 2.3 0 4.6.3 6.7.8 2.2.5 4.2 1.5 6.2 2.9l1.5 9.5-5.9.7-1.3-6.1c-2.1-1.2-4.5-1.8-7.2-1.8-3.5 0-6.1 1.2-7.7 3.7-1.7 2.5-2.5 5.7-2.5 9.6 0 4.1.9 7.3 2.7 9.5 1.8 2.3 4.4 3.4 7.8 3.4 5.2 0 8.2-2.9 9.2-8.8l6.2 1.3zm34.7 1.9c0 3.6-1.5 6.5-4.6 8.5s-7 3-11.7 3c-5.7 0-10.6-1.2-14.6-3.6l1.2-8.8 5.7.6-.2 4.7c1.1.5 2.3.9 3.6 1.1s2.6.3 3.9.3c2.4 0 4.5-.4 6.5-1.3 1.9-.9 2.9-2.2 2.9-4.1 0-1.8-.8-3.1-2.3-3.8s-3.5-1.3-5.8-1.7-4.6-.9-6.9-1.4c-2.3-.6-4.2-1.6-5.7-2.9-1.6-1.4-2.3-3.5-2.3-6.3 0-4.1 1.5-6.9 4.6-8.5s6.4-2.4 9.9-2.4c2.6 0 5 .3 7.2.9 2.2.6 4.3 1.4 6.1 2.4l.8 8.8-5.8.7-.8-5.7c-2.3-1-4.7-1.6-7.2-1.6-2.1 0-3.7.4-5.1 1.1-1.3.8-2 2-2 3.8 0 1.7.8 2.9 2.3 3.6 1.5.7 3.4 1.2 5.7 1.6 2.2.4 4.5.8 6.7 1.4 2.2.6 4.1 1.6 5.7 3 1.4 1.6 2.2 3.7 2.2 6.6zM197.6 73.2h-17.1v-5.5h3.8V51.9c0-3.7-.7-6.3-2.1-7.9-1.4-1.6-3.3-2.3-5.7-2.3-3.2 0-5.6 1.1-7.2 3.4s-2.4 4.6-2.5 6.9v15.6h6v5.5h-17.1v-5.5h3.8V51.9c0-3.8-.7-6.4-2.1-7.9-1.4-1.5-3.3-2.3-5.6-2.3-3.2 0-5.5 1.1-7.2 3.3-1.6 2.2-2.4 4.5-2.5 6.9v15.8h6.9v5.5h-20.2v-5.5h6V42.4h-6.1v-5.6h13.4v6.4c1.2-2.1 2.7-3.8 4.7-5.2 2-1.3 4.4-2 7.3-2s5.3.7 7.5 2.1c2.2 1.4 3.7 3.5 4.5 6.4 1.1-2.5 2.7-4.5 4.9-6.1s4.8-2.4 7.9-2.4c3.5 0 6.5 1.1 8.9 3.3s3.7 5.6 3.7 10.2v18.2h6.1v5.5zm42.5 0h-13.2V66c-1.2 2.2-2.8 4.1-4.9 5.6-2.1 1.6-4.8 2.4-8.3 2.4-4.8 0-8.7-1.6-11.6-4.9-2.9-3.2-4.3-7.7-4.3-13.3 0-5 1.3-9.6 4-13.7 2.6-4.1 6.9-6.2 12.8-6.2s9.8 2.2 12.3 6.5V22.7h-8.6v-5.6h15.8v50.6h6v5.5zm-13.3-16.8V52c-.1-3-1.2-5.5-3.2-7.3s-4.4-2.8-7.2-2.8c-3.6 0-6.3 1.3-8.2 3.9-1.9 2.6-2.8 5.8-2.8 9.6 0 4.1 1 7.3 3 9.5s4.5 3.3 7.4 3.3c3.2 0 5.8-1.3 7.8-3.8 2.1-2.6 3.1-5.3 3.2-8zm61.5 16.8H269v-5.5h6V51.9c0-3.7-.7-6.3-2.2-7.9-1.4-1.6-3.4-2.3-5.7-2.3-3.1 0-5.6 1-7.4 3s-2.8 4.4-2.9 7v15.9h6v5.5h-19.3v-5.5h6V42.4h-6.2v-5.6h13.6V43c2.6-4.6 6.8-6.9 12.7-6.9 3.6 0 6.7 1.1 9.2 3.3s3.7 5.6 3.7 10.2v18.2h6v5.4h-.2z" class="logo-text"></path></svg></a><button title="Open main menu" type="button" class="button action has-icon main-menu-toggle" aria-haspopup="menu" aria-label="Open main menu" aria-expanded="false"><span class="button-wrap"><span class="icon icon-menu "></span><span class="visually-hidden">Open main menu</span></span></button></div><div class="top-navigation-main"><nav class="main-nav" aria-label="Main menu"><ul class="main-menu nojs"><li class="top-level-entry-container active"><button type="button" id="references-button" class="top-level-entry menu-toggle" aria-controls="references-menu" aria-expanded="false">References</button><a href="/en-US/docs/Web" class="top-level-entry">References</a><ul id="references-menu" class="submenu references hidden inline-submenu-lg" aria-labelledby="references-button"><li class="apis-link-container mobile-only "><a href="/en-US/docs/Web" class="submenu-item "><div class="submenu-icon"></div><div class="submenu-content-container"><div class="submenu-item-heading">Overview / Web Technology</div><p class="submenu-item-description">Web technology reference for developers</p></div></a></li><li class="html-link-container "><a href="/en-US/docs/Web/HTML" class="submenu-item "><div class="submenu-icon html"></div><div class="submenu-content-container"><div class="submenu-item-heading">HTML</div><p class="submenu-item-description">Structure of content on the web</p></div></a></li><li class="css-link-container "><a href="/en-US/docs/Web/CSS" class="submenu-item "><div class="submenu-icon css"></div><div class="submenu-content-container"><div class="submenu-item-heading">CSS</div><p class="submenu-item-description">Code used to describe document style</p></div></a></li><li class="javascript-link-container "><a href="/en-US/docs/Web/JavaScript" class="submenu-item "><div class="submenu-icon javascript"></div><div class="submenu-content-container"><div class="submenu-item-heading">JavaScript</div><p class="submenu-item-description">General-purpose scripting language</p></div></a></li><li class="http-link-container "><a href="/en-US/docs/Web/HTTP" class="submenu-item "><div class="submenu-icon http"></div><div class="submenu-content-container"><div class="submenu-item-heading">HTTP</div><p class="submenu-item-description">Protocol for transmitting web resources</p></div></a></li><li class="apis-link-container "><a href="/en-US/docs/Web/API" class="submenu-item "><div class="submenu-icon apis"></div><div class="submenu-content-container"><div class="submenu-item-heading">Web APIs</div><p class="submenu-item-description">Interfaces for building web applications</p></div></a></li><li class="apis-link-container "><a href="/en-US/docs/Mozilla/Add-ons/WebExtensions" class="submenu-item "><div class="submenu-icon"></div><div class="submenu-content-container"><div class="submenu-item-heading">Web Extensions</div><p class="submenu-item-description">Developing extensions for web browsers</p></div></a></li><li class="apis-link-container desktop-only "><a href="/en-US/docs/Web" class="submenu-item "><div class="submenu-icon"></div><div class="submenu-content-container"><div class="submenu-item-heading">Web Technology</div><p class="submenu-item-description">Web technology reference for developers</p></div></a></li></ul></li><li class="top-level-entry-container "><button type="button" id="guides-button" class="top-level-entry menu-toggle" aria-controls="guides-menu" aria-expanded="false">Guides</button><a href="/en-US/docs/Learn" class="top-level-entry">Guides</a><ul id="guides-menu" class="submenu guides hidden inline-submenu-lg" aria-labelledby="guides-button"><li class="apis-link-container mobile-only "><a href="/en-US/docs/Learn" class="submenu-item "><div class="submenu-icon learn"></div><div class="submenu-content-container"><div class="submenu-item-heading">Overview / MDN Learning Area</div><p class="submenu-item-description">Learn web development</p></div></a></li><li class="apis-link-container desktop-only "><a href="/en-US/docs/Learn" class="submenu-item "><div class="submenu-icon learn"></div><div class="submenu-content-container"><div class="submenu-item-heading">MDN Learning Area</div><p class="submenu-item-description">Learn web development</p></div></a></li><li class="html-link-container "><a href="/en-US/docs/Learn/HTML" class="submenu-item "><div class="submenu-icon html"></div><div class="submenu-content-container"><div class="submenu-item-heading">HTML</div><p class="submenu-item-description">Learn to structure web content with HTML</p></div></a></li><li class="css-link-container "><a href="/en-US/docs/Learn/CSS" class="submenu-item "><div class="submenu-icon css"></div><div class="submenu-content-container"><div class="submenu-item-heading">CSS</div><p class="submenu-item-description">Learn to style content using CSS</p></div></a></li><li class="javascript-link-container "><a href="/en-US/docs/Learn/JavaScript" class="submenu-item "><div class="submenu-icon javascript"></div><div class="submenu-content-container"><div class="submenu-item-heading">JavaScript</div><p class="submenu-item-description">Learn to run scripts in the browser</p></div></a></li><li class=" "><a href="/en-US/docs/Web/Accessibility" class="submenu-item "><div class="submenu-icon"></div><div class="submenu-content-container"><div class="submenu-item-heading">Accessibility</div><p class="submenu-item-description">Learn to make the web accessible to all</p></div></a></li></ul></li><li class="top-level-entry-container "><button type="button" id="mdn-plus-button" class="top-level-entry menu-toggle" aria-controls="mdn-plus-menu" aria-expanded="false">Plus</button><a href="/en-US/plus" class="top-level-entry">Plus</a><ul id="mdn-plus-menu" class="submenu mdn-plus hidden inline-submenu-lg" aria-labelledby="mdn-plus-button"><li class=" "><a href="/en-US/plus" class="submenu-item "><div class="submenu-icon"></div><div class="submenu-content-container"><div class="submenu-item-heading">Overview</div><p class="submenu-item-description">A customized MDN experience</p></div></a></li><li class=" "><a href="/en-US/plus/ai-help" class="submenu-item "><div class="submenu-icon"></div><div class="submenu-content-container"><div class="submenu-item-heading">AI Help</div><p class="submenu-item-description">Get real-time assistance and support</p></div></a></li><li class=" "><a href="/en-US/plus/updates" class="submenu-item "><div class="submenu-icon"></div><div class="submenu-content-container"><div class="submenu-item-heading">Updates</div><p class="submenu-item-description">All browser compatibility updates at a glance</p></div></a></li><li class=" "><a href="/en-US/plus/docs/features/overview" class="submenu-item "><div class="submenu-icon"></div><div class="submenu-content-container"><div class="submenu-item-heading">Documentation</div><p class="submenu-item-description">Learn how to use MDN Plus</p></div></a></li><li class=" "><a href="/en-US/plus/docs/faq" class="submenu-item "><div class="submenu-icon"></div><div class="submenu-content-container"><div class="submenu-item-heading">FAQ</div><p class="submenu-item-description">Frequently asked questions about MDN Plus</p></div></a></li></ul></li><li class="top-level-entry-container "><a class="top-level-entry menu-link" href="/en-US/curriculum/">Curriculum <sup class="new">New</sup></a></li><li class="top-level-entry-container "><a class="top-level-entry menu-link" href="/en-US/blog/">Blog</a></li><li class="top-level-entry-container "><button type="button" id="tools-button" class="top-level-entry menu-toggle" aria-controls="tools-menu" aria-expanded="false">Tools</button><ul id="tools-menu" class="submenu tools hidden inline-submenu-lg" aria-labelledby="tools-button"><li class=" "><a href="/en-US/play" class="submenu-item "><div class="submenu-icon"></div><div class="submenu-content-container"><div class="submenu-item-heading">Playground</div><p class="submenu-item-description">Write, test and share your code</p></div></a></li><li class=" "><a href="/en-US/observatory" class="submenu-item "><div class="submenu-icon"></div><div class="submenu-content-container"><div class="submenu-item-heading">HTTP Observatory</div><p class="submenu-item-description">Scan a website for free</p></div></a></li><li class=" "><a href="/en-US/plus/ai-help" class="submenu-item "><div class="submenu-icon"></div><div class="submenu-content-container"><div class="submenu-item-heading">AI Help</div><p class="submenu-item-description">Get real-time assistance and support</p></div></a></li></ul></li></ul></nav><div class="header-search"><form action="/en-US/search" class="search-form search-widget" id="top-nav-search-form" role="search"><label id="top-nav-search-label" for="top-nav-search-input" class="visually-hidden">Search MDN</label><input aria-activedescendant="" aria-autocomplete="list" aria-controls="top-nav-search-menu" aria-expanded="false" aria-labelledby="top-nav-search-label" autoComplete="off" id="top-nav-search-input" role="combobox" type="search" class="search-input-field" name="q" placeholder="   " required="" value=""/><button type="button" class="button action has-icon clear-search-button"><span class="button-wrap"><span class="icon icon-cancel "></span><span class="visually-hidden">Clear search input</span></span></button><button type="submit" class="button action has-icon search-button"><span class="button-wrap"><span class="icon icon-search "></span><span class="visually-hidden">Search</span></span></button><div id="top-nav-search-menu" role="listbox" aria-labelledby="top-nav-search-label"></div></form></div><div class="theme-switcher-menu"><button type="button" class="button action has-icon theme-switcher-menu small" aria-haspopup="menu"><span class="button-wrap"><span class="icon icon-theme-os-default "></span>Theme</span></button></div><ul class="auth-container"><li><a href="/users/fxa/login/authenticate/?next=%2Fen-US%2Fdocs%2FWeb%2FAPI%2FPointer_Lock_API" class="login-link" rel="nofollow">Log in</a></li><li><a href="/users/fxa/login/authenticate/?next=%2Fen-US%2Fdocs%2FWeb%2FAPI%2FPointer_Lock_API" target="_self" rel="nofollow" class="button primary mdn-plus-subscribe-link"><span class="button-wrap">Sign up for free</span></a></li></ul></div></div></header><div class="article-actions-container"><div class="container"><button type="button" class="button action has-icon sidebar-button" aria-label="Expand sidebar" aria-expanded="false" aria-controls="sidebar-quicklinks"><span class="button-wrap"><span class="icon icon-sidebar "></span></span></button><nav class="breadcrumbs-container" aria-label="Breadcrumb"><ol typeof="BreadcrumbList" vocab="https://schema.org/" aria-label="breadcrumbs"><li property="itemListElement" typeof="ListItem"><a href="/en-US/docs/Web" class="breadcrumb" property="item" typeof="WebPage"><span property="name">References</span></a><meta property="position" content="1"/></li><li property="itemListElement" typeof="ListItem"><a href="/en-US/docs/Web/API" class="breadcrumb" property="item" typeof="WebPage"><span property="name">Web APIs</span></a><meta property="position" content="2"/></li><li property="itemListElement" typeof="ListItem"><a href="/en-US/docs/Web/API/Pointer_Lock_API" class="breadcrumb-current-page" property="item" typeof="WebPage"><span property="name">Pointer Lock API</span></a><meta property="position" content="3"/></li></ol></nav><div class="article-actions"><button type="button" class="button action has-icon article-actions-toggle" aria-label="Article actions"><span class="button-wrap"><span class="icon icon-ellipses "></span><span class="article-actions-dialog-heading">Article Actions</span></span></button><ul class="article-actions-entries"><li class="article-actions-entry"><div class="languages-switcher-menu open-on-focus-within"><button id="languages-switcher-button" type="button" class="button action small has-icon languages-switcher-menu" aria-haspopup="menu"><span class="button-wrap"><span class="icon icon-language "></span>English (US)</span></button><div class="hidden"><ul class="submenu language-menu " aria-labelledby="language-menu-button"><li class=" "><form class="submenu-item locale-redirect-setting"><div class="group"><label class="switch"><input type="checkbox" name="locale-redirect"/><span class="slider"></span><span class="label">Remember language</span></label><a href="https://github.com/orgs/mdn/discussions/739" rel="external noopener noreferrer" target="_blank" title="Enable this setting to automatically switch to this language when it&#x27;s available. (Click to learn more.)"><span class="icon icon-question-mark "></span></a></div></form></li><li class=" "><a data-locale="de" href="/de/docs/Web/API/Pointer_Lock_API" class="button submenu-item"><span>Deutsch</span><span title="Diese Übersetzung ist Teil eines Experiments."><span class="icon icon-experimental "></span></span></a></li><li class=" "><a data-locale="es" href="/es/docs/Web/API/Pointer_Lock_API" class="button submenu-item"><span>Español</span></a></li><li class=" "><a data-locale="fr" href="/fr/docs/Web/API/Pointer_Lock_API" class="button submenu-item"><span>Français</span></a></li><li class=" "><a data-locale="ja" href="/ja/docs/Web/API/Pointer_Lock_API" class="button submenu-item"><span>日本語</span></a></li><li class=" "><a data-locale="ru" href="/ru/docs/Web/API/Pointer_Lock_API" class="button submenu-item"><span>Русский</span></a></li><li class=" "><a data-locale="zh-CN" href="/zh-CN/docs/Web/API/Pointer_Lock_API" class="button submenu-item"><span>中文 (简体)</span></a></li><li class=" "><a data-locale="zh-TW" href="/zh-TW/docs/Web/API/Pointer_Lock_API" class="button submenu-item"><span>正體中文 (繁體)</span></a></li></ul></div></div></li></ul></div></div></div></div><div class="main-wrapper"><div class="sidebar-container"><aside id="sidebar-quicklinks" class="sidebar" data-macro="DefaultAPISidebar"><button type="button" class="button action backdrop" aria-label="Collapse sidebar"><span class="button-wrap"></span></button><nav aria-label="Related Topics" class="sidebar-inner"><header class="sidebar-actions"><section class="sidebar-filter-container"><div class="sidebar-filter "><label id="sidebar-filter-label" class="sidebar-filter-label" for="sidebar-filter-input"><span class="icon icon-filter"></span><span class="visually-hidden">Filter sidebar</span></label><input id="sidebar-filter-input" autoComplete="off" class="sidebar-filter-input-field false" type="text" placeholder="Filter" value=""/><button type="button" class="button action has-icon clear-sidebar-filter-button"><span class="button-wrap"><span class="icon icon-cancel "></span><span class="visually-hidden">Clear filter input</span></span></button></div></section></header><div class="sidebar-inner-nav"><div class="in-nav-toc"><div class="document-toc-container"><section class="document-toc"><header><h2 class="document-toc-heading">In this article</h2></header><ul class="document-toc-list"><li class="document-toc-item "><a class="document-toc-link" href="#basic_concepts">Basic concepts</a></li><li class="document-toc-item "><a class="document-toc-link" href="#methodproperties_overview">Method/properties overview</a></li><li class="document-toc-item "><a class="document-toc-link" href="#handling_promise_and_non-promise_versions_of_requestpointerlock">Handling promise and non-promise versions of requestPointerLock()</a></li><li class="document-toc-item "><a class="document-toc-link" href="#pointerlockchange_event">pointerlockchange event</a></li><li class="document-toc-item "><a class="document-toc-link" href="#pointerlockerror_event">pointerlockerror event</a></li><li class="document-toc-item "><a class="document-toc-link" href="#extensions_to_mouse_events">Extensions to mouse events</a></li><li class="document-toc-item "><a class="document-toc-link" href="#simple_example_walkthrough">Simple example walkthrough</a></li><li class="document-toc-item "><a class="document-toc-link" href="#iframe_limitations">IFrame limitations</a></li><li class="document-toc-item "><a class="document-toc-link" href="#specifications">Specifications</a></li><li class="document-toc-item "><a class="document-toc-link" href="#browser_compatibility">Browser compatibility</a></li><li class="document-toc-item "><a class="document-toc-link" href="#see_also">See also</a></li></ul></section></div></div><div class="sidebar-body"><ol><li class="section"><em><a href="/en-US/docs/Web/API/Pointer_Lock_API" aria-current="page">Pointer Lock API</a></em></li><li class="toggle"><details open=""><summary>Properties</summary><ol><li><a href="/en-US/docs/Web/API/Document/pointerLockElement"><code>Document.pointerLockElement</code></a></li><li><a href="/en-US/docs/Web/API/MouseEvent/movementX"><code>MouseEvent.movementX</code></a></li><li><a href="/en-US/docs/Web/API/MouseEvent/movementY"><code>MouseEvent.movementY</code></a></li><li><a href="/en-US/docs/Web/API/ShadowRoot/pointerLockElement"><code>ShadowRoot.pointerLockElement</code></a></li></ol></details></li><li class="toggle"><details open=""><summary>Methods</summary><ol><li><a href="/en-US/docs/Web/API/Element/requestPointerLock"><code>Element.requestPointerLock()</code></a></li><li><a href="/en-US/docs/Web/API/Document/exitPointerLock"><code>Document.exitPointerLock()</code></a></li></ol></details></li><li class="toggle"><details open=""><summary>Events</summary><ol><li><a href="/en-US/docs/Web/API/Document/pointerlockchange_event"><code>Document</code>: <code>pointerlockchange</code></a></li><li><a href="/en-US/docs/Web/API/Document/pointerlockerror_event"><code>Document</code>: <code>pointerlockerror</code></a></li></ol></details></li></ol></div></div><section class="place side"></section></nav></aside><div class="toc-container"><aside class="toc"><nav><div class="document-toc-container"><section class="document-toc"><header><h2 class="document-toc-heading">In this article</h2></header><ul class="document-toc-list"><li class="document-toc-item "><a class="document-toc-link" href="#basic_concepts">Basic concepts</a></li><li class="document-toc-item "><a class="document-toc-link" href="#methodproperties_overview">Method/properties overview</a></li><li class="document-toc-item "><a class="document-toc-link" href="#handling_promise_and_non-promise_versions_of_requestpointerlock">Handling promise and non-promise versions of requestPointerLock()</a></li><li class="document-toc-item "><a class="document-toc-link" href="#pointerlockchange_event">pointerlockchange event</a></li><li class="document-toc-item "><a class="document-toc-link" href="#pointerlockerror_event">pointerlockerror event</a></li><li class="document-toc-item "><a class="document-toc-link" href="#extensions_to_mouse_events">Extensions to mouse events</a></li><li class="document-toc-item "><a class="document-toc-link" href="#simple_example_walkthrough">Simple example walkthrough</a></li><li class="document-toc-item "><a class="document-toc-link" href="#iframe_limitations">IFrame limitations</a></li><li class="document-toc-item "><a class="document-toc-link" href="#specifications">Specifications</a></li><li class="document-toc-item "><a class="document-toc-link" href="#browser_compatibility">Browser compatibility</a></li><li class="document-toc-item "><a class="document-toc-link" href="#see_also">See also</a></li></ul></section></div></nav></aside><section class="place side"></section></div></div><main id="content" class="main-content "><article class="main-page-content" lang="en-US"><header><h1>Pointer Lock API</h1></header><div class="section-content"><p>The <strong>Pointer Lock API</strong> (formerly called <em>Mouse Lock API</em>) provides input methods based on the movement of the mouse over time (i.e., deltas), not just the absolute position of the mouse cursor in the viewport. It gives you access to raw mouse movement, locks the target of mouse events to a single element, eliminates limits on how far mouse movement can go in a single direction, and removes the cursor from view. It is ideal for first-person 3D games, for example.</p> <p>More than that, the API is useful for any applications that require significant mouse input to control movements, rotate objects, and change entries, for example allowing users to control the viewing angle by moving the mouse around without any button clicking. The buttons are then freed up for other actions. Other examples include apps for viewing maps or satellite imagery.</p> <p>Pointer lock lets you access mouse events even when the cursor goes past the boundary of the browser or screen. For example, your users can continue to rotate or manipulate a 3D model by moving the mouse without end. Without Pointer lock, the rotation or manipulation stops the moment the pointer reaches the edge of the browser or screen. Game players can now click buttons and swipe the mouse cursor back and forth without worrying about leaving the game play area and accidentally clicking another application that would take mouse focus away from the game.</p></div><section aria-labelledby="basic_concepts"><h2 id="basic_concepts"><a href="#basic_concepts">Basic concepts</a></h2><div class="section-content"><p>Pointer lock is related to <a href="/en-US/docs/Web/API/Pointer_events#pointer_capture">pointer capture</a>. Pointer capture provides continued delivery of events to a target element while a mouse is being dragged, but it stops when the mouse button is released. Pointer lock is different from pointer capture in the following ways:</p> <ul> <li>It is persistent: Pointer lock does not release the mouse until an explicit API call is made or the user uses a specific release gesture.</li> <li>It is not limited by browser or screen boundaries.</li> <li>It continues to send events regardless of mouse button state.</li> <li>It hides the cursor.</li> </ul></div></section><section aria-labelledby="methodproperties_overview"><h2 id="methodproperties_overview"><a href="#methodproperties_overview">Method/properties overview</a></h2><div class="section-content"><p>This section provides a brief description of each property and method related to the pointer lock specification.</p></div></section><section aria-labelledby="requestpointerlock"><h3 id="requestpointerlock"><a href="#requestpointerlock">requestPointerLock()</a></h3><div class="section-content"><p>The Pointer lock API, similar to the <a href="/en-US/docs/Web/API/Fullscreen_API">Fullscreen API</a>, extends DOM elements by adding a new method, <a href="/en-US/docs/Web/API/Element/requestPointerLock" title="requestPointerLock()"><code>requestPointerLock()</code></a>. The following example requests pointer lock on a <a href="/en-US/docs/Web/HTML/Element/canvas"><code>&lt;canvas&gt;</code></a> element:</p> <div class="code-example"><div class="example-header"><span class="language-name">js</span></div><pre class="brush: js notranslate"><code>canvas.addEventListener("click", async () =&gt; { await canvas.requestPointerLock(); }); </code></pre></div> <div class="notecard note"> <p><strong>Note:</strong> If a user has exited pointer lock via the <a href="https://w3c.github.io/pointerlock/#dfn-default-unlock-gesture" class="external" target="_blank">default unlock gesture</a>, or pointer lock has not previously been entered for this document, an event generated as a result of an <a href="https://w3c.github.io/pointerlock/#dfn-engagement-gesture" class="external" target="_blank">engagement gesture</a> must be received by the document before <a href="https://w3c.github.io/pointerlock/#dom-element-requestpointerlock" class="external" target="_blank"><code>requestPointerLock</code></a> will succeed. (from <a href="https://w3c.github.io/pointerlock/#extensions-to-the-element-interface" class="external" target="_blank">https://w3c.github.io/pointerlock/#extensions-to-the-element-interface</a>)</p> </div> <p>Operating systems enable mouse acceleration by default, which is useful when you sometimes want slow precise movement (think about you might use a graphics package), but also want to move great distances with a faster mouse movement (think about scrolling, and selecting several files). For some first-person perspective games however, raw mouse input data is preferred for controlling camera rotation — where the same distance movement, fast or slow, results in the same rotation. This results in a better gaming experience and higher accuracy, according to professional gamers.</p> <p>To disable OS-level mouse acceleration and access raw mouse input, you can set the <code>unadjustedMovement</code> to <code>true</code>:</p> <div class="code-example"><div class="example-header"><span class="language-name">js</span></div><pre class="brush: js notranslate"><code>canvas.addEventListener("click", async () =&gt; { await canvas.requestPointerLock({ unadjustedMovement: true, }); }); </code></pre></div></div></section><section aria-labelledby="handling_promise_and_non-promise_versions_of_requestpointerlock"><h2 id="handling_promise_and_non-promise_versions_of_requestpointerlock"><a href="#handling_promise_and_non-promise_versions_of_requestpointerlock">Handling promise and non-promise versions of requestPointerLock()</a></h2><div class="section-content"><p>The above code snippet will still work in browsers that do not support the promise-based version of <code>requestPointerLock()</code> or the <code>unadjustedMovement</code> option — the <a href="/en-US/docs/Web/JavaScript/Reference/Operators/await"><code>await</code></a> operator is permitted in front of a function that does not return a promise, and the options object will just be ignored in non-supporting browsers.</p> <p>However, this could be confusing, and has other potential side-effects (for example, trying to use <code>requestPointerLock().then()</code> would throw an error in non-supporting browsers), so you may want to handle this explicitly using code along the following lines:</p> <div class="code-example"><div class="example-header"><span class="language-name">js</span></div><pre class="brush: js notranslate"><code>function requestPointerLockWithUnadjustedMovement() { const promise = myTargetElement.requestPointerLock({ unadjustedMovement: true, }); if (!promise) { console.log("disabling mouse acceleration is not supported"); return; } return promise .then(() =&gt; console.log("pointer is locked")) .catch((error) =&gt; { if (error.name === "NotSupportedError") { // Some platforms may not support unadjusted movement. // You can request again a regular pointer lock. return myTargetElement.requestPointerLock(); } }); } </code></pre></div></div></section><section aria-labelledby="pointerlockelement_and_exitpointerlock"><h3 id="pointerlockelement_and_exitpointerlock"><a href="#pointerlockelement_and_exitpointerlock">pointerLockElement and exitPointerLock()</a></h3><div class="section-content"><p>The Pointer lock API also extends the <a href="/en-US/docs/Web/API/Document"><code>Document</code></a> interface, adding a new property and a new method:</p> <ul> <li><a href="/en-US/docs/Web/API/Document/pointerLockElement" title="pointerLockElement"><code>pointerLockElement</code></a> is used for accessing the currently locked element (if any).</li> <li><a href="/en-US/docs/Web/API/Document/exitPointerLock" title="exitPointerLock()"><code>exitPointerLock()</code></a> is used to exit the pointer lock.</li> </ul> <p>The <a href="/en-US/docs/Web/API/Document/pointerLockElement" title="pointerLockElement"><code>pointerLockElement</code></a> property is useful for determining if any element is currently pointer locked (e.g., for doing a boolean check) and also for obtaining a reference to the locked element, if any.</p> <p>Here is an example of using <code>pointerLockElement</code>:</p> <div class="code-example"><div class="example-header"><span class="language-name">js</span></div><pre class="brush: js notranslate"><code>if (document.pointerLockElement === canvas) { console.log("The pointer lock status is now locked"); } else { console.log("The pointer lock status is now unlocked"); } </code></pre></div> <p>The <a href="/en-US/docs/Web/API/Document/exitPointerLock"><code>Document.exitPointerLock()</code></a> method is used to exit pointer lock, and like <a href="/en-US/docs/Web/API/Element/requestPointerLock" title="requestPointerLock"><code>requestPointerLock</code></a>, works asynchronously using the <a href="/en-US/docs/Web/API/Document/pointerlockchange_event" title="pointerlockchange"><code>pointerlockchange</code></a> and <a href="/en-US/docs/Web/API/Document/pointerlockerror_event" title="pointerlockerror"><code>pointerlockerror</code></a> events, which you'll see more about below.</p> <div class="code-example"><div class="example-header"><span class="language-name">js</span></div><pre class="brush: js notranslate"><code>document.exitPointerLock(); </code></pre></div></div></section><section aria-labelledby="pointerlockchange_event"><h2 id="pointerlockchange_event"><a href="#pointerlockchange_event">pointerlockchange event</a></h2><div class="section-content"><p>When the Pointer lock state changes—for example, when calling <a href="/en-US/docs/Web/API/Element/requestPointerLock" title="requestPointerLock()"><code>requestPointerLock()</code></a> or <a href="/en-US/docs/Web/API/Document/exitPointerLock" title="exitPointerLock()"><code>exitPointerLock()</code></a>, the user pressing the ESC key, etc.—the <a href="/en-US/docs/Web/API/Document/pointerlockchange_event" title="pointerlockchange"><code>pointerlockchange</code></a> event is dispatched to the <code>document</code>. This is a simple event containing no extra data.</p> <div class="code-example"><div class="example-header"><span class="language-name">js</span></div><pre class="brush: js notranslate"><code>document.addEventListener("pointerlockchange", lockChangeAlert, false); function lockChangeAlert() { if (document.pointerLockElement === canvas) { console.log("The pointer lock status is now locked"); // Do something useful in response } else { console.log("The pointer lock status is now unlocked"); // Do something useful in response } } </code></pre></div></div></section><section aria-labelledby="pointerlockerror_event"><h2 id="pointerlockerror_event"><a href="#pointerlockerror_event">pointerlockerror event</a></h2><div class="section-content"><p>When there is an error caused by calling <a href="/en-US/docs/Web/API/Element/requestPointerLock" title="requestPointerLock()"><code>requestPointerLock()</code></a> or <a href="/en-US/docs/Web/API/Document/exitPointerLock" title="exitPointerLock()"><code>exitPointerLock()</code></a>, the <a href="/en-US/docs/Web/API/Document/pointerlockerror_event" title="pointerlockerror"><code>pointerlockerror</code></a> event is dispatched to the <code>document</code>. This is a simple event containing no extra data.</p> <div class="code-example"><div class="example-header"><span class="language-name">js</span></div><pre class="brush: js notranslate"><code>document.addEventListener("pointerlockerror", lockError, false); function lockError(e) { alert("Pointer lock failed"); } </code></pre></div></div></section><section aria-labelledby="extensions_to_mouse_events"><h2 id="extensions_to_mouse_events"><a href="#extensions_to_mouse_events">Extensions to mouse events</a></h2><div class="section-content"><p>The Pointer lock API extends the normal <a href="/en-US/docs/Web/API/MouseEvent"><code>MouseEvent</code></a> interface with movement attributes. Two new attributes to mouse events—<a href="/en-US/docs/Web/API/MouseEvent/movementX" title="movementX"><code>movementX</code></a> and <a href="/en-US/docs/Web/API/MouseEvent/movementY" title="movementY"><code>movementY</code></a>—provide the change in mouse positions. The values of the parameters are the same as the difference between the values of <a href="/en-US/docs/Web/API/MouseEvent"><code>MouseEvent</code></a> properties, <a href="/en-US/docs/Web/API/MouseEvent/screenX" title="screenX"><code>screenX</code></a> and <a href="/en-US/docs/Web/API/MouseEvent/screenY" title="screenY"><code>screenY</code></a>, which are stored in two subsequent <a href="/en-US/docs/Web/API/Element/mousemove_event" title="mousemove"><code>mousemove</code></a> events, <code>eNow</code> and <code>ePrevious</code>. In other words, the Pointer lock parameter <code>movementX = eNow.screenX - ePrevious.screenX</code>.</p></div></section><section aria-labelledby="locked_state"><h3 id="locked_state"><a href="#locked_state">Locked state</a></h3><div class="section-content"><p>When Pointer lock is enabled, the standard <a href="/en-US/docs/Web/API/MouseEvent"><code>MouseEvent</code></a> properties <a href="/en-US/docs/Web/API/MouseEvent/clientX" title="clientX"><code>clientX</code></a>, <a href="/en-US/docs/Web/API/MouseEvent/clientY" title="clientY"><code>clientY</code></a>, <a href="/en-US/docs/Web/API/MouseEvent/screenX" title="screenX"><code>screenX</code></a>, and <a href="/en-US/docs/Web/API/MouseEvent/screenY" title="screenY"><code>screenY</code></a> are held constant, as if the mouse is not moving. The <a href="/en-US/docs/Web/API/MouseEvent/movementX" title="movementX"><code>movementX</code></a> and <a href="/en-US/docs/Web/API/MouseEvent/movementY" title="movementY"><code>movementY</code></a> properties continue to provide the mouse's change in position. There is no limit to <a href="/en-US/docs/Web/API/MouseEvent/movementX" title="movementX"><code>movementX</code></a> and <a href="/en-US/docs/Web/API/MouseEvent/movementY" title="movementY"><code>movementY</code></a> values if the mouse is continuously moving in a single direction. The concept of the mouse cursor does not exist and the cursor cannot move off the window or be clamped by a screen edge.</p></div></section><section aria-labelledby="unlocked_state"><h3 id="unlocked_state"><a href="#unlocked_state">Unlocked state</a></h3><div class="section-content"><p>The parameters <a href="/en-US/docs/Web/API/MouseEvent/movementX" title="movementX"><code>movementX</code></a> and <a href="/en-US/docs/Web/API/MouseEvent/movementY" title="movementY"><code>movementY</code></a> are valid regardless of the mouse lock state, and are available even when unlocked for convenience.</p> <p>When the mouse is unlocked, the system cursor can exit and re-enter the browser window. If that happens, <a href="/en-US/docs/Web/API/MouseEvent/movementX" title="movementX"><code>movementX</code></a> and <a href="/en-US/docs/Web/API/MouseEvent/movementY" title="movementY"><code>movementY</code></a> could be set to zero.</p></div></section><section aria-labelledby="simple_example_walkthrough"><h2 id="simple_example_walkthrough"><a href="#simple_example_walkthrough">Simple example walkthrough</a></h2><div class="section-content"><p>We've written a <a href="https://mdn.github.io/dom-examples/pointer-lock/" class="external" target="_blank">pointer lock demo</a> (<a href="https://github.com/mdn/dom-examples/tree/main/pointer-lock" class="external" target="_blank">see source code</a>) to show you how to use it to set up a simple control system. This demo uses JavaScript to draw a ball on top of an <a href="/en-US/docs/Web/HTML/Element/canvas"><code>&lt;canvas&gt;</code></a> element. When you click the canvas, pointer lock is then used to remove the mouse pointer and allow you to move the ball directly using the mouse. Let's see how this works.</p> <p>We set initial x and y positions on the canvas:</p> <div class="code-example"><div class="example-header"><span class="language-name">js</span></div><pre class="brush: js notranslate"><code>let x = 50; let y = 50; </code></pre></div> <p>Next we set up an event listener to run the <code>requestPointerLock()</code> method on the canvas when it is clicked, which initiates pointer lock. The <code>document.pointerLockElement</code> check is to see if there is already an active pointer lock — we don't want to keep calling <code>requestPointerLock()</code> on the canvas every time we click inside it if we already have pointer lock.</p> <div class="code-example"><div class="example-header"><span class="language-name">js</span></div><pre class="brush: js notranslate"><code>canvas.addEventListener("click", async () =&gt; { if (!document.pointerLockElement) { await canvas.requestPointerLock({ unadjustedMovement: true, }); } }); </code></pre></div> <div class="notecard note"> <p><strong>Note:</strong> The above snippet works in browsers that don't support the promise version of <code>requestPointerLock()</code>. See <a href="#handling_promise_and_non-promise_versions_of_requestpointerlock">Handling promise and non-promise versions of requestPointerLock()</a> for an explanation.</p> </div> <p>Now for the dedicated pointer lock event listener: <code>pointerlockchange</code>. When this occurs, we run a function called <code>lockChangeAlert()</code> to handle the change.</p> <div class="code-example"><div class="example-header"><span class="language-name">js</span></div><pre class="brush: js notranslate"><code>document.addEventListener("pointerlockchange", lockChangeAlert, false); </code></pre></div> <p>This function checks the <code>pointerLockElement</code> property to see if it is our canvas. If so, it attached an event listener to handle the mouse movements with the <code>updatePosition()</code> function. If not, it removes the event listener again.</p> <div class="code-example"><div class="example-header"><span class="language-name">js</span></div><pre class="brush: js notranslate"><code>function lockChangeAlert() { if (document.pointerLockElement === canvas) { console.log("The pointer lock status is now locked"); document.addEventListener("mousemove", updatePosition, false); } else { console.log("The pointer lock status is now unlocked"); document.removeEventListener("mousemove", updatePosition, false); } } </code></pre></div> <p>The <code>updatePosition()</code> function updates the position of the ball on the canvas (<code>x</code> and <code>y</code>), and also includes <code>if ()</code> statements to check whether the ball has gone off the edges of the canvas. If so, it makes the ball wrap around to the opposite edge. It also includes a check whether a <a href="/en-US/docs/Web/API/Window/requestAnimationFrame"><code>requestAnimationFrame()</code></a> call has previously been made, and if so, calls it again as required, and calls the <code>canvasDraw()</code> function that updates the canvas scene. A tracker is also set up to write out the X and Y values to the screen, for reference.</p> <div class="code-example"><div class="example-header"><span class="language-name">js</span></div><pre class="brush: js notranslate"><code>const tracker = document.getElementById("tracker"); let animation; function updatePosition(e) { x += e.movementX; y += e.movementY; if (x &gt; canvas.width + RADIUS) { x = -RADIUS; } if (y &gt; canvas.height + RADIUS) { y = -RADIUS; } if (x &lt; -RADIUS) { x = canvas.width + RADIUS; } if (y &lt; -RADIUS) { y = canvas.height + RADIUS; } tracker.textContent = `X position: ${x}, Y position: ${y}`; if (!animation) { animation = requestAnimationFrame(() =&gt; { animation = null; canvasDraw(); }); } } </code></pre></div> <p>The <code>canvasDraw()</code> function draws the ball in the current <code>x</code> and <code>y</code> positions:</p> <div class="code-example"><div class="example-header"><span class="language-name">js</span></div><pre class="brush: js notranslate"><code>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(); } </code></pre></div></div></section><section aria-labelledby="iframe_limitations"><h2 id="iframe_limitations"><a href="#iframe_limitations">IFrame limitations</a></h2><div class="section-content"><p>Pointer lock can only lock one <a href="/en-US/docs/Web/HTML/Element/iframe"><code>&lt;iframe&gt;</code></a> at a time. If you lock one <code>&lt;iframe&gt;</code>, you can't lock another one and transfer the target to it; pointer lock will error out. To avoid this limitation, first unlock the locked <code>&lt;iframe&gt;</code>, and then lock the other.</p> <p>While <code>&lt;iframe&gt;</code> work by default, "sandboxed" <code>&lt;iframe&gt;</code>s block Pointer lock. To avoid this limitation, use <code>&lt;iframe sandbox="allow-pointer-lock"&gt;</code>.</p></div></section><h2 id="specifications"><a href="#specifications">Specifications</a></h2><table class="standard-table"><thead><tr><th scope="col">Specification</th></tr></thead><tbody><tr><td><a href="https://w3c.github.io/pointerlock/">Pointer Lock 2.0<!-- --> <br/></a></td></tr></tbody></table><section aria-labelledby="browser_compatibility"><h2 id="browser_compatibility"><a href="#browser_compatibility">Browser compatibility</a></h2><div class="section-content"></div></section><h3 id="api.document.exitpointerlock"><a href="#api.document.exitpointerlock">api.Document.exitPointerLock</a></h3><p>BCD tables only load in the browser<noscript> <!-- -->with JavaScript enabled. Enable JavaScript to view data.</noscript></p><h3 id="api.element.requestpointerlock"><a href="#api.element.requestpointerlock">api.Element.requestPointerLock</a></h3><p>BCD tables only load in the browser<noscript> <!-- -->with JavaScript enabled. Enable JavaScript to view data.</noscript></p><section aria-labelledby="see_also"><h2 id="see_also"><a href="#see_also">See also</a></h2><div class="section-content"><ul> <li><a href="/en-US/docs/Web/API/MouseEvent"><code>MouseEvent</code></a></li> <li><a href="/en-US/docs/Web/API/Element/requestPointerLock"><code>Element.requestPointerLock()</code></a></li> </ul></div></section></article><aside class="article-footer"><div class="article-footer-inner"><div class="svg-container"><svg xmlns="http://www.w3.org/2000/svg" width="162" height="162" viewBox="0 0 162 162" fill="none" role="none"><mask id="b" fill="#fff"><path d="M97.203 47.04c8.113-7.886 18.004-13.871 28.906-17.492a78 78 0 0 1 33.969-3.39c11.443 1.39 22.401 5.295 32.024 11.411s17.656 14.28 23.476 23.86c5.819 9.579 9.269 20.318 10.083 31.385a69.85 69.85 0 0 1-5.387 32.44c-4.358 10.272-11.115 19.443-19.747 26.801-8.632 7.359-18.908 12.709-30.034 15.637l-6.17-21.698c7.666-2.017 14.746-5.703 20.694-10.773 5.948-5.071 10.603-11.389 13.606-18.467a48.14 48.14 0 0 0 3.712-22.352c-.561-7.625-2.938-15.025-6.948-21.625s-9.544-12.226-16.175-16.44-14.181-6.904-22.065-7.863a53.75 53.75 0 0 0-23.405 2.336c-7.513 2.495-14.327 6.62-19.918 12.053z"></path></mask><path stroke="url(#a)" stroke-dasharray="6, 6" stroke-width="2" d="M97.203 47.04c8.113-7.886 18.004-13.871 28.906-17.492a78 78 0 0 1 33.969-3.39c11.443 1.39 22.401 5.295 32.024 11.411s17.656 14.28 23.476 23.86c5.819 9.579 9.269 20.318 10.083 31.385a69.85 69.85 0 0 1-5.387 32.44c-4.358 10.272-11.115 19.443-19.747 26.801-8.632 7.359-18.908 12.709-30.034 15.637l-6.17-21.698c7.666-2.017 14.746-5.703 20.694-10.773 5.948-5.071 10.603-11.389 13.606-18.467a48.14 48.14 0 0 0 3.712-22.352c-.561-7.625-2.938-15.025-6.948-21.625s-9.544-12.226-16.175-16.44-14.181-6.904-22.065-7.863a53.75 53.75 0 0 0-23.405 2.336c-7.513 2.495-14.327 6.62-19.918 12.053z" mask="url(#b)" style="stroke:url(#a)" transform="translate(-63.992 -25.587)"></path><ellipse cx="8.066" cy="111.597" fill="var(--background-tertiary)" rx="53.677" ry="53.699" transform="matrix(.71707 -.697 .7243 .6895 0 0)"></ellipse><g clip-path="url(#c)" transform="translate(-63.992 -25.587)"><path fill="#9abff5" d="m144.256 137.379 32.906 12.434a4.41 4.41 0 0 1 2.559 5.667l-9.326 24.679a4.41 4.41 0 0 1-5.667 2.559l-8.226-3.108-2.332 6.17c-.466 1.233-.375 1.883-1.609 1.417l-2.253-.527c-.411-.155-.95-.594-1.206-1.161l-4.734-10.484-12.545-4.741a4.41 4.41 0 0 1-2.559-5.667l9.325-24.679a4.41 4.41 0 0 1 5.667-2.559m9.961 29.617 8.227 3.108 3.264-8.638-.498-6.768-4.113-1.555.548 7.258-4.319-1.632zm-12.339-4.663 8.226 3.108 3.264-8.637-.498-6.769-4.113-1.554.548 7.257-4.319-1.632z"></path></g><g clip-path="url(#d)" transform="translate(-63.992 -25.587)"><path fill="#81b0f3" d="M135.35 60.136 86.67 41.654c-3.346-1.27-7.124.428-8.394 3.775L64.414 81.938c-1.27 3.347.428 7.125 3.774 8.395l12.17 4.62-3.465 9.128c-.693 1.826-1.432 2.457.394 3.15l3.014 1.625c.609.231 1.637.274 2.477-.104l15.53-6.983 18.56 7.047c3.346 1.27 7.124-.428 8.395-3.775l13.862-36.51c1.27-3.346-.428-7.124-3.775-8.395M95.261 83.207l-12.17-4.62 4.852-12.779 7.19-7.017 6.085 2.31-7.725 7.51 6.389 2.426zm18.255 6.93-12.17-4.62 4.852-12.778 7.189-7.017 6.085 2.31-7.725 7.51 6.39 2.426z"></path></g><defs><clipPath id="c"><path fill="#fff" d="m198.638 146.586-65.056-24.583-24.583 65.057 65.056 24.582z"></path></clipPath><clipPath id="d"><path fill="#fff" d="m66.438 14.055 96.242 36.54-36.54 96.243-96.243-36.54z"></path></clipPath><linearGradient id="a" x1="97.203" x2="199.995" y1="47.04" y2="152.793" gradientUnits="userSpaceOnUse"><stop stop-color="#086DFC"></stop><stop offset="0.246" stop-color="#2C81FA"></stop><stop offset="0.516" stop-color="#5497F8"></stop><stop offset="0.821" stop-color="#80B0F6"></stop><stop offset="1" stop-color="#9ABFF5"></stop></linearGradient></defs></svg></div><h2>Help improve MDN</h2><fieldset class="feedback"><label>Was this page helpful to you?</label><div class="button-container"><button type="button" class="button primary has-icon yes"><span class="button-wrap"><span class="icon icon-thumbs-up "></span>Yes</span></button><button type="button" class="button primary has-icon no"><span class="button-wrap"><span class="icon icon-thumbs-down "></span>No</span></button></div></fieldset><a class="contribute" href="https://github.com/mdn/content/blob/main/CONTRIBUTING.md" title="This will take you to our contribution guidelines on GitHub." target="_blank" rel="noopener noreferrer">Learn how to contribute</a>.<p class="last-modified-date">This page was last modified on<!-- --> <time dateTime="2024-07-26T03:45:33.000Z">Jul 26, 2024</time> by<!-- --> <a href="/en-US/docs/Web/API/Pointer_Lock_API/contributors.txt" rel="nofollow">MDN contributors</a>.</p><div id="on-github" class="on-github"><a href="https://github.com/mdn/content/blob/main/files/en-us/web/api/pointer_lock_api/index.md?plain=1" title="Folder: en-us/web/api/pointer_lock_api (Opens in a new tab)" target="_blank" rel="noopener noreferrer">View this page on GitHub</a> <!-- -->•<!-- --> <a href="https://github.com/mdn/content/issues/new?template=page-report.yml&amp;mdn-url=https%3A%2F%2Fdeveloper.mozilla.org%2Fen-US%2Fdocs%2FWeb%2FAPI%2FPointer_Lock_API&amp;metadata=%3C%21--+Do+not+make+changes+below+this+line+--%3E%0A%3Cdetails%3E%0A%3Csummary%3EPage+report+details%3C%2Fsummary%3E%0A%0A*+Folder%3A+%60en-us%2Fweb%2Fapi%2Fpointer_lock_api%60%0A*+MDN+URL%3A+https%3A%2F%2Fdeveloper.mozilla.org%2Fen-US%2Fdocs%2FWeb%2FAPI%2FPointer_Lock_API%0A*+GitHub+URL%3A+https%3A%2F%2Fgithub.com%2Fmdn%2Fcontent%2Fblob%2Fmain%2Ffiles%2Fen-us%2Fweb%2Fapi%2Fpointer_lock_api%2Findex.md%0A*+Last+commit%3A+https%3A%2F%2Fgithub.com%2Fmdn%2Fcontent%2Fcommit%2F802b6063046dffb7634d2138aadcd92cb22ed40c%0A*+Document+last+modified%3A+2024-07-26T03%3A45%3A33.000Z%0A%0A%3C%2Fdetails%3E" title="This will take you to GitHub to file a new issue." target="_blank" rel="noopener noreferrer">Report a problem with this content</a></div></div></aside></main></div></div><footer id="nav-footer" class="page-footer"><div class="page-footer-grid"><div class="page-footer-logo-col"><a href="/" class="mdn-footer-logo" aria-label="MDN homepage"><svg width="48" height="17" viewBox="0 0 48 17" fill="none" xmlns="http://www.w3.org/2000/svg"><title id="mdn-footer-logo-svg">MDN logo</title><path d="M20.04 16.512H15.504V10.416C15.504 9.488 15.344 8.824 15.024 8.424C14.72 8.024 14.264 7.824 13.656 7.824C12.92 7.824 12.384 8.064 12.048 8.544C11.728 9.024 11.568 9.64 11.568 10.392V14.184H13.008V16.512H8.472V10.416C8.472 9.488 8.312 8.824 7.992 8.424C7.688 8.024 7.232 7.824 6.624 7.824C5.872 7.824 5.336 8.064 5.016 8.544C4.696 9.024 4.536 9.64 4.536 10.392V14.184H6.6V16.512H0V14.184H1.44V8.04H0.024V5.688H4.536V7.32C5.224 6.088 6.32 5.472 7.824 5.472C8.608 5.472 9.328 5.664 9.984 6.048C10.64 6.432 11.096 7.016 11.352 7.8C11.992 6.248 13.168 5.472 14.88 5.472C15.856 5.472 16.72 5.776 17.472 6.384C18.224 6.992 18.6 7.936 18.6 9.216V14.184H20.04V16.512Z" fill="currentColor"></path><path d="M33.6714 16.512H29.1354V14.496C28.8314 15.12 28.3834 15.656 27.7914 16.104C27.1994 16.536 26.4154 16.752 25.4394 16.752C24.0154 16.752 22.8954 16.264 22.0794 15.288C21.2634 14.312 20.8554 12.984 20.8554 11.304C20.8554 9.688 21.2554 8.312 22.0554 7.176C22.8554 6.04 24.0634 5.472 25.6794 5.472C26.5594 5.472 27.2794 5.648 27.8394 6C28.3994 6.352 28.8314 6.8 29.1354 7.344V2.352H26.9754V0H32.2314V14.184H33.6714V16.512ZM29.1354 11.04V10.776C29.1354 9.88 28.8954 9.184 28.4154 8.688C27.9514 8.176 27.3674 7.92 26.6634 7.92C25.9754 7.92 25.3674 8.176 24.8394 8.688C24.3274 9.2 24.0714 10.008 24.0714 11.112C24.0714 12.152 24.3114 12.944 24.7914 13.488C25.2714 14.032 25.8394 14.304 26.4954 14.304C27.3114 14.304 27.9514 13.96 28.4154 13.272C28.8954 12.584 29.1354 11.84 29.1354 11.04Z" fill="currentColor"></path><path d="M47.9589 16.512H41.9829V14.184H43.4229V10.416C43.4229 9.488 43.2629 8.824 42.9429 8.424C42.6389 8.024 42.1829 7.824 41.5749 7.824C40.8389 7.824 40.2709 8.056 39.8709 8.52C39.4709 8.968 39.2629 9.56 39.2469 10.296V14.184H40.6869V16.512H34.7109V14.184H36.1509V8.04H34.5909V5.688H39.2469V7.344C39.9669 6.096 41.1269 5.472 42.7269 5.472C43.7509 5.472 44.6389 5.776 45.3909 6.384C46.1429 6.992 46.5189 7.936 46.5189 9.216V14.184H47.9589V16.512Z" fill="currentColor"></path></svg></a><p>Your blueprint for a better internet.</p><ul class="social-icons"><li><a href="https://mozilla.social/@mdn" target="_blank" rel="me noopener noreferrer"><span class="icon icon-mastodon"></span><span class="visually-hidden">MDN on Mastodon</span></a></li><li><a href="https://twitter.com/mozdevnet" target="_blank" rel="noopener noreferrer"><span class="icon icon-twitter-x"></span><span class="visually-hidden">MDN on X (formerly Twitter)</span></a></li><li><a href="https://github.com/mdn/" target="_blank" rel="noopener noreferrer"><span class="icon icon-github-mark-small"></span><span class="visually-hidden">MDN on GitHub</span></a></li><li><a href="/en-US/blog/rss.xml" target="_blank"><span class="icon icon-feed"></span><span class="visually-hidden">MDN Blog RSS Feed</span></a></li></ul></div><div class="page-footer-nav-col-1"><h2 class="footer-nav-heading">MDN</h2><ul class="footer-nav-list"><li class="footer-nav-item"><a href="/en-US/about">About</a></li><li class="footer-nav-item"><a href="/en-US/blog/">Blog</a></li><li class="footer-nav-item"><a href="https://www.mozilla.org/en-US/careers/listings/?team=ProdOps" target="_blank" rel="noopener noreferrer">Careers</a></li><li class="footer-nav-item"><a href="/en-US/advertising">Advertise with us</a></li></ul></div><div class="page-footer-nav-col-2"><h2 class="footer-nav-heading">Support</h2><ul class="footer-nav-list"><li class="footer-nav-item"><a class="footer-nav-link" href="https://support.mozilla.org/products/mdn-plus">Product help</a></li><li class="footer-nav-item"><a class="footer-nav-link" href="/en-US/docs/MDN/Community/Issues">Report an issue</a></li></ul></div><div class="page-footer-nav-col-3"><h2 class="footer-nav-heading">Our communities</h2><ul class="footer-nav-list"><li class="footer-nav-item"><a class="footer-nav-link" href="/en-US/community">MDN Community</a></li><li class="footer-nav-item"><a class="footer-nav-link" href="https://discourse.mozilla.org/c/mdn/236" target="_blank" rel="noopener noreferrer">MDN Forum</a></li><li class="footer-nav-item"><a class="footer-nav-link" href="/discord" target="_blank" rel="noopener noreferrer">MDN Chat</a></li></ul></div><div class="page-footer-nav-col-4"><h2 class="footer-nav-heading">Developers</h2><ul class="footer-nav-list"><li class="footer-nav-item"><a class="footer-nav-link" href="/en-US/docs/Web">Web Technologies</a></li><li class="footer-nav-item"><a class="footer-nav-link" href="/en-US/docs/Learn">Learn Web Development</a></li><li class="footer-nav-item"><a class="footer-nav-link" href="/en-US/plus">MDN Plus</a></li><li class="footer-nav-item"><a href="https://hacks.mozilla.org/" target="_blank" rel="noopener noreferrer">Hacks Blog</a></li></ul></div><div class="page-footer-moz"><a href="https://www.mozilla.org/" class="footer-moz-logo-link" target="_blank" rel="noopener noreferrer"><svg width="112" height="32" fill="none" xmlns="http://www.w3.org/2000/svg"><title id="mozilla-footer-logo-svg">Mozilla logo</title><path d="M41.753 14.218c-2.048 0-3.324 1.522-3.324 4.157 0 2.423 1.119 4.286 3.29 4.286 2.082 0 3.447-1.678 3.447-4.347 0-2.826-1.522-4.096-3.413-4.096Zm54.89 7.044c0 .901.437 1.618 1.645 1.618 1.427 0 2.949-1.024 3.044-3.352-.649-.095-1.365-.185-2.02-.185-1.426-.005-2.668.397-2.668 1.92Z" fill="currentColor"></path><path d="M0 0v32h111.908V0H0Zm32.56 25.426h-5.87v-7.884c0-2.423-.806-3.352-2.39-3.352-1.924 0-2.702 1.365-2.702 3.324v4.868h1.864v3.044h-5.864v-7.884c0-2.423-.806-3.352-2.39-3.352-1.924 0-2.702 1.365-2.702 3.324v4.868h2.669v3.044H6.642v-3.044h1.863v-7.918H6.642V11.42h5.864v2.11c.839-1.489 2.3-2.39 4.252-2.39 2.02 0 3.878.963 4.566 3.01.778-1.862 2.361-3.01 4.566-3.01 2.512 0 4.812 1.522 4.812 4.84v6.402h1.863v3.044h-.005Zm9.036.307c-4.314 0-7.296-2.635-7.296-7.106 0-4.096 2.484-7.481 7.514-7.481s7.481 3.38 7.481 7.29c0 4.472-3.228 7.297-7.699 7.297Zm22.578-.307H51.942l-.403-2.11 7.7-8.846h-4.376l-.621 2.17-2.888-.313.498-4.907h12.294l.313 2.11-7.767 8.852h4.533l.654-2.172 3.167.308-.872 4.908Zm7.99 0h-4.191v-5.03h4.19v5.03Zm0-8.976h-4.191v-5.03h4.19v5.03Zm2.618 8.976 6.054-21.358h3.945l-6.054 21.358h-3.945Zm8.136 0 6.048-21.358h3.945l-6.054 21.358h-3.939Zm21.486.307c-1.863 0-2.887-1.085-3.072-2.792-.805 1.427-2.232 2.792-4.498 2.792-2.02 0-4.314-1.085-4.314-4.006 0-3.447 3.323-4.253 6.518-4.253.778 0 1.584.034 2.3.124v-.465c0-1.427-.034-3.133-2.3-3.133-.84 0-1.488.061-2.143.402l-.453 1.578-3.195-.34.549-3.224c2.45-.996 3.692-1.27 5.992-1.27 3.01 0 5.556 1.55 5.556 4.75v6.083c0 .805.314 1.085.963 1.085.184 0 .375-.034.587-.095l.034 2.11a5.432 5.432 0 0 1-2.524.654Z" fill="currentColor"></path></svg></a><ul class="footer-moz-list"><li class="footer-moz-item"><a href="https://www.mozilla.org/privacy/websites/" class="footer-moz-link" target="_blank" rel="noopener noreferrer">Website Privacy Notice</a></li><li class="footer-moz-item"><a href="https://www.mozilla.org/privacy/websites/#cookies" class="footer-moz-link" target="_blank" rel="noopener noreferrer">Cookies</a></li><li class="footer-moz-item"><a href="https://www.mozilla.org/about/legal/terms/mozilla" class="footer-moz-link" target="_blank" rel="noopener noreferrer">Legal</a></li><li class="footer-moz-item"><a href="https://www.mozilla.org/about/governance/policies/participation/" class="footer-moz-link" target="_blank" rel="noopener noreferrer">Community Participation Guidelines</a></li></ul></div><div class="page-footer-legal"><p id="license" class="page-footer-legal-text">Visit<!-- --> <a href="https://www.mozilla.org" target="_blank" rel="noopener noreferrer">Mozilla Corporation’s</a> <!-- -->not-for-profit parent, the<!-- --> <a target="_blank" rel="noopener noreferrer" href="https://foundation.mozilla.org/">Mozilla Foundation</a>.<br/>Portions of this content are ©1998–<!-- -->2024<!-- --> by individual mozilla.org contributors. Content available under<!-- --> <a href="/en-US/docs/MDN/Writing_guidelines/Attrib_copyright_license">a Creative Commons license</a>.</p></div></div></footer></div><script type="application/json" id="hydration">{"url":"/en-US/docs/Web/API/Pointer_Lock_API","doc":{"isMarkdown":true,"isTranslated":false,"isActive":true,"flaws":{},"title":"Pointer Lock API","mdn_url":"/en-US/docs/Web/API/Pointer_Lock_API","locale":"en-US","native":"English (US)","browserCompat":["api.Document.exitPointerLock","api.Element.requestPointerLock"],"sidebarHTML":"<ol><li class=\"section\"><em><a href=\"/en-US/docs/Web/API/Pointer_Lock_API\" aria-current=\"page\">Pointer Lock API</a></em></li><li class=\"toggle\"><details open=\"\"><summary>Properties</summary><ol><li><a href=\"/en-US/docs/Web/API/Document/pointerLockElement\"><code>Document.pointerLockElement</code></a></li><li><a href=\"/en-US/docs/Web/API/MouseEvent/movementX\"><code>MouseEvent.movementX</code></a></li><li><a href=\"/en-US/docs/Web/API/MouseEvent/movementY\"><code>MouseEvent.movementY</code></a></li><li><a href=\"/en-US/docs/Web/API/ShadowRoot/pointerLockElement\"><code>ShadowRoot.pointerLockElement</code></a></li></ol></details></li><li class=\"toggle\"><details open=\"\"><summary>Methods</summary><ol><li><a href=\"/en-US/docs/Web/API/Element/requestPointerLock\"><code>Element.requestPointerLock()</code></a></li><li><a href=\"/en-US/docs/Web/API/Document/exitPointerLock\"><code>Document.exitPointerLock()</code></a></li></ol></details></li><li class=\"toggle\"><details open=\"\"><summary>Events</summary><ol><li><a href=\"/en-US/docs/Web/API/Document/pointerlockchange_event\"><code>Document</code>: <code>pointerlockchange</code></a></li><li><a href=\"/en-US/docs/Web/API/Document/pointerlockerror_event\"><code>Document</code>: <code>pointerlockerror</code></a></li></ol></details></li></ol>","sidebarMacro":"DefaultAPISidebar","body":[{"type":"prose","value":{"id":null,"title":null,"isH3":false,"content":"<p>The <strong>Pointer Lock API</strong> (formerly called <em>Mouse Lock API</em>) provides input methods based on the movement of the mouse over time (i.e., deltas), not just the absolute position of the mouse cursor in the viewport. It gives you access to raw mouse movement, locks the target of mouse events to a single element, eliminates limits on how far mouse movement can go in a single direction, and removes the cursor from view. It is ideal for first-person 3D games, for example.</p>\n<p>More than that, the API is useful for any applications that require significant mouse input to control movements, rotate objects, and change entries, for example allowing users to control the viewing angle by moving the mouse around without any button clicking. The buttons are then freed up for other actions. Other examples include apps for viewing maps or satellite imagery.</p>\n<p>Pointer lock lets you access mouse events even when the cursor goes past the boundary of the browser or screen. For example, your users can continue to rotate or manipulate a 3D model by moving the mouse without end. Without Pointer lock, the rotation or manipulation stops the moment the pointer reaches the edge of the browser or screen. Game players can now click buttons and swipe the mouse cursor back and forth without worrying about leaving the game play area and accidentally clicking another application that would take mouse focus away from the game.</p>"}},{"type":"prose","value":{"id":"basic_concepts","title":"Basic concepts","isH3":false,"content":"<p>Pointer lock is related to <a href=\"/en-US/docs/Web/API/Pointer_events#pointer_capture\">pointer capture</a>. Pointer capture provides continued delivery of events to a target element while a mouse is being dragged, but it stops when the mouse button is released. Pointer lock is different from pointer capture in the following ways:</p>\n<ul>\n <li>It is persistent: Pointer lock does not release the mouse until an explicit API call is made or the user uses a specific release gesture.</li>\n <li>It is not limited by browser or screen boundaries.</li>\n <li>It continues to send events regardless of mouse button state.</li>\n <li>It hides the cursor.</li>\n</ul>"}},{"type":"prose","value":{"id":"methodproperties_overview","title":"Method/properties overview","isH3":false,"content":"<p>This section provides a brief description of each property and method related to the pointer lock specification.</p>"}},{"type":"prose","value":{"id":"requestpointerlock","title":"requestPointerLock()","isH3":true,"content":"<p>The Pointer lock API, similar to the <a href=\"/en-US/docs/Web/API/Fullscreen_API\">Fullscreen API</a>, extends DOM elements by adding a new method, <a href=\"/en-US/docs/Web/API/Element/requestPointerLock\" title=\"requestPointerLock()\"><code>requestPointerLock()</code></a>. The following example requests pointer lock on a <a href=\"/en-US/docs/Web/HTML/Element/canvas\"><code>&lt;canvas&gt;</code></a> element:</p>\n<div class=\"code-example\"><div class=\"example-header\"><span class=\"language-name\">js</span></div><pre class=\"brush: js notranslate\"><code>canvas.addEventListener(\"click\", async () =&gt; {\n await canvas.requestPointerLock();\n});\n</code></pre></div>\n<div class=\"notecard note\">\n <p><strong>Note:</strong> If a user has exited pointer lock via the <a href=\"https://w3c.github.io/pointerlock/#dfn-default-unlock-gesture\" class=\"external\" target=\"_blank\">default unlock gesture</a>, or pointer lock has not previously been entered for this document, an event generated as a result of an <a href=\"https://w3c.github.io/pointerlock/#dfn-engagement-gesture\" class=\"external\" target=\"_blank\">engagement gesture</a> must be received by the document before <a href=\"https://w3c.github.io/pointerlock/#dom-element-requestpointerlock\" class=\"external\" target=\"_blank\"><code>requestPointerLock</code></a> will succeed. (from <a href=\"https://w3c.github.io/pointerlock/#extensions-to-the-element-interface\" class=\"external\" target=\"_blank\">https://w3c.github.io/pointerlock/#extensions-to-the-element-interface</a>)</p>\n</div>\n<p>Operating systems enable mouse acceleration by default, which is useful when you sometimes want slow precise movement (think about you might use a graphics package), but also want to move great distances with a faster mouse movement (think about scrolling, and selecting several files). For some first-person perspective games however, raw mouse input data is preferred for controlling camera rotation — where the same distance movement, fast or slow, results in the same rotation. This results in a better gaming experience and higher accuracy, according to professional gamers.</p>\n<p>To disable OS-level mouse acceleration and access raw mouse input, you can set the <code>unadjustedMovement</code> to <code>true</code>:</p>\n<div class=\"code-example\"><div class=\"example-header\"><span class=\"language-name\">js</span></div><pre class=\"brush: js notranslate\"><code>canvas.addEventListener(\"click\", async () =&gt; {\n await canvas.requestPointerLock({\n unadjustedMovement: true,\n });\n});\n</code></pre></div>"}},{"type":"prose","value":{"id":"handling_promise_and_non-promise_versions_of_requestpointerlock","title":"Handling promise and non-promise versions of requestPointerLock()","isH3":false,"content":"<p>The above code snippet will still work in browsers that do not support the promise-based version of <code>requestPointerLock()</code> or the <code>unadjustedMovement</code> option — the <a href=\"/en-US/docs/Web/JavaScript/Reference/Operators/await\"><code>await</code></a> operator is permitted in front of a function that does not return a promise, and the options object will just be ignored in non-supporting browsers.</p>\n<p>However, this could be confusing, and has other potential side-effects (for example, trying to use <code>requestPointerLock().then()</code> would throw an error in non-supporting browsers), so you may want to handle this explicitly using code along the following lines:</p>\n<div class=\"code-example\"><div class=\"example-header\"><span class=\"language-name\">js</span></div><pre class=\"brush: js notranslate\"><code>function requestPointerLockWithUnadjustedMovement() {\n const promise = myTargetElement.requestPointerLock({\n unadjustedMovement: true,\n });\n\n if (!promise) {\n console.log(\"disabling mouse acceleration is not supported\");\n return;\n }\n\n return promise\n .then(() =&gt; console.log(\"pointer is locked\"))\n .catch((error) =&gt; {\n if (error.name === \"NotSupportedError\") {\n // Some platforms may not support unadjusted movement.\n // You can request again a regular pointer lock.\n return myTargetElement.requestPointerLock();\n }\n });\n}\n</code></pre></div>"}},{"type":"prose","value":{"id":"pointerlockelement_and_exitpointerlock","title":"pointerLockElement and exitPointerLock()","isH3":true,"content":"<p>The Pointer lock API also extends the <a href=\"/en-US/docs/Web/API/Document\"><code>Document</code></a> interface, adding a new property and a new method:</p>\n<ul>\n <li><a href=\"/en-US/docs/Web/API/Document/pointerLockElement\" title=\"pointerLockElement\"><code>pointerLockElement</code></a> is used for accessing the currently locked element (if any).</li>\n <li><a href=\"/en-US/docs/Web/API/Document/exitPointerLock\" title=\"exitPointerLock()\"><code>exitPointerLock()</code></a> is used to exit the pointer lock.</li>\n</ul>\n<p>The <a href=\"/en-US/docs/Web/API/Document/pointerLockElement\" title=\"pointerLockElement\"><code>pointerLockElement</code></a> property is useful for determining if any element is currently pointer locked (e.g., for doing a boolean check) and also for obtaining a reference to the locked element, if any.</p>\n<p>Here is an example of using <code>pointerLockElement</code>:</p>\n<div class=\"code-example\"><div class=\"example-header\"><span class=\"language-name\">js</span></div><pre class=\"brush: js notranslate\"><code>if (document.pointerLockElement === canvas) {\n console.log(\"The pointer lock status is now locked\");\n} else {\n console.log(\"The pointer lock status is now unlocked\");\n}\n</code></pre></div>\n<p>The <a href=\"/en-US/docs/Web/API/Document/exitPointerLock\"><code>Document.exitPointerLock()</code></a> method is used to exit pointer lock, and like <a href=\"/en-US/docs/Web/API/Element/requestPointerLock\" title=\"requestPointerLock\"><code>requestPointerLock</code></a>, works asynchronously using the <a href=\"/en-US/docs/Web/API/Document/pointerlockchange_event\" title=\"pointerlockchange\"><code>pointerlockchange</code></a> and <a href=\"/en-US/docs/Web/API/Document/pointerlockerror_event\" title=\"pointerlockerror\"><code>pointerlockerror</code></a> events, which you'll see more about below.</p>\n<div class=\"code-example\"><div class=\"example-header\"><span class=\"language-name\">js</span></div><pre class=\"brush: js notranslate\"><code>document.exitPointerLock();\n</code></pre></div>"}},{"type":"prose","value":{"id":"pointerlockchange_event","title":"pointerlockchange event","isH3":false,"content":"<p>When the Pointer lock state changes—for example, when calling <a href=\"/en-US/docs/Web/API/Element/requestPointerLock\" title=\"requestPointerLock()\"><code>requestPointerLock()</code></a> or <a href=\"/en-US/docs/Web/API/Document/exitPointerLock\" title=\"exitPointerLock()\"><code>exitPointerLock()</code></a>, the user pressing the ESC key, etc.—the <a href=\"/en-US/docs/Web/API/Document/pointerlockchange_event\" title=\"pointerlockchange\"><code>pointerlockchange</code></a> event is dispatched to the <code>document</code>. This is a simple event containing no extra data.</p>\n<div class=\"code-example\"><div class=\"example-header\"><span class=\"language-name\">js</span></div><pre class=\"brush: js notranslate\"><code>document.addEventListener(\"pointerlockchange\", lockChangeAlert, false);\n\nfunction lockChangeAlert() {\n if (document.pointerLockElement === canvas) {\n console.log(\"The pointer lock status is now locked\");\n // Do something useful in response\n } else {\n console.log(\"The pointer lock status is now unlocked\");\n // Do something useful in response\n }\n}\n</code></pre></div>"}},{"type":"prose","value":{"id":"pointerlockerror_event","title":"pointerlockerror event","isH3":false,"content":"<p>When there is an error caused by calling <a href=\"/en-US/docs/Web/API/Element/requestPointerLock\" title=\"requestPointerLock()\"><code>requestPointerLock()</code></a> or <a href=\"/en-US/docs/Web/API/Document/exitPointerLock\" title=\"exitPointerLock()\"><code>exitPointerLock()</code></a>, the <a href=\"/en-US/docs/Web/API/Document/pointerlockerror_event\" title=\"pointerlockerror\"><code>pointerlockerror</code></a> event is dispatched to the <code>document</code>. This is a simple event containing no extra data.</p>\n<div class=\"code-example\"><div class=\"example-header\"><span class=\"language-name\">js</span></div><pre class=\"brush: js notranslate\"><code>document.addEventListener(\"pointerlockerror\", lockError, false);\n\nfunction lockError(e) {\n alert(\"Pointer lock failed\");\n}\n</code></pre></div>"}},{"type":"prose","value":{"id":"extensions_to_mouse_events","title":"Extensions to mouse events","isH3":false,"content":"<p>The Pointer lock API extends the normal <a href=\"/en-US/docs/Web/API/MouseEvent\"><code>MouseEvent</code></a> interface with movement attributes. Two new attributes to mouse events—<a href=\"/en-US/docs/Web/API/MouseEvent/movementX\" title=\"movementX\"><code>movementX</code></a> and <a href=\"/en-US/docs/Web/API/MouseEvent/movementY\" title=\"movementY\"><code>movementY</code></a>—provide the change in mouse positions. The values of the parameters are the same as the difference between the values of <a href=\"/en-US/docs/Web/API/MouseEvent\"><code>MouseEvent</code></a> properties, <a href=\"/en-US/docs/Web/API/MouseEvent/screenX\" title=\"screenX\"><code>screenX</code></a> and <a href=\"/en-US/docs/Web/API/MouseEvent/screenY\" title=\"screenY\"><code>screenY</code></a>, which are stored in two subsequent <a href=\"/en-US/docs/Web/API/Element/mousemove_event\" title=\"mousemove\"><code>mousemove</code></a> events, <code>eNow</code> and <code>ePrevious</code>. In other words, the Pointer lock parameter <code>movementX = eNow.screenX - ePrevious.screenX</code>.</p>"}},{"type":"prose","value":{"id":"locked_state","title":"Locked state","isH3":true,"content":"<p>When Pointer lock is enabled, the standard <a href=\"/en-US/docs/Web/API/MouseEvent\"><code>MouseEvent</code></a> properties <a href=\"/en-US/docs/Web/API/MouseEvent/clientX\" title=\"clientX\"><code>clientX</code></a>, <a href=\"/en-US/docs/Web/API/MouseEvent/clientY\" title=\"clientY\"><code>clientY</code></a>, <a href=\"/en-US/docs/Web/API/MouseEvent/screenX\" title=\"screenX\"><code>screenX</code></a>, and <a href=\"/en-US/docs/Web/API/MouseEvent/screenY\" title=\"screenY\"><code>screenY</code></a> are held constant, as if the mouse is not moving. The <a href=\"/en-US/docs/Web/API/MouseEvent/movementX\" title=\"movementX\"><code>movementX</code></a> and <a href=\"/en-US/docs/Web/API/MouseEvent/movementY\" title=\"movementY\"><code>movementY</code></a> properties continue to provide the mouse's change in position. There is no limit to <a href=\"/en-US/docs/Web/API/MouseEvent/movementX\" title=\"movementX\"><code>movementX</code></a> and <a href=\"/en-US/docs/Web/API/MouseEvent/movementY\" title=\"movementY\"><code>movementY</code></a> values if the mouse is continuously moving in a single direction. The concept of the mouse cursor does not exist and the cursor cannot move off the window or be clamped by a screen edge.</p>"}},{"type":"prose","value":{"id":"unlocked_state","title":"Unlocked state","isH3":true,"content":"<p>The parameters <a href=\"/en-US/docs/Web/API/MouseEvent/movementX\" title=\"movementX\"><code>movementX</code></a> and <a href=\"/en-US/docs/Web/API/MouseEvent/movementY\" title=\"movementY\"><code>movementY</code></a> are valid regardless of the mouse lock state, and are available even when unlocked for convenience.</p>\n<p>When the mouse is unlocked, the system cursor can exit and re-enter the browser window. If that happens, <a href=\"/en-US/docs/Web/API/MouseEvent/movementX\" title=\"movementX\"><code>movementX</code></a> and <a href=\"/en-US/docs/Web/API/MouseEvent/movementY\" title=\"movementY\"><code>movementY</code></a> could be set to zero.</p>"}},{"type":"prose","value":{"id":"simple_example_walkthrough","title":"Simple example walkthrough","isH3":false,"content":"<p>We've written a <a href=\"https://mdn.github.io/dom-examples/pointer-lock/\" class=\"external\" target=\"_blank\">pointer lock demo</a> (<a href=\"https://github.com/mdn/dom-examples/tree/main/pointer-lock\" class=\"external\" target=\"_blank\">see source code</a>) to show you how to use it to set up a simple control system. This demo uses JavaScript to draw a ball on top of an <a href=\"/en-US/docs/Web/HTML/Element/canvas\"><code>&lt;canvas&gt;</code></a> element. When you click the canvas, pointer lock is then used to remove the mouse pointer and allow you to move the ball directly using the mouse. Let's see how this works.</p>\n<p>We set initial x and y positions on the canvas:</p>\n<div class=\"code-example\"><div class=\"example-header\"><span class=\"language-name\">js</span></div><pre class=\"brush: js notranslate\"><code>let x = 50;\nlet y = 50;\n</code></pre></div>\n<p>Next we set up an event listener to run the <code>requestPointerLock()</code> method on the canvas when it is clicked, which initiates pointer lock. The <code>document.pointerLockElement</code> check is to see if there is already an active pointer lock — we don't want to keep calling <code>requestPointerLock()</code> on the canvas every time we click inside it if we already have pointer lock.</p>\n<div class=\"code-example\"><div class=\"example-header\"><span class=\"language-name\">js</span></div><pre class=\"brush: js notranslate\"><code>canvas.addEventListener(\"click\", async () =&gt; {\n if (!document.pointerLockElement) {\n await canvas.requestPointerLock({\n unadjustedMovement: true,\n });\n }\n});\n</code></pre></div>\n<div class=\"notecard note\">\n <p><strong>Note:</strong> The above snippet works in browsers that don't support the promise version of <code>requestPointerLock()</code>. See <a href=\"#handling_promise_and_non-promise_versions_of_requestpointerlock\">Handling promise and non-promise versions of requestPointerLock()</a> for an explanation.</p>\n</div>\n<p>Now for the dedicated pointer lock event listener: <code>pointerlockchange</code>. When this occurs, we run a function called <code>lockChangeAlert()</code> to handle the change.</p>\n<div class=\"code-example\"><div class=\"example-header\"><span class=\"language-name\">js</span></div><pre class=\"brush: js notranslate\"><code>document.addEventListener(\"pointerlockchange\", lockChangeAlert, false);\n</code></pre></div>\n<p>This function checks the <code>pointerLockElement</code> property to see if it is our canvas. If so, it attached an event listener to handle the mouse movements with the <code>updatePosition()</code> function. If not, it removes the event listener again.</p>\n<div class=\"code-example\"><div class=\"example-header\"><span class=\"language-name\">js</span></div><pre class=\"brush: js notranslate\"><code>function lockChangeAlert() {\n if (document.pointerLockElement === canvas) {\n console.log(\"The pointer lock status is now locked\");\n document.addEventListener(\"mousemove\", updatePosition, false);\n } else {\n console.log(\"The pointer lock status is now unlocked\");\n document.removeEventListener(\"mousemove\", updatePosition, false);\n }\n}\n</code></pre></div>\n<p>The <code>updatePosition()</code> function updates the position of the ball on the canvas (<code>x</code> and <code>y</code>), and also includes <code>if ()</code> statements to check whether the ball has gone off the edges of the canvas. If so, it makes the ball wrap around to the opposite edge. It also includes a check whether a <a href=\"/en-US/docs/Web/API/Window/requestAnimationFrame\"><code>requestAnimationFrame()</code></a> call has previously been made, and if so, calls it again as required, and calls the <code>canvasDraw()</code> function that updates the canvas scene. A tracker is also set up to write out the X and Y values to the screen, for reference.</p>\n<div class=\"code-example\"><div class=\"example-header\"><span class=\"language-name\">js</span></div><pre class=\"brush: js notranslate\"><code>const tracker = document.getElementById(\"tracker\");\n\nlet animation;\nfunction updatePosition(e) {\n x += e.movementX;\n y += e.movementY;\n if (x &gt; canvas.width + RADIUS) {\n x = -RADIUS;\n }\n if (y &gt; canvas.height + RADIUS) {\n y = -RADIUS;\n }\n if (x &lt; -RADIUS) {\n x = canvas.width + RADIUS;\n }\n if (y &lt; -RADIUS) {\n y = canvas.height + RADIUS;\n }\n tracker.textContent = `X position: ${x}, Y position: ${y}`;\n\n if (!animation) {\n animation = requestAnimationFrame(() =&gt; {\n animation = null;\n canvasDraw();\n });\n }\n}\n</code></pre></div>\n<p>The <code>canvasDraw()</code> function draws the ball in the current <code>x</code> and <code>y</code> positions:</p>\n<div class=\"code-example\"><div class=\"example-header\"><span class=\"language-name\">js</span></div><pre class=\"brush: js notranslate\"><code>function canvasDraw() {\n ctx.fillStyle = \"black\";\n ctx.fillRect(0, 0, canvas.width, canvas.height);\n ctx.fillStyle = \"#f00\";\n ctx.beginPath();\n ctx.arc(x, y, RADIUS, 0, degToRad(360), true);\n ctx.fill();\n}\n</code></pre></div>"}},{"type":"prose","value":{"id":"iframe_limitations","title":"IFrame limitations","isH3":false,"content":"<p>Pointer lock can only lock one <a href=\"/en-US/docs/Web/HTML/Element/iframe\"><code>&lt;iframe&gt;</code></a> at a time. If you lock one <code>&lt;iframe&gt;</code>, you can't lock another one and transfer the target to it; pointer lock will error out. To avoid this limitation, first unlock the locked <code>&lt;iframe&gt;</code>, and then lock the other.</p>\n<p>While <code>&lt;iframe&gt;</code> work by default, \"sandboxed\" <code>&lt;iframe&gt;</code>s block Pointer lock. To avoid this limitation, use <code>&lt;iframe sandbox=\"allow-pointer-lock\"&gt;</code>.</p>"}},{"type":"specifications","value":{"title":"Specifications","id":"specifications","isH3":false,"specifications":[{"bcdSpecificationURL":"https://w3c.github.io/pointerlock/","title":"Pointer Lock 2.0"}],"query":"api.Document.exitPointerLock,api.Element.requestPointerLock"}},{"type":"prose","value":{"id":"browser_compatibility","title":"Browser compatibility","isH3":false,"content":""}},{"type":"browser_compatibility","value":{"title":"api.Document.exitPointerLock","id":"api.Document.exitPointerLock","isH3":true,"query":"api.Document.exitPointerLock"}},{"type":"browser_compatibility","value":{"title":"api.Element.requestPointerLock","id":"api.Element.requestPointerLock","isH3":true,"query":"api.Element.requestPointerLock"}},{"type":"prose","value":{"id":"see_also","title":"See also","isH3":false,"content":"<ul>\n <li><a href=\"/en-US/docs/Web/API/MouseEvent\"><code>MouseEvent</code></a></li>\n <li><a href=\"/en-US/docs/Web/API/Element/requestPointerLock\"><code>Element.requestPointerLock()</code></a></li>\n</ul>"}}],"toc":[{"text":"Basic concepts","id":"basic_concepts"},{"text":"Method/properties overview","id":"methodproperties_overview"},{"text":"Handling promise and non-promise versions of requestPointerLock()","id":"handling_promise_and_non-promise_versions_of_requestpointerlock"},{"text":"pointerlockchange event","id":"pointerlockchange_event"},{"text":"pointerlockerror event","id":"pointerlockerror_event"},{"text":"Extensions to mouse events","id":"extensions_to_mouse_events"},{"text":"Simple example walkthrough","id":"simple_example_walkthrough"},{"text":"IFrame limitations","id":"iframe_limitations"},{"text":"Specifications","id":"specifications"},{"text":"Browser compatibility","id":"browser_compatibility"},{"text":"See also","id":"see_also"}],"summary":"The Pointer Lock API (formerly called Mouse Lock API) provides input methods based on the movement of the mouse over time (i.e., deltas), not just the absolute position of the mouse cursor in the viewport. It gives you access to raw mouse movement, locks the target of mouse events to a single element, eliminates limits on how far mouse movement can go in a single direction, and removes the cursor from view. It is ideal for first-person 3D games, for example.","popularity":0.0098,"modified":"2024-07-26T03:45:33.000Z","other_translations":[{"locale":"de","title":"Pointer Lock API","native":"Deutsch"},{"locale":"es","title":"API Pointer Lock","native":"Español"},{"locale":"fr","title":"Pointer Lock API","native":"Français"},{"locale":"ja","title":"ポインターロック API","native":"日本語"},{"locale":"ru","title":"Pointer Lock API","native":"Русский"},{"locale":"zh-CN","title":"指针锁定 API","native":"中文 (简体)"},{"locale":"zh-TW","title":"Pointer Lock API","native":"正體中文 (繁體)"}],"pageType":"web-api-overview","source":{"folder":"en-us/web/api/pointer_lock_api","github_url":"https://github.com/mdn/content/blob/main/files/en-us/web/api/pointer_lock_api/index.md","last_commit_url":"https://github.com/mdn/content/commit/802b6063046dffb7634d2138aadcd92cb22ed40c","filename":"index.md"},"short_title":"Pointer Lock API","parents":[{"uri":"/en-US/docs/Web","title":"References"},{"uri":"/en-US/docs/Web/API","title":"Web APIs"},{"uri":"/en-US/docs/Web/API/Pointer_Lock_API","title":"Pointer Lock API"}],"pageTitle":"Pointer Lock API - Web APIs | MDN","noIndexing":false}}</script></body></html>

Pages: 1 2 3 4 5 6 7 8 9 10