'why is my clientwidth/100 different than my width by percent?
I have a small program that when you press down on ArrowDown, the circle should move downwards from its position on screen. The issue I have is that my initial positioning for my svg circle object set by cx: 5% and cy:5% are different than my 5 * xshift and 5 * yshift which are derived from document.getElementById("test").clientWidth/100 and document.getElementById("test").clientHeight/100 which I would believe to be a good conversion to percentage. However when the program is run, the initial ArrowDown corrects the initial placement and creates a noticable shifted difference.
var goal = {x: window.innerWidth, y: window.innerHeight}
var xshift = document.getElementById("test").clientWidth/100
var yshift = document.getElementById("test").clientHeight/100
var player= {type:"Player", x:5 * xshift, y: 5 * yshift}
document.addEventListener('keydown', function(event) {
if (event.key === 'ArrowDown'){
player.y += yshift;
if(player.y > (100 * yshift) -(9 * yshift)){
player.y = 91 * yshift;
}
//document.getElementById("UI").innerHTML = "Player position is x: " +player.x + " y: " + player.y;
document.getElementById('circe').setAttribute("transform", 'translate('+player.x+","+player.y+")");
}
}, true);
<!DOCTYPE html>
<html lang="en" dir="ltr">
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1">
<title>Basic Snake Game</title>
<style>
html, body {
margin: 0;
padding: 0;
border: 0;
height: 100%
}
svg {
position: absolute;
margin: 0;
padding: 0;
border: 0;
background-color: blueviolet;
}
</style>
</head>
<body>
<!-- <h1 id="UI">Player position is x: 0 y: 0</h1> -->
<svg id="test" width="100%" height="100%">
<circle id="circe" cx="5%" cy="5%" r="5%" stroke="green" stroke-width="0%" fill="yellow" transform="translate(0,0)" />
</svg>
<script src="test.js"></script>
</body>
</html>
Solution 1:[1]
You can check complete code from: this fiddle, I combined your pieces of code and added a single line.
`
var goal = {x: window.innerWidth, y: window.innerHeight}
var xshift = document.getElementById("test").clientWidth/100
var yshift = document.getElementById("test").clientHeight/100
var player= {type:"Player", x:5 * xshift, y: 5 * yshift}
document.addEventListener('keydown', function(event) {
if (event.key === 'ArrowDown'){
doShift();
}
}, true);
function doShift(){
player.y += yshift;
if(player.y > (100 * yshift) -(9 * yshift)){
player.y = 91 * yshift;
}
//document.getElementById("UI").innerHTML = "Player position is x: " +player.x + " y: " + player.y;
document.getElementById('circe').setAttribute("transform", 'translate('+player.x+","+player.y+")");
}
//document.addEventListener("onready", ()=> doShift());
//document.ondomcontentready=doShift;
doShift();
`;
Although it looks like a hack, the final doShift();
call creates the same effect as when you first press the down button - you specify what you want.
Solution 2:[2]
They are different because you are using a transform. The transform is being applied on top of (in addition to) the cx
and cy
coordinates.
In other words, the circle is being positioned at:
x = cx + translate.x = 5% + 5%
y = cy + (n * translate.y) = 5% + (n * 5%)
One way to fix this is to forget the transform
attribute and just update the cx
and cy
attributes instead. Eg.
document.getElementById('circe').setAttribute("cy", player.y);
Demo
var goal = {x: window.innerWidth, y: window.innerHeight}
var xshift = document.getElementById("test").clientWidth/100
var yshift = document.getElementById("test").clientHeight/100
var player= {type:"Player", x:5 * xshift, y: 5 * yshift}
document.addEventListener('keydown', function(event) {
if (event.key === 'ArrowDown'){
player.y += yshift;
if(player.y > (100 * yshift) -(9 * yshift)){
player.y = 91 * yshift;
}
//document.getElementById("UI").innerHTML = "Player position is x: " +player.x + " y: " + player.y;
document.getElementById('circe').setAttribute("cy", player.y);
}
}, true);
html, body {
margin: 0;
padding: 0;
border: 0;
height: 100%;
}
svg {
position: absolute;
margin: 0;
padding: 0;
border: 0;
background-color: blueviolet;
}
<!-- <h1 id="UI">Player position is x: 0 y: 0</h1> -->
<svg id="test" width="100%" height="100%">
<circle id="circe" cx="5%" cy="5%" r="5%" stroke="green" stroke-width="0%" fill="yellow" transform="translate(0,0)" />
</svg>
Sources
This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.
Source: Stack Overflow
Solution | Source |
---|---|
Solution 1 | |
Solution 2 | Paul LeBeau |