What is the best way to prevent an element from reaching the border of the screen?

As a JavaScript beginner, I am working on creating a simple game. My objective is to prevent the player (20px x 20px) box from causing the screen to scroll. I want a fixed screen where the player cannot go beyond the edges of the screen. Below are my previous attempts.


HTML :

<!DOCTYPE html>
<html lang="en" dir="ltr">
  <head>
    <meta charset="utf-8">
    <title></title>
    <link rel="stylesheet" href="Style.css">
  </head>
  <body>
    <div id="player"></div>
  <script type="text/javascript" src="Script.js"></script>
  </body>
</html>

CSS:

body{
  margin: 0;
  padding: 0;
  background-color: red;
}
#player{
  border-radius: 30%;
  padding: 0px;
  margin: 0px;
  background-color: white;
  width: 20px;
  height: 20px;
  position: absolute;
}

JavaScript:

var player = document.getElementById("player")
var pros = {'top': 0, 'left': 0, 'speed': 10}
var ws = {'h': screen.height, 'w': screen.width}
document.addEventListener("keydown", function(event){
  var keyP = event.key;
  if(keyP === "ArrowDown"){
    pros.top = pros.top + pros.speed;
  }else if(keyP === "ArrowUp"){
    pros.top = pros.top - pros.speed;
  }else if(keyP === "ArrowLeft"){
    pros.left = pros.left - pros.speed;
  }else if(keyP === "ArrowRight"){
    pros.left = pros.left + pros.speed;
  }
  if(pros.top < 0){
    pros.top = 0;
  }else if(pros.top > ws.h){
    pros.top = ws.h;
  }else if(pros.left < 0){
    pros.left = 0;
  }else if(pros.left > ws.w){
    pros.left = ws.w;
  }
  player.style.top = `${pros.top}px`;
  player.style.left = `${pros.left}px`;
});

My goal now is to ensure that the element never leaves the designated screen area. Despite using screen.height/screen.width in the code to control it, the element still escapes the area and activates scroll bars even in full-screen mode. This ruins the gaming experience.
Here is a picture demonstrating how it escapes the area:

In Full Screen Mode : https://i.sstatic.net/RekWI.png

Without Full Screen Mode : https://i.sstatic.net/FwufI.png

Answer №1

To achieve the most precise position and dimension measurements, utilize the getBoundingClientRect() function.

In your keystroke callback function, include the following two lines at the beginning:

var screenRect = document.body.getBoundingClientRect();
var playerRect = player.getBoundingClientRect();

It is crucial to recalculate these values at each iteration to ensure that the game adjusts properly to any changes in screen size. Additionally, it is recommended to calculate position increments as percentages of the screen size rather than fixed pixel values.

Your screen edge check can be improved with the following code:

if(playerRect.top < 0){
    pros.top = 0;
} else if(playerRect.top + playerRect.height > screenRect.height){
    // Ensure player bottom doesn't extend beyond screen bottom
    pros.top = screenRect.height - playerRect.height;
}

if(playerRect.left < 0){
    pros.left = 0;
} else if(playerRect.left + playerRect.width + > screenRect.width){
    // Ensure player right edge stays within screen's right edge
    pros.left = screenRect.width - playerRect.width;
}

For CSS styling adjustments, consider the following:

body{
  margin: 0;
  padding: 0;
  background-color: red;
  width: 100vw;
  height: 100vh;
  overflow: hidden;
}
#player{
  border-radius: 30%;
  padding: 0px;
  margin: 0px;
  background-color: white;
  width: 20px;
  height: 20px;
  position: fixed;
} 

Answer №2

Based on the Stylesheet you provided, it appears that the height and width of your PLAYER object are set to 20px.

When placing your element on a 2D plane, its coordinates will be determined by where its TOP-LEFT corner is located. Keep this in mind.

To ensure proper positioning, update your JavaScript code as follows:

  ...
  if(pros.top < 0){
    pros.top = 0;
  }else if(pros.top > ws.h-20){ // adjustment made here
    pros.top = ws.h-20; // feel free to experiment with this value
  }else if(pros.left < 0){ 
    pros.left = 0;
  }else if(pros.left > ws.w-20){ // adjustment made here
    pros.left = ws.w-20; // feel free to experiment with this value
  }
  ...

With these changes, the #player element will always maintain a distance of 20px from the edges both horizontally and vertically. I managed to eliminate the horizontal scroll-bar by adjusting the vertical placement to ws.h-40.

https://i.sstatic.net/Cp09I.png

I hope this information proves useful for you.

Answer №3

Hello there! Here is a suggestion that could be useful for you:

<style type="text/css>
body {
    overflow: hidden;
}
</style>

By adding overflow: hidden to the CSS, you can effectively hide the scrollbar on your webpage.

Similar questions

If you have not found the answer to your question or you are interested in this topic, then look at other similar questions below or use the search

Tips for extracting the two characters following a space in a string with or without the use of regex

How can I extract only the initials of 2 characters after spaces? See the code snippet below: const name = "John Peter Don"; const result = name.match(/\b(\w)/g).join(''); console.log(result)// JPD->> i want only JP ...

Embed the website onto a webpage using ajax or an iframe without any need for navigation

I have a unique challenge ahead. Imagine there are two websites, one is a web page and the other is hosted within the same domain. My goal is to load the entire second website into a div or iframe of the first web page, similar to how a free proxy browser ...

Consecutive pair of JavaScript date picker functions

My issue involves setting up a java script calendar date picker. Here are my input fields and related java scripts: <input type="text" class="text date" maxlength="12" name="customerServiceAccountForm:fromDateInput" id="customerServiceAccountForm:from ...

When using Vimeo's JS API, the player.loadVideo() method will revert the player's settings back to their default options

Using Vimeo's player.js API, I'm setting options on the player to disable the title upon initialization: var options = { id: 59777392, title: false }; var vimPlayer = new Vimeo.Player('myDiv', options); The video player correc ...

Puppet Master: Retrieve the inner content

Is there a way to retrieve the innerHTML or text of an element? Or even better, how can I click on an element with a specific innerHTML? The approach in regular JavaScript would be as follows: let found = false; $(selector).each(function() { if (found ...

The parseFloat function only considers numbers before the decimal point and disregards

I need my function to properly format a number or string into a decimal number with X amount of digits after the decimal point. The issue I'm facing is that when I pass 3.0004 to my function, it returns 3. After reviewing the documentation, I realized ...

Creating a client-server application in JavaScript with the npm-net module

In my possession is a straightforward piece of code titled echo_server.js. It serves as a server that simply echoes back any text received from the connected client. var net=require('net'); var server=net.createServer(function (socket) { socke ...

Encountering a Typescript TypeError in es2022 that is not present in es2021

I'm attempting to switch the target property in the tsconfig.json file from es2015 to es2022, but I am encountering an error while running tests that seem to only use tsc without babel: Chrome Headless 110.0.5481.177 (Mac OS 10.15.7) TypeError: Can ...

What is the inner workings behind server side rendering in Next.js?

I am seeking clarification on Server Side Rendering, specifically with Next.js. During server side rendering, I want to confirm the 'execution path' as follows: Client makes a request to the server for the webpage, which serves up an HTML only ...

What is the best way to deliver data from the main Vue instance to components that are being utilized by vue-router?

Currently, I am utilizing vue-router within a single HTML file instead of using separate file components. I am encountering an issue where I am unsure how to pass the data stored in the Vue data object to the component when loading it for a route. Oddly e ...

Is it possible to adjust text wrapping based on the size of the screen?

I am currently facing an issue with my modal form where the text does not wrap properly depending on the size of the modal form. I need help with correcting this using CSS. My current approach involves using angular with new lines and hardcoding line brea ...

Challenges with HTML and CSS drop-down menus

My navigation is giving me a headache. I've been trying to add a dropdown menu, but nothing seems to be working. Here's my current HTML/CSS code. If you have any suggestions on how to fix it, please lend a hand! I've also included a picture ...

How can I keep dragging objects on Raphael JS Freetransform without showing the handles?

Hey there! Currently, I am immersed in a new project that hinges on the utilization of Raphael JS alongside the Raphael.Freetransform plugin. The plugin has been performing admirably with smooth transitions so far. Nonetheless, upon utilizing the hideHandl ...

What methods can I employ to utilize the name attribute for POST requests instead of the ID attribute in TinyMCE?

My inline TinyMCE form sends content to qry.php with the key "edit_me". I prefer the default behavior of sending content using the name attribute instead. <script type="text/javascript"> tinymce.init({ selector: '#edit_me', ...

Tips for enabling multiple v-list-group components to remain open simultaneously (bypassing the default Vue behavior)

Currently, I am facing an issue with Vue's default behavior where only one v-list-group can be open at a time. I am using Vuetify 2.6 and have attempted to use the multiple prop without success. Additionally, individually assigning the :value prop to ...

Resolving DataTables Error

Here is my JavaScript code snippet. <link rel="stylesheet" type="text/css" href="https://cdn.datatables.net/1.10.12/css/jquery.dataTables.min.css"> <link rel="stylesheet" type="text/css" href="https://cdn.datatables.net/buttons/1.2.1/css/but ...

The parameter of type 'never' cannot be assigned with the argument of type 'number | boolean | undefined'

In my project, I am creating a validation input using TypeScript in Next.js. interface InputRules { required?: boolean min?: number max?: number minLength?: number maxLength?: number } I have defined an object that contains methods to handle val ...

Steps to avoid HTML encoding the ' character in Next.js _document.js file

Currently, I am working on integrating VWO into my website by following the steps mentioned here. I have included the VWO script tag within a NextJs Head tag as shown below: <Head> <script type='text/javascript' id='vwoC ...

Switching the background color of alternating divs in reverse order: a step-by-step guide

I am looking to alternate the background color of divs between odd and even, with the last div being grey and the second to last div being green. I have tried using the odd/even classes in CSS, but it did not work as expected. .main{ width:500px; height ...

"Modify marker icon upon click event in Google Maps by utilizing the loadGeoJson function

I have successfully loaded the markers from a json file using loadGeoJson. While I am able to SET the marker icon/img on load, I am unsure of how to CHANGE it upon click. Is there a way to target the clicked marker and perform a setIcon or similar action ...