Ease in and out curve in for loop - javascript

I have a for loop like this:
var speed = 100;
var curve = [];
for (var i = 0; i < 5; i++) {
curve.push(i*speed);
}
So for the last loop its 400, the question is how do i implement ease in and out in the for loop? roughly in the end the result should be like this? [0,52,200,348,400]
EDIT:
var defaultSpin = 24;
var totalSlices = 12;
for (var i = 0; i < defaultSpin; i++) {
highlight(divs[i%totalSlices], i*100, 100);
}
function highlight(el, delay, duration) {
setTimeout(function() {
el.className += ' active';
setTimeout(function() {
el.className = 'pie';
}, duration)
}, delay)
}
It is a spin wheel with highlight instead of actually spinning it. I'm calling the above function with the loop. for now it only has constant speed because each loop difference is only 100 so the 1st hightlight delay is 0 and it start immediately. 2nd is 100, 3rd is 200 and so on.

Lots of common easing functions are shown here:
http://gizma.com/easing/
Here is an example of how to use one:
// from http://gizma.com/easing/
var easeInOutQuad = function (t, b, c, d) {
t /= d/2;
if (t < 1) return c/2*t*t + b;
t--;
return -c/2 * (t*(t-2) - 1) + b;
};
var steps = 4
var speed = 100
var curve = []
for (var i = 0; i < steps+1; i++) {
var stepValue = easeInOutQuad(i, 0, speed*steps, steps);
curve.push(stepValue);
}
console.log(curve); // [0, 50, 200, 350, 400]

Hey take a note of this snippet
/*\
* Raphael.easing_formulas
[ property ]
**
* Object that contains easing formulas for animation. You could extend it with your own. By default it has following list of easing:
# <ul>
# <li>“linear”</li>
# <li>“<” or “easeIn” or “ease-in”</li>
# <li>“>” or “easeOut” or “ease-out”</li>
# <li>“<>” or “easeInOut” or “ease-in-out”</li>
# <li>“backIn” or “back-in”</li>
# <li>“backOut” or “back-out”</li>
# <li>“elastic”</li>
# <li>“bounce”</li>
# </ul>
# <p>See also Easing demo.</p>
\*/
var ef = R.easing_formulas = {
linear: function (n) {
return n;
},
"<": function (n) {
return pow(n, 1.7);
},
">": function (n) {
return pow(n, .48);
},
"<>": function (n) {
var q = .48 - n / 1.04,
Q = math.sqrt(.1734 + q * q),
x = Q - q,
X = pow(abs(x), 1 / 3) * (x < 0 ? -1 : 1),
y = -Q - q,
Y = pow(abs(y), 1 / 3) * (y < 0 ? -1 : 1),
t = X + Y + .5;
return (1 - t) * 3 * t * t + t * t * t;
},
backIn: function (n) {
var s = 1.70158;
return n * n * ((s + 1) * n - s);
},
backOut: function (n) {
n = n - 1;
var s = 1.70158;
return n * n * ((s + 1) * n + s) + 1;
},
elastic: function (n) {
if (n == !!n) {
return n;
}
return pow(2, -10 * n) * math.sin((n - .075) * (2 * PI) / .3) + 1;
},
bounce: function (n) {
var s = 7.5625,
p = 2.75,
l;
if (n < (1 / p)) {
l = s * n * n;
} else {
if (n < (2 / p)) {
n -= (1.5 / p);
l = s * n * n + .75;
} else {
if (n < (2.5 / p)) {
n -= (2.25 / p);
l = s * n * n + .9375;
} else {
n -= (2.625 / p);
l = s * n * n + .984375;
}
}
}
return l;
}
};
ef.easeIn = ef["ease-in"] = ef["<"];
ef.easeOut = ef["ease-out"] = ef[">"];
ef.easeInOut = ef["ease-in-out"] = ef["<>"];
ef["back-in"] = ef.backIn;
ef["back-out"] = ef.backOut;
This is a snippet from Raphael. Here you see you have a list of animation ease-in formulas.
Lets try one of them, e.g. ease-in
var pow = Math.pow;
function easeIn(n) {
return pow(n, 1.7);
}
function easeOut(n) {
return pow(n, .48);
}
function process(min, max, intervals, fN) {
var diff = 1 / intervals,
difference = max - min,
curve = [];
for (i = diff; i <= 1; i += diff) {
curve.push(min + (difference * fN(i)));
}
return curve;
}
console.log('easeIn: \n', process(0, 400, 5, easeIn));
console.log('easeOut: \n', process(0, 400, 5, easeOut));
This might not be in sync with the output you have expected. But these are the formulas a renowned JS SVG library like Rapahel uses. You would love this demo

Related

Why RSA Encryption decryption is wrong when I change the message using JavaScript?

RSA is an encryption algorithm based on factoring large integers. In RSA, two large prime numbers and a supplementary value are generated as public key. Anyone can use the public key to encrypt a message, but only those with the prime factors can decode the message. There are three phases in the process:
key generation - The public key and private key are generated. The construction method of the keys
generated should be secret.
encryption - The message can be encrypted via public key
decryption - Only the private key can be used to decrypt the
message
Encryption process is as shown:
m - message:
m^e % n = c
c - encrypted message
Decryption process is as shown:
c^d % n = m
This is the implementation of calculating d:
function modInverse(e, phi) {
var m0 = phi, t, q;
var x0 = 0, x1 = 1;
if (phi == 1)
return 0;
while (e > 1) {
// q is quotient
q = Math.floor(e / phi);
t = phi;
// phi is remainder now, process same as
// Euclid's algo
phi = e % phi, e = t;
t = x0;
x0 = x1 - q * x0;
x1 = t;
}
// Make x1 positive
if (x1 < 0)
x1 += m0;
return x1;
}
modInverse(7, 40) // 23
Key pairs of a public key and a private key also need to be generated. Let’s pick 5 and 11 as the primes:
function modInverse(e, phi) {
var m0 = phi, t, q;
var x0 = 0, x1 = 1;
if (phi == 1)
return 0;
while (e > 1) {
// q is quotient
q = Math.floor(e / phi);
t = phi;
// phi is remainder now, process same as
// Euclid's algo
phi = e % phi, e = t;
t = x0;
x0 = x1 - q * x0;
x1 = t;
}
// Make x1 positive
if (x1 < 0)
x1 += m0;
return x1;
}
function isPrime(n){
var prime_numbers=[2,3,5,7,11,13,17,19,23,29,31,37,41,43,47,53,59,61,67,71,73,79,83,89,97]
for(let i of prime_numbers){
if(n===i){
return true
}
}
}
function RSAKeyPair(p, q) {
// Need to check that they are primes
if (!(isPrime(p) && isPrime(q)))
return;
// Need to check that they're not the same
if (p == q)
return;
var n = p * q,
phi = (p - 1) * (q - 1),
e = 3,
d = modInverse(e, phi);
// Public key: [e,n], Private key: [d,n]
return [[e, n], [d, n]]
}
RSAKeyPair(5,11) //Public key: [3,55], Private key: [27,55]
Complete: Encryption and Decryption
function modInverse(e, phi) {
var m0 = phi, t, q;
var x0 = 0, x1 = 1;
if (phi == 1) {
return 0;
}
while (e > 1) {
// q is quotient
q = Math.floor(e / phi);
t = phi;
// phi is remainder now, process same as
// Euclid's algo
phi = e % phi // 3 % 40
e = t; // e = 40
t = x0; // t = 0
x0 = x1 - q * x0; // 1-0|13|3 x 0
x1 = t; // 0
}
// Make x1 positive
if (x1 < 0) {
x1 += m0;
}
return x1;
}
function isPrime(n){
var prime_numbers=[2,3,5,7,11,13,17,19,23,29,31,37,41,43,47,53,59,61,67,71,73,79,83,89,97]
for(let i of prime_numbers){
if(n===i){
return true
}
}
}
function RSAKeyPair(p, q) {
// Need to check that they are primes
if (!(isPrime(p) && isPrime(q))) {
return;
}
// Need to check that they're not the same
if (p==q) {
return;
}
var n = p * q,
phi = (p-1)*(q-1),
e = 3,
d = modInverse(e,phi);
// Public key: [e,n], Private key: [d,n]
return [[e,n], [d,n]]
}
RSAKeyPair(5,11)
for (let i in RSAKeyPair(5,11)){
var encrypted_message;
const encryption=c=>{
var m = 2,e = c[0], n = c[1], Encrypted_Message = m ** e % n
console.log("Encryption: " + Encrypted_Message)
encrypted_message=Encrypted_Message
}
const decryption=c=>{
var d = c[0], n = c[1], Decrypted_Message = encrypted_message ** d % n
console.log("Decryption: " + Decrypted_Message)
}
i=="0"?encryption(RSAKeyPair(5, 11)[0]) : i == "1" ? decryption(RSAKeyPair(5, 11)[1]) : false
}
Run it:
function modInverse(e, phi) {
var m0 = phi, t, q;
var x0 = 0, x1 = 1;
if (phi == 1) {
return 0;
}
while (e > 1) {
// q is quotient
q = Math.floor(e / phi);
t = phi;
// phi is remainder now, process same as
// Euclid's algo
phi = e % phi // 3 % 40
e = t; // e = 40
t = x0; // t = 0
x0 = x1 - q * x0; // 1-0|13|3 x 0
x1 = t; // 0
}
// Make x1 positive
if (x1 < 0) {
x1 += m0;
}
return x1;
}
function isPrime(n){
var prime_numbers=[2,3,5,7,11,13,17,19,23,29,31,37,41,43,47,53,59,61,67,71,73,79,83,89,97]
for(let i of prime_numbers){
if(n===i){
return true
}
}
}
function RSAKeyPair(p, q) {
// Need to check that they are primes
if (!(isPrime(p) && isPrime(q))) {
return;
}
// Need to check that they're not the same
if (p==q) {
return;
}
var n = p * q,
phi = (p-1)*(q-1),
e = 3,
d = modInverse(e,phi);
// Public key: [e,n], Private key: [d,n]
return [[e,n], [d,n]]
}
RSAKeyPair(5,11)
for (let i in RSAKeyPair(5,11)){
var encrypted_message;
const encryption=c=>{
var m=2,e=c[0],n=c[1],Encrypted_Message=m**e%n
console.log("Encryption: "+Encrypted_Message)
encrypted_message=Encrypted_Message
}
const decryption=c=>{
var d=c[0],n=c[1],Decrypted_Message=encrypted_message**d % n
console.log("Decryption: "+Decrypted_Message)
}
i=="0"?encryption(RSAKeyPair(5,11)[0]):i=="1"?decryption(RSAKeyPair(5,11)[1]):false
}
This encrypts the message 2, and the receiver can decrypt that back to 2. However, when I change the message 2 to 3:
function modInverse(e, phi) {
var m0 = phi, t, q;
var x0 = 0, x1 = 1;
if (phi == 1) {
return 0;
}
while (e > 1) {
// q is quotient
q = Math.floor(e / phi);
t = phi;
// phi is remainder now, process same as
// Euclid's algo
phi = e % phi // 3 % 40
e = t; // e = 40
t = x0; // t = 0
x0 = x1 - q * x0; // 1-0|13|3 x 0
x1 = t; // 0
}
// Make x1 positive
if (x1 < 0) {
x1 += m0;
}
return x1;
}
function isPrime(n) {
var prime_numbers = [2, 3, 5, 7, 11, 13, 17, 19, 23, 29, 31, 37, 41, 43, 47, 53, 59, 61, 67, 71, 73, 79, 83, 89, 97]
for (let i of prime_numbers) {
if (n === i) {
return true
}
}
}
function RSAKeyPair(p, q) {
// Need to check that they are primes
if (!(isPrime(p) && isPrime(q))) {
return;
}
// Need to check that they're not the same
if (p == q) {
return;
}
var n = p * q,
phi = (p - 1) * (q - 1),
e = 3,
d = modInverse(e, phi);
// Public key: [e,n], Private key: [d,n]
return [[e, n], [d, n]]
}
RSAKeyPair(5, 11)
for (let i in RSAKeyPair(5, 11)) {
var encrypted_message;
const encryption = c => {
var m = 3, e = c[0], n = c[1], Encrypted_Message = m ** e % n
console.log("Encryption: " + Encrypted_Message)
encrypted_message = Encrypted_Message
}
const decryption = c => {
var d = c[0], n = c[1], Decrypted_Message = encrypted_message ** d % n
console.log("Decryption: " + Decrypted_Message)
}
i == "0" ? encryption(RSAKeyPair(5, 11)[0]) : i == "1" ? decryption(RSAKeyPair(5, 11)[1]) : false
}
It gives different result. I expect 3 should be the answer, what is wrong?
The posted example uses p = 5 and q = 11 and determines for the modulus N = 55, the public exponent e = 3 and the private exponent d = 27 (returned by RSAKeyPair(5, 11)). This corresponds to a valid key pair.
Although small values are used, the intermediate results can be quite large.
With the plaintext m = 3 the ciphertext c = me mod 55 = 27 results for the encyrption. The value 33 = 27 is obviously uncritical.
For decryption, however, the decrypted data is m = cd mod 55 = 2727 mod 55. The value 2727 (approx. 4.4 * 1038) is critical, since it is above the maximum (safe) integer possible for JavaScript Number.MAX_SAFE_INTEGER = 253 - 1 = 9,007,199,254,740,991. This generally results in a wrong plaintext during decryption.
The problem can be solved by using BigInt for larger numbers:
var e = 3;
var d = 27;
var N = 55;
// Encryption
var m = 3; // getRandomInt(N) // For arbitrary plaintexts uncomment getRandomInt(N)
var c = m ** e % N;
console.log("Plaintext : " + m);
console.log("Ciphertext : " + c);
// Decryption without BigInt
var dec = c ** d % N;
console.log("Result without BigInt: " + dec); // Wrong
// Decryption with BigInt
var dec = BigInt(c) ** BigInt(d) % BigInt(N);
console.log("Result with BigInt : " + dec); // Correct
function getRandomInt(max) {
return Math.floor(Math.random() * Math.floor(max));
}
Of course this applies in general, i.e. not only to encryption and decryption, but also to the key generation, as soon as the values (including intermediate results) become accordingly large.
Edit: As mentioned in the comment, there are more efficient implementations for modular exponentiation than the direct one (= exponentiate, then taking the result modulo). For this, also existing libraries can be used, e.g. bigint-mod-arith, which applies the right-to-left binary method for modular exponentiation.

Stopping skew of the object while using camera.lookat() in three.js

I have made this short code to move a object randomly on the screen. I used camera.lookat(). But while using it I observed that when the model/object moves to the sides of the screen, in order to look at the camera it changes its shape a little. In a way one can say that it skews a little.
I wanted to used camera.lookat() without this skewing of the object. I have been trying for a while now but couldn't figure out a way to do it. Can anyone help me out here please. Here is my code:
EDIT
while running code snippet here you may find a error footer here. It's because of unavailability of tween.js cdn. Wait for some time after clicking on "run snippet" here and you will see a tower moving here and there.
My JS:
var scene = new THREE.Scene();
var camera = new THREE.PerspectiveCamera(75, window.innerWidth / window.innerHeight, 0.1, 1000);
var renderer = new THREE.WebGLRenderer();
renderer.setSize(window.innerWidth, window.innerHeight);
renderer.setClearColor(0xff0000, .5);
document.body.appendChild(renderer.domElement);
var light1 = new THREE.AmbientLight(0xffffff);
light1.position.set(0, -70, 100).normalize();
scene.add(light1);
var light2 = new THREE.AmbientLight(0xffffff);
light2.position.set(0, 70, 100).normalize();
scene.add(light2);
camera.position.z = 20;
var loader = new THREE.GLTFLoader();
loader.crossOrigin = true;
loader.load('https://docs.mapbox.com/mapbox-gl-js/assets/34M_17/34M_17.gltf', function(gltf) {
cube = gltf.scene;
// gltf.scene.position.y -= 15;
// gltf.scene.position.x -= 24;
// gltf.scene.lookAt(camera.position);
gltf.scene.position.set(-40, 0, -3.75);
gltf.scene.scale.set(0.4, 0.4, 0.4);
// gltf.scene.rotation.y += 0.6;
// gltf.scene.rotation.z -= 0.3;
scene.add(gltf.scene);
renderer.render(scene, camera);
maketween();
});
//// Setup the animation loop.
function animate(time) {
requestAnimationFrame(animate);
TWEEN.update(time);
renderer.render(scene, camera);
}
requestAnimationFrame(animate);
function maketween() {
var randomX = Math.floor(Math.random() * 57) - 28;
var randomY = Math.floor(Math.random() * 23) - 10;
var tween = new TWEEN.Tween({
x: cube.position.x,
y: cube.position.y,
z: cube.position.z
}) // Create a new tween that modifies 'coords'.
.to({
x: randomX,
y: randomY,
z: 0
}, 1000) // Move to (300, 200) in 1 second.
.easing(TWEEN.Easing.Quadratic.Out) // Use an easing function to make the animation smooth.
.repeat(0)
.onUpdate(function(object) {
// console.log("tween",randomX,randomY,object.x);
if (object.x == randomX || object.x == 0) {
var randomX = Math.floor(Math.random() * 57) - 28;
var randomY = Math.floor(Math.random() * 23) - 10;
// console.log("*",randomX,randomY);
} else {
cube.position.x = object.x;
cube.position.y = object.y;
}
cube.lookAt(camera.position);
}).onComplete(() => {
// console.log("tween stopped");
maketween();
});
tween.chain(tween);
tween.start();
}
//BELOW THIS POINT IS TWEEN.JS (NOT MY CODE)
(function (global, factory) {
typeof exports === 'object' && typeof module !== 'undefined' ? module.exports = factory() :
typeof define === 'function' && define.amd ? define(factory) :
(global.TWEEN = factory());
}(this, (function () { 'use strict';
var version = '18.4.2';
/**
* Tween.js - Licensed under the MIT license
* https://github.com/tweenjs/tween.js
* ----------------------------------------------
*
* See https://github.com/tweenjs/tween.js/graphs/contributors for the full list of contributors.
* Thank you all, you're awesome!
*/
var _Group = function () {
this._tweens = {};
this._tweensAddedDuringUpdate = {};
};
_Group.prototype = {
getAll: function () {
return Object.keys(this._tweens).map(function (tweenId) {
return this._tweens[tweenId];
}.bind(this));
},
removeAll: function () {
this._tweens = {};
},
add: function (tween) {
this._tweens[tween.getId()] = tween;
this._tweensAddedDuringUpdate[tween.getId()] = tween;
},
remove: function (tween) {
delete this._tweens[tween.getId()];
delete this._tweensAddedDuringUpdate[tween.getId()];
},
update: function (time, preserve) {
var tweenIds = Object.keys(this._tweens);
if (tweenIds.length === 0) {
return false;
}
time = time !== undefined ? time : TWEEN.now();
// Tweens are updated in "batches". If you add a new tween during an
// update, then the new tween will be updated in the next batch.
// If you remove a tween during an update, it may or may not be updated.
// However, if the removed tween was added during the current batch,
// then it will not be updated.
while (tweenIds.length > 0) {
this._tweensAddedDuringUpdate = {};
for (var i = 0; i < tweenIds.length; i++) {
var tween = this._tweens[tweenIds[i]];
if (tween && tween.update(time) === false) {
tween._isPlaying = false;
if (!preserve) {
delete this._tweens[tweenIds[i]];
}
}
}
tweenIds = Object.keys(this._tweensAddedDuringUpdate);
}
return true;
}
};
var TWEEN = new _Group();
TWEEN.Group = _Group;
TWEEN._nextId = 0;
TWEEN.nextId = function () {
return TWEEN._nextId++;
};
// Include a performance.now polyfill.
// In node.js, use process.hrtime.
if (typeof (self) === 'undefined' && typeof (process) !== 'undefined' && process.hrtime) {
TWEEN.now = function () {
var time = process.hrtime();
// Convert [seconds, nanoseconds] to milliseconds.
return time[0] * 1000 + time[1] / 1000000;
};
}
// In a browser, use self.performance.now if it is available.
else if (typeof (self) !== 'undefined' &&
self.performance !== undefined &&
self.performance.now !== undefined) {
// This must be bound, because directly assigning this function
// leads to an invocation exception in Chrome.
TWEEN.now = self.performance.now.bind(self.performance);
}
// Use Date.now if it is available.
else if (Date.now !== undefined) {
TWEEN.now = Date.now;
}
// Otherwise, use 'new Date().getTime()'.
else {
TWEEN.now = function () {
return new Date().getTime();
};
}
TWEEN.Tween = function (object, group) {
this._isPaused = false;
this._pauseStart = null;
this._object = object;
this._valuesStart = {};
this._valuesEnd = {};
this._valuesStartRepeat = {};
this._duration = 1000;
this._repeat = 0;
this._repeatDelayTime = undefined;
this._yoyo = false;
this._isPlaying = false;
this._reversed = false;
this._delayTime = 0;
this._startTime = null;
this._easingFunction = TWEEN.Easing.Linear.None;
this._interpolationFunction = TWEEN.Interpolation.Linear;
this._chainedTweens = [];
this._onStartCallback = null;
this._onStartCallbackFired = false;
this._onUpdateCallback = null;
this._onRepeatCallback = null;
this._onCompleteCallback = null;
this._onStopCallback = null;
this._group = group || TWEEN;
this._id = TWEEN.nextId();
};
TWEEN.Tween.prototype = {
getId: function () {
return this._id;
},
isPlaying: function () {
return this._isPlaying;
},
isPaused: function () {
return this._isPaused;
},
to: function (properties, duration) {
this._valuesEnd = Object.create(properties);
if (duration !== undefined) {
this._duration = duration;
}
return this;
},
duration: function duration(d) {
this._duration = d;
return this;
},
start: function (time) {
this._group.add(this);
this._isPlaying = true;
this._isPaused = false;
this._onStartCallbackFired = false;
this._startTime = time !== undefined ? typeof time === 'string' ? TWEEN.now() + parseFloat(time) : time : TWEEN.now();
this._startTime += this._delayTime;
for (var property in this._valuesEnd) {
// Check if an Array was provided as property value
if (this._valuesEnd[property] instanceof Array) {
if (this._valuesEnd[property].length === 0) {
continue;
}
// Create a local copy of the Array with the start value at the front
this._valuesEnd[property] = [this._object[property]].concat(this._valuesEnd[property]);
}
// If `to()` specifies a property that doesn't exist in the source object,
// we should not set that property in the object
if (this._object[property] === undefined) {
continue;
}
// Save the starting value, but only once.
if (typeof(this._valuesStart[property]) === 'undefined') {
this._valuesStart[property] = this._object[property];
}
if ((this._valuesStart[property] instanceof Array) === false) {
this._valuesStart[property] *= 1.0; // Ensures we're using numbers, not strings
}
this._valuesStartRepeat[property] = this._valuesStart[property] || 0;
}
return this;
},
stop: function () {
if (!this._isPlaying) {
return this;
}
this._group.remove(this);
this._isPlaying = false;
this._isPaused = false;
if (this._onStopCallback !== null) {
this._onStopCallback(this._object);
}
this.stopChainedTweens();
return this;
},
end: function () {
this.update(Infinity);
return this;
},
pause: function(time) {
if (this._isPaused || !this._isPlaying) {
return this;
}
this._isPaused = true;
this._pauseStart = time === undefined ? TWEEN.now() : time;
this._group.remove(this);
return this;
},
resume: function(time) {
if (!this._isPaused || !this._isPlaying) {
return this;
}
this._isPaused = false;
this._startTime += (time === undefined ? TWEEN.now() : time)
- this._pauseStart;
this._pauseStart = 0;
this._group.add(this);
return this;
},
stopChainedTweens: function () {
for (var i = 0, numChainedTweens = this._chainedTweens.length; i < numChainedTweens; i++) {
this._chainedTweens[i].stop();
}
},
group: function (group) {
this._group = group;
return this;
},
delay: function (amount) {
this._delayTime = amount;
return this;
},
repeat: function (times) {
this._repeat = times;
return this;
},
repeatDelay: function (amount) {
this._repeatDelayTime = amount;
return this;
},
yoyo: function (yoyo) {
this._yoyo = yoyo;
return this;
},
easing: function (easingFunction) {
this._easingFunction = easingFunction;
return this;
},
interpolation: function (interpolationFunction) {
this._interpolationFunction = interpolationFunction;
return this;
},
chain: function () {
this._chainedTweens = arguments;
return this;
},
onStart: function (callback) {
this._onStartCallback = callback;
return this;
},
onUpdate: function (callback) {
this._onUpdateCallback = callback;
return this;
},
onRepeat: function onRepeat(callback) {
this._onRepeatCallback = callback;
return this;
},
onComplete: function (callback) {
this._onCompleteCallback = callback;
return this;
},
onStop: function (callback) {
this._onStopCallback = callback;
return this;
},
update: function (time) {
var property;
var elapsed;
var value;
if (time < this._startTime) {
return true;
}
if (this._onStartCallbackFired === false) {
if (this._onStartCallback !== null) {
this._onStartCallback(this._object);
}
this._onStartCallbackFired = true;
}
elapsed = (time - this._startTime) / this._duration;
elapsed = (this._duration === 0 || elapsed > 1) ? 1 : elapsed;
value = this._easingFunction(elapsed);
for (property in this._valuesEnd) {
// Don't update properties that do not exist in the source object
if (this._valuesStart[property] === undefined) {
continue;
}
var start = this._valuesStart[property] || 0;
var end = this._valuesEnd[property];
if (end instanceof Array) {
this._object[property] = this._interpolationFunction(end, value);
} else {
// Parses relative end values with start as base (e.g.: +10, -3)
if (typeof (end) === 'string') {
if (end.charAt(0) === '+' || end.charAt(0) === '-') {
end = start + parseFloat(end);
} else {
end = parseFloat(end);
}
}
// Protect against non numeric properties.
if (typeof (end) === 'number') {
this._object[property] = start + (end - start) * value;
}
}
}
if (this._onUpdateCallback !== null) {
this._onUpdateCallback(this._object, elapsed);
}
if (elapsed === 1) {
if (this._repeat > 0) {
if (isFinite(this._repeat)) {
this._repeat--;
}
// Reassign starting values, restart by making startTime = now
for (property in this._valuesStartRepeat) {
if (typeof (this._valuesEnd[property]) === 'string') {
this._valuesStartRepeat[property] = this._valuesStartRepeat[property] + parseFloat(this._valuesEnd[property]);
}
if (this._yoyo) {
var tmp = this._valuesStartRepeat[property];
this._valuesStartRepeat[property] = this._valuesEnd[property];
this._valuesEnd[property] = tmp;
}
this._valuesStart[property] = this._valuesStartRepeat[property];
}
if (this._yoyo) {
this._reversed = !this._reversed;
}
if (this._repeatDelayTime !== undefined) {
this._startTime = time + this._repeatDelayTime;
} else {
this._startTime = time + this._delayTime;
}
if (this._onRepeatCallback !== null) {
this._onRepeatCallback(this._object);
}
return true;
} else {
if (this._onCompleteCallback !== null) {
this._onCompleteCallback(this._object);
}
for (var i = 0, numChainedTweens = this._chainedTweens.length; i < numChainedTweens; i++) {
// Make the chained tweens start exactly at the time they should,
// even if the `update()` method was called way past the duration of the tween
this._chainedTweens[i].start(this._startTime + this._duration);
}
return false;
}
}
return true;
}
};
TWEEN.Easing = {
Linear: {
None: function (k) {
return k;
}
},
Quadratic: {
In: function (k) {
return k * k;
},
Out: function (k) {
return k * (2 - k);
},
InOut: function (k) {
if ((k *= 2) < 1) {
return 0.5 * k * k;
}
return - 0.5 * (--k * (k - 2) - 1);
}
},
Cubic: {
In: function (k) {
return k * k * k;
},
Out: function (k) {
return --k * k * k + 1;
},
InOut: function (k) {
if ((k *= 2) < 1) {
return 0.5 * k * k * k;
}
return 0.5 * ((k -= 2) * k * k + 2);
}
},
Quartic: {
In: function (k) {
return k * k * k * k;
},
Out: function (k) {
return 1 - (--k * k * k * k);
},
InOut: function (k) {
if ((k *= 2) < 1) {
return 0.5 * k * k * k * k;
}
return - 0.5 * ((k -= 2) * k * k * k - 2);
}
},
Quintic: {
In: function (k) {
return k * k * k * k * k;
},
Out: function (k) {
return --k * k * k * k * k + 1;
},
InOut: function (k) {
if ((k *= 2) < 1) {
return 0.5 * k * k * k * k * k;
}
return 0.5 * ((k -= 2) * k * k * k * k + 2);
}
},
Sinusoidal: {
In: function (k) {
return 1 - Math.cos(k * Math.PI / 2);
},
Out: function (k) {
return Math.sin(k * Math.PI / 2);
},
InOut: function (k) {
return 0.5 * (1 - Math.cos(Math.PI * k));
}
},
Exponential: {
In: function (k) {
return k === 0 ? 0 : Math.pow(1024, k - 1);
},
Out: function (k) {
return k === 1 ? 1 : 1 - Math.pow(2, - 10 * k);
},
InOut: function (k) {
if (k === 0) {
return 0;
}
if (k === 1) {
return 1;
}
if ((k *= 2) < 1) {
return 0.5 * Math.pow(1024, k - 1);
}
return 0.5 * (- Math.pow(2, - 10 * (k - 1)) + 2);
}
},
Circular: {
In: function (k) {
return 1 - Math.sqrt(1 - k * k);
},
Out: function (k) {
return Math.sqrt(1 - (--k * k));
},
InOut: function (k) {
if ((k *= 2) < 1) {
return - 0.5 * (Math.sqrt(1 - k * k) - 1);
}
return 0.5 * (Math.sqrt(1 - (k -= 2) * k) + 1);
}
},
Elastic: {
In: function (k) {
if (k === 0) {
return 0;
}
if (k === 1) {
return 1;
}
return -Math.pow(2, 10 * (k - 1)) * Math.sin((k - 1.1) * 5 * Math.PI);
},
Out: function (k) {
if (k === 0) {
return 0;
}
if (k === 1) {
return 1;
}
return Math.pow(2, -10 * k) * Math.sin((k - 0.1) * 5 * Math.PI) + 1;
},
InOut: function (k) {
if (k === 0) {
return 0;
}
if (k === 1) {
return 1;
}
k *= 2;
if (k < 1) {
return -0.5 * Math.pow(2, 10 * (k - 1)) * Math.sin((k - 1.1) * 5 * Math.PI);
}
return 0.5 * Math.pow(2, -10 * (k - 1)) * Math.sin((k - 1.1) * 5 * Math.PI) + 1;
}
},
Back: {
In: function (k) {
var s = 1.70158;
return k * k * ((s + 1) * k - s);
},
Out: function (k) {
var s = 1.70158;
return --k * k * ((s + 1) * k + s) + 1;
},
InOut: function (k) {
var s = 1.70158 * 1.525;
if ((k *= 2) < 1) {
return 0.5 * (k * k * ((s + 1) * k - s));
}
return 0.5 * ((k -= 2) * k * ((s + 1) * k + s) + 2);
}
},
Bounce: {
In: function (k) {
return 1 - TWEEN.Easing.Bounce.Out(1 - k);
},
Out: function (k) {
if (k < (1 / 2.75)) {
return 7.5625 * k * k;
} else if (k < (2 / 2.75)) {
return 7.5625 * (k -= (1.5 / 2.75)) * k + 0.75;
} else if (k < (2.5 / 2.75)) {
return 7.5625 * (k -= (2.25 / 2.75)) * k + 0.9375;
} else {
return 7.5625 * (k -= (2.625 / 2.75)) * k + 0.984375;
}
},
InOut: function (k) {
if (k < 0.5) {
return TWEEN.Easing.Bounce.In(k * 2) * 0.5;
}
return TWEEN.Easing.Bounce.Out(k * 2 - 1) * 0.5 + 0.5;
}
}
};
TWEEN.Interpolation = {
Linear: function (v, k) {
var m = v.length - 1;
var f = m * k;
var i = Math.floor(f);
var fn = TWEEN.Interpolation.Utils.Linear;
if (k < 0) {
return fn(v[0], v[1], f);
}
if (k > 1) {
return fn(v[m], v[m - 1], m - f);
}
return fn(v[i], v[i + 1 > m ? m : i + 1], f - i);
},
Bezier: function (v, k) {
var b = 0;
var n = v.length - 1;
var pw = Math.pow;
var bn = TWEEN.Interpolation.Utils.Bernstein;
for (var i = 0; i <= n; i++) {
b += pw(1 - k, n - i) * pw(k, i) * v[i] * bn(n, i);
}
return b;
},
CatmullRom: function (v, k) {
var m = v.length - 1;
var f = m * k;
var i = Math.floor(f);
var fn = TWEEN.Interpolation.Utils.CatmullRom;
if (v[0] === v[m]) {
if (k < 0) {
i = Math.floor(f = m * (1 + k));
}
return fn(v[(i - 1 + m) % m], v[i], v[(i + 1) % m], v[(i + 2) % m], f - i);
} else {
if (k < 0) {
return v[0] - (fn(v[0], v[0], v[1], v[1], -f) - v[0]);
}
if (k > 1) {
return v[m] - (fn(v[m], v[m], v[m - 1], v[m - 1], f - m) - v[m]);
}
return fn(v[i ? i - 1 : 0], v[i], v[m < i + 1 ? m : i + 1], v[m < i + 2 ? m : i + 2], f - i);
}
},
Utils: {
Linear: function (p0, p1, t) {
return (p1 - p0) * t + p0;
},
Bernstein: function (n, i) {
var fc = TWEEN.Interpolation.Utils.Factorial;
return fc(n) / fc(i) / fc(n - i);
},
Factorial: (function () {
var a = [1];
return function (n) {
var s = 1;
if (a[n]) {
return a[n];
}
for (var i = n; i > 1; i--) {
s *= i;
}
a[n] = s;
return s;
};
})(),
CatmullRom: function (p0, p1, p2, p3, t) {
var v0 = (p2 - p0) * 0.5;
var v1 = (p3 - p1) * 0.5;
var t2 = t * t;
var t3 = t * t2;
return (2 * p1 - 2 * p2 + v0 + v1) * t3 + (- 3 * p1 + 3 * p2 - 2 * v0 - v1) * t2 + v0 * t + p1;
}
}
};
TWEEN.version = version;
return TWEEN;
})));
MY HTML:
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8" />
<title>Locate the user</title>
<script src="https://ajax.googleapis.com/ajax/libs/jquery/3.4.1/jquery.min.js"></script>
<script src="https://cdn.jsdelivr.net/npm/three#0.115/build/three.js"></script>
<script src="https://cdn.rawgit.com/mrdoob/three.js/master/examples/js/loaders/GLTFLoader.js"></script>
<script src="https://cdn.tutorialjinni.com/tween.js/18.5.0/Tween.js"></script>
<style>
body {
margin: 0;
}
canvas {
display: block;
}
</style>
</head>
<body>
<script src="js/capture.js"></script>
</body>
</html>
The issue is the field of view is wide.
Similar to the way a wide angle lens distorts
The code had a 75 degree field of view (75 vertically)
Here's a 25 degree field of view. Had to move to the camera back.
var scene = new THREE.Scene();
var fieldOfView = 25;
var camera = new THREE.PerspectiveCamera(fieldOfView, window.innerWidth / window.innerHeight, 0.1, 1000);
var renderer = new THREE.WebGLRenderer();
renderer.setSize(window.innerWidth, window.innerHeight);
renderer.setClearColor(0xff0000, .5);
document.body.appendChild(renderer.domElement);
var light1 = new THREE.AmbientLight(0xffffff);
light1.position.set(0, -70, 100).normalize();
scene.add(light1);
var light2 = new THREE.AmbientLight(0xffffff);
light2.position.set(0, 70, 100).normalize();
scene.add(light2);
camera.position.z = 80;
var loader = new THREE.GLTFLoader();
loader.crossOrigin = true;
loader.load('https://docs.mapbox.com/mapbox-gl-js/assets/34M_17/34M_17.gltf', function(gltf) {
cube = gltf.scene;
// gltf.scene.position.y -= 15;
// gltf.scene.position.x -= 24;
// gltf.scene.lookAt(camera.position);
gltf.scene.position.set(-40, 0, -3.75);
gltf.scene.scale.set(0.4, 0.4, 0.4);
// gltf.scene.rotation.y += 0.6;
// gltf.scene.rotation.z -= 0.3;
scene.add(gltf.scene);
renderer.render(scene, camera);
maketween();
});
//// Setup the animation loop.
function animate(time) {
requestAnimationFrame(animate);
TWEEN.update(time);
renderer.render(scene, camera);
}
requestAnimationFrame(animate);
function maketween() {
var randomX = Math.floor(Math.random() * 40) - 20;
var randomY = Math.floor(Math.random() * 20) - 10;
var tween = new TWEEN.Tween({
x: cube.position.x,
y: cube.position.y,
z: cube.position.z
}) // Create a new tween that modifies 'coords'.
.to({
x: randomX,
y: randomY,
z: 0
}, 1000) // Move to (300, 200) in 1 second.
.easing(TWEEN.Easing.Quadratic.Out) // Use an easing function to make the animation smooth.
.repeat(0)
.onUpdate(function(object) {
// console.log("tween",randomX,randomY,object.x);
if (object.x == randomX || object.x == 0) {
var randomX = Math.floor(Math.random() * 57) - 28;
var randomY = Math.floor(Math.random() * 23) - 10;
// console.log("*",randomX,randomY);
} else {
cube.position.x = object.x;
cube.position.y = object.y;
}
cube.lookAt(camera.position);
}).onComplete(() => {
// console.log("tween stopped");
maketween();
});
tween.chain(tween);
tween.start();
}
//BELOW THIS POINT IS TWEEN.JS (NOT MY CODE)
(function (global, factory) {
typeof exports === 'object' && typeof module !== 'undefined' ? module.exports = factory() :
typeof define === 'function' && define.amd ? define(factory) :
(global.TWEEN = factory());
}(this, (function () { 'use strict';
var version = '18.4.2';
/**
* Tween.js - Licensed under the MIT license
* https://github.com/tweenjs/tween.js
* ----------------------------------------------
*
* See https://github.com/tweenjs/tween.js/graphs/contributors for the full list of contributors.
* Thank you all, you're awesome!
*/
var _Group = function () {
this._tweens = {};
this._tweensAddedDuringUpdate = {};
};
_Group.prototype = {
getAll: function () {
return Object.keys(this._tweens).map(function (tweenId) {
return this._tweens[tweenId];
}.bind(this));
},
removeAll: function () {
this._tweens = {};
},
add: function (tween) {
this._tweens[tween.getId()] = tween;
this._tweensAddedDuringUpdate[tween.getId()] = tween;
},
remove: function (tween) {
delete this._tweens[tween.getId()];
delete this._tweensAddedDuringUpdate[tween.getId()];
},
update: function (time, preserve) {
var tweenIds = Object.keys(this._tweens);
if (tweenIds.length === 0) {
return false;
}
time = time !== undefined ? time : TWEEN.now();
// Tweens are updated in "batches". If you add a new tween during an
// update, then the new tween will be updated in the next batch.
// If you remove a tween during an update, it may or may not be updated.
// However, if the removed tween was added during the current batch,
// then it will not be updated.
while (tweenIds.length > 0) {
this._tweensAddedDuringUpdate = {};
for (var i = 0; i < tweenIds.length; i++) {
var tween = this._tweens[tweenIds[i]];
if (tween && tween.update(time) === false) {
tween._isPlaying = false;
if (!preserve) {
delete this._tweens[tweenIds[i]];
}
}
}
tweenIds = Object.keys(this._tweensAddedDuringUpdate);
}
return true;
}
};
var TWEEN = new _Group();
TWEEN.Group = _Group;
TWEEN._nextId = 0;
TWEEN.nextId = function () {
return TWEEN._nextId++;
};
// Include a performance.now polyfill.
// In node.js, use process.hrtime.
if (typeof (self) === 'undefined' && typeof (process) !== 'undefined' && process.hrtime) {
TWEEN.now = function () {
var time = process.hrtime();
// Convert [seconds, nanoseconds] to milliseconds.
return time[0] * 1000 + time[1] / 1000000;
};
}
// In a browser, use self.performance.now if it is available.
else if (typeof (self) !== 'undefined' &&
self.performance !== undefined &&
self.performance.now !== undefined) {
// This must be bound, because directly assigning this function
// leads to an invocation exception in Chrome.
TWEEN.now = self.performance.now.bind(self.performance);
}
// Use Date.now if it is available.
else if (Date.now !== undefined) {
TWEEN.now = Date.now;
}
// Otherwise, use 'new Date().getTime()'.
else {
TWEEN.now = function () {
return new Date().getTime();
};
}
TWEEN.Tween = function (object, group) {
this._isPaused = false;
this._pauseStart = null;
this._object = object;
this._valuesStart = {};
this._valuesEnd = {};
this._valuesStartRepeat = {};
this._duration = 1000;
this._repeat = 0;
this._repeatDelayTime = undefined;
this._yoyo = false;
this._isPlaying = false;
this._reversed = false;
this._delayTime = 0;
this._startTime = null;
this._easingFunction = TWEEN.Easing.Linear.None;
this._interpolationFunction = TWEEN.Interpolation.Linear;
this._chainedTweens = [];
this._onStartCallback = null;
this._onStartCallbackFired = false;
this._onUpdateCallback = null;
this._onRepeatCallback = null;
this._onCompleteCallback = null;
this._onStopCallback = null;
this._group = group || TWEEN;
this._id = TWEEN.nextId();
};
TWEEN.Tween.prototype = {
getId: function () {
return this._id;
},
isPlaying: function () {
return this._isPlaying;
},
isPaused: function () {
return this._isPaused;
},
to: function (properties, duration) {
this._valuesEnd = Object.create(properties);
if (duration !== undefined) {
this._duration = duration;
}
return this;
},
duration: function duration(d) {
this._duration = d;
return this;
},
start: function (time) {
this._group.add(this);
this._isPlaying = true;
this._isPaused = false;
this._onStartCallbackFired = false;
this._startTime = time !== undefined ? typeof time === 'string' ? TWEEN.now() + parseFloat(time) : time : TWEEN.now();
this._startTime += this._delayTime;
for (var property in this._valuesEnd) {
// Check if an Array was provided as property value
if (this._valuesEnd[property] instanceof Array) {
if (this._valuesEnd[property].length === 0) {
continue;
}
// Create a local copy of the Array with the start value at the front
this._valuesEnd[property] = [this._object[property]].concat(this._valuesEnd[property]);
}
// If `to()` specifies a property that doesn't exist in the source object,
// we should not set that property in the object
if (this._object[property] === undefined) {
continue;
}
// Save the starting value, but only once.
if (typeof(this._valuesStart[property]) === 'undefined') {
this._valuesStart[property] = this._object[property];
}
if ((this._valuesStart[property] instanceof Array) === false) {
this._valuesStart[property] *= 1.0; // Ensures we're using numbers, not strings
}
this._valuesStartRepeat[property] = this._valuesStart[property] || 0;
}
return this;
},
stop: function () {
if (!this._isPlaying) {
return this;
}
this._group.remove(this);
this._isPlaying = false;
this._isPaused = false;
if (this._onStopCallback !== null) {
this._onStopCallback(this._object);
}
this.stopChainedTweens();
return this;
},
end: function () {
this.update(Infinity);
return this;
},
pause: function(time) {
if (this._isPaused || !this._isPlaying) {
return this;
}
this._isPaused = true;
this._pauseStart = time === undefined ? TWEEN.now() : time;
this._group.remove(this);
return this;
},
resume: function(time) {
if (!this._isPaused || !this._isPlaying) {
return this;
}
this._isPaused = false;
this._startTime += (time === undefined ? TWEEN.now() : time)
- this._pauseStart;
this._pauseStart = 0;
this._group.add(this);
return this;
},
stopChainedTweens: function () {
for (var i = 0, numChainedTweens = this._chainedTweens.length; i < numChainedTweens; i++) {
this._chainedTweens[i].stop();
}
},
group: function (group) {
this._group = group;
return this;
},
delay: function (amount) {
this._delayTime = amount;
return this;
},
repeat: function (times) {
this._repeat = times;
return this;
},
repeatDelay: function (amount) {
this._repeatDelayTime = amount;
return this;
},
yoyo: function (yoyo) {
this._yoyo = yoyo;
return this;
},
easing: function (easingFunction) {
this._easingFunction = easingFunction;
return this;
},
interpolation: function (interpolationFunction) {
this._interpolationFunction = interpolationFunction;
return this;
},
chain: function () {
this._chainedTweens = arguments;
return this;
},
onStart: function (callback) {
this._onStartCallback = callback;
return this;
},
onUpdate: function (callback) {
this._onUpdateCallback = callback;
return this;
},
onRepeat: function onRepeat(callback) {
this._onRepeatCallback = callback;
return this;
},
onComplete: function (callback) {
this._onCompleteCallback = callback;
return this;
},
onStop: function (callback) {
this._onStopCallback = callback;
return this;
},
update: function (time) {
var property;
var elapsed;
var value;
if (time < this._startTime) {
return true;
}
if (this._onStartCallbackFired === false) {
if (this._onStartCallback !== null) {
this._onStartCallback(this._object);
}
this._onStartCallbackFired = true;
}
elapsed = (time - this._startTime) / this._duration;
elapsed = (this._duration === 0 || elapsed > 1) ? 1 : elapsed;
value = this._easingFunction(elapsed);
for (property in this._valuesEnd) {
// Don't update properties that do not exist in the source object
if (this._valuesStart[property] === undefined) {
continue;
}
var start = this._valuesStart[property] || 0;
var end = this._valuesEnd[property];
if (end instanceof Array) {
this._object[property] = this._interpolationFunction(end, value);
} else {
// Parses relative end values with start as base (e.g.: +10, -3)
if (typeof (end) === 'string') {
if (end.charAt(0) === '+' || end.charAt(0) === '-') {
end = start + parseFloat(end);
} else {
end = parseFloat(end);
}
}
// Protect against non numeric properties.
if (typeof (end) === 'number') {
this._object[property] = start + (end - start) * value;
}
}
}
if (this._onUpdateCallback !== null) {
this._onUpdateCallback(this._object, elapsed);
}
if (elapsed === 1) {
if (this._repeat > 0) {
if (isFinite(this._repeat)) {
this._repeat--;
}
// Reassign starting values, restart by making startTime = now
for (property in this._valuesStartRepeat) {
if (typeof (this._valuesEnd[property]) === 'string') {
this._valuesStartRepeat[property] = this._valuesStartRepeat[property] + parseFloat(this._valuesEnd[property]);
}
if (this._yoyo) {
var tmp = this._valuesStartRepeat[property];
this._valuesStartRepeat[property] = this._valuesEnd[property];
this._valuesEnd[property] = tmp;
}
this._valuesStart[property] = this._valuesStartRepeat[property];
}
if (this._yoyo) {
this._reversed = !this._reversed;
}
if (this._repeatDelayTime !== undefined) {
this._startTime = time + this._repeatDelayTime;
} else {
this._startTime = time + this._delayTime;
}
if (this._onRepeatCallback !== null) {
this._onRepeatCallback(this._object);
}
return true;
} else {
if (this._onCompleteCallback !== null) {
this._onCompleteCallback(this._object);
}
for (var i = 0, numChainedTweens = this._chainedTweens.length; i < numChainedTweens; i++) {
// Make the chained tweens start exactly at the time they should,
// even if the `update()` method was called way past the duration of the tween
this._chainedTweens[i].start(this._startTime + this._duration);
}
return false;
}
}
return true;
}
};
TWEEN.Easing = {
Linear: {
None: function (k) {
return k;
}
},
Quadratic: {
In: function (k) {
return k * k;
},
Out: function (k) {
return k * (2 - k);
},
InOut: function (k) {
if ((k *= 2) < 1) {
return 0.5 * k * k;
}
return - 0.5 * (--k * (k - 2) - 1);
}
},
Cubic: {
In: function (k) {
return k * k * k;
},
Out: function (k) {
return --k * k * k + 1;
},
InOut: function (k) {
if ((k *= 2) < 1) {
return 0.5 * k * k * k;
}
return 0.5 * ((k -= 2) * k * k + 2);
}
},
Quartic: {
In: function (k) {
return k * k * k * k;
},
Out: function (k) {
return 1 - (--k * k * k * k);
},
InOut: function (k) {
if ((k *= 2) < 1) {
return 0.5 * k * k * k * k;
}
return - 0.5 * ((k -= 2) * k * k * k - 2);
}
},
Quintic: {
In: function (k) {
return k * k * k * k * k;
},
Out: function (k) {
return --k * k * k * k * k + 1;
},
InOut: function (k) {
if ((k *= 2) < 1) {
return 0.5 * k * k * k * k * k;
}
return 0.5 * ((k -= 2) * k * k * k * k + 2);
}
},
Sinusoidal: {
In: function (k) {
return 1 - Math.cos(k * Math.PI / 2);
},
Out: function (k) {
return Math.sin(k * Math.PI / 2);
},
InOut: function (k) {
return 0.5 * (1 - Math.cos(Math.PI * k));
}
},
Exponential: {
In: function (k) {
return k === 0 ? 0 : Math.pow(1024, k - 1);
},
Out: function (k) {
return k === 1 ? 1 : 1 - Math.pow(2, - 10 * k);
},
InOut: function (k) {
if (k === 0) {
return 0;
}
if (k === 1) {
return 1;
}
if ((k *= 2) < 1) {
return 0.5 * Math.pow(1024, k - 1);
}
return 0.5 * (- Math.pow(2, - 10 * (k - 1)) + 2);
}
},
Circular: {
In: function (k) {
return 1 - Math.sqrt(1 - k * k);
},
Out: function (k) {
return Math.sqrt(1 - (--k * k));
},
InOut: function (k) {
if ((k *= 2) < 1) {
return - 0.5 * (Math.sqrt(1 - k * k) - 1);
}
return 0.5 * (Math.sqrt(1 - (k -= 2) * k) + 1);
}
},
Elastic: {
In: function (k) {
if (k === 0) {
return 0;
}
if (k === 1) {
return 1;
}
return -Math.pow(2, 10 * (k - 1)) * Math.sin((k - 1.1) * 5 * Math.PI);
},
Out: function (k) {
if (k === 0) {
return 0;
}
if (k === 1) {
return 1;
}
return Math.pow(2, -10 * k) * Math.sin((k - 0.1) * 5 * Math.PI) + 1;
},
InOut: function (k) {
if (k === 0) {
return 0;
}
if (k === 1) {
return 1;
}
k *= 2;
if (k < 1) {
return -0.5 * Math.pow(2, 10 * (k - 1)) * Math.sin((k - 1.1) * 5 * Math.PI);
}
return 0.5 * Math.pow(2, -10 * (k - 1)) * Math.sin((k - 1.1) * 5 * Math.PI) + 1;
}
},
Back: {
In: function (k) {
var s = 1.70158;
return k * k * ((s + 1) * k - s);
},
Out: function (k) {
var s = 1.70158;
return --k * k * ((s + 1) * k + s) + 1;
},
InOut: function (k) {
var s = 1.70158 * 1.525;
if ((k *= 2) < 1) {
return 0.5 * (k * k * ((s + 1) * k - s));
}
return 0.5 * ((k -= 2) * k * ((s + 1) * k + s) + 2);
}
},
Bounce: {
In: function (k) {
return 1 - TWEEN.Easing.Bounce.Out(1 - k);
},
Out: function (k) {
if (k < (1 / 2.75)) {
return 7.5625 * k * k;
} else if (k < (2 / 2.75)) {
return 7.5625 * (k -= (1.5 / 2.75)) * k + 0.75;
} else if (k < (2.5 / 2.75)) {
return 7.5625 * (k -= (2.25 / 2.75)) * k + 0.9375;
} else {
return 7.5625 * (k -= (2.625 / 2.75)) * k + 0.984375;
}
},
InOut: function (k) {
if (k < 0.5) {
return TWEEN.Easing.Bounce.In(k * 2) * 0.5;
}
return TWEEN.Easing.Bounce.Out(k * 2 - 1) * 0.5 + 0.5;
}
}
};
TWEEN.Interpolation = {
Linear: function (v, k) {
var m = v.length - 1;
var f = m * k;
var i = Math.floor(f);
var fn = TWEEN.Interpolation.Utils.Linear;
if (k < 0) {
return fn(v[0], v[1], f);
}
if (k > 1) {
return fn(v[m], v[m - 1], m - f);
}
return fn(v[i], v[i + 1 > m ? m : i + 1], f - i);
},
Bezier: function (v, k) {
var b = 0;
var n = v.length - 1;
var pw = Math.pow;
var bn = TWEEN.Interpolation.Utils.Bernstein;
for (var i = 0; i <= n; i++) {
b += pw(1 - k, n - i) * pw(k, i) * v[i] * bn(n, i);
}
return b;
},
CatmullRom: function (v, k) {
var m = v.length - 1;
var f = m * k;
var i = Math.floor(f);
var fn = TWEEN.Interpolation.Utils.CatmullRom;
if (v[0] === v[m]) {
if (k < 0) {
i = Math.floor(f = m * (1 + k));
}
return fn(v[(i - 1 + m) % m], v[i], v[(i + 1) % m], v[(i + 2) % m], f - i);
} else {
if (k < 0) {
return v[0] - (fn(v[0], v[0], v[1], v[1], -f) - v[0]);
}
if (k > 1) {
return v[m] - (fn(v[m], v[m], v[m - 1], v[m - 1], f - m) - v[m]);
}
return fn(v[i ? i - 1 : 0], v[i], v[m < i + 1 ? m : i + 1], v[m < i + 2 ? m : i + 2], f - i);
}
},
Utils: {
Linear: function (p0, p1, t) {
return (p1 - p0) * t + p0;
},
Bernstein: function (n, i) {
var fc = TWEEN.Interpolation.Utils.Factorial;
return fc(n) / fc(i) / fc(n - i);
},
Factorial: (function () {
var a = [1];
return function (n) {
var s = 1;
if (a[n]) {
return a[n];
}
for (var i = n; i > 1; i--) {
s *= i;
}
a[n] = s;
return s;
};
})(),
CatmullRom: function (p0, p1, p2, p3, t) {
var v0 = (p2 - p0) * 0.5;
var v1 = (p3 - p1) * 0.5;
var t2 = t * t;
var t3 = t * t2;
return (2 * p1 - 2 * p2 + v0 + v1) * t3 + (- 3 * p1 + 3 * p2 - 2 * v0 - v1) * t2 + v0 * t + p1;
}
}
};
TWEEN.version = version;
return TWEEN;
})));
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8" />
<title>Locate the user</title>
<script src="https://ajax.googleapis.com/ajax/libs/jquery/3.4.1/jquery.min.js"></script>
<script src="https://cdn.jsdelivr.net/npm/three#0.115/build/three.js"></script>
<script src="https://cdn.rawgit.com/mrdoob/three.js/master/examples/js/loaders/GLTFLoader.js"></script>
<script src="https://cdn.tutorialjinni.com/tween.js/18.5.0/Tween.js"></script>
<style>
body {
margin: 0;
}
canvas {
display: block;
}
</style>
</head>
<body>
<script src="js/capture.js"></script>
</body>
</html>

Creating svg paths with javascript(shape morphing)

So I have this class which is used for shape morphing:
class ShapeOverlays {
constructor(elm) {
this.elm = elm;
this.path = elm.querySelectorAll('path');
this.numPoints = 18;
this.duration = 600;
this.delayPointsArray = [];
this.delayPointsMax = 300;
this.delayPerPath = 100;
this.timeStart = Date.now();
this.isOpened = false;
this.isAnimating = false;
}
toggle() {
this.isAnimating = true;
const range = 4 * Math.random() + 6;
for (var i = 0; i < this.numPoints; i++) {
const radian = i / (this.numPoints - 1) * Math.PI;
this.delayPointsArray[i] = (Math.sin(-radian) + Math.sin(-radian * range) + 2) / 4 * this.delayPointsMax;
}
if (this.isOpened === false) {
this.open();
} else {
this.close();
}
}
open() {
this.isOpened = true;
this.elm.classList.add('is-opened');
this.timeStart = Date.now();
this.renderLoop();
}
close() {
this.isOpened = false;
this.elm.classList.remove('is-opened');
this.timeStart = Date.now();
this.renderLoop();
}
updatePath(time) {
const points = [];
for (var i = 0; i < this.numPoints + 1; i++) {
points[i] = ease.cubicInOut(Math.min(Math.max(time - this.delayPointsArray[i], 0) / this.duration, 1)) * 100
}
let str = '';
str += (this.isOpened) ? `M 0 0 V ${points[0]} ` : `M 0 ${points[0]} `;
for (var i = 0; i < this.numPoints - 1; i++) {
const p = (i + 1) / (this.numPoints - 1) * 100;
const cp = p - (1 / (this.numPoints - 1) * 100) / 2;
str += `C ${cp} ${points[i]} ${cp} ${points[i + 1]} ${p} ${points[i + 1]} `;
}
str += (this.isOpened) ? `V 0 H 0` : `V 100 H 0`;
return str;
}
render() {
if (this.isOpened) {
for (var i = 0; i < this.path.length; i++) {
this.path[i].setAttribute('d', this.updatePath(Date.now() - (this.timeStart + this.delayPerPath * i)));
}
} else {
for (var i = 0; i < this.path.length; i++) {
this.path[i].setAttribute('d', this.updatePath(Date.now() - (this.timeStart + this.delayPerPath * (this.path.length - i - 1))));
}
}
}
renderLoop() {
this.render();
if (Date.now() - this.timeStart < this.duration + this.delayPerPath * (this.path.length - 1) + this.delayPointsMax) {
requestAnimationFrame(() => {
this.renderLoop();
});
}
else {
this.isAnimating = false;
}
}
}
(function() {
const elmHamburger = document.querySelector('.hamburger');
const gNavItems = document.querySelectorAll('.global-menu__item');
const elmOverlay = document.querySelector('.shape-overlays');
const overlay = new ShapeOverlays(elmOverlay);
elmHamburger.addEventListener('click', () => {
if (overlay.isAnimating) {
return false;
}
overlay.toggle();
if (overlay.isOpened === true) {
elmHamburger.classList.add('is-opened-navi');
for (var i = 0; i < gNavItems.length; i++) {
gNavItems[i].classList.add('is-opened');
}
} else {
elmHamburger.classList.remove('is-opened-navi');
for (var i = 0; i < gNavItems.length; i++) {
gNavItems[i].classList.remove('is-opened');
}
}
});
}());
Can some one please explain this code? I don't really get how the paths are created using time,how the points are placed and how could I modify it.What is range used for? Why are trigonometral functions used for the delayPointsArray?
Basically it's this part that I don't get:
updatePath(time) {
const points = [];
for (var i = 0; i < this.numPoints + 1; i++) {
points[i] = ease.cubicInOut(Math.min(Math.max(time - this.delayPointsArray[i], 0) / this.duration, 1)) * 100
}
let str = '';
str += (this.isOpened) ? `M 0 0 V ${points[0]} ` : `M 0 ${points[0]} `;
for (var i = 0; i < this.numPoints - 1; i++) {
const p = (i + 1) / (this.numPoints - 1) * 100;
const cp = p - (1 / (this.numPoints - 1) * 100) / 2;
str += `C ${cp} ${points[i]} ${cp} ${points[i + 1]} ${p} ${points[i + 1]} `;
}
str += (this.isOpened) ? `V 0 H 0` : `V 100 H 0`;
return str;
}
render() {
if (this.isOpened) {
for (var i = 0; i < this.path.length; i++) {
this.path[i].setAttribute('d', this.updatePath(Date.now() - (this.timeStart + this.delayPerPath * i)));
}
} else {
for (var i = 0; i < this.path.length; i++) {
this.path[i].setAttribute('d', this.updatePath(Date.now() - (this.timeStart + this.delayPerPath * (this.path.length - i - 1))));
}
}
}
Why is time being used? What is the purpose of this:
points[i] = ease.cubicInOut(Math.min(Math.max(time - this.delayPointsArray[i], 0) / this.duration, 1)) * 100
If you look at how updatePath() is being called, it's like this:
this.updatePath(Date.now() - (this.timeStart + this.delayPerPath * i))
So the time value passed in is the difference between the current time, and the start time of the path we are working with.
So what then is the line of code you are interested in, doing?
points[i] = ease.cubicInOut(Math.min(Math.max(time - this.delayPointsArray[i], 0) / this.duration, 1)) * 100
I'm going to ignore delayPointsArray. It is modifying the start time slightly based on angle. Without seeing the full demo, I'm not sure of the reason for that.
The purpose of this line of code is to calculate how far through the current path's animation we are. The result is in the form of a coordinate value from 0 to 100.
It's doing a lot in that one line of code. So let's break down the individual steps.
Firstly, we are clamping the elapsed time to minimum of 0.
Math.max(time, 0)
In other words, anything before the animation start time becomes zero.
Then we divide by the animation's duration.
Math.max(time, 0) / duration
This will result in a value from 0, representing the start of the animation, to 1, representing the end of the animation. However, the value might also be greater than 1 if the elapsed time is after the end of the animation. Hence the next step.
Now clamp this value to a maximum of 1.
Math.min( Math.max(time, 0) / duration, 1)
We now have a value >= 0 and <= 1 whichdescribes where in the course of the animation, the path is supposed to be. 0 if we should be at the animations start position. 1 if we should be at the animations end position. And somewhere in between if the animation is in progress.
However this value is strictly linear, corresponding with the progression of time. And usually linear movement is not what you want. It is unnatural. Objects accelarate when the start moving and decelerate when the come to a stop. That will be what the easeInOut() function will be doing. If you are not familiar with easing curves, take a look at the diagram below.
Source: Google: The Basics of Easing
So we pass in a linear time value from 0..1 (horizontal axis). It will return a modified value that takes into account acceleration and deceleration.
The final step is to multiply by 100, to convert to a final coordinate value (0..100).
Hope this helps.

Calculate the nearest value on a circular variable

I have an problem where i have 3 times of the 24 hour day. To keep it simple i can use the decimal representation:
a) 23:45 (23.75)
b) 11:30 (11.50)
c) 00:15 (00.25)
I'd like to know , for each time, which other time is closest.
var closestTime = 24
var closestActualTime = 0;
for (var i = 0; i < times.length; i++) {
if (times[i].time == this.time) continue;
var temp = Math.abs(this.time - times[i].time)
if (temp < closestTime) {
closestTime = temp;
closestActualTime = times[i].time;
}
}
My issue is that 23:45 and 00:25 are actually really close but i don't know how process a variable with a modulo type
I suggest to build a list with the pairs and then calculate the difference.
The difference is the third element in the pairs array.
Basically you need to check the delta and if it greater than 12 hours, take the difference from 24 and delta.
delta = Math.abs(aa - bb);
if (delta > 12) {
delta = 24 - delta;
}
function combination(array, size) {
function c(part, start) {
var i, l, p;
for (i = start, l = array.length + part.length + 1 - size; i < l; i++) {
p = part.slice();
p.push(array[i]);
p.length < size ? c(p, i + 1) : result.push(p);
}
}
var result = [];
c([], 0);
return result;
}
function timeDelta(a, b) {
function decimalTime(s) {
var p = s.split(':');
return +p[0] + p[1] / 60;
}
function padZero(v) {
return (v < 10) ? '0' + v : String(v);
}
var aa = decimalTime(a),
bb = decimalTime(b),
delta = Math.abs(aa - bb);
if (delta > 12) {
delta = 24 - delta;
}
return padZero(Math.floor(delta)) + ':' + padZero(Math.round(60 * (delta - Math.floor(delta))));
}
var times = ['23:45', '11:30', '00:15'],
pairs = combination(times, 2);
pairs.forEach(function (a, i, aa) {
aa[i][2] = timeDelta(a[0], a[1]);
});
console.log(pairs);
.as-console-wrapper { max-height: 100% !important; top: 0; }
Loop over times.
Try combinations of delta time, offset by 24 hours.
Pick smallest delta time.
var times = [23.75, 11.50, 3, 6, 7];
/**
* timeClosestTo
*
* #param {number} time
* #returns {number}
*/
function timeClosestTo(time) {
//Distance variable to compare against
var distance = 100;
//Hours in a day
var day = 24;
//Current best
var best = null;
//Test against all times
for (var i = 0; i < times.length; i++) {
//Find best score based upon day
var d = Math.min(Math.abs((times[i]) - (time)), Math.abs((times[i] + day) - time), Math.abs((times[i]) - (time + day)), Math.abs((times[i] + day) - (time + day)));
//If best found distance yet, set best to current
if (d < distance) {
best = times[i];
distance = d;
}
}
//Return best
return best;
}
console.log("times to deal with:",times.join(", "));
console.log("closest to 1:", timeClosestTo(1), "closest to 11:", timeClosestTo(11), "closest to 5:", timeClosestTo(5));
Quite functionally i would do this job as follows
var times = [23.75,11.50,0.25],
diffs = times.reduce((d,t1,i,a) => a[i+1] ? d.concat(a.slice(i+1)
.map(t2 => [t1,t2,[Math.min(Math.abs(t1-t2),24-Math.abs(t1-t2))]
.map(n => ~~n + ":" + (n%1)*60)[0]]))
: d,[]);
console.log(diffs);

Automatically fire a JavaScript code after loading a page in Google Chrome

I have a Javascript code, which I use to bring Night Mode effect on an HTML page...
The code goes something like this-
javascript: (function () {
function RGBtoHSL(RGBColor) {
with(Math) {
var R, G, B;
var cMax, cMin;
var sum, diff;
var Rdelta, Gdelta, Bdelta;
var H, L, S;
R = RGBColor[0];
G = RGBColor[1];
B = RGBColor[2];
cMax = max(max(R, G), B);
cMin = min(min(R, G), B);
sum = cMax + cMin;
diff = cMax - cMin;
L = sum / 2;
if (cMax == cMin) {
S = 0;
H = 0;
} else {
if (L <= (1 / 2)) S = diff / sum;
else S = diff / (2 - sum);
Rdelta = R / 6 / diff;
Gdelta = G / 6 / diff;
Bdelta = B / 6 / diff;
if (R == cMax) H = Gdelta - Bdelta;
else if (G == cMax) H = (1 / 3) + Bdelta - Rdelta;
else H = (2 / 3) + Rdelta - Gdelta; if (H < 0) H += 1;
if (H > 1) H -= 1;
}
return [H, S, L];
}
}
function getRGBColor(node, prop) {
var rgb = getComputedStyle(node, null).getPropertyValue(prop);
var r, g, b;
if (/rgb\((\d+),\s(\d+),\s(\d+)\)/.exec(rgb)) {
r = parseInt(RegExp.$1, 10);
g = parseInt(RegExp.$2, 10);
b = parseInt(RegExp.$3, 10);
return [r / 255, g / 255, b / 255];
}
return rgb;
}
function hslToCSS(hsl) {
return "hsl(" + Math.round(hsl[0] * 360) + ", " + Math.round(hsl[1] * 100) + "%, " + Math.round(hsl[2] * 100) + "%)";
}
var props = ["color", "background-color", "border-left-color", "border-right-color", "border-top-color", "border-bottom-color"];
var props2 = ["color", "backgroundColor", "borderLeftColor", "borderRightColor", "borderTopColor", "borderBottomColor"];
if (typeof getRGBColor(document.documentElement, "background-color") == "string") document.documentElement.style.backgroundColor = "white";
revl(document.documentElement);
function revl(n) {
var i, x, color, hsl;
if (n.nodeType == Node.ELEMENT_NODE) {
for (i = 0; x = n.childNodes[i]; ++i) revl(x);
for (i = 0; x = props[i]; ++i) {
color = getRGBColor(n, x);
if (typeof (color) != "string") {
hsl = RGBtoHSL(color);
hsl[2] = 1 - hsl[2];
n.style[props2[i]] = hslToCSS(hsl);
}
}
}
}
})()
I have saved this as a Bookmarklet in my Bookmark Bar on Google Chrome, but I want this to be automatically applied to every page I load. What should I do to achieve this?
You should write this as a userscript and run it with something like tampermonkey

Categories

Resources