Skip to content

Instantly share code, notes, and snippets.

@antenando
Created May 10, 2017 20:25
Show Gist options
  • Save antenando/a239e7ed6cbd2565d240b0673c4ccd53 to your computer and use it in GitHub Desktop.
Save antenando/a239e7ed6cbd2565d240b0673c4ccd53 to your computer and use it in GitHub Desktop.
JS Bin // source http://jsbin.com/jinewul
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width">
<title>JS Bin</title>
<style id="jsbin-css">
html {
cursor: none;
}
.cursor {
will-change: transform;
transition: transform 0.1s linear;
transform:
translate3d(
calc(var(--posX) - 15px),
calc(var(--posY) - 20px), 0)
rotate(calc(90deg + var(--rotate, 90deg)));
background-size: cover;
width: 30px;
height: 40px;
background-image: url("data:image/svg+xml;base64,PD94bWwgdmVyc2lvbj0iMS4wIj8+PHN2ZyB3aWR0aD0iNTk1LjI3NSIgaGVpZ2h0PSI4NDEuODkiIHhtbG5zPSJodHRwOi8vd3d3LnczLm9yZy8yMDAwL3N2ZyI+CiA8Zz4KICA8dGl0bGU+TGF5ZXIgMTwvdGl0bGU+CiAgPGcgaWQ9InN2Z18xIj4KICAgPHBvbHlnb24gZmlsbD0iIzAwMDAwMCIgaWQ9InN2Z18yIiBwb2ludHM9IjEyMS4zNCA0MjcuODkgMTYwLjIgNDI3Ljg5IDE2MC4yIDQ2NS41MTUgMTk5LjA2IDQ2NS41MTUgMTk5LjA2IDE1NS4xMTkgMjM3LjY3OSAxNTUuMTE5IDIzNy43MzUgMTU1LjExOSAyNzYuNTQgMTU1LjExOSAyNzYuNTQgMjcxLjkyNSAyNzYuNTQgMzEwLjc0MSAyNzYuNTQgMzEwLjk5MyAyNzYuNTQgMzQ5LjgxIDI3Ni41NCAzODguODgyIDMxNS40IDM4OC44ODIgMzE1LjQgMzQ5LjgxIDMxNS40IDMxMC45OTMgMzE1LjQgMzEwLjg2NyAzOTIuOTQgMzEwLjg2NyAzOTIuOTQgMzQ5Ljg3NSAzOTIuOTQgMzQ5Ljk0IDM5Mi45NCAzODguOTQ3IDQzMS44IDM4OC45NDcgNDMxLjggMzQ5Ljk0IDQzMS44IDM0OS44NzUgNDMxLjggMzEwLjg2NyA0NjkuOTQ1IDMxMC44NjcgNDY5Ljk0NSAyNzEuNzk1IDMxNS40IDI3MS43OTUgMzE1LjQgMTU0LjgzNyAyNzYuNTQgMTU0LjgzNyAyNzYuNTQgMTE2LjA1MSAyMzcuNzM1IDExNi4wNTEgMjM3LjY3OSAxMTYuMDUxIDE5OC44NzUgMTE2LjA1MSAxOTguODc1IDE1NC44MzcgMTYwLjIgMTU0LjgzNyAxNjAuMiAzODguODE3IDEyMS40NiAzODguODE3IDEyMS40NiAzNDkuODc1IDQ0LjUyIDM0OS44NzUgNDQuNTIgMzg4Ljk0NyAxMjEuMzQgMzg4Ljk0NyIvPgogICA8cG9seWdvbiBmaWxsPSIjMDAwMDAwIiBpZD0ic3ZnXzMiIHBvaW50cz0iNTA5LjM0IDU4My44NTUgNTA5LjM0IDU4My45MiA1MDkuMzQgNjIyLjkyOCA0NzAuNiA2MjIuOTI4IDQ3MC42IDU4My44NTUgNDcwLjYgNTQ1LjAzOCA0NzAuNiA1NDQuNzg2IDQ3MC42IDUwNS45NyA0NzAuNiA0NjYuODk4IDQzMS43NCA0NjYuODk4IDQzMS43NCA1MDUuOTcgNDMxLjc0IDU0NC43ODYgNDMxLjc0IDU0NS4wMzggNDMxLjc0IDU4My44NTUgNDMxLjc0IDYyMi45MjggNDcwLjU0IDYyMi45MjggNDcwLjU0IDY2MS45MzUgNDcwLjU0IDY2MiA0NzAuNTQgNzAwLjk0MyA0MzEuOCA3MDAuOTQzIDQzMS44IDc0MC4wMTUgNDcwLjU0IDc0MC4wMTUgNDcwLjY2IDc0MC4wMTUgNTA5LjQgNzQwLjAxNSA1MDkuNCA3MDEuMDA4IDUwOS40IDcwMC45NDMgNTA5LjQgNjYyIDUwOS40IDY2MS45MzUgNTA5LjQgNjIyLjkyOCA1NDguMiA2MjIuOTI4IDU0OC4yIDU4My45MiA1NDguMiA1ODMuODU1IDU0OC4yIDU0NC44NDcgNTA5LjM0IDU0NC44NDciLz4KICAgPHBvbHlnb24gZmlsbD0iIzAwMDAwMCIgaWQ9InN2Z180IiBwb2ludHM9IjU0OC4yIDM0OS44MSA1NDguMiAzMTAuODY3IDUwOS40IDMxMC44NjcgNTA5LjM0IDMxMC44NjcgNDcwLjU0IDMxMC44NjcgNDcwLjU0IDM0OS44NzUgNDcwLjU0IDM0OS45NCA0NzAuNTQgMzg4Ljk0NyA1MDkuNCAzODguOTQ3IDUwOS40IDM0OS45NCA1NDguMTQgMzQ5Ljk0IDU0OC4xNCA1NDQuMTg5IDU4NyA1NDQuMTg5IDU4NyAzNDkuODEiLz4KICAgPHBvbHlnb24gZmlsbD0iIzAwMDAwMCIgaWQ9InN2Z181IiBwb2ludHM9IjgyLjYzMDIgNTA1Ljg3NSA4Mi42MzAyIDQ2Ni44MDcgNDMuODYwNCA0NjYuODA3IDQzLjg2MDQgNDI3Ljg5IDQzLjg2MDQgMzg4LjgxNyA1LjAwMDAyIDM4OC44MTcgNS4wMDAwMiA0MjcuODkgNS4wMDAwMiA0NjYuOTYzIDQzLjc2OTggNDY2Ljk2MyA0My43Njk4IDUwNS44NzUiLz4KICAgPHJlY3QgZmlsbD0iIzAwMDAwMCIgaWQ9InN2Z182IiBoZWlnaHQ9IjM5LjA3MjUxMiIgd2lkdGg9IjM4Ljg2MDM1MyIgeT0iNjYxLjg2OTk1OSIgeD0iMzkyLjkzOTYzOCIvPgogICA8cG9seWdvbiBmaWxsPSIjMDAwMDAwIiBpZD0ic3ZnXzciIHBvaW50cz0iMjc2LjU0IDUwNS45NyAyNzYuNTQgNTQ0Ljc4NiAyNzYuNTQgNTQ1LjAzOCAyNzYuNTQgNTgzLjg1NSAyNzYuNTQgNjIyLjkyOCAzMTUuNCA2MjIuOTI4IDMxNS40IDU4My44NTUgMzE1LjQgNTQ1LjAzOCAzMTUuNCA1NDQuNzg2IDMxNS40IDUwNS45NyAzMTUuNCA0NjYuODk4IDI3Ni41NCA0NjYuODk4Ii8+CiAgIDxwb2x5Z29uIGZpbGw9IiMwMDAwMDAiIGlkPSJzdmdfOCIgcG9pbnRzPSIzNTQuMTQgNTA1Ljk3IDM1NC4xNCA1NDQuNzg2IDM1NC4xNCA1NDUuMDM4IDM1NC4xNCA1ODMuODU1IDM1NC4xNCA2MjIuOTI4IDM5MyA2MjIuOTI4IDM5MyA1ODMuODU1IDM5MyA1NDUuMDM4IDM5MyA1NDQuNzg2IDM5MyA1MDUuOTcgMzkzIDQ2Ni44OTggMzU0LjE0IDQ2Ni44OTgiLz4KICAgPHBvbHlnb24gZmlsbD0iIzAwMDAwMCIgaWQ9InN2Z185IiBwb2ludHM9IjIzNy44IDcwMC44NzggMjM3LjggNjYxLjgwOSAxOTkgNjYxLjgwOSAxOTkgNjIyLjkyOCAxNjAuMiA2MjIuOTI4IDE2MC4yIDU4My45MiAxMjEuNDYgNTgzLjkyIDEyMS40NiA1NDQuOTc3IDEyMS40NiA1MDUuOTA1IDgyLjYgNTA1LjkwNSA4Mi42IDU0NC45NzcgODIuNiA1ODQuMDQ2IDEyMS4zNCA1ODQuMDQ2IDEyMS4zNCA2MjIuOTkyIDE2MC4xNCA2MjIuOTkyIDE2MC4xNCA2NjIgMTk4Ljk0IDY2MiAxOTguOTQgNzAwLjg3OCAxOTguOTQgNzM5Ljk1IDIzNy44IDczOS45NSAyMzcuOCA3NDAuMDE1IDM5Mi4zNDUgNzQwLjAxNSAzOTIuMzQ1IDcwMC45NDMgMjM3LjggNzAwLjk0MyIvPgogIDwvZz4KIDwvZz4KPC9zdmc+");
}
</style>
</head>
<body>
<div class="cursor"></div>
<script src="https://cdnjs.cloudflare.com/ajax/libs/rxjs/5.4.0/Rx.min.js"></script>
</div>
<script id="jsbin-javascript">
class V {
constructor({clientX: clientX = 0, clientY: clientY = 0} = {}) {
this.x = clientX;
this.y = clientY;
}
magnitude() {
return Math.sqrt(this.x*this.x + this.y*this.y);
}
normalize() {
const mag = this.magnitude();
return new V({
clientX: this.x / mag,
clientY: this.y / mag
});
}
subtract(v) {
return new V({
clientX: this.x - v.x,
clientY: this.y - v.y
});
}
degree() {
const norm = this.normalize();
return Math.round(Math.atan2(norm.y, norm.x) * 180 / Math.PI);
}
}
const cursor = document.querySelector('.cursor');
Rx.Observable
.fromEvent(window, 'mousemove')
.throttleTime(30)
.map((event) => new V(event))
.do((position) => {
cursor.style.setProperty('--posX', `${position.x}px`);
cursor.style.setProperty('--posY', `${position.y}px`);
})
.bufferCount(2)
.map(([previous, current]) => current.subtract(previous).normalize())
.filter((direction) => direction.magnitude())
.map((direction) => direction.degree())
.subscribe((degree) => cursor.style.setProperty('--rotate', `${degree}deg`));
</script>
<script id="jsbin-source-css" type="text/css">html {
cursor: none;
}
.cursor {
will-change: transform;
transition: transform 0.1s linear;
transform:
translate3d(
calc(var(--posX) - 15px),
calc(var(--posY) - 20px), 0)
rotate(calc(90deg + var(--rotate, 90deg)));
background-size: cover;
width: 30px;
height: 40px;
background-image: url("data:image/svg+xml;base64,PD94bWwgdmVyc2lvbj0iMS4wIj8+PHN2ZyB3aWR0aD0iNTk1LjI3NSIgaGVpZ2h0PSI4NDEuODkiIHhtbG5zPSJodHRwOi8vd3d3LnczLm9yZy8yMDAwL3N2ZyI+CiA8Zz4KICA8dGl0bGU+TGF5ZXIgMTwvdGl0bGU+CiAgPGcgaWQ9InN2Z18xIj4KICAgPHBvbHlnb24gZmlsbD0iIzAwMDAwMCIgaWQ9InN2Z18yIiBwb2ludHM9IjEyMS4zNCA0MjcuODkgMTYwLjIgNDI3Ljg5IDE2MC4yIDQ2NS41MTUgMTk5LjA2IDQ2NS41MTUgMTk5LjA2IDE1NS4xMTkgMjM3LjY3OSAxNTUuMTE5IDIzNy43MzUgMTU1LjExOSAyNzYuNTQgMTU1LjExOSAyNzYuNTQgMjcxLjkyNSAyNzYuNTQgMzEwLjc0MSAyNzYuNTQgMzEwLjk5MyAyNzYuNTQgMzQ5LjgxIDI3Ni41NCAzODguODgyIDMxNS40IDM4OC44ODIgMzE1LjQgMzQ5LjgxIDMxNS40IDMxMC45OTMgMzE1LjQgMzEwLjg2NyAzOTIuOTQgMzEwLjg2NyAzOTIuOTQgMzQ5Ljg3NSAzOTIuOTQgMzQ5Ljk0IDM5Mi45NCAzODguOTQ3IDQzMS44IDM4OC45NDcgNDMxLjggMzQ5Ljk0IDQzMS44IDM0OS44NzUgNDMxLjggMzEwLjg2NyA0NjkuOTQ1IDMxMC44NjcgNDY5Ljk0NSAyNzEuNzk1IDMxNS40IDI3MS43OTUgMzE1LjQgMTU0LjgzNyAyNzYuNTQgMTU0LjgzNyAyNzYuNTQgMTE2LjA1MSAyMzcuNzM1IDExNi4wNTEgMjM3LjY3OSAxMTYuMDUxIDE5OC44NzUgMTE2LjA1MSAxOTguODc1IDE1NC44MzcgMTYwLjIgMTU0LjgzNyAxNjAuMiAzODguODE3IDEyMS40NiAzODguODE3IDEyMS40NiAzNDkuODc1IDQ0LjUyIDM0OS44NzUgNDQuNTIgMzg4Ljk0NyAxMjEuMzQgMzg4Ljk0NyIvPgogICA8cG9seWdvbiBmaWxsPSIjMDAwMDAwIiBpZD0ic3ZnXzMiIHBvaW50cz0iNTA5LjM0IDU4My44NTUgNTA5LjM0IDU4My45MiA1MDkuMzQgNjIyLjkyOCA0NzAuNiA2MjIuOTI4IDQ3MC42IDU4My44NTUgNDcwLjYgNTQ1LjAzOCA0NzAuNiA1NDQuNzg2IDQ3MC42IDUwNS45NyA0NzAuNiA0NjYuODk4IDQzMS43NCA0NjYuODk4IDQzMS43NCA1MDUuOTcgNDMxLjc0IDU0NC43ODYgNDMxLjc0IDU0NS4wMzggNDMxLjc0IDU4My44NTUgNDMxLjc0IDYyMi45MjggNDcwLjU0IDYyMi45MjggNDcwLjU0IDY2MS45MzUgNDcwLjU0IDY2MiA0NzAuNTQgNzAwLjk0MyA0MzEuOCA3MDAuOTQzIDQzMS44IDc0MC4wMTUgNDcwLjU0IDc0MC4wMTUgNDcwLjY2IDc0MC4wMTUgNTA5LjQgNzQwLjAxNSA1MDkuNCA3MDEuMDA4IDUwOS40IDcwMC45NDMgNTA5LjQgNjYyIDUwOS40IDY2MS45MzUgNTA5LjQgNjIyLjkyOCA1NDguMiA2MjIuOTI4IDU0OC4yIDU4My45MiA1NDguMiA1ODMuODU1IDU0OC4yIDU0NC44NDcgNTA5LjM0IDU0NC44NDciLz4KICAgPHBvbHlnb24gZmlsbD0iIzAwMDAwMCIgaWQ9InN2Z180IiBwb2ludHM9IjU0OC4yIDM0OS44MSA1NDguMiAzMTAuODY3IDUwOS40IDMxMC44NjcgNTA5LjM0IDMxMC44NjcgNDcwLjU0IDMxMC44NjcgNDcwLjU0IDM0OS44NzUgNDcwLjU0IDM0OS45NCA0NzAuNTQgMzg4Ljk0NyA1MDkuNCAzODguOTQ3IDUwOS40IDM0OS45NCA1NDguMTQgMzQ5Ljk0IDU0OC4xNCA1NDQuMTg5IDU4NyA1NDQuMTg5IDU4NyAzNDkuODEiLz4KICAgPHBvbHlnb24gZmlsbD0iIzAwMDAwMCIgaWQ9InN2Z181IiBwb2ludHM9IjgyLjYzMDIgNTA1Ljg3NSA4Mi42MzAyIDQ2Ni44MDcgNDMuODYwNCA0NjYuODA3IDQzLjg2MDQgNDI3Ljg5IDQzLjg2MDQgMzg4LjgxNyA1LjAwMDAyIDM4OC44MTcgNS4wMDAwMiA0MjcuODkgNS4wMDAwMiA0NjYuOTYzIDQzLjc2OTggNDY2Ljk2MyA0My43Njk4IDUwNS44NzUiLz4KICAgPHJlY3QgZmlsbD0iIzAwMDAwMCIgaWQ9InN2Z182IiBoZWlnaHQ9IjM5LjA3MjUxMiIgd2lkdGg9IjM4Ljg2MDM1MyIgeT0iNjYxLjg2OTk1OSIgeD0iMzkyLjkzOTYzOCIvPgogICA8cG9seWdvbiBmaWxsPSIjMDAwMDAwIiBpZD0ic3ZnXzciIHBvaW50cz0iMjc2LjU0IDUwNS45NyAyNzYuNTQgNTQ0Ljc4NiAyNzYuNTQgNTQ1LjAzOCAyNzYuNTQgNTgzLjg1NSAyNzYuNTQgNjIyLjkyOCAzMTUuNCA2MjIuOTI4IDMxNS40IDU4My44NTUgMzE1LjQgNTQ1LjAzOCAzMTUuNCA1NDQuNzg2IDMxNS40IDUwNS45NyAzMTUuNCA0NjYuODk4IDI3Ni41NCA0NjYuODk4Ii8+CiAgIDxwb2x5Z29uIGZpbGw9IiMwMDAwMDAiIGlkPSJzdmdfOCIgcG9pbnRzPSIzNTQuMTQgNTA1Ljk3IDM1NC4xNCA1NDQuNzg2IDM1NC4xNCA1NDUuMDM4IDM1NC4xNCA1ODMuODU1IDM1NC4xNCA2MjIuOTI4IDM5MyA2MjIuOTI4IDM5MyA1ODMuODU1IDM5MyA1NDUuMDM4IDM5MyA1NDQuNzg2IDM5MyA1MDUuOTcgMzkzIDQ2Ni44OTggMzU0LjE0IDQ2Ni44OTgiLz4KICAgPHBvbHlnb24gZmlsbD0iIzAwMDAwMCIgaWQ9InN2Z185IiBwb2ludHM9IjIzNy44IDcwMC44NzggMjM3LjggNjYxLjgwOSAxOTkgNjYxLjgwOSAxOTkgNjIyLjkyOCAxNjAuMiA2MjIuOTI4IDE2MC4yIDU4My45MiAxMjEuNDYgNTgzLjkyIDEyMS40NiA1NDQuOTc3IDEyMS40NiA1MDUuOTA1IDgyLjYgNTA1LjkwNSA4Mi42IDU0NC45NzcgODIuNiA1ODQuMDQ2IDEyMS4zNCA1ODQuMDQ2IDEyMS4zNCA2MjIuOTkyIDE2MC4xNCA2MjIuOTkyIDE2MC4xNCA2NjIgMTk4Ljk0IDY2MiAxOTguOTQgNzAwLjg3OCAxOTguOTQgNzM5Ljk1IDIzNy44IDczOS45NSAyMzcuOCA3NDAuMDE1IDM5Mi4zNDUgNzQwLjAxNSAzOTIuMzQ1IDcwMC45NDMgMjM3LjggNzAwLjk0MyIvPgogIDwvZz4KIDwvZz4KPC9zdmc+");
}</script>
<script id="jsbin-source-javascript" type="text/javascript">class V {
constructor({clientX: clientX = 0, clientY: clientY = 0} = {}) {
this.x = clientX;
this.y = clientY;
}
magnitude() {
return Math.sqrt(this.x*this.x + this.y*this.y);
}
normalize() {
const mag = this.magnitude();
return new V({
clientX: this.x / mag,
clientY: this.y / mag
});
}
subtract(v) {
return new V({
clientX: this.x - v.x,
clientY: this.y - v.y
});
}
degree() {
const norm = this.normalize();
return Math.round(Math.atan2(norm.y, norm.x) * 180 / Math.PI);
}
}
const cursor = document.querySelector('.cursor');
Rx.Observable
.fromEvent(window, 'mousemove')
.throttleTime(30)
.map((event) => new V(event))
.do((position) => {
cursor.style.setProperty('--posX', `${position.x}px`);
cursor.style.setProperty('--posY', `${position.y}px`);
})
.bufferCount(2)
.map(([previous, current]) => current.subtract(previous).normalize())
.filter((direction) => direction.magnitude())
.map((direction) => direction.degree())
.subscribe((degree) => cursor.style.setProperty('--rotate', `${degree}deg`));</script></body>
</html>
html {
cursor: none;
}
.cursor {
will-change: transform;
transition: transform 0.1s linear;
transform:
translate3d(
calc(var(--posX) - 15px),
calc(var(--posY) - 20px), 0)
rotate(calc(90deg + var(--rotate, 90deg)));
background-size: cover;
width: 30px;
height: 40px;
background-image: url("data:image/svg+xml;base64,PD94bWwgdmVyc2lvbj0iMS4wIj8+PHN2ZyB3aWR0aD0iNTk1LjI3NSIgaGVpZ2h0PSI4NDEuODkiIHhtbG5zPSJodHRwOi8vd3d3LnczLm9yZy8yMDAwL3N2ZyI+CiA8Zz4KICA8dGl0bGU+TGF5ZXIgMTwvdGl0bGU+CiAgPGcgaWQ9InN2Z18xIj4KICAgPHBvbHlnb24gZmlsbD0iIzAwMDAwMCIgaWQ9InN2Z18yIiBwb2ludHM9IjEyMS4zNCA0MjcuODkgMTYwLjIgNDI3Ljg5IDE2MC4yIDQ2NS41MTUgMTk5LjA2IDQ2NS41MTUgMTk5LjA2IDE1NS4xMTkgMjM3LjY3OSAxNTUuMTE5IDIzNy43MzUgMTU1LjExOSAyNzYuNTQgMTU1LjExOSAyNzYuNTQgMjcxLjkyNSAyNzYuNTQgMzEwLjc0MSAyNzYuNTQgMzEwLjk5MyAyNzYuNTQgMzQ5LjgxIDI3Ni41NCAzODguODgyIDMxNS40IDM4OC44ODIgMzE1LjQgMzQ5LjgxIDMxNS40IDMxMC45OTMgMzE1LjQgMzEwLjg2NyAzOTIuOTQgMzEwLjg2NyAzOTIuOTQgMzQ5Ljg3NSAzOTIuOTQgMzQ5Ljk0IDM5Mi45NCAzODguOTQ3IDQzMS44IDM4OC45NDcgNDMxLjggMzQ5Ljk0IDQzMS44IDM0OS44NzUgNDMxLjggMzEwLjg2NyA0NjkuOTQ1IDMxMC44NjcgNDY5Ljk0NSAyNzEuNzk1IDMxNS40IDI3MS43OTUgMzE1LjQgMTU0LjgzNyAyNzYuNTQgMTU0LjgzNyAyNzYuNTQgMTE2LjA1MSAyMzcuNzM1IDExNi4wNTEgMjM3LjY3OSAxMTYuMDUxIDE5OC44NzUgMTE2LjA1MSAxOTguODc1IDE1NC44MzcgMTYwLjIgMTU0LjgzNyAxNjAuMiAzODguODE3IDEyMS40NiAzODguODE3IDEyMS40NiAzNDkuODc1IDQ0LjUyIDM0OS44NzUgNDQuNTIgMzg4Ljk0NyAxMjEuMzQgMzg4Ljk0NyIvPgogICA8cG9seWdvbiBmaWxsPSIjMDAwMDAwIiBpZD0ic3ZnXzMiIHBvaW50cz0iNTA5LjM0IDU4My44NTUgNTA5LjM0IDU4My45MiA1MDkuMzQgNjIyLjkyOCA0NzAuNiA2MjIuOTI4IDQ3MC42IDU4My44NTUgNDcwLjYgNTQ1LjAzOCA0NzAuNiA1NDQuNzg2IDQ3MC42IDUwNS45NyA0NzAuNiA0NjYuODk4IDQzMS43NCA0NjYuODk4IDQzMS43NCA1MDUuOTcgNDMxLjc0IDU0NC43ODYgNDMxLjc0IDU0NS4wMzggNDMxLjc0IDU4My44NTUgNDMxLjc0IDYyMi45MjggNDcwLjU0IDYyMi45MjggNDcwLjU0IDY2MS45MzUgNDcwLjU0IDY2MiA0NzAuNTQgNzAwLjk0MyA0MzEuOCA3MDAuOTQzIDQzMS44IDc0MC4wMTUgNDcwLjU0IDc0MC4wMTUgNDcwLjY2IDc0MC4wMTUgNTA5LjQgNzQwLjAxNSA1MDkuNCA3MDEuMDA4IDUwOS40IDcwMC45NDMgNTA5LjQgNjYyIDUwOS40IDY2MS45MzUgNTA5LjQgNjIyLjkyOCA1NDguMiA2MjIuOTI4IDU0OC4yIDU4My45MiA1NDguMiA1ODMuODU1IDU0OC4yIDU0NC44NDcgNTA5LjM0IDU0NC44NDciLz4KICAgPHBvbHlnb24gZmlsbD0iIzAwMDAwMCIgaWQ9InN2Z180IiBwb2ludHM9IjU0OC4yIDM0OS44MSA1NDguMiAzMTAuODY3IDUwOS40IDMxMC44NjcgNTA5LjM0IDMxMC44NjcgNDcwLjU0IDMxMC44NjcgNDcwLjU0IDM0OS44NzUgNDcwLjU0IDM0OS45NCA0NzAuNTQgMzg4Ljk0NyA1MDkuNCAzODguOTQ3IDUwOS40IDM0OS45NCA1NDguMTQgMzQ5Ljk0IDU0OC4xNCA1NDQuMTg5IDU4NyA1NDQuMTg5IDU4NyAzNDkuODEiLz4KICAgPHBvbHlnb24gZmlsbD0iIzAwMDAwMCIgaWQ9InN2Z181IiBwb2ludHM9IjgyLjYzMDIgNTA1Ljg3NSA4Mi42MzAyIDQ2Ni44MDcgNDMuODYwNCA0NjYuODA3IDQzLjg2MDQgNDI3Ljg5IDQzLjg2MDQgMzg4LjgxNyA1LjAwMDAyIDM4OC44MTcgNS4wMDAwMiA0MjcuODkgNS4wMDAwMiA0NjYuOTYzIDQzLjc2OTggNDY2Ljk2MyA0My43Njk4IDUwNS44NzUiLz4KICAgPHJlY3QgZmlsbD0iIzAwMDAwMCIgaWQ9InN2Z182IiBoZWlnaHQ9IjM5LjA3MjUxMiIgd2lkdGg9IjM4Ljg2MDM1MyIgeT0iNjYxLjg2OTk1OSIgeD0iMzkyLjkzOTYzOCIvPgogICA8cG9seWdvbiBmaWxsPSIjMDAwMDAwIiBpZD0ic3ZnXzciIHBvaW50cz0iMjc2LjU0IDUwNS45NyAyNzYuNTQgNTQ0Ljc4NiAyNzYuNTQgNTQ1LjAzOCAyNzYuNTQgNTgzLjg1NSAyNzYuNTQgNjIyLjkyOCAzMTUuNCA2MjIuOTI4IDMxNS40IDU4My44NTUgMzE1LjQgNTQ1LjAzOCAzMTUuNCA1NDQuNzg2IDMxNS40IDUwNS45NyAzMTUuNCA0NjYuODk4IDI3Ni41NCA0NjYuODk4Ii8+CiAgIDxwb2x5Z29uIGZpbGw9IiMwMDAwMDAiIGlkPSJzdmdfOCIgcG9pbnRzPSIzNTQuMTQgNTA1Ljk3IDM1NC4xNCA1NDQuNzg2IDM1NC4xNCA1NDUuMDM4IDM1NC4xNCA1ODMuODU1IDM1NC4xNCA2MjIuOTI4IDM5MyA2MjIuOTI4IDM5MyA1ODMuODU1IDM5MyA1NDUuMDM4IDM5MyA1NDQuNzg2IDM5MyA1MDUuOTcgMzkzIDQ2Ni44OTggMzU0LjE0IDQ2Ni44OTgiLz4KICAgPHBvbHlnb24gZmlsbD0iIzAwMDAwMCIgaWQ9InN2Z185IiBwb2ludHM9IjIzNy44IDcwMC44NzggMjM3LjggNjYxLjgwOSAxOTkgNjYxLjgwOSAxOTkgNjIyLjkyOCAxNjAuMiA2MjIuOTI4IDE2MC4yIDU4My45MiAxMjEuNDYgNTgzLjkyIDEyMS40NiA1NDQuOTc3IDEyMS40NiA1MDUuOTA1IDgyLjYgNTA1LjkwNSA4Mi42IDU0NC45NzcgODIuNiA1ODQuMDQ2IDEyMS4zNCA1ODQuMDQ2IDEyMS4zNCA2MjIuOTkyIDE2MC4xNCA2MjIuOTkyIDE2MC4xNCA2NjIgMTk4Ljk0IDY2MiAxOTguOTQgNzAwLjg3OCAxOTguOTQgNzM5Ljk1IDIzNy44IDczOS45NSAyMzcuOCA3NDAuMDE1IDM5Mi4zNDUgNzQwLjAxNSAzOTIuMzQ1IDcwMC45NDMgMjM3LjggNzAwLjk0MyIvPgogIDwvZz4KIDwvZz4KPC9zdmc+");
}
class V {
constructor({clientX: clientX = 0, clientY: clientY = 0} = {}) {
this.x = clientX;
this.y = clientY;
}
magnitude() {
return Math.sqrt(this.x*this.x + this.y*this.y);
}
normalize() {
const mag = this.magnitude();
return new V({
clientX: this.x / mag,
clientY: this.y / mag
});
}
subtract(v) {
return new V({
clientX: this.x - v.x,
clientY: this.y - v.y
});
}
degree() {
const norm = this.normalize();
return Math.round(Math.atan2(norm.y, norm.x) * 180 / Math.PI);
}
}
const cursor = document.querySelector('.cursor');
Rx.Observable
.fromEvent(window, 'mousemove')
.throttleTime(30)
.map((event) => new V(event))
.do((position) => {
cursor.style.setProperty('--posX', `${position.x}px`);
cursor.style.setProperty('--posY', `${position.y}px`);
})
.bufferCount(2)
.map(([previous, current]) => current.subtract(previous).normalize())
.filter((direction) => direction.magnitude())
.map((direction) => direction.degree())
.subscribe((degree) => cursor.style.setProperty('--rotate', `${degree}deg`));
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment