How to translate Jquery.animate to Vanilla JS - javascript

I use only a little part of Jquery code and I want to translate it
$("html,body").animate(
{
scrollTop: sections[counter].offsetTop,
behavior: "smooth",
},
800
);
Window.scrollTo() doesn't work
Full code
let delay = false;
let counter = 0;
// let scrollHeight = 0;
const sections = document.querySelectorAll(".scrolling-block");
function scrollToSection(e, directionY, directionX) {
if (delay) return;
// console.log(e);
delay = true;
if (directionY !== 0) {
// if scroll by y
setTimeout(function () {
delay = false;
}, 1500);
} else {
// if scroll by x
delay = false;
}
if (directionY !== 0 || directionY !== -0) {
e.preventDefault();
}
if (directionY > 0) {
//scroll down
if (counter + 1 !== sections.length) {
// scrollHeight += sections[counter].clientHeight;
counter++;
} else {
scrollHeight = scrollHeight;
counter = counter;
}
$("html,body").animate(
{
scrollTop: sections[counter].offsetTop,
behavior: "smooth",
},
800
);
// console.log(scrollHeight + "\n", counter);
return counter;
} else if (directionY < 0) {
//scroll up
if (counter - 1 !== -1) {
// scrollHeight -= sections[counter - 1].clientHeight;
counter--;
} else {
scrollHeight = scrollHeight;
counter = counter;
}
$("html,body").animate(
{
scrollTop: sections[counter].offsetTop,
behavior: "smooth",
},
800
);
// console.log(scrollHeight);
return counter;
}
}
window.addEventListener(
"wheel",
function (e) {
let directionY = e.deltaY;
let directionX = e.deltaX;
let maxY = sections[sections.length - 1].offsetTop;
if (pageYOffset < maxY - 10) {
// console.log(scrollHeight, " < ", maxY);
if (directionY !== 0) {
e.preventDefault();
}
scrollToSection(e, directionY, directionX);
} else {
if (pageYOffset < maxY && directionY < 0) {
if (directionY !== 0) {
e.preventDefault();
}
scrollToSection(e, directionY, directionX);
}
// console.log(scrollHeight, " > ", maxY);
}
// e.stopPropagation();
},
{ passive: false }
);

Technically both scroll and scrollTo should do the same thing
window.scrollTo({
top: 100,
left: 100,
behavior: 'smooth'
});
OR
window.scroll({
top: 100,
left: 100,
behavior: 'smooth'
});
Please check the documentation here:
[1]: https://developer.mozilla.org/en-US/docs/Web/API/Window/scrollTo
[2]: https://developer.mozilla.org/en-US/docs/Web/API/Window/scroll

Related

Customised scroll isnt working on smartphones

i have an issue concerning a JS scrolling function.
const scroll = document.querySelectorAll(".scroll");
const maxIndex = 3; //NB DE PAGES
let index = 0;
let animationEnd = true;
let boolUp = 0;
const start = {
x: 0,
y: 0
};
function touchStart(event) {
event.preventDefault();
start.x = event.touches[0].pageX;
start.y = event.touches[0].pageY;
}
function touchMove(event) {
event.preventDefault();
const offset = {};
offset.x = start.x - event.touches[0].pageX;
offset.y = start.y - event.touches[0].pageY;
scrollHandler({
deltaY: offset.y
});
}
function scrollHandler(e) {
if(e.preventDefault) e.preventDefault();
if (animationEnd) {
if (e.deltaY > 0) index++;
else index--;
if (index < 0) index = 0;
if (index > scroll.length - 1) index = scroll.length - 1;
scroll[0].style.marginTop = "-" + index * 100 + "vh";
animationEnd = false;
setTimeout(() => animationEnd = true, 450)
}
}
function keyScroll(e) {
if (e.key == "ArrowUp") {
index--;
if (index < 0) {
index = 0;
}
scroll[0].style.marginTop = "-" + index * 100 + "vh";
animationEnd = false;
setTimeout(() => animationEnd = true, 450);
} else if (e.key == "ArrowDown") {
if (index < maxIndex) {
index++;
scroll[0].style.marginTop = "-" + index * 100 + "vh";
animationEnd = false;
setTimeout(() => animationEnd = true, 450);
}
}
}
I'm calling those by body event listeners :
document.addEventListener("scroll", (e) => e.preventDefault())
document.body.addEventListener("keydown", keyScroll);
document.body.addEventListener("wheel", scrollHandler,);
document.body.addEventListener("touchstart", touchStart, false);
document.body.addEventListener("touchmove", touchMove, false);
It's working perfectly => example at https://darleanow.github.io .
But when i'm on smartphone (Iphone), scroll might bug and the height of divs would appear different, you can try it on your own smartphone to see what i'm talking about, try scrolling a bit fast etc...
If anybody has an idea :)
This isn't a solution necessarily, but you might try printing scroll[0].stlye.marginTop to the console every time it changes.
If that value is never erroneous, I'd guess the issue is with the animation (maybe scrolling while it's animating, or something like that).

Infinite continuous looping scroll on mobile

I have a small problem with my looping scroll. It works pretty well on larger displays, but on handheld devices it glitches quite a lot. I'm not sure where I'm doing something wrong or where I should adjust the code to work on mobile as well.
Link to site: https://studio-6-9ede0f.webflow.io/
Here's what I got so far:
var origDivHeight = document.querySelector(".infinite").offsetHeight;
var clone=$(".infinite").contents().clone();
clone.appendTo(".infinite");
clone.prependTo(".infinite");
$(document).scroll(function(){
var scrollWindowPos = $(document).scrollTop();
if(scrollWindowPos >= origDivHeight ) {
$(document).scrollTop(0);
}
if(scrollWindowPos <= 0 ) {
$(document).scrollTop(origDivHeight);
}
});
window.scrollBy(0, 1);
window.scrollBy(0, -1);
Got it to work based on this codepen: https://codepen.io/vincentorback/pen/zxRyzj
Sharing it here as well if somebody finds it useful:
<style>
html,
body {
height: 100%;
overflow: hidden;
}
.infinite {
overflow: auto;
-webkit-overflow-scrolling: touch;
}
.clone {
height: 50vw;
}
</style>
<script>
var doc = window.document,
context = doc.querySelector('.infinite'),
clones = context.querySelectorAll('.clone'),
disableScroll = false,
scrollHeight = 0,
scrollPos = 0,
clonesHeight = 0,
i = 0;
function getScrollPos () {
return (context.pageYOffset || context.scrollTop) - (context.clientTop || 0);
}
function setScrollPos (pos) {
context.scrollTop = pos;
}
function getClonesHeight () {
clonesHeight = 0;
for (i = 0; i < clones.length; i += 1) {
clonesHeight = clonesHeight + clones[i].offsetHeight;
}
return clonesHeight;
}
function reCalc () {
scrollPos = getScrollPos();
scrollHeight = context.scrollHeight;
clonesHeight = getClonesHeight();
if (scrollPos <= 0) {
setScrollPos(1); // Scroll 1 pixel to allow upwards scrolling
}
}
function scrollUpdate () {
if (!disableScroll) {
scrollPos = getScrollPos();
if (clonesHeight + scrollPos >= scrollHeight) {
// Scroll to the top when you’ve reached the bottom
setScrollPos(1); // Scroll down 1 pixel to allow upwards scrolling
disableScroll = true;
} else if (scrollPos <= 0) {
// Scroll to the bottom when you reach the top
setScrollPos(scrollHeight - clonesHeight);
disableScroll = true;
}
}
if (disableScroll) {
// Disable scroll-jumping for a short time to avoid flickering
window.setTimeout(function () {
disableScroll = false;
}, 40);
}
}
function init () {
reCalc();
context.addEventListener('scroll', function () {
window.requestAnimationFrame(scrollUpdate);
}, false);
window.addEventListener('resize', function () {
window.requestAnimationFrame(reCalc);
}, false);
}
if (document.readyState !== 'loading') {
init()
} else {
doc.addEventListener('DOMContentLoaded', init, false)
}
</script>

How to detect collision?

I am building a video game where a spaceship moves with controllers and it must avoid some fireballs in order to win. However now I would like to setup a collision system: when a fireball touches the spaceship, game is over (alert("game over")). Any help with this? Thanks!!!
let spaceship = document.querySelector("#icon")
//Fireball script
const fireballArray = []
function generateFireBallWithAttributes(el, attrs) {
for (var key in attrs) {
el.setAttribute(key, attrs[key])
};
return el
}
function createFireBalls(amount) {
for (let i = 0; i <= amount; i++) {
fireballArray.push(generateFireBallWithAttributes(document.createElement("img"), {
src: "Photo/fireball.png",
width: "40"
}))
}
}
createFireBalls(10)
fireballArray.forEach((fireballElement) => {
const fallStartInterval = setInterval(function() {})
document.querySelector("body").appendChild(fireballElement);
const fireballMovement = {
x: fireballRandom(fireballElement.offsetWidth),
y: 0
}
const fireLoop = function() {
fireballMovement.y += 2;
fireballElement.style.top = fireballMovement.y + "px";
if (fireballMovement.y > window.innerHeight) {
fireballMovement.x = fireballRandom(fireballElement.offsetWidth);
fireballElement.style.left = fireballMovement.x + "px";
fireballMovement.y = 0
}
}
fireballElement.style.left = fireballMovement.x + "px";
let fireInterval = setInterval(fireLoop, 1000 / ((Math.random() * (50)) + 75))
})
function fireballRandom(offset) {
return Math.floor(Math.random() * (window.innerWidth - offset))
}
//Spaceship moves into space + prevent going out borders
let hits = 0
let pos = {
top: 1000,
left: 570
}
const keys = {}
window.addEventListener("keydown", function(e) {
keys[e.keyCode] = true
})
window.addEventListener("keyup", function(e) {
keys[e.keyCode] = false
})
const loop = function() {
if (keys[37] || keys[81]) {pos.left -= 5}
if (keys[39] || keys[68]) {pos.left += 5}
if (keys[38] || keys[90]) {pos.top -= 4}
if (keys[40] || keys[83]) {pos.top += 4}
if (pos.left < 0) { pos.left = -1}
if (pos.top < 0) {pos.top = -1}
if (pos.left + spaceship.offsetWidth >= body.offsetWidth) {
pos.left = body.offsetWidth - spaceship.offsetWidth
}
if (pos.top + spaceship.offsetHeight >= body.offsetHeight) {
pos.top = body.offsetHeight - spaceship.offsetHeight
}
spaceship.setAttribute("data", body.offsetWidth + ":" + body.offsetHeight)
spaceship.style.left = pos.left + "px";
spaceship.style.top = pos.top + "px"
}
let sensibilty = setInterval(loop, 8)
<body>
<img src="Photo/Spaceship1.png" id="icon">
</body>
Check this out (hitboxes)
Also this
Your code is missing complete information. That said, as your game progresses with explicit and independent setIntervals on fireballs and spaceship, and you dont want to make bigger changes I suggest you call the checkCollision() function any time fireball moves or spaceship moves (that is in the loop and fireloop "animation functions").
The collision itself is done with the following:
function detectOverlap(fireball) {
const shipRect = spaceship.getBoundingClientRect();
const fireballRect = fireball.getBoundingClientRect();
//these two variables are of following type
//DOMRect {x: 570, y: 836, width: 104.484375, height: 112.828125, ...}
// this will test if the ship collides with specific fireball
if (
(shipRect.x + shipRect.width > fireballRect.x && shipRect.x < fireballRect.x + fireball.width)
&& (shipRect.y + shipRect.height > fireballRect.y && shipRect.y < fireballRect.y + fireball.height)
) {
return true;
} else {
return false;
}
};
function checkCollision() {
let collision = false;
fireballArray.forEach(fireball => {
if (detectOverlap(fireball)) { collision = true };
});
// this is satisfied if the ship collides with any fireball
if (collision === true) {
// do some logic on collision
console.log('collision');
}
};
This will do rectangle vs rectangle collision detection. This might not fit the best, but it is a good first approximation.
NOTE: You can check the devtools console (F12) to assess the correct collision detection.

Scrolling issues on mac os

So I have write a script for my portfolio website to scroll to section by index. It works on every tested browser and smartphone but on a mac device it does not work probably instead to scroll to the next sections it is going automatically to the second next section.
Hopefully someone can help me.
var anchorPoints = [];
var anchorLocation = [];
var anchorIndex = 0;
var waiting = false;
var canScroll = true;
var offset = 0
window.onload = function () {
anchorPoints = document.getElementsByClassName("js-anchor");
for (i = 0; i < anchorPoints.length; i++) {
getLocation = anchorPoints[i].getBoundingClientRect();
getLocation = getLocation.top - offset;
anchorLocation.push(parseInt(getLocation));
}
}
$(document).on('mousewheel DOMMouseScroll', function (e) {
if (detectMobile() == true) {
return;
}
if ((waiting || canScroll == false)) {
return;
}
e.preventDefault();//prevent the default mousewheel scrolling
var active = $('section.active');
var delta = e.originalEvent.detail < 0 || e.originalEvent.wheelDelta > 0 ? 1 : -1;
waiting = true;
if (delta < 0) {
anchorIndex += 1;
if (anchorIndex > (anchorPoints.length - 1)) {
anchorIndex = 0;
}
scrollTo({
top: anchorLocation[anchorIndex],
left: 0,
behavior: 'smooth'
});
console.log(anchorIndex);
console.log('scrolling down');
} else {
anchorIndex -= 1;
if (anchorIndex < 0) {
anchorIndex = anchorPoints.length - 1;
}
scrollTo({
top: anchorLocation[anchorIndex],
left: 0,
behavior: 'smooth'
});
console.log(anchorIndex);
console.log('scrolling up');
}
setTimeout(function () {
waiting = false;
}, 1000);
});

Callback function to add newly loaded images to a roll

Hi I'm working on a site with a infinite scroll script and am trying to figure out how to add a callback for Image Lightbox:
http://osvaldas.info/image-lightbox-responsive-touch-friendly
I've managed to get the images on the second page to work with image light box and have them styled with the same variables using this:
$(function () {
$('a[data-imagelightbox="d"]').imageLightbox({
onStart: function () {
overlayOn();
},
onLoadStart: function () {
captionOff();
activityIndicatorOn();
},
onLoadEnd: function () {
captionOn();
activityIndicatorOff();
},
onEnd: function () {
captionOff();
overlayOff();
activityIndicatorOff();
}
});
});
My problem is that while the images from "page two" can be viewed within the lightbox, they are not added to the gallery/roll for the user to cycle/navigate through. When the user views an image from "page two" and attempts to cycle through they can only view images from "page one".
Anyone know what script I should be using to get the images refreshed/added after infinite scroll loads more content? Thanks in advance!!
Here is the full js for the Image Lightbox:
var cssTransitionSupport = function () {
var s = document.body || document.documentElement,
s = s.style;
if (s.WebkitTransition == '') return '-webkit-';
if (s.MozTransition == '') return '-moz-';
if (s.OTransition == '') return '-o-';
if (s.transition == '') return '';
return false;
},
isCssTransitionSupport = cssTransitionSupport() === false ? false : true,
cssTransitionTranslateX = function (element, positionX, speed) {
var options = {}, prefix = cssTransitionSupport();
options[prefix + 'transform'] = 'translateX(' + positionX + ')';
options[prefix + 'transition'] = prefix + 'transform ' + speed + 's linear';
element.css(options);
},
hasTouch = ('ontouchstart' in window),
hasPointers = window.navigator.pointerEnabled || window.navigator.msPointerEnabled,
wasTouched = function (event) {
if (hasTouch) return true;
if (!hasPointers || typeof event === 'undefined' || typeof event.pointerType === 'undefined') return false;
if (typeof event.MSPOINTER_TYPE_MOUSE !== 'undefined') {
if (event.MSPOINTER_TYPE_MOUSE != event.pointerType) return true;
} else if (event.pointerType != 'mouse') return true;
return false;
};
$.fn.imageLightbox = function (options) {
var options = $.extend({
selector: 'id="imagelightbox"',
allowedTypes: 'png|jpg|jpeg|gif',
animationSpeed: 250,
preloadNext: true,
enableKeyboard: true,
quitOnEnd: false,
quitOnImgClick: false,
quitOnDocClick: true,
onStart: false,
onEnd: false,
onLoadStart: false,
onLoadEnd: false
},
options),
targets = $([]),
target = $(),
image = $(),
imageWidth = 0,
imageHeight = 0,
swipeDiff = 0,
inProgress = false,
isTargetValid = function (element) {
return $(element).prop('tagName').toLowerCase() == 'a' && (new RegExp('\.(' + options.allowedTypes + ')$', 'i')).test($(element).attr('href'));
},
setImage = function () {
if (!image.length) return true;
var screenWidth = $(window).width() * 0.8,
screenHeight = $(window).height() * 0.9,
tmpImage = new Image();
tmpImage.src = image.attr('src');
tmpImage.onload = function () {
imageWidth = tmpImage.width;
imageHeight = tmpImage.height;
if (imageWidth > screenWidth || imageHeight > screenHeight) {
var ratio = imageWidth / imageHeight > screenWidth / screenHeight ? imageWidth / screenWidth : imageHeight / screenHeight;
imageWidth /= ratio;
imageHeight /= ratio;
}
image.css({
'width': imageWidth + 'px',
'height': imageHeight + 'px',
'top': ($(window).height() - imageHeight) / 2 + 'px',
'left': ($(window).width() - imageWidth) / 2 + 'px'
});
};
},
loadImage = function (direction) {
if (inProgress) return false;
direction = typeof direction === 'undefined' ? false : direction == 'left' ? 1 : -1;
if (image.length) {
if (direction !== false && (targets.length < 2 || (options.quitOnEnd === true && ((direction === -1 && targets.index(target) == 0) || (direction === 1 && targets.index(target) == targets.length - 1))))) {
quitLightbox();
return false;
}
var params = {
'opacity': 0
};
if (isCssTransitionSupport) cssTransitionTranslateX(image, (100 * direction) - swipeDiff + 'px', options.animationSpeed / 1000);
else params.left = parseInt(image.css('left')) + 100 * direction + 'px';
image.animate(params, options.animationSpeed, function () {
removeImage();
});
swipeDiff = 0;
}
inProgress = true;
if (options.onLoadStart !== false) options.onLoadStart();
setTimeout(function () {
image = $('<img ' + options.selector + ' />')
.attr('src', target.attr('href'))
.load(function () {
image.appendTo('body');
setImage();
var params = {
'opacity': 1
};
image.css('opacity', 0);
if (isCssTransitionSupport) {
cssTransitionTranslateX(image, -100 * direction + 'px', 0);
setTimeout(function () {
cssTransitionTranslateX(image, 0 + 'px', options.animationSpeed / 1000)
}, 50);
} else {
var imagePosLeft = parseInt(image.css('left'));
params.left = imagePosLeft + 'px';
image.css('left', imagePosLeft - 100 * direction + 'px');
}
image.animate(params, options.animationSpeed, function () {
inProgress = false;
if (options.onLoadEnd !== false) options.onLoadEnd();
});
if (options.preloadNext) {
var nextTarget = targets.eq(targets.index(target) + 1);
if (!nextTarget.length) nextTarget = targets.eq(0);
$('<img />').attr('src', nextTarget.attr('href')).load();
}
})
.error(function () {
if (options.onLoadEnd !== false) options.onLoadEnd();
})
var swipeStart = 0,
swipeEnd = 0,
imagePosLeft = 0;
image.on(hasPointers ? 'pointerup MSPointerUp' : 'click', function (e) {
e.preventDefault();
if (options.quitOnImgClick) {
quitLightbox();
return false;
}
if (wasTouched(e.originalEvent)) return true;
var posX = (e.pageX || e.originalEvent.pageX) - e.target.offsetLeft;
target = targets.eq(targets.index(target) - (imageWidth / 2 > posX ? 1 : -1));
if (!target.length) target = targets.eq(imageWidth / 2 > posX ? targets.length : 0);
loadImage(imageWidth / 2 > posX ? 'left' : 'right');
})
.on('touchstart pointerdown MSPointerDown', function (e) {
if (!wasTouched(e.originalEvent) || options.quitOnImgClick) return true;
if (isCssTransitionSupport) imagePosLeft = parseInt(image.css('left'));
swipeStart = e.originalEvent.pageX || e.originalEvent.touches[0].pageX;
})
.on('touchmove pointermove MSPointerMove', function (e) {
if (!wasTouched(e.originalEvent) || options.quitOnImgClick) return true;
e.preventDefault();
swipeEnd = e.originalEvent.pageX || e.originalEvent.touches[0].pageX;
swipeDiff = swipeStart - swipeEnd;
if (isCssTransitionSupport) cssTransitionTranslateX(image, -swipeDiff + 'px', 0);
else image.css('left', imagePosLeft - swipeDiff + 'px');
})
.on('touchend touchcancel pointerup pointercancel MSPointerUp MSPointerCancel', function (e) {
if (!wasTouched(e.originalEvent) || options.quitOnImgClick) return true;
if (Math.abs(swipeDiff) > 50) {
target = targets.eq(targets.index(target) - (swipeDiff < 0 ? 1 : -1));
if (!target.length) target = targets.eq(swipeDiff < 0 ? targets.length : 0);
loadImage(swipeDiff > 0 ? 'right' : 'left');
} else {
if (isCssTransitionSupport) cssTransitionTranslateX(image, 0 + 'px', options.animationSpeed / 1000);
else image.animate({
'left': imagePosLeft + 'px'
}, options.animationSpeed / 2);
}
});
}, options.animationSpeed + 100);
},
removeImage = function () {
if (!image.length) return false;
image.remove();
image = $();
},
quitLightbox = function () {
if (!image.length) return false;
image.animate({
'opacity': 0
}, options.animationSpeed, function () {
removeImage();
inProgress = false;
if (options.onEnd !== false) options.onEnd();
});
};
$(window).on('resize', setImage);
if (options.quitOnDocClick) {
$(document).on(hasTouch ? 'touchend' : 'click', function (e) {
if (image.length && !$(e.target).is(image)) quitLightbox();
})
}
if (options.enableKeyboard) {
$(document).on('keyup', function (e) {
if (!image.length) return true;
e.preventDefault();
if (e.keyCode == 27) quitLightbox();
if (e.keyCode == 37 || e.keyCode == 39) {
target = targets.eq(targets.index(target) - (e.keyCode == 37 ? 1 : -1));
if (!target.length) target = targets.eq(e.keyCode == 37 ? targets.length : 0);
loadImage(e.keyCode == 37 ? 'left' : 'right');
}
});
}
$(document).on('click', this.selector, function (e) {
if (!isTargetValid(this)) return true;
e.preventDefault();
if (inProgress) return false;
inProgress = false;
if (options.onStart !== false) options.onStart();
target = $(this);
loadImage();
});
this.each(function () {
if (!isTargetValid(this)) return true;
targets = targets.add($(this));
});
this.switchImageLightbox = function (index) {
var tmpTarget = targets.eq(index);
if (tmpTarget.length) {
var currentIndex = targets.index(target);
target = tmpTarget;
loadImage(index < currentIndex ? 'left' : 'right');
}
return this;
};
this.quitImageLightbox = function () {
quitLightbox();
return this;
};
return this;
};
Firstly,
$(function () {
window.lightbox = $('a[data-imagelightbox="d"]').imageLightbox();
});
At the end of your "imagelightbox.js", Add the below code.
this.quitImageLightbox = function() {
quitLightbox();
return this;
};
this.loadImages = function(images_array) {
targets = images_array;
console.log(targets);
console.log(targets.length);
return this;
};
And when you get newly loaded images
windows.lightbox.loadImages(images_array)
and it should be working...!

Categories

Resources