Pass a Class
function callMethods(evt) {
const e = new evt
e.one()
e.two()
}
callMethods(class {
one() {
console.log('one')
}
two() {
console.log('two')
}
})
This is so tempting for something I want to do… but too strange to use probably… maybe…
function callMethods(evt) {
const e = new evt
e.one()
e.two()
}
callMethods(class {
one() {
console.log('one')
}
two() {
console.log('two')
}
})
This is so tempting for something I want to do… but too strange to use probably… maybe…
// read through the comments of this snippet...
function dist1(x1, y1, x2, y2) {
const dx = x1 - x2
const dy = y1 - y2
return Math.sqrt(dx**2 + dy**2)
}
function dist2({x1, y1, x2, y2}) {
const dx = x1 - x2
const dy = y1 - y2
return Math.sqrt(dx**2 + dy**2)
}
// What's the difference here... well
dist1(50, 50, 100, 100)
// vs
dist2({ x1: 50, y1: 50, x2: 100, y2: 100 })
// so what?
// With `dist2` the order of the arguments doesn't matter
// and the arguments are named now as a result of being keys
// in an object
// How many times have you changed a core function or method as you're
// working on a project?
// Let's see another example:
// circle(100, 200, 300, 'red', 'blue', 0, 0)
// Can you guess what those arguments are? It's not really a big deal
// and editors help with this, typescript helps with this... but what about:
circle({
x: 10,
y: 110,
radius: 120,
fill: 'red',
stroke: 'blue',
velocityX: 0,
velocitY: 0
})
// how about...
circle({ radius: 50, fill: 'blue' })
// or...
circle({ stroke: 'green', x: 40, velocityX: 1 })
// etc...
circle({
radius: 50,
stroke: 'black', x: 200,
fill: 'teal',
velocityY: 1, velocityX: -1 })
// In combination with default arguments we end up with a very easy pattern for functions/methods
// with a complex argument signature. gsap (aka TweenLite/TweenMax) has used this pattern for many
// years. I've seen similar things in many languages...
// How does the circle function look?
function circle({
x = 0, y = 0,
radius = 30,
fill = 'black',
stroke = 'transparent',
velocityX = 0, velocityY = 0}) {
const diam = radius * 2;
const circle = document.body.appendChild(
Object.assign(
document.createElement('div'),
{ style: `
position: absolute;
left: ${x}px;
top: ${y}px;
width: ${diam}px;
height: ${diam}px;
background: ${fill};
border: 3px solid ${stroke};
border-radius: 100%;
`
}
)
)
if (velocityX != 0 || velocityY != 0) {
setInterval(() => {
x += velocityX
y += velocityY
circle.style.left = `${x}px`
circle.style.top = `${y}px`
}, 16)
}
return circle
}
// here is a golfed distance function - for no reason
d=(a,b,c,d,e=a-c,f=b-d)=>Math.sqrt(e*e+f*f)
console.log(
dist1(0, 0, 140, 140) ===
d(0, 0, 140, 140)
)
const obj = { 11: 'eleven', 23: 'twenty-three', 1: 'one', 2: 'two', '-1': 'negative 1' };
console.log(Reflect.ownKeys(obj))
I noticed that for in..
over an object was giving me weirdly consistent results across all browsers the other day and stumbled upon this.
Great news, but it’s Reflect.ownKeys
for me… now that IE11 is dying/dead.
const { pow, PI } = Math;
// mostly unedited code from Raphaël
var ef = {
linear: function(n) {
return n;
},
'<': function(n) {
return pow(n, 1.7);
},
'>': function(n) {
return pow(n, 0.48);
},
'<>': function(n) {
var q = 0.48 - n / 1.04,
Q = Math.sqrt(0.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 + 0.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 - 0.075) * (2 * PI)) / 0.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 + 0.75;
} else {
if (n < 2.5 / p) {
n -= 2.25 / p;
l = s * n * n + 0.9375;
} else {
n -= 2.625 / p;
l = s * n * n + 0.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;
// create a dot
function dot(x, y, radius, color) {
const el = document.createElement('div');
const size = `${radius * 2}px`;
Object.assign(el.style, {
position: 'absolute',
left: `${x}px`,
top: `${y}px`,
width: size,
height: size,
transform: `translate(${-radius}px, ${-radius}px)`,
borderRadius: '50%',
background: color
});
el.classList.add('dot');
document.body.appendChild(el);
return el;
}
const elA = dot(0, 40, 30, 'red');
const elB = dot(0, 110, 30, 'blue');
const elC = dot(0, 160, 20, 'green');
// how to use the easing equations:
let t = 0;
let start = Date.now();
let time = 0;
let duration = 2; // 2 seconds
function loop() {
// frame based
elA.style.left = `${ef.elastic(t) * 50}%`;
t += 0.005;
// time based
if (time <= duration) {
time = (Date.now() - start) / 1000;
const param = time / duration;
elB.style.left = `${ef.elastic(param) * 50}%`;
// green bounce example
elC.style.left = `${ef.bounce(param) * 50}%`;
}
requestAnimationFrame(loop);
}
loop();
I realized it might not be obvious how to use Raphaël’s easing equations. So I speed coded this example.
If you’d like to learn more about this kind of thing gsap is a great place to start… it is amazing… I highly recommend browsing the source.
rot = (
cx, cy, X, Y, ang,
cos = Math.cos(-ang),
sin = Math.sin(-ang),
x = cos * (X - cx) + sin * (Y - cy) + cx,
y = cos * (Y - cy) - sin * (X - cx) + cy) => ({ x, y })
Rotate one point around another… I like to use something like this when speed-coding and golfing…