There are two divs vertically having unequal height. The minimum height of each div can be 40px.
When i resize the browser window, I want the divs to resize maintaining the aspect ratio.
I have created a demo in JSBIN. It works but it gets into Maximum call stack.
function divideEqually(h1, h2, diff) {
let threshold = 40;
let diffSplit = diff / 2;
let leftOut1 = 0,
leftOut2 = 0,
leftOut = 0;
if (h1 != threshold) {
h1 = h1 + diffSplit;
} else {
leftOut1 = diffSplit;
}
if (h2 != threshold) {
h2 = h2 + diffSplit;
} else {
leftOut2 = diffSplit;
}
diff = 0;
if (h1 < threshold) {
leftOut1 = threshold - h1;
h1 = threshold;
}
if (h2 < threshold) {
leftOut2 = threshold - h2;
h2 = threshold;
}
diff = Math.ceil(leftOut1 + leftOut2);
// error margin
if (Math.abs(diff) > 0.5) {
return divideEqually(h1, h2, diff);
}
return {
h1: h1,
h2: h2
};
}
const qs = handle => document.querySelector(handle)
let initialHeight = window.innerHeight;
window.addEventListener('resize',()=>{
const newHeight = window.innerHeight;
const changeInHeight = newHeight - initialHeight;
const h1 = qs("#top");
const h2 = qs("#bottom")
const h = divideEqually(h1.clientHeight,h2.clientHeight,changeInHeight);
initialHeight = newHeight;
h1.style.height = h.h1 + "px";
h2.style.height = h.h2 + "px";
// debug
h1.innerHTML = h.h1;
h2.innerHTML = h.h2;
})
Is their any better way of doing this or optimising the function ?
No need for Javascript; modern browsers have got you covered. Just add the flex property to the divs' CSS. This example gives the divs a 65/35 split.
#container {
display: flex;
flex-direction: column;
height: 100vh;
}
#top {
flex: 65 0 0%;
min-height: 40px;
width: 200px;
background: red;
}
#bottom {
flex: 35 0 0%;
min-height: 40px;
width: 200px;
background: orange;
}
<div id="container">
<div id="top"></div>
<div id="bottom"></div>
</div>
Related
Im working on a project game and I want to see if a div "rope" hits one of my pictures class='Fish1'.
I managed to get it to work by using document.GetElementsById("fish") but when I change it to document.getElementsByClassName('fish1') it gives me an error saying:
TypeError: Cannot read properties of undefined (reading
'getBoundingClientRect') at checkCollision
How can i fix this error? Also how can I check the height during the transition of a div and have it give me the height that it is at that point in the transition?
I've tried this:
function checkCollision(rope, fishy) {
var line = rope;
var fishy = document.getElementsByClassName('fish1');
var ropeRect = line.getBoundingClientRect();
for (var i = 0; i < fishy.length; i++) {
var fishyRect = fishy[i].getBoundingClientRect(i);
}
return (ropeRect.right >= fishyRect.left &&
ropeRect.left <= fishyRect.right) &&
(ropeRect.bottom >= fishyRect.top &&
ropeRect.top <= fishyRect.bottom);
}
And this is what worked for the id only:
function checkCollision(line, fishy) {
var line = rope;
var fishy = document.getElementById('fish');
var lineRect = line.getBoundingClientRect();
var fishyRect = fishy.getBoundingClientRect();
return (lineRect.right >= fishyRect.left &&
lineRect.left <= fishyRect.right) &&
(lineRect.bottom >= fishyRect.top &&
lineRect.top <= fishyRect.bottom);
}
Checking collision:
You can check if two elements overlap by using conditions that compare their x,y coords also involving their width, height:
//returns true if obj1 and obj2 collided, otherwise false
function checkCollision(obj1, obj2) {
const rect1 = obj1.getBoundingClientRect();
const rect2 = obj2.getBoundingClientRect();
return (rect1.x + rect1.width >= rect2.x && rect1.x <= rect2.x + rect2.width) &&
(rect1.y + rect1.height >= rect2.y && rect1.y <= rect2.y + rect2.height)
}
Moving the elements:
Once you have the function, you can call it inside your loop after changing the position of the elements at each iteration.
You didn't share any other detail apart the not working checkCollision function so I have no idea how did you perform the motion or probably you didn't at all yet.
Here I used Window.requestAnimationFrame()
https://developer.mozilla.org/en-US/docs/Web/API/window/requestAnimationFrame
The window.requestAnimationFrame() method tells the browser that you
wish to perform an animation and requests that the browser calls a
specified function to update an animation before the next repaint. The
method takes a callback as an argument to be invoked before the
repaint.
Here in this example, I animate a group of .fish elements over a sin wave crossing a line in the middle. Every time an element overlaps with the rope, it calls the function collisionOccurred printing on console its id property.
Since you have the exact element partecipating to the event you are free to fetch anything about it like for example the exact position where it is at in that instant (or the height you were expecting to know).
Later I also added the events fishEnter and fishLeave that fire respectively when the element enters and leaves the rope area.
const container = document.querySelector('body');
const rope = document.getElementById('rope');
const fishes = document.getElementsByClassName('fish');
let start = null;
let containerWidth, containerHeight;
beginAnimation();
//begins the fishes animation
function beginAnimation() {
window.requestAnimationFrame(moveFish);
}
//returns the x,y coords of a sin function
function getSin(millisecondsPast, cycleDuration = 2000) {
//ranging 0-1 in the span of cycleDuration (ms)
const progress = (millisecondsPast % cycleDuration) / cycleDuration;
//=~6.28
const twoPi = 2 * Math.PI;
//x ranging from 0-6.28 in the span of cycleDuration
const x = twoPi * progress;
//sin(x) (radius=1)
const y = Math.sin(x);
return {
//[0-1] (in the span of cycleDuration ms)
x: progress,
//[-1,+1]
y: y
}
}
//moves all the fishes following a sin wave
function moveFish(timestamp) {
const containerWidth = parseInt(container.offsetWidth);
const containerHeight = parseInt(container.offsetHeight);
//keep track of the animation progress
if (!start) start = timestamp;
let progress = timestamp - start;
//for all the fishes
for (fish of fishes) {
//calculate the x and y of a sin wave
//spread across the container width in the 0-2pi space
const duration = parseInt(fish.dataset.duration);
const vertical = parseInt(fish.dataset.verticalspan);
const sin = getSin(progress, duration);
let x = sin.x * containerWidth;
let y = sin.y * (vertical/2) + (containerHeight / 2);
//change the position of the current fish
fish.style.left = `${x}px`;
fish.style.top = `${y}px`;
const didcollide = checkCollision(rope, fish);
const overlapping = (fish.dataset.overlapping == 'true') ? true : false;
//calls fishEnter if the fish entered in the space of the rope
if (!overlapping && didcollide) {
fish.dataset.overlapping = 'true';
fishEnter(fish);
}
//calls fishLeave if the fish left the space of the rope
else if (overlapping && !didcollide) {
fish.dataset.overlapping = 'false';
fishLeave(fish);
}
//calls collisionOccurred if the fish collided with the rope
if (didcollide)
collisionOccurred(fish);
}
//render next iteration
window.requestAnimationFrame(moveFish);
}
//returns true if obj1 and obj2 collided, otherwise false
function checkCollision(obj1, obj2) {
const rect1 = obj1.getBoundingClientRect();
const rect2 = obj2.getBoundingClientRect();
const didcollide =
(rect1.x + rect1.width >= rect2.x && rect1.x <= rect2.x + rect2.width) &&
(rect1.y + rect1.height >= rect2.y && rect1.y <= rect2.y + rect2.height);
return didcollide;
}
//gets fired when the fish enters in the space of the rope
function fishEnter(target) {
target.classList.add('crossing');
console.log(`The fish id: ${target.id} entered in the rope space!`);
}
//gets fired when the fish leaves in the space of the rope
function fishLeave(target) {
target.classList.remove('crossing');
console.log(`The fish id: ${target.id} left the rope space!`);
}
//gets fired when the collision event occurs
function collisionOccurred(target) {
//console.log(`The fish id: ${target.id} crossed the rope!`);
}
*{
box-sizing: border-box;
}
body {
position: relative;
height: 100vh;
padding: 0;
margin: 0;
overflow: hidden;
}
#rope {
--size: 80px;
--border: 5px;
position: absolute;
top: calc(50% + var(--border) - var(--size) / 2) ;
width: 100%;
height: var(--size);
background: brown;
display: flex;
justify-content: center;
align-items: center;
font-weight: 600;
outline: solid var(--border) darkorange;
color: darkorange;
font-size: 2rem;
}
.fish {
position: absolute;
width: 80px;
line-height: 2rem;
background: blue;
font-weight: 600;
outline: solid darkblue;
text-align: center;
font-size: 1.5rem;
}
.fish::after {
content: attr(id);
color: white;
}
button {
padding: 1rem;
cursor: pointer;
}
.crossing{
background: yellow;
}
.crossing::after{
color: black !important;
}
<div id="rope">ROPE AREA</div>
<div id="fish1" class="fish" data-duration="5000" data-verticalspan="200"></div>
<div id="fish2" class="fish" data-duration="8000" data-verticalspan="300"></div>
<div id="fish3" class="fish" data-duration="10000" data-verticalspan="100"></div>
<div id="fish4" class="fish" data-duration="3000" data-verticalspan="500"></div>
I'm interested in how I can make a grid with an undetermined amount of columns and rows that I can put inside another div and have it not spill into others objects or mess with the parent size.
I want it to be square and I'm using Tailwind CSS but I can adapt to SCSS or vanilla CSS. Also I want it to be touchable/moveable with a mouse on desktop and touch capable devices.
How would I go about accomplishing this?
Assuming I've understood your question correctly, here is one way you could do it. I haven't tested it with a touch device but it shouldn't be hard to modify it to also respond to touch events.
const items = [
['a0', 'a1', 'a2'],
['b0', 'b1', 'b2'],
['c0', 'c1', 'c2']
];
let html = '';
for (let rowItems of items) {
html += '<div class="row">';
for (let item of rowItems) {
html += '<div class="item">';
html += item;
html += '</div>';
}
html += '</div>';
}
const viewElem = document.querySelector('#view');
const outputElem = document.querySelector('#output');
outputElem.innerHTML = html;
let mouseStartPos = null;
let startOffset = null;
outputElem.addEventListener('mousedown', e => {
outputElem.classList.remove('animate');
mouseStartPos = {
x: e.clientX,
y: e.clientY
};
startOffset = {
x: outputElem.offsetLeft - viewElem.offsetLeft,
y: outputElem.offsetTop - viewElem.offsetTop
};
});
window.addEventListener('mouseup', e => {
mouseStartPos = null;
startOffset = null;
outputElem.classList.add('animate');
const xGridOffset = -1 * Math.max(0, Math.min(Math.round((outputElem.offsetLeft - viewElem.offsetLeft) / -100), items.length - 1));
const yGridOffset = -1 * Math.max(0, Math.min(Math.round((outputElem.offsetTop - viewElem.offsetTop) / -100), items[0].length - 1));
outputElem.style.left = `${xGridOffset * 100}px`;
outputElem.style.top = `${yGridOffset * 100}px`;
});
window.addEventListener('mousemove', e => {
if (mouseStartPos) {
const xOffset = mouseStartPos.x - e.clientX;
const yOffset = mouseStartPos.y - e.clientY;
outputElem.style.left = `${-1 * xOffset + startOffset.x}px`;
outputElem.style.top = `${-1 * yOffset + startOffset.y}px`;
}
});
#view {
width: 100px;
height: 100px;
overflow: hidden;
border: 2px solid blue;
}
#output {
position: relative;
}
.row {
display: flex;
}
.item {
display: flex;
min-width: 100px;
width: 100px;
height: 100px;
box-sizing: border-box;
justify-content: center;
align-items: center;
border: 1px solid red;
}
#output.animate {
transition: left 1s ease 0s, top 1s ease 0s;
}
Drag it!<br/>
<br/>
<div id="view">
<div id="output"></div>
</div>
I have a 11500x11500 div that consists of 400 images, that obviously overflows the viewport.
I would like to pan around the whole div programmatically.
I want to generate an animation and by the time the animation is over, the whole of the div must have been panned across the viewport, top to bottom, left to right.
Right now, I am "splitting" my 11500x1500 div into tiles. The maximum width and height of each tile is the width and height of the viewport.
I store the coordinates of each tile and then I randomly choose one, pan it left-to-right and then move on to the next one.
I would like to know:
whether my method is correct or whether I am missing something in my calculations/approach and it could be improved. Given the size, it is hard for me to tell whether I'm actually panning the whole of the div after all
whether I can make the panning effect feel more "organic"/"natural". In order to be sure that the whole div is eventually panned, I pick each tile and pan it left-to-right, move on to the next one etc. This feels kind of rigid and too formalised. Is there a way to pan at let's say an angle or with a movement that is even more random and yet be sure that the whole div will eventually be panned ?
Thank in advance for any help.
This is the jsfiddle and this is the code (for the sake of the example/test every "image" is actually a div containing its index as text):
function forMs(time) {
return new Promise((resolve) => {
setTimeout(() => {
resolve()
}, time)
})
}
let container = document.getElementById('container')
let {
width,
height
} = container.getBoundingClientRect()
let minLeft = window.innerWidth - width
let minTop = window.innerHeight - height
let i = 0
while (i < 400) {
// adding "image" to the container
let image = document.createElement('div')
// add some text to the "image"
// to know what we're looking at while panning
image.innerHTML = ''
let j = 0
while (j < 100) {
image.innerHTML += ` ${i + 1}`
j++
}
container.appendChild(image)
i++
}
let coords = []
let x = 0
while (x < width) {
let y = 0
while (y < height) {
coords.push({
x,
y
})
y += window.innerHeight
}
x += window.innerWidth
}
async function pan() {
if (!coords.length) {
return;
}
let randomIdx = Math.floor(Math.random() * coords.length)
let [randomCoord] = coords.splice(randomIdx, 1);
console.log(coords.length)
container.classList.add('fast')
// update style in new thread so new transition-duration is applied
await forMs(10)
// move to new yet-unpanned area
container.style.top = Math.max(-randomCoord.y, minTop) + 'px'
container.style.left = Math.max(-randomCoord.x, minLeft) + 'px'
// wait (approx.) for transition to end
await forMs(2500)
container.classList.remove('fast')
// update style in new thread so new transition-duration is applied
await forMs(10)
//pan that area
let newLeft = -(randomCoord.x + window.innerWidth)
if (newLeft < minLeft) {
newLeft = minLeft
}
container.style.left = newLeft + 'px'
// wait (approx.) for transition to end
await forMs(4500)
// move on to next random area
await pan()
}
pan()
html,
body {
position: relative;
width: 100%;
height: 100%;
margin: 0;
padding: 0;
overflow: auto;
}
* {
margin: 0;
padding: 0;
}
#container {
position: absolute;
top: 0;
left: 0;
text-align: left;
width: 11500px;
height: 11500px;
transition: all 4s ease-in-out;
transition-property: top left;
font-size: 0;
}
#container.fast {
transition-duration: 2s;
}
#container div {
display: inline-block;
height: 575px;
width: 575px;
border: 1px solid black;
box-sizing: border-box;
font-size: 45px;
overflow: hidden;
word-break: break-all;
}
<div id="container"></div>
I think following improvements can be made:
Hide overflow on html and body so user can not move scrollbar and disturb the flow.
Calculate minLeft and minTop every time to account for window resizing. You might need ResizeObserver to recalculate things.
Increase transition times to avoid Cybersickness. In worse case RNG will pick bottom right tile first so your container will move the longest in 2seconds! Maybe, you can zoom-out and move then zoom-in then perform pan. Or use any serpentine path which will make shorter jumps.
Performance improvements:
Use transform instead of top, left for animation.
Use will-change: transform;. will-change will let browser know what to optimize.
Use translate3D() instead of translate(). ref
Use requestAnimationFrame. Avoid setTimeout, setInterval.
This is an old but good article: https://www.paulirish.com/2012/why-moving-elements-with-translate-is-better-than-posabs-topleft/
Modified code to use transform:
function forMs(time) {
return new Promise((resolve) => {
setTimeout(() => {
resolve()
}, time)
})
}
let container = document.getElementById('container')
let stat = document.getElementById('stats');
let {
width,
height
} = container.getBoundingClientRect()
let minLeft = window.innerWidth - width
let minTop = window.innerHeight - height
let i = 0
while (i < 400) {
// adding "image" to the container
let image = document.createElement('div')
// add some text to the "image"
// to know what we're looking at while panning
image.innerHTML = ''
let j = 0
while (j < 100) {
image.innerHTML += ` ${i + 1}`
j++
}
container.appendChild(image)
i++
}
let coords = []
let x = 0
while (x < width) {
let y = 0
while (y < height) {
coords.push({
x,
y
})
y += window.innerHeight
}
x += window.innerWidth
}
let count = 0;
async function pan() {
if (!coords.length) {
stat.innerText = 'iteration: ' +
(++count) + '\n tile# ' + randomIdx + ' done!!';
stat.style.backgroundColor = 'red';
return;
}
let minLeft = window.innerWidth - width
let minTop = window.innerHeight - height
let randomIdx = Math.floor(Math.random() * coords.length);
randomIdx = 1; //remove after debugging
let [randomCoord] = coords.splice(randomIdx, 1);
stat.innerText = 'iteration: ' +
(++count) + '\n tile# ' + randomIdx;
console.log(coords.length + ' - ' + randomIdx)
container.classList.add('fast')
// update style in new thread so new transition-duration is applied
await forMs(10)
// move to new yet-unpanned area
let yy = Math.max(-randomCoord.y, minTop);
let xx = Math.max(-randomCoord.x, minLeft);
move(xx, yy);
// wait (approx.) for transition to end
await forMs(2500)
container.classList.remove('fast')
// update style in new thread so new transition-duration is applied
await forMs(10)
//pan that area
let newLeft = -(randomCoord.x + window.innerWidth)
if (newLeft < minLeft) {
newLeft = minLeft
}
xx = newLeft;
//container.style.left = newLeft + 'px'
move(xx, yy);
// wait (approx.) for transition to end
await forMs(4500)
// move on to next random area
await pan()
}
pan()
function move(xx, yy) {
container.style.transform = "translate3D(" + xx + "px," + yy + "px,0px)";
}
html,
body {
position: relative;
width: 100%;
height: 100%;
margin: 0;
padding: 0;
overflow: hidden;
}
* {
margin: 0;
padding: 0;
box-sizing: border-box;
}
#container {
text-align: left;
width: 11500px;
height: 11500px;
transition: all 4s ease-in-out;
transition-property: transform;
font-size: 0;
will-change: transform;
}
#container.fast {
transition-duration: 2s;
}
#container div {
display: inline-block;
height: 575px;
width: 575px;
border: 1px solid black;
box-sizing: border-box;
font-size: 45px;
overflow: hidden;
word-break: break-all;
}
#stats {
border: 2px solid green;
width: 100px;
background-color: lightgreen;
position: fixed;
opacity: 1;
top: 0;
left: 0;
z-index: 10;
}
<div id=stats>iteration: 1 tile# 11</div>
<div id="container"></div>
Note I haven't implemented everything in above snippet.
I have a large background image and some much smaller images for the user to drag around on the background. I need this to be efficient in terms of performance, so i'm trying to avoid libraries. I'm fine with drag 'n' drop if it work's well, but im trying to get drag.
Im pretty much trying to do this. But after 8 years there must be a cleaner way to do this right?
I currently have a drag 'n' drop system that almost works, but when i drop the smaller images, they are just a little off and it's very annoying. Is there a way to fix my code, or do i need to take a whole different approach?
This is my code so far:
var draggedPoint;
function dragStart(event) {
draggedPoint = event.target; // my global var
}
function drop(event) {
event.preventDefault();
let xDiff = draggedPoint.x - event.pageX;
let yDiff = draggedPoint.y - event.pageY;
let left = draggedPoint.style.marginLeft; // get margins
let top = draggedPoint.style.marginTop;
let leftNum = Number(left.substring(0, left.length - 2)); // cut off px from the end
let topNum = Number(top.substring(0, top.length - 2));
let newLeft = leftNum - xDiff + "px" // count new margins and put px back to the end
let newTop = topNum - yDiff + "px"
draggedPoint.style.marginLeft = newLeft;
draggedPoint.style.marginTop = newTop;
}
function allowDrop(event) {
event.preventDefault();
}
let imgs = [
"https://upload.wikimedia.org/wikipedia/commons/6/67/Orange_juice_1_edit1.jpg",
"https://upload.wikimedia.org/wikipedia/commons/f/ff/Solid_blue.svg",
"https://upload.wikimedia.org/wikipedia/commons/b/b4/Litoria_infrafrenata_-_Julatten.jpg"
]
/* my smaller images: */
for (let i = 0; i < 6; i++) {
let sensor = document.createElement("img");
sensor.src = imgs[i % imgs.length];
sensor.alt = i;
sensor.draggable = true;
sensor.classList.add("sensor");
sensor.style.marginLeft = `${Math.floor(Math.random() * 900)}px`
sensor.style.marginTop = `${Math.floor(Math.random() * 500)}px`
sensor.onclick = function() {
sensorClick(logs[i].id)
};
sensor.addEventListener("dragstart", dragStart, null);
let parent = document.getElementsByClassName("map")[0];
parent.appendChild(sensor);
}
<!-- my html: -->
<style>
.map {
width: 900px;
height: 500px;
align-content: center;
margin: 150px auto 150px auto;
}
.map .base {
position: absolute;
width: inherit;
height: inherit;
}
.map .sensor {
position: absolute;
width: 50px;
height: 50px;
}
</style>
<div class="map" onDrop="drop(event)" ondragover="allowDrop(event)">
<img src='https://upload.wikimedia.org/wikipedia/commons/f/f7/Plan-Oum-el-Awamid.jpg' alt="pohja" class="base" draggable="false">
<div>
With the answers from here and some time i was able to get a smooth drag and click with pure js.
Here is a JSFiddle to see it in action.
let maxLeft;
let maxTop;
const minLeft = 0;
const minTop = 0;
let timeDelta;
let imgs = [
"https://upload.wikimedia.org/wikipedia/commons/6/67/Orange_juice_1_edit1.jpg",
"https://upload.wikimedia.org/wikipedia/commons/f/ff/Solid_blue.svg",
"https://upload.wikimedia.org/wikipedia/commons/b/b4/Litoria_infrafrenata_-_Julatten.jpg"
]
var originalX;
var originalY;
window.onload = function() {
document.onmousedown = startDrag;
document.onmouseup = stopDrag;
}
function sensorClick () {
if (Date.now() - timeDelta < 150) { // check that we didn't drag
createPopup(this);
}
}
// create a popup when we click
function createPopup(parent) {
let p = document.getElementById("popup");
if (p) {
p.parentNode.removeChild(p);
}
let popup = document.createElement("div");
popup.id = "popup";
popup.className = "popup";
popup.style.top = parent.y - 110 + "px";
popup.style.left = parent.x - 75 + "px";
let text = document.createElement("span");
text.textContent = parent.id;
popup.appendChild(text);
var map = document.getElementsByClassName("map")[0];
map.appendChild(popup);
}
// when our base is loaded
function baseOnLoad() {
var map = document.getElementsByClassName("map")[0];
let base = document.getElementsByClassName("base")[0];
maxLeft = base.width - 50;
maxTop = base.height - 50;
/* my smaller images: */
for (let i = 0; i < 6; i++) {
let sensor = document.createElement("img");
sensor.src = imgs[i % imgs.length];
sensor.alt = i;
sensor.id = i;
sensor.draggable = true;
sensor.classList.add("sensor");
sensor.classList.add("dragme");
sensor.style.left = `${Math.floor(Math.random() * 900)}px`
sensor.style.top = `${Math.floor(Math.random() * 500)}px`
sensor.onclick = sensorClick;
let parent = document.getElementsByClassName("map")[0];
parent.appendChild(sensor);
}
}
function startDrag(e) {
timeDelta = Date.now(); // get current millis
// determine event object
if (!e) var e = window.event;
// prevent default event
if(e.preventDefault) e.preventDefault();
// IE uses srcElement, others use target
targ = e.target ? e.target : e.srcElement;
originalX = targ.style.left;
originalY = targ.style.top;
// check that this is a draggable element
if (!targ.classList.contains('dragme')) return;
// calculate event X, Y coordinates
offsetX = e.clientX;
offsetY = e.clientY;
// calculate integer values for top and left properties
coordX = parseInt(targ.style.left);
coordY = parseInt(targ.style.top);
drag = true;
document.onmousemove = dragDiv; // move div element
return false; // prevent default event
}
function dragDiv(e) {
if (!drag) return;
if (!e) var e = window.event;
// move div element and check for borders
let newLeft = coordX + e.clientX - offsetX;
if (newLeft < maxLeft && newLeft > minLeft) targ.style.left = newLeft + 'px'
let newTop = coordY + e.clientY - offsetY;
if (newTop < maxTop && newTop > minTop) targ.style.top = newTop + 'px'
return false; // prevent default event
}
function stopDrag() {
if (typeof drag == "undefined") return;
if (drag) {
if (Date.now() - timeDelta > 150) { // we dragged
let p = document.getElementById("popup");
if (p) {
p.parentNode.removeChild(p);
}
} else {
targ.style.left = originalX;
targ.style.top = originalY;
}
}
drag = false;
}
.map {
width: 900px;
height: 500px;
margin: 50px
position: relative;
}
.map .base {
position: absolute;
width: inherit;
height: inherit;
}
.map .sensor {
display: inline-block;
position: absolute;
width: 50px;
height: 50px;
}
.dragme {
cursor: move;
left: 0px;
top: 0px;
}
.popup {
position: absolute;
display: inline-block;
width: 200px;
height: 100px;
background-color: #9FC990;
border-radius: 10%;
}
.popup::after {
content: "";
position: absolute;
top: 100%;
left: 50%;
margin-left: -10px;
border-width: 10px;
border-style: solid;
border-color: #9FC990 transparent transparent transparent;
}
.popup span {
width: 90%;
margin: 10px;
display: inline-block;
text-align: center;
}
<div class="map" width="950px" height="500px">
<img src='https://upload.wikimedia.org/wikipedia/commons/f/f7/Plan-Oum-el-Awamid.jpg' alt="pohja" class="base" draggable="false" onload="baseOnLoad()">
<div>
I have tried to create single scroll and move to next section, I have using javascript, It is not working fine, The window top distance not giving properly, I need to div fullscreen moved to next screen, Please without jquery, Please help
if (window.addEventListener) {window.addEventListener('DOMMouseScroll', wheel, false);
window.onmousewheel = document.onmousewheel = wheel;}
function wheel(event) {
var delta = 0;
if (event.wheelDelta) delta = (event.wheelDelta)/120 ;
else if (event.detail) delta = -(event.detail)/3;
handle(delta);
if (event.preventDefault) event.preventDefault();
event.returnValue = false;
}
function handle(sentido) {
var inicial = document.body.scrollTop;
var time = 500;
var distance = 900;
animate({
delay: 0,
duration: time,
delta: function(p) {return p;},
step: function(delta) {
window.scrollTo(0, inicial-distance*delta*sentido);
}
});
}
function animate(opts) {
var start = new Date();
var id = setInterval(function() {
var timePassed = new Date() - start;
var progress = (timePassed / opts.duration);
if (progress > 1) {progress = 1;}
var delta = opts.delta(progress);
opts.step(delta);
if (progress == 1) {clearInterval(id);}}, opts.delay || 10);
}
body{
width: 100%;
height: 100%;
margin:0;
padding:0;
}
.wrapper{
width: 100%;
height: 100%;
position: absolute;
}
section{
width: 100%;
height: 100%;
}
.pg1{
background: green;
}
.pg2{
background: blue;
}
.pg3{
background: yellow;
}
<div class="wrapper" id="myDiv">
<section class="pg1" id="sec1"></section>
<section class="pg2"></section>
<section class="pg3"></section>
</div>
Return the height of the element and store it in distance variable, instead of giving it a static 900.
From this:
var distance = 900;
To this:
var distance = document.getElementById('sec1').clientHeight;