I want to create a half sinus curve between two points. I have a loop every minute to calculate the new value.
Start value: 6500
End value: 2700
The timerange ist for example sunrise to sunset (eg: 1673931600000 and 1673970886131)
I have the "sun minutes per day". eg. 654.76885
Now, I want to calculate every minute the new value. => adaptiveCtTimed
Here a example of the Curve;
For a linear curve, I use the following code which works perfect.
sunMinutesDay = (sunset - sunrise) / 1000 / 60;
RangePerMinute = CtRange / sunMinutesDay;
if (await compareTime(adapter, sunrise, sunset, "between", ActualTime)) {
adaptiveCtTimed = Math.round(maxCt - ((ActualTime - morningTime) / 1000 / 60) * RangePerMinute);
}
Related
Based on this SO answer:
Changing the interval of SetInterval while it's running
I created this mini Svelte-Repl:
https://svelte.dev/repl/ae3987eff26446b49af4a85d029acd80?version=3.49.0
Which looks like this:
<script>
let display = 100
let interval = 1;
let myFunction = function() {
display--
interval *= 1.07;
setTimeout(myFunction, interval);
}
setTimeout(myFunction, interval);
</script>
{#if display > 0}
{display}
{:else}
End
{/if}
So the function myFunction calls itself while changing (increasing) the interval so that the count-down slows down. Now I would like to count down from 100 and slowly make the interval longer. I was thinking about the Math on how to achieve that, but couldn't work it out. I'd be grateful for any tips:)
Update:
I guess the question is kind of badly expressed. The idea was to:
Have a decreasing counter (display) from 100 to 0
The speed in which this counter decreases should become smaller, meaning that changing from e.g. 90 to 89 takes less time than from 10 to 9
The function in which it decreases does not matter. It can be exponentially, linearly or any other function. My aim was more about knowing how to solve this "generally"
The entire process, decreasing the variable display from 100 to 0, should take (can also be roughly) 10 seconds.
How would I do the Math?
Instead of changing the interval times, have a fast rate (frame rate, with requestAnimationRate), and calculate the counter's value based on the timestamp (i.e. the time that has elapsed since the start of the count down).
I would go for a formula that does not lead to exponentially increasing delays, but a less "drastic" one. For instance, you could use this formula to translate elapsed time to a counter value:
initialCount - r * sqrt(elapsed_time)
The coefficient r is then determined by the requirement that after 10 seconds this expression should be zero, so that brings us to:
r = initialCount / sqrt(total_duration)
Instead of a square root (i.e. exponent 0.5), you could use another exponent. The derivation of the value of r remains the same then (using that exponent).
Here is an implementation, where I have also displayed the elapsed time, so to verify it works as intended:
let [span, control] = document.querySelectorAll("span");
function countDown(counterStart, duration) {
const exp = 0.3; // Between 0 and 1: determines the gravity of the slow-down
let r = counterStart / duration ** exp;
let startTime;
function loop(timestamp) {
if (!startTime) startTime = timestamp;
const elapsed = timestamp - startTime;
const counter = Math.ceil(counterStart - r * elapsed ** exp);
span.textContent = Math.max(0, counter);
control.textContent = Math.floor(elapsed / 100) / 10;
if (counter > 0) requestAnimationFrame(loop);
}
requestAnimationFrame(loop);
}
countDown(100, 10000);
Count down: <span></span><br>
Elapsed time: <span></span>
If you wish to stick with exponentially increasing delays, then use a logarithm instead of a root:
initialCount - r * log(elapsed_time)
The code is very similar:
let [span, control] = document.querySelectorAll("span");
function countDown(counterStart, duration) {
let r = counterStart / Math.log(duration);
let startTime;
function loop(timestamp) {
if (!startTime) startTime = timestamp;
const elapsed = timestamp - startTime;
const counter = Math.ceil(counterStart - r * Math.log(elapsed));
span.textContent = Math.max(0, counter);
control.textContent = Math.floor(elapsed / 100) / 10;
if (counter > 0) requestAnimationFrame(loop);
}
requestAnimationFrame(loop);
}
countDown(100, 10000);
Count down: <span></span><br>
Elapsed time: <span></span>
I am using map coordinates as a part of website logo. (2.378628, 48.853373).
What I want to do, is count both numbers from 0.000000 so they reach given points during the same time (3-5 seconds), incrementing by 0.000001. How is that possible? This crashes my computer, and setInterval does sth every ms, which is not enough.
while (i < 48.853373) {
i = i + 0.000001;
$('.js-center-lat').text(i);
}
Sounds like you want to "animate" the floating point number to count up to a defined value.
Have you considered third party libraries, like CountUp.js?
CountUp.js is a dependency-free, lightweight JavaScript "class" that can be used to quickly create animations that display numerical data in a more interesting way.
Quick example on how to use it:
var options = {
useEasing: true,
useGrouping: true,
separator: '',
decimal: '.',
};
var demo = new CountUp('myTargetElement', 0, 2.415543, 6, 2.5, options);
if (!demo.error) {
demo.start();
} else {
console.error(demo.error);
}
Hope this helps!
You take the time when you started the animation (startTime), and you have value how long the animation should last (duration).
For each animation step you can calculate the percentage of the animation.
And with that percentage you can count up multiple values.
let startTime = Date.now();
let duration = 3000;
function updateText() {
let percent = Math.min(1, (Date.now() - startTime) / duration);
// Math min ensures that percent does not become larger then 1
$('.val1').text(50 * percent); // 0 - 50
$('.val2').text(33 * percent); // 0 - 33
$('.val3').text(13 + 10 * percent); // 13 - 23
if (percent <= 1) {
requestAnimationFrame(updateText)
}
}
updateText();
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<div class="val1">
</div>
<div class="val2">
</div>
<div class="val3">
</div>
Am writing a javascript function to rotate the hour hand per second .
For example:
1 second = 6 deg ("rotation angle")
1 minute = 6 / 60 = 0.1 deg ("rotation angle per second")
Question
1 hour = ???? = ???? deg ("rotation angle per second")
My Initial guess
my guess was : since 1 hour = 3600 seconds
then 1 hour = 6 / 3600 = 0.001666667 deg ("rotation angle per second")
But this was wrong when i implemented it in my clock application.
It made the hour hand move only by 1 / 5 hours per hour instead of 1
12 hours : 360 degs
1 hour : 30 degs
60 mins : 30 degs
1 min : 0.5 degs
60 s : 0.5 degs
1 s : 0.00833333333... degs
If my math is right, that's your answer
The hour hand rotates 360 degrees in twelve hours; its angular velocity is 360 degrees/12 hours = 30 degrees/hour.
There are 3600 seconds in an hour.
Therefore, the angular velocity of the hour hand is
(30 degrees/hour)*(1 hour/3600 seconds) = 0.0083333333 degree/second
It's a simple matter of units.
I've seen this kinda structure inside the update function in HTML5, Canvas games, with a "modifier" variable:
function update(modifier) {
obj.x += obj.speed * modifier
obj.y += obj.speed * modifier
}
function main() {
var thisLoop = new Date
var delta = thisLoop - lastLoop
update(delta / 1000)
render()
var lastLoop = new Date
}
var lastLoop = new Date
setInterval(main, 1)
Now I use myself this structure:
function update() {
obj.x += obj.speed
obj.y += obj.speed
render()
window.requestAnimationFrame(update)
}
What is the "modifier" supposed to do in the first structure?
And which one of them is the best to use, or is there maybe structure with both "modifier" and "requestAnimationFrame" too?
If you need your animation to be locked to time then you need a way to compensate for for example variable frame rates which of course then also have variable time between each frame.
A modifier could (as it's not shown how it is calculated) be used to fine-tune the speed/movement by compensating for this variation.
A couple of things though: don't use such as short time interval (1) as this could have an overall negative effect - you won't be able to update anything faster than the frame rate anyways so use nothing less than 16 ms.
Try to use requestAnimationFrame (rAF) instead as this is the only mechanism able to actually synchronize to the monitor update. rAF also passes a high-resolution timestamp which you can use for the compensator.
For example:
At 60 FPS you would expect a frame to last about 16.67ms.
So a modifier could be set as:
modifier = timeElapsed / 16.67;
If frame was able to run on time the value would be 1 in theory.
modifier = 16.67 / 16.67 = 1;
Now, if a frame iteration for some reason took more time, for example the double, you would get 2 as value for modifier.
modifier = 33.34 / 16.67 = 2;
How does this manifest in practical terms?
If you needed to move 100 pixels per frame then in the first situation when we were on time:
modifier = 16.67 / 16.67 = 1;
vx = 100 * modifier = 100; // # 1 frame = 100 pixels / frame
In the second case we spent two frames which means we needed it to move 200 pixels but since we didn't get that frame in between we need to use the modifier to compensate:
modifier = 33.34 / 16.67 = 2;
vx = 100 * modifier = 200; // # 2 frames = 100 pixels / frame
So here you see even if the frame rate was variant we moved what we expected to move anyways.
To calculate time elapsed simply use the rAF argument:
var oldTime = 0 // old time
frameTime = 1000 / 60; // frame time, based on 60 FPS, in ms
function loop(time) {
var timeElapsed = time - oldTime; // get difference
oldTime = time; // store current time as old time
var modifier = timeElapsed / frameTime; // get modifier based on FPS
...
requestAnimationFrame(loop);
}
Now, all that being said - modifier could also be just a value used to control speed... :-)
The newer version of requestAnimationFrame will return an elapsed time since the animation began.
You can use this elapsed time to determine where your animated objects should be redrawn.
For example, assume you have a ball object with an x property indicating it's x-coordinate.
If you want the ball to move 10 pixels right every 1000ms you can do this (untested!):
// set the starting x-coordinate of the ball
var ballStartingX=50;
ball.x=ballStartingX;
// get the time when the animation is started
var startingTime = performance.now();
// start the animation
requestAnimationFrame(update);
// update() is the animation loop function
function update(timestamp){
// request another frame
requestAnimationFrame(update);
// reposition the ball
// (timestamp-startTime) is the milliseconds elapsed
ball.x = ballStartingX + 10 * (timestamp-startTime)/1000;
}
i am trying to make a character based on Time and FPS.
What i need is make my character jump last for exactly 1 second.Right now i am using below code and it makes the character jump for 1 second.But problem is ..if the fps is 60 character moves 60 pixels , and if fps is 30 it moves only 30 pixels...How can i solve this..
I need character to move 60 pixels regardless fps and within 1 second.
//Below is the requestanimation frame loop
// which runs the loop 60 to 30 times per second ,
// which vary according to browser.
function jumpcheck()
{
if(isjump)
{
ball.posy -=1; //make the character move 10 px based on fps..
window.timeoutHandle = window.setTimeout(function() {
isjump = false;
}, 1000);
}
}
}
note:request animation frame fps is something between 20 to 60 always changing.
Code as said by constantinous
var lastUpdate = Date.now();
function jumpcheck()
{
if(isjump)
{
speed = 1;
position = ball.posy;
var now = Date.now();
var dt = (now - lastUpdate) / 1000;
lastUpdate = now;
ball.posy = position + (speed * dt)
}
}
For games it is usual to include the time since the last frame into your calculations. This time is usually called dt for delta-time. To calculate your new position you simply multiply the passed time with the current speed to get the new position. In pseudo-code this looks like this:
speed = ...
position = ...
dt = ...
position = position + (speed * dt)