So smooth scrolling like on this website - smooth-scrolling

How to implement smooth scrolling like on this website?
https://boredomdoctors.com/banjo-dog/

I've found on website similar solution:
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 / 2;
handle(delta);
if (event.preventDefault) event.preventDefault();
event.returnValue = false;
}
function handle(delta) {
var time = 900; // delay time
var distance = 140; // delta point
// Dom where it will apply
$('html, body').stop().animate({
scrollTop: $(window).scrollTop() - (distance * delta)
}, time, 'easeOutExpo' );
}

Related

Threejs lerp, lerpVectors work without animation

I am trying to move 10 meshes in different directions after some amount of time through functions lerp, lerpVectors. Both of them gave me the same result, they just teleported meshes in new positions without animation of moving there. Here is my code (with "lerp"):
var newPos;
var timer = 0;
function render() {
if (timer === 120) {
for (var i = 0; i < count; i++) {
mesh = meshes[i];
newPos = new THREE.Vector3(Math.random() * 200 - 100, Math.random() * 200 - 100, Math.random() * 200 - 100);
mesh.position.lerp(newPos, 0.5);
}
}
timer++;
renderer.render(scene, camera);
}
I am sure there is another way through calculated distances and then decreasing them to 0. But I suppose lerp and leprVectors do the same thing, so the question is what I do wrong?
r83
Maybe these both functions work not as I expect.
Okay, I've just figured out where was the problem. Lerp in the official documentation looks as .lerp(v3, alpha) and the value alpha should changing dynamically, so I added clock:
var delta = clock.getDelta();
and alpha now:
alpha += delta;
also I added boolean variable to the each mesh to check whether it's enough to do lerp or not, moreover, I set a new position during initiating for each of them as a parameter like so:
mesh.newPosition = new THREE.Vector3(
Math.random() * 200 - 100, Math.random() * 200 - 100, Math.random() * 200 - 100
);
and as a result I updated my render function:
var timer = 0;
var alpha = 0;
var delta;
var currentX, currentY, currentZ;
function render() {
delta = clock.getDelta();
for (var i = 0; i < count; i++) {
mesh = meshes[i];
if (timer === 120) {
mesh.endTransition = false;
}
if (!mesh.endTransition ) {
currentX = Math.abs(mesh.newPosition.x - mesh.position.x);
currentY = Math.abs(mesh.newPosition.y - mesh.position.y);
currentZ = Math.abs(mesh.newPosition.z - mesh.position.z);
if (currentX >= 1 || currentY >= 1 || currentZ >= 1) {
alpha += delta;
mesh.position.lerp(mesh.newPosition, alpha);
} else {
mesh.endTransition = true;
}
}
}
timer++;
renderer.render(scene, camera);
}
Perhaps my solution can be improved.

Change duration of canvas animation with Request Animation Frame

I'm trying to animate a circle that will draw itself similar to a progress bar. I'm intending to use it on a carousel to track when the next slide is coming up. The problem I'm having is I don't know how to change the duration of the animation. I tried adjusting the framerate, and it works but the animation gets really choppy. setInterval kind of works but it displays the entire circle rather than just a portion of it like I'm intending, so I can't time things properly. I need to be able to control the speed of the animation, slowing it down without it being stuttery. The code I'm working on is below.
<script>
(function() {
var requestAnimationFrame = window.requestAnimationFrame ||
window.mozRequestAnimationFrame ||
window.webkitRequestAnimationFrame ||
window.msRequestAnimationFrame;
window.requestAnimationFrame = requestAnimationFrame;
})();
var canvas = document.getElementById('myCanvas');
var context = canvas.getContext('2d');
var centerX = canvas.width / 2;
var centerY = canvas.height / 2;
var radius = 90;
var endPercent = 85;
var curPerc = 0;
var circ = -Math.PI;
var quart = -(Math.PI * 2) + 1;
function animate(current) {
context.clearRect(0, 0, canvas.width, canvas.height);
context.beginPath();
context.arc(centerX, centerY, radius, -(quart), ((circ) * current) - quart, true);
context.lineWidth = 3;
context.strokeStyle = '#000';
context.stroke();
curPerc++;
if (curPerc < endPercent) {
requestAnimationFrame(function () {
animate(curPerc / 100)
});
}
}
animate();
</script>
requestAnimationFrame does pass an high resolution timestamp in the callback argument. So you could use it to determine where you are in your current animation, and use this delta time to set your positions variables instead of curPerc++.
Here is a naive implementation.
var canvas = document.getElementById('myCanvas');
var context = canvas.getContext('2d');
var centerX = canvas.width / 2;
var centerY = canvas.height / 2;
var radius = 90;
var endPercent = 85;
var quart = -(Math.PI * 2) + 1;
var startTime = null;
var duration = null;
function animate(time) {
if (!startTime) {
startTime = time;
}
var delta = Math.min(1, (time - startTime) / duration);
var curPerc = ((-2 * Math.PI) / 100) * (endPercent * delta);
context.clearRect(0, 0, canvas.width, canvas.height);
context.beginPath();
context.arc(centerX, centerY, radius, -quart, curPerc - quart, true);
context.stroke();
if (delta < 1) {
requestAnimationFrame(animate);
} else {
startTime = null;
slider.disabled = false;
}
}
var startAnim = function() {
context.lineWidth = 3;
context.strokeStyle = '#000';
slider.disabled = true;
duration = +slider.value;
l.textContent = duration + 'ms';
requestAnimationFrame(animate);
};
slider.onchange = startAnim;
startAnim();
<p>use the slider to update the animation's duration</p>
<input type="range" min="250" max="9000" value="2000"id="slider" />
<label id="l"></label><br>
<canvas id="myCanvas" height="300"></canvas>

three.js animation logic for spinning cuboids

I'm trying to create a cuboid from 5 cuboids one of top of the other - that rotates 180 CW degrees every two seconds.
It's kinda working but I'm not getting smooth results... I thought a good strategy would be that during the rotating period- the z-position of the top-left and top-right vertices of a single face will be compared- if they are the same then it's time to stop the rotating period.
The problem is that the difference between the vertices is never zero.. it's very close to zero... so I check if it's in a margin of 0.1 and thus I have a problem with the beginning of a rotation that is jammed because sometimes it's less than 0.1. Also sometimes the rotations continue when they should stop because the difference is not less than 0.1.
var spinningPeriod = false, counter = 0, lastTime = 0;
function animate(){
counter++;
var time = (new Date()).getTime();
var timeDiff = time - lastTime;
var angleChange = 0.2 * timeDiff * 2 * Math.PI / 1000;
if (counter%200==0 && counter > 0) {
spinningPeriod = true;
}
if (spinningPeriod) {
var v1 = cubes[0].geometry.vertices[0].clone();
var v2 = cubes[0].geometry.vertices[3].clone();
cubes[0].updateMatrixWorld();
cubes[0].localToWorld(v1);
cubes[0].localToWorld(v2);
if (Math.abs(v1.x - v2.x) < 0.1) {
spinningPeriod = false;
}
for (var ii =0; ii<5; ++ii) {
cubes[ii].rotation.y += angleChange;
}
}
lastTime = time;
renderer.render(scene, camera);
// request new frame
requestAnimationFrame(function(){
animate();
});
}
// renderer
var renderer = new THREE.WebGLRenderer();
renderer.setSize(window.innerWidth, window.innerHeight);
document.body.appendChild(renderer.domElement);
// camera
var camera = new THREE.PerspectiveCamera(45, window.innerWidth / window.innerHeight, 1, 1000);
camera.position.z = 500;
// scene
var scene = new THREE.Scene();
// cube
var cubes = new Array();
var currentHeight = -150;
for (var ii =0; ii<5; ++ii) {
cubes[ii] = new THREE.Mesh(new THREE.CubeGeometry(400, 50, 20));
currentHeight += 50;
cubes[ii].position.y = currentHeight;
cubes[ii].overdraw = true;
scene.add(cubes[ii]);
}
// start animation
animate();
I agree, looking at the position is probably not the best way to do it. If you're concerned with the angle, then the angle should be your focus. Basically you want to have your test be based on the spin vs a max spin - when you're more than that, stop and adjust as needed (in this case, it was sometimes > 1 with the amount of angleChange, so I just reset it to 1).
Instead of your animate function above, try this one - it looks like it works pretty reliably for me.
var spinningPeriod = false, counter = 0, lastTime = 0;
var spinAngle = 0, spinMax = 1 * Math.PI;
function animate(){
counter++;
var time = (new Date()).getTime(),
timeDiff = time - lastTime,
speed = 0.2 * 2 * Math.PI / 1000,
angleChange = speed * timeDiff;
if (counter%200==0 && counter > 0) {
spinningPeriod = true;
spinAngle = 0;
}
console.log(counter, spinningPeriod, cubes[0].rotation.y / Math.PI);
if (spinningPeriod) {
spinAngle += angleChange;
if (spinAngle > spinMax) {
spinningPeriod = false;
spinAngle = spinMax;
}
for (var ii =0; ii<5; ++ii) {
cubes[ii].rotation.y = spinAngle;
}
}
lastTime = time;
renderer.render(scene, camera);
// request new frame
requestAnimationFrame(function(){
animate();
});
}

Accessing single particles in THREE.js Particle System

I really tried every example, searched the web for hours but I can't seem to get it working!
So I simply tried to implement a little particle system simulating falling snow, just like this: http://www.aerotwist.com/tutorials/creating-particles-with-three-js/
But I only can access it in whole. Meaning I can rotate it as such but as soon as I try to iterate over it's vertices, the whole animation is getting the hiccups! I would really appreciate some help here!
-
Here are the key parts:
-> Setting up the particle system:
var partikelGeo = new THREE.Geometry();
var partikelMaterial = new THREE.ParticleBasicMaterial({
color:0xffffff,
size: 10,
map: THREE.ImageUtils.loadTexture('snowflake2.png'),
blending: THREE.AdditiveBlending,
transparent:true
});
var partikelAnzahl = 3500;
for (var p = 0; p < partikelAnzahl; p++) {
var pX = Math.random() * 1000 -500;
var pY = Math.random() * 1000 -500;
var pZ = Math.random() * 1000 -500;
var partikel = new THREE.Vertex(new THREE.Vector3(pX,pY,pZ));
partikel.velocity = new THREE.Vector3(0,-Math.random(),0);
partikelGeo.vertices.push(partikel);
}
var partikelSystem = new THREE.ParticleSystem(partikelGeo, partikelMaterial);
partikelSystem.sortParticles = true;
scene.add(partikelSystem);
-> Rendering & Animation on mouseclick
var frame = 0;
function animate(){
// request new frame
requestAnimationFrame(function(){
animate();
});
// render
render();
}
animate();
var check = 0;
onmousedown = function(){
if (check) {
check = 0;
}else{
check = 1;
}
}
function render() {
if (check) {
clickDo();
}
camera.lookAt(new THREE.Vector3(0,0,0));
renderer.render(scene,camera);
}
function clickDo() {
frame++;
partikelSystem.rotation.y += 0.01;
var pCount = partikelAnzahl;
while(pCount--) {
// get the particle
var particle =
partikelGeo.vertices[pCount];
// check if we need to reset
if(particle.position.y < -200) {
particle.position.y = 200;
particle.velocity.y = 0;
}
// update the velocity with
// a splat of randomniz
particle.velocity.y -=
Math.random() * .1;
// and the position
particle.position.addSelf(
particle.velocity);
}
// flag to the particle system
// that we've changed its vertices.
partikelSystem.
geometry.
__dirtyVertices = true;
}
Rah
Your code looks good to me. I would just suggest to try not sorting your particles as you use an additive blending:
partikelSystem.sortParticles = false;

Scroll to top does no work

Hello I am new to jQuery and I have a problem!
I want to scroll to the top, in a page that is loaded via AJAX call.
This works (test):
$(document).on('click', '#top_icon', function() {
alert('ok');
});
But this is not working (this is what I want to achieve):
$(document).on('click', '#top_icon', function() {
$('html, body').animate({scrollTop: '0px'}, 800);
});
Try this,
$(document).on('click', '#top_icon', function() {
$('html, body').animate({'scrollTop': '0px'}, 800);
return false;
});
scrollTop is undefined in your case.
I am not sure about jQuery, but scrollTop is not a CSS property and therefor might not be part of the properties that can be animated.
But you can create a simple animation for this yourself:
var startValue = 0;
var endValue = 0;
var duration = 800;
var distance = 0;
var velocity = 0;
var step = 0;
var endTime = 0;
var animate = function() {
var elapsedTime = new Date().getTime() - step;
document.body.scrollTop += velocity * elapsedTime;
step = new Date().getTime();
if (step > endTime)
document.body.scrollTop = endValue;
else
setTimeout(animate, 15);
}
yourButton.onclick = function() {
startValue = document.body.scrollTop;
distance = endValue - startValue;
velocity = distance / duration;
step = new Date().getTime();
endTime = step + duration;
animate();
};
​
Here is a fiddle: http://jsfiddle.net/pXvQG/12/, animate by scrolling down and click the body.

Resources