conflicting value for pageY on Ipad - javascript

I am testing a page on an IPad (IOS 14.3) in portrait mode . (see code below)
I am outputting the touched Y-value of the screen.
When I tap the screen near the top the output is near 0 (depending on the thickness of finger).
When I tap the screen near the bottom the output is near 1000.
However when I swipe vertically from the top to bottom the values start from 0 but when I reach the bottom with my finger it stops near 600.
The same issue in the other directory, when I start at the bottom is shows a value around 1000 and when it reaches the top is stops around 300.
It almost seems there are missing 300px in each (vertical) direction.
Note: the X-value (horizontal swipes) is accurate, hence I've excluded it in this example. Also on Android the output from the console.log seems fine.
<!doctype html>
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />
<meta name="viewport" content="width=device-width, initial-scale=1,minimum-scale=1.0, user-scalable=yes">
<style>
body,
html {
position: fixed;
width: 100%;
height: 100%;
margin: 0;
padding 0;
background-color: #AAAAAA;
}
</style>
</head>
<body>
<div style='text-align:center;font-size:25px;width:100px;border:1px solid blue;margin:auto' id='feedback'>Hello</div>
</body>
</html>
<script>
var func = function (e) {
var evt = (typeof e.originalEvent === 'undefined') ? e : e.originalEvent;
var touch = evt.touches[0] || evt.changedTouches[0];
document.getElementById('feedback').textContent = 'top:'+touch.pageY;
};
document.body.addEventListener('touchstart', func);
document.body.addEventListener('touchmove', func);
document.body.addEventListener('touchend', func);
</script>
What is the reason the with swipping vertically I am getting different results than when I touch the screen?

It was solved by changing
document.getElementById('feedback').textContent = 'top:'+touch.pageY;
into
document.getElementById('feedback').textContent =
'top:'+touch.clientY;
Although I don't quite see why these would differ in this case.

Related

Drag doesn't work after mouseup in scope of drop container (Chrome, Edge)

When an element is dragged around and dropped somewhere in the page, the next element should have the same dragging behaviour as the first element.
I decided to implement the dragging with mouseevents instead of the drag and drop API. The dragged element should be rotatable during the dragging process with press on a button and this is not possible with the drag and drop API.
The problem happens if an element is dragged to the socpe of the drop container and the mouseup event happens in this scope. When the next element is dragged it isn't dragged as expected. There appears a grabbing cursor instead of a mouse cursor and the element doesn't follow the cursor. (In Chrome and Edge, in Firefox everything's fine)
Everything works as expected if an element is dragged over scope of the drop container and the mouseup event gets fired outside the scope.
Here is a link to a gif where you can see the problem.
The problem happens in Chrome and Edge, but not in Firefox. There is a mouseevent feature not supported in Chrome/Edge but in Firefox: "Support for mouseEventInit optional region field". Enabling "Experimental Web Platform Features" in Chrome still didn't solve the problem.
Checking the events in Chrome developer tools and Firefox Developer Tools one difference is that the offsetX and offsetY is in Firefox "0" but in Chrome a value is assigned. Don't know if this points to the potential issue.
How can the right dragging behaviour can be also implemented for Chrome and Edge?
const dragContainer = document.querySelector('#drag-container')
const dropContainer = document.querySelector('#drop-container')
const element1 = document.querySelector('#element-1')
const element2 = document.querySelector('#element-2')
makeElementDraggable(element1)
makeElementDraggable(element2)
function makeElementDraggable(element) {
element.addEventListener('mousedown', startDrag)
// Regards to: https://javascript.info/mouse-drag-and-drop
function startDrag(ev) {
element.style.position = 'absolute'
element.style.zIndex = 1000
document.body.append(element)
moveAt(ev.pageX, ev.pageY)
document.addEventListener('mousemove', onMouseMove)
document.addEventListener('mouseup', reset)
}
function onMouseMove(ev) {
moveAt(ev.pageX, ev.pageY)
}
function moveAt(pageX, pageY) {
element.style.left = pageX + 10 + 'px'
element.style.top = pageY + 'px'
}
function reset() {
document.removeEventListener('mousemove', onMouseMove)
element.removeEventListener('mousedown', startDrag)
}
}
#drag-container {
width: 250px;
height: 500px;
border: 1px solid black;
}
#element-1 {
background-color: aqua;
width: 250px;
height: 50px;
}
#element-2 {
background-color: blueviolet;
width: 200px;
height: 50px;
}
#drop-container {
height: 500px;
width: 500px;
border: 1px solid black;
}
<html lang="en">
<head>
<meta charset="UTF-8" />
<meta http-equiv="X-UA-Compatible" content="IE=edge" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>Document</title>
</head>
<body>
<div id="drag-container">
<div id="element-1"></div>
<div id="element-2"></div>
</div>
<div id="drop-container"></div>
<script src="script.js"></script>
</body>
</html>

How can I trigger a function when a section touches the top of the viewport with Vanilla JS?

I basically want the browser to trigger a function when a section touches the top of the viewport as the user scrolls and I'm not really sure how to do this with Vanilla JS.
I've found some jQuery alternatives, but I'm just trying to figure out how Javascript works at the moment, so I'm not exactly sure where to begin or what to google for that matter.
The following example creates a page with a single div inside.
The scroll event handler uses Element.getBoundingClientRect() in order to get the div's position relative to the viewport and logs a msg to the console when the div is at or above the top edge of the viewport.
var handlerFired;
window.addEventListener('scroll', function(e){
var containerTop = document.querySelector('.container').getBoundingClientRect().top;
if (containerTop <= 0) {
if (!handlerFired) {
handlerFired = 1;
console.log('container at top of viewport or above');
}
}
if (containerTop > 0) {
handlerFired = 0;
}
});
body{
height:2000px;
}
.container{
width:300px;
height:200px;
border:5px solid red;
position: absolute;
top: 100px;
}
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
</head>
<body>
<div class='container'> <p>scroll window ...</p> </div>
</body>
</html>

I have a Div Element acting as a button but it will only work once

I am 11 years old and I started learning Javascript a couple of months ago, So I am trying to make a page where if you scroll down too much it will take you back to the top so I made a Div element that fills up a large space and onmouseover it will take you back up to the top but if you try it a second time it won't do anything. Please help. Thanks in advance !
I hope my understanding of your problem is right. You have a div and you want to go up each time you scroll too much.
As an example of how to handle the scroll in vanilla JavaScript you can have a look at the document for the onscroll event: https://developer.mozilla.org/en-US/docs/Web/API/GlobalEventHandlers/onscroll.
Here is an example:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<style>
#container {
height: 500px;
width: 515px;
overflow: auto;
}
#foo {
height: 1000px;
width: 500px;
background-color: #777;
}
</style>
</head>
<body>
<div id="container">
<div id="foo"></div>
</div>
<script>
var container = document.getElementById('container');
container.addEventListener('scroll', function(event) {
// Get top and left value
var top = container.scrollTop
if (top > 400) {
// Go to the top
container.scrollTop = 0;
}
}, false);
</script>
</body>
</html>
In this example the contained element is bigger that the container so the container becomes scrollable with the overflow: auto; css property.
The scripts applies a onscroll event that checks the scroll value of the container and reset it to 0 when it exceed an arbitrary value (400 in the example).
I hope this has been useful to your work.

Javascript moving circle

I need to program a html-based monitoring surface.
For the surface I need to code circles which move from x to y and only if number xy is greater than xy.
Hard to explain but actually similar like they have it on
https://www.solarweb.com
click "click to try the preview now" on the top, than click "view demo" and choose the first system "Fronius AT Sattledt Hybrid 2"
and see the animation above on the left side.
I´ve still been able to get a circle running from the beginning of a div to the end. but only 1 circle! is it possible to have more circles in a row doing the same?
Maybe anyone can help me :)
<!DOCTYPE HTML>
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
<title>Moving Bullet</title>
<meta charset="utf8" />
<meta name="viewport" content="width=device-width, initial-scale=1" />
<script src="http://cdnjs.cloudflare.com/ajax/libs/jquery/2.1.3/jquery.min.js"></script>
<style>
#energieFluss {
width: 900px;
height: 500px;
border: 5px black solid;
overflow: hidden;
}
#bullet {
position: relative;
left: 50px;
top: 25px;
}
</style>
<body>
<div id="energieFluss" width="900px" height="500px" color="red">
<img id="bullet" src="ball-blau.png" height ="25" width= "25">
</div>
<script>
var Bullet = document.querySelector ("#bullet");
var currentPos = 0;
var requestAnimationFrame = window.requestAnimationFrame ||
window.mozRequestAnimationFrame ||
window.webkitRequestAnimationFrame ||
window.msRequestAnimationFrame;
function moveBullet () {
currentPos += 8;
Bullet.style.left = currentPos + "px";
if (Math.abs(currentPos) >= 900) {
currentPos = -50;
}
requestAnimationFrame(moveBullet);
}
moveBullet ();
</script>
</body>
I think what you'll want to do here is create your image elements on the fly and then animate them. You could also do other fancy things like render on a canvas or use a JavaScript rendering library to do it more efficiently.
To create the elements on the fly, do something like this:
var balls = [];
// Run this in a loop to add each ball to the balls array.
var img = document.createElement("img");
img.src = "ball-blau.png";
img.height = 25;
img.width = 25;
document.getElementById("energieFluss").appendChild(img);
balls.push(img)
Post thought:
You could just statically define your image elements and animate multiple elements. If you already know how to animate one element, then you can apply that same knowledge to multiple.

Converting Edge/IE JavaScript WheelEvent deltas to native scroll amounts?

In Edge and Internet Explorer, I'm noticing a strange issue with wheel events not equating to their expected scroll amounts. Even though the deltaMode values are reported as DOM_DELTA_PIXEL (0), the number of pixels found in deltaY is greater then the number of pixels actually being scrolled in a small scrollable div.
Take this code for example:
<!DOCTYPE html>
<html>
<head>
<title>test</title>
<style>
#scroller {
width: 200px;
height: 200px;
overflow: scroll;
}
</style>
</head>
<body>
<div id="scroller">
<p>test</p><p>test</p><p>test</p><p>test</p>
<p>test</p><p>test</p><p>test</p><p>test</p>
<p>test</p><p>test</p><p>test</p><p>test</p>
</div>
<script>
(function() {'use strict';
var scroller = document.getElementById('scroller');
scroller.addEventListener('wheel', function(e) {
var scrollY = e.deltaY;
console.log('scrollY:', scrollY);
setTimeout(function() {
console.log('scroller.scrollTop:', scroller.scrollTop);
}, 250);
});
})();
</script>
</body>
</html>
In the console I'm seeing values like this:
scrollY: 101.8499984741211
scroller.scrollTop: 28
In other browsers like Chrome, these values match or are at-least very close.
So the amount actually being scrolled is not the same as what is reported. Why is this, and can we get the correct value?
The reason the values are different is because IE and Edge actually scale the DOM pixels down based on how much of the window the scrolling area being scrolled takes up.
This complicates computing the proper scaling for a browser, and since IE/Edge are the only ones doing it, you will have to use some form of user-agent sniffing.
To get the correct amount of scrolling, you need to multiply the deltaY by (scroller.clientHeight / window.innerHeight) (and likewise with deltaX).
Here is that same sample with these adjustments:
<!DOCTYPE html>
<html>
<head>
<title>test</title>
<style>
#scroller {
width: 200px;
height: 200px;
overflow: scroll;
}
</style>
</head>
<body>
<div id="scroller">
<p>test</p><p>test</p><p>test</p><p>test</p>
<p>test</p><p>test</p><p>test</p><p>test</p>
<p>test</p><p>test</p><p>test</p><p>test</p>
</div>
<script>
(function() {
'use strict';
var scroller = document.getElementById('scroller');
scroller.addEventListener('wheel', function(e) {
var deltaY = e.deltaY;
var scaleY = scroller.clientHeight / window.innerHeight;
var scrollY = deltaY * scaleY;
console.log('scrollY:', scrollY);
setTimeout(function() {
console.log('scroller.scrollTop:', scroller.scrollTop);
}, 250);
});
})();
</script>
</body>
</html>
Which gives the following output in my console:
scrollY: 28.199999577518067
scroller.scrollTop: 28
Note that scrollTop values do not have floating points, so if you want the values to match exactly, you can Math.round them.

Categories

Resources