Point DIV at Another DIV (Angle Between Two Points)
const dot = document.createElement('div')
Object.assign(dot.style, {
position: 'absolute',
left: '100px',
top: '100px',
width: '10px',
height: '10px',
transform: 'translate(-5px, -5px)',
background: 'black'
});
document.body.appendChild(dot);
const pointer = document.createElement('div');
Object.assign(pointer.style, {
position: 'absolute',
left: '-10px',
top: '-5px',
width: '20px',
height: '10px',
background: 'red'
});
document.body.appendChild(pointer);
// desktop only (`touchmove` needed for mobile)
document.addEventListener('mousemove', (e) => {
const dx = parseFloat(dot.style.left) - e.clientX;
const dy = parseFloat(dot.style.top) - e.clientY;
const angle = Math.atan2(dy, dx) / Math.PI * 180;
pointer.style.transform = `
translate(${e.clientX}px, ${e.clientY}px)
rotate(${angle}deg)
`;
});
Moving your mouse around the page, you’ll notice the red div
always points at the black div
.
(more…)
No Scrolling on Mobile
document.addEventListener('touchmove',
e => e.preventDefault(), { passive: false });
document.body.innerHTML = 'Hi, no page scrolling here...';
It’s common to want to prevent page scrolling on mobile. Here is an easy way to do it.
Rectangle Path with SVG
const rectPath = rect =>
`M ${rect.left} ${rect.top}
L ${rect.right} ${rect.top}
${rect.right} ${rect.bottom}
${rect.left} ${rect.bottom}
${rect.left} ${rect.top} `;
const el = document.body.appendChild(
document.createElement('div'));
el.innerHTML = `
<svg width="100%" height="100%" viewBox="0 0 550 496">
<path d="
${rectPath({left: 20, top: 10, right: 100, bottom: 100})}
${rectPath({left: 50, top: 50, right: 200, bottom: 200})}
${rectPath({left: 150, top: 20, right: 250, bottom: 100})}
${rectPath({left: 150, top: 120, right: 250, bottom: 230})}
" stroke="black" fill="red" fill-rule="evenodd" vector-effect="non-scaling-stroke"/>
<path d="
${rectPath({left: 10, top: 220, right: 100, bottom: 300})}
${rectPath({left: 20, top: 250, right: 150, bottom: 350})}
" stroke="white" fill="#64a7ff" fill-rule="nonzero" vector-effect="non-scaling-stroke"/>
<path d="
${rectPath({left: 350, top: 10, right: 450, bottom: 150})}
" fill="#2e9997" />
</svg>
<style>
svg, div, body, html {
overflow: visible;
height: 100%;
width: 100%;
margin: 0; padding: 0;
}
</style>
`;
In this snippet rectPath
creates a rectangle with “move to” and “line to” commands to be used in conjunction with SVG paths.
Wobbling Ball With Canvas
// same as yesterday but with canvas instead of svg
const canvas = document.createElement('canvas'),
c = canvas.getContext('2d');
document.body.appendChild(canvas);
document.body.style.margin = 0;
let w = window.innerWidth,
h = window.innerHeight,
x = w / 2,
y = h / 2,
vx = vy = dx = dy = 0,
damp = 0.99, div = 8, ticks = 0,
wobbleChance = 0.03,
startTick = 50;
function loop() {
w = window.innerWidth;
h = window.innerHeight;
radius = w * 0.05;
diam = radius * 2;
diam2x = diam * 2;
if (x > w){
vx *= -1;
dx *= -1;
x = w;
} else if (x < 0){
vx *= -1;
dx *= -1;
x = 0;
}
if (y > h) {
vy *= -1;
dy *= -1;
y = h;
} else if (y < 0) {
vy *= -1;
dy *= -1;
y = 0
}
if (
Math.random() < wobbleChance ||
ticks === startTick) {
dx += Math.random() * 10 - 5;
dy += Math.random() * 10 - 5;
}
dx *= damp;
dy *= damp;
vx += (dx - vx) / div;
vy += (dy - vy) / div;
x += vx;
y += vy;
// in most cases these days you
// just clear the whole canvas, but for
// this example we clear a rectangle around
// the circle
c.clearRect(
x - diam,
y - diam,
diam2x,
diam2x
);
// draw the path
c.fillStyle = 'red'
c.beginPath();
c.arc(x, y, radius, 0, Math.PI * 2, false);
c.fill();
ticks++;
window.requestAnimationFrame(loop);
}
loop();
function resize() {
canvas.width = window.innerWidth;
canvas.height = window.innerHeight;
}
resize();
window.addEventListener('resize', resize);
A wobbling ball with canvas.
Wobbling Ball with SVG
const el = document.body.appendChild(
document.createElement('div'));
el.innerHTML = `
<svg width="100%" height="100%">
<circle
id="circ"
cx="0" cy="0" r="50"
fill="red" style="will-change: transform;"/>
</svg>
<style>
svg, div, body, html {
overflow: visible;
height: 100%;
width: 100%;
margin: 0; padding: 0;
}
</style>
`;
let w = window.innerWidth,
h = window.innerHeight,
x = w / 2,
y = h / 2,
vx = vy = dx = dy = 0,
damp = 0.99, div = 8, ticks = 0,
wobbleChance = 0.03,
startTick = 50;
function loop() {
w = window.innerWidth;
h = window.innerHeight;
if (x > w){
vx *= -1;
dx *= -1;
x = w;
} else if (x < 0){
vx *= -1;
dx *= -1;
x = 0;
}
if (y > h) {
vy *= -1;
dy *= -1;
y = h;
} else if (y < 0) {
vy *= -1;
dy *= -1;
y = 0
}
if (
Math.random() < wobbleChance ||
ticks === startTick) {
dx += Math.random() * 10 - 5;
dy += Math.random() * 10 - 5;
}
dx *= damp;
dy *= damp;
vx += (dx - vx) / div;
vy += (dy - vy) / div;
x += vx;
y += vy;
circ.setAttribute('transform', `translate(${x} ${y})`);
ticks++;
window.requestAnimationFrame(loop);
}
loop();
function resize() {
const radius = Math.min(w, h) * .05;
// `window.circ` is the global id (⌐■_■)
circ.r.baseVal.value = radius;
}
resize();
window.addEventListener('resize', resize);
A wobbling ball with svg.