JSFiddle - React, Tailwind, and code Playground
Paint API border experiment 2
by Travis Almand
HTML
<div class="container">
container 1
</div>
<div class="container">
container 2
</div>
<div class="container">
container 3
</div>
<div class="container">
container 4
</div>
SCSS
.container {
align-items: center;
background-color: white;
border-radius: 10px;
box-shadow: 0 0 8px 0 rgba(0, 0, 0, 0.5);
display: flex;
height: 100px;
justify-content: center;
margin: 50px 20px;
position: relative;
overflow: hidden;
width: 300px;
// you can adjust these
--decorate-width: 10;
--decorate-color: rgba(255,0,0,1);
--decorate-duration: 500;
&.decorate {
background-image: paint(decorate);
}
&:nth-child(2) {
--decorate-width: 20;
--decorate-duration: 1000;
height: 150px;
width: 100px;
}
&:nth-child(3) {
height: 200px;
}
&:nth-child(4) {
border-radius: 0;
height: 200px;
width: 200px;
}
}
JavaScript
function decorateMouseOver (e) {
this.classList.toggle('decorate');
let self = this;
let start = performance.now();
let rect = self.getBoundingClientRect();
let x = e.clientX - rect.x;
let mx = e.movementX < 0 ? e.movementX * -1 : e.movementX;
let y = e.clientY - rect.y;
let my = e.movementY < 0 ? e.movementY * -1 : e.movementY;
let duration = getComputedStyle(self).getPropertyValue('--decorate-duration');
requestAnimationFrame(function raf(now) {
const count = Math.floor(now - start);
self.style.cssText = `--decorate-x: ${x}; --decorate-mx: ${mx}; --decorate-y: ${y}; --decorate-my: ${my}; --decorate-tick: ${count};`;
if(count > duration) {
return;
}
requestAnimationFrame(raf);
});
}
function decorateMouseOut (e) {
this.classList.remove('decorate');
this.style.cssText = '--decorate-tick: 0';
}
const accountContainers = document.querySelectorAll('.container');
accountContainers.forEach(container => {
container.addEventListener('mouseover', decorateMouseOver);
container.addEventListener('mouseout', decorateMouseOut);
});
CSS.registerProperty({
name: '--decorate-width',
syntax: '<number>',
inherits: false,
initialValue: 10
});
CSS.registerProperty({
name: '--decorate-color',
syntax: '<color>',
inherits: false,
initialValue: 'rgba(0, 0, 0, 1)'
});
CSS.registerProperty({
name: '--decorate-duration',
syntax: '<number>',
inherits: false,
initialValue: 500
});
CSS.paintWorklet.addModule(URL.createObjectURL(new Blob([`
class AccountDecorator {
static get inputProperties() { return ['--decorate-color', '--decorate-tick', '--decorate-x', '--decorate-mx', '--decorate-y', '--decorate-my', '--decorate-width', '--decorate-duration']; }
paint(ctx, geom, properties) {
const color = properties.get('--decorate-color').toString();
const x = parseFloat(properties.get('--decorate-x'));
const mx = parseFloat(properties.get('--decorate-mx'));
const y =...