96 lines
2.9 KiB
JavaScript
96 lines
2.9 KiB
JavaScript
|
var CURSOR;
|
||
|
|
||
|
Math.lerp = (a, b, n) => (1 - n) * a + n * b;
|
||
|
|
||
|
const getStyle = (el, attr) => {
|
||
|
try {
|
||
|
return window.getComputedStyle ?
|
||
|
window.getComputedStyle(el)[attr] :
|
||
|
el.currentStyle[attr];
|
||
|
} catch (e) {}
|
||
|
return "";
|
||
|
};
|
||
|
|
||
|
class Cursor {
|
||
|
constructor() {
|
||
|
this.pos = {
|
||
|
curr: null,
|
||
|
prev: null
|
||
|
};
|
||
|
this.pt = [];
|
||
|
this.create();
|
||
|
this.init();
|
||
|
this.render();
|
||
|
}
|
||
|
|
||
|
move(left, top) {
|
||
|
this.cursor.style["left"] = `${left}px`;
|
||
|
this.cursor.style["top"] = `${top}px`;
|
||
|
}
|
||
|
|
||
|
create() {
|
||
|
if (!this.cursor) {
|
||
|
this.cursor = document.createElement("div");
|
||
|
this.cursor.id = "cursor";
|
||
|
this.cursor.classList.add("hidden");
|
||
|
document.body.append(this.cursor);
|
||
|
}
|
||
|
|
||
|
var el = document.getElementsByTagName('*');
|
||
|
for (let i = 0; i < el.length; i++)
|
||
|
if (getStyle(el[i], "cursor") == "pointer")
|
||
|
this.pt.push(el[i].outerHTML);
|
||
|
|
||
|
document.body.appendChild((this.scr = document.createElement("style")));
|
||
|
this.scr.innerHTML =
|
||
|
`* {cursor: url("data:image/svg+xml,<svg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 8 8' width='8px' height='8px'><circle cx='4' cy='4' r='4' opacity='.5'/></svg>") 4 4, auto}`;
|
||
|
}
|
||
|
|
||
|
refresh() {
|
||
|
this.scr.remove();
|
||
|
this.cursor.classList.remove("hover");
|
||
|
this.cursor.classList.remove("active");
|
||
|
this.pos = {
|
||
|
curr: null,
|
||
|
prev: null
|
||
|
};
|
||
|
this.pt = [];
|
||
|
|
||
|
this.create();
|
||
|
this.init();
|
||
|
this.render();
|
||
|
}
|
||
|
|
||
|
init() {
|
||
|
document.onmouseover = e => this.pt.includes(e.target.outerHTML) && this.cursor.classList.add("hover");
|
||
|
document.onmouseout = e => this.pt.includes(e.target.outerHTML) && this.cursor.classList.remove("hover");
|
||
|
document.onmousemove = e => {
|
||
|
(this.pos.curr == null) && this.move(e.clientX - 8, e.clientY - 8);
|
||
|
this.pos.curr = {
|
||
|
x: e.clientX - 8,
|
||
|
y: e.clientY - 8
|
||
|
};
|
||
|
this.cursor.classList.remove("hidden");
|
||
|
};
|
||
|
document.onmouseenter = e => this.cursor.classList.remove("hidden");
|
||
|
document.onmouseleave = e => this.cursor.classList.add("hidden");
|
||
|
document.onmousedown = e => this.cursor.classList.add("active");
|
||
|
document.onmouseup = e => this.cursor.classList.remove("active");
|
||
|
}
|
||
|
|
||
|
render() {
|
||
|
if (this.pos.prev) {
|
||
|
this.pos.prev.x = Math.lerp(this.pos.prev.x, this.pos.curr.x, 0.45);
|
||
|
this.pos.prev.y = Math.lerp(this.pos.prev.y, this.pos.curr.y, 0.45);
|
||
|
this.move(this.pos.prev.x, this.pos.prev.y);
|
||
|
} else {
|
||
|
this.pos.prev = this.pos.curr;
|
||
|
}
|
||
|
requestAnimationFrame(() => this.render());
|
||
|
}
|
||
|
}
|
||
|
|
||
|
(() => {
|
||
|
CURSOR = new Cursor();
|
||
|
// 需要重新获取列表时,使用 CURSOR.refresh()
|
||
|
})();
|