valueOf for Shorter Function Calls
r={valueOf:_=>Math.random()}
console.log(+r)
console.log(+r)
console.log(+r)
Use valueOf
to shorten function calls. I learned this trick over at stackexchange codegolf here from user cyoce.
r={valueOf:_=>Math.random()}
console.log(+r)
console.log(+r)
console.log(+r)
Use valueOf
to shorten function calls. I learned this trick over at stackexchange codegolf here from user cyoce.
console.log(1e1); // 10
console.log(1e2); // 100
console.log(1e3); // 1000
console.log(1e4); // 10000
console.log(12e3); // 12000
This can be helpful when you need big numbers like 100000
.
function rect(x1, y1, x2, y2, col, blur=.1) {
const dx = x1 - x2;
const dy = y1 - y2;
const dist = Math.sqrt(dx * dx + dy * dy);
return `radial-gradient(circle at ${x1}% ${y1}%, ${col} 0, ${col} ${dist}%, transparent ${dist +
blur}%)`;
}
const NUM = 8;
let rects = [];
const colors = ['rgba(0, 0, 0, 0.2)', 'white', 'black'];
let x = 0;
let y = 0;
let t = 8;
function loop() {
rects = [];
for (let i = 0; i < NUM; i++) {
x = 50 + 30 * Math.sin(t + i / 2);
y = 50 + 30 * Math.cos(t * 1.5 * i / 10);
rects.push(rect(x, y, x + 5, y + 5, 'rgba(255, 255, 255, 1)', 1));
rects.push(rect(x, y, x + 5, y + 5, 'rgba(0, 0, 0, 0.4)',
8 + 6 * Math.cos(y / 10)));
}
t += .04;
document.body.style.backgroundImage = rects.join(', ');
window.requestAnimationFrame(loop);
}
loop()
document.body.innerHTML += `
<style>
body, html {
height: 100%;
background: #ccc;
margin: 0;
background-repeat: no-repeat;
width: 100%;
}
</style>
`;
Animated variation on yesterdays post – many animating circles with no divs or canvas, just radial-gradients…
const Key = {
LEFT: 37,
UP: 38,
RIGHT: 39,
DOWN: 40,
disabled: false
};
const keyDown = {};
function setupKeys() {
const alph = 'abcdefghijklmnopqrstuvwxyz'.split('');
const keys = {};
const aKey = 65;
alph.forEach((letter, i) => {
const idx = aKey + i;
keyDown[idx] = false;
Key[letter.toUpperCase()] = idx;
});
keyDown.allLetters = () => {
const lettersDown = alph.filter(
letter => keyDown[Key[letter.toUpperCase()]]
);
return lettersDown;
};
document.addEventListener('keydown', e => {
e.preventDefault();
if (!Key.disabled) {
keyDown[e.which] = true;
}
});
document.addEventListener('keyup', e => {
e.preventDefault();
keyDown[e.which] = false;
});
}
setupKeys();
// later:
const dots = {};
let id = 0;
function dot(letter = '') {
const el = document.createElement('div');
el.innerHTML = letter;
const size = 20;
const scale = 1 + Math.random() * 2;
const vel = (2 - scale / 2) / 4;
let x = innerWidth / 2 - size;
let y = innerHeight / 2 - size;
let vx = Math.random() * 6 - 3;
let vy = Math.random() * 6 - 3;
let life = 0;
let maxLife = Math.floor(50 + Math.random() * 30);
Object.assign(el.style, {
position: 'absolute',
left: 0,
top: 0,
transform: `translate3d(${x}px, ${y}px)`,
borderRadius: '500px',
background: 'red',
width: `${size}px`,
fontFamily: 'sans-serif',
textAlign: 'center',
color: 'white'
});
id++;
let props = {
el,
id,
right() {
vx += vel;
},
left() {
vx -= vel;
},
down() {
vy += vel;
},
up() {
vy -= vel;
},
run() {
life++;
if (life === maxLife) {
document.body.removeChild(dots[props.id].el);
delete dots[props.id];
}
x += vx;
y += vy;
vx *= 0.999;
vy *= 0.999;
el.style.transform = `translate(${x}px, ${y}px) scale(${scale}) `;
}
};
dots[id] = props;
document.body.appendChild(el);
}
function loop() {
keyDown.allLetters().forEach(letter => {
dot(letter);
});
for (let i in dots) {
dots[i].run();
}
if (keyDown[Key.LEFT]) {
for (let i in dots) {
dots[i].left();
}
}
if (keyDown[Key.DOWN]) {
for (let i in dots) {
dots[i].down();
}
}
if (keyDown[Key.RIGHT]) {
for (let i in dots) {
dots[i].right();
}
}
if (keyDown[Key.UP]) {
for (let i in dots) {
dots[i].up();
}
}
requestAnimationFrame(loop);
}
loop();
const info = document.createElement('div')
info.innerHTML = 'click here, then type letters and use arrow keys'
document.body.appendChild(info)
A demo showing how to use the keyboard snippet from yesterday. Also added a function to obtain an array of all currently pressed letter keys
document.addEventListener('touchmove', e => e.preventDefault(), {
passive: false
});
document.body.innerHTML += `
<style>
* {
-moz-user-select: none;
-webkit-user-select: none;
-ms-user-select: none;
user-select: none;
}
body {
background: #333;
}
.select-box {
border: 1px solid white;
outline: 1px solid black;
}
.swatch {
border: none;
outline: none;
}
</style>
`;
const col = document.body.appendChild(document.createElement('div'));
Object.assign(col.style, {
position: 'absolute',
left: 0,
top: 0,
width: '100%',
height: '200px',
background:
`linear-gradient(0, black 0%, transparent 50%, transparent 50%, white 100%),
linear-gradient(90deg, #ff0000, #ffff00, #00ff00, #00ffff, #0000ff, #ff00ff, #ff0000)`
});
const swatches = document.body.appendChild(document.createElement('div'));
Object.assign(swatches.style, {
position: 'absolute',
top: '200px',
left: 0,
width: '100%'
});
function box(x, y, cls = 'select-box', parent = document.body) {
const box = parent.appendChild(document.createElement`div`);
box.classList.add(cls);
Object.assign(box.style, {
position: 'absolute',
left: `${x}%`,
top: `${y}px`,
width: '40px',
height: '40px',
background: 'none',
transform: 'translate(-50%, -50%)',
cursor: 'pointer',
color: 'white'
});
return box;
}
function touch(e) {
let x = e.clientX;
let y = e.clientY;
if (e.touches != null && e.touches.length > 0) {
x = e.touches[0].clientX;
y = e.touches[0].clientY;
}
return { x, y };
}
document.addEventListener('touchstart', onDown);
document.addEventListener('touchmove', onMove);
document.addEventListener('touchend', onUp);
document.addEventListener('mousedown', onDown);
document.addEventListener('mousemove', onMove);
document.addEventListener('mouseup', onUp);
let down = false;
let currBox;
let currSwatch;
let swatchHeight = 30;
let id = 0;
function toHSL(x, y) {
let deg = x * 360;
return `hsl(${deg}deg, 100%, ${100 - y / 2}%)`;
}
function onDown(e) {
let { x, y } = touch(e);
down = true;
let hPercent = x / innerWidth;
let color = toHSL(hPercent, y);
if (e.target.classList.contains('swatch')) {
e.target.style.outline = '2px solid red';
e.target.style.zIndex = 999;
down = false;
setTimeout(() => {
if (confirm('Would you like to remove this swatch?')) {
currBox = document.querySelector(
`.select-box[data-id="${e.target.dataset.id}"]`
);
if (currBox != null) {
currBox.parentNode.removeChild(currBox);
e.target.parentNode.removeChild(e.target);
}
} else {
e.target.style.outline = null;
e.target.style.zIndex = null;
}
}, 250);
} else if (e.target.classList.contains('select-box')) {
currBox = e.target;
c = document.querySelector(`.swatch[data-id="${currBox.dataset.id}"]`);
} else {
currBox = box(hPercent * 100, y);
currBox.dataset.id = id++;
currSwatch = box(0, 0, 'swatch', swatches);
currSwatch.dataset.id = currBox.dataset.id;
Object.assign(currSwatch.style, {
width: '100%',
position: 'relative',
height: `${swatchHeight}px`,
transform: 'none',
background: color
});
}
}
function onMove(e) {
if (down) {
let { x, y } = touch(e);
let hPercent = x / innerWidth;
let color = toHSL(hPercent, y);
Object.assign(currBox.style, {
left: `${hPercent * 100}%`,
top: `${y}px`
});
currSwatch.style.background = color;
}
}
function onUp(e) {
down = false;
currBox = null;
}
Click anywhere on the spectrum to add a color… color boxes can be dragged, color swatches can be deleted by clicking on them…
Just something that popped into my head awhile back so figured I’d do a speed-coded prototype. I’d like to revisit this and add more to it.