
開発するWebシステムに合うように、マウスカーソルデザインをカスタマイズしたいですよね。
マウスカーソルデザインはライブラリ等を使わず、Vanilla JSで好きなように変更可能です。
動作イメージ

コード
<!DOCTYPE html>
<html lang="ja">
<head>
<meta charset="utf-8">
<title>カーソルデザイン</title>
<script type="text/javascript">
const skinableCursor = {
// publicプロパティ。カーソルデザインを変更する場合はここで変更します。
//skinPath: 'skin.gif',
skinPath: '',
// privateプロパティ。ブラウザを検出します。
IE: (document.all && document.getElementById && !window.opera),
FF: (!document.all && document.getElementById && !window.opera),
OP: (document.all && document.getElementById && window.opera),
// privateプロパティ。カーソルの属性。
cursor: {
lt: {
x: '0px',
y: '0px',
w: '19px',
h: '26px',
dx: -22,
dy: -22
},
rt: {
x: '19px',
y: '0px',
w: '26px',
h: '19px',
dx: -3,
dy: -22
},
rb: {
x: '26px',
y: '19px',
w: '19px',
h: '26px',
dx: 4,
dy: -3
},
lb: {
x: '0px',
y: '26px',
w: '26px',
h: '19px',
dx: -22,
dy: 4
}
},
// privateメソッド。初期化。
init: function() {
skinableCursor.cursor.browserDelta = (skinableCursor.IE ? 2 : 0);
if (skinableCursor.FF || skinableCursor.OP) {
document.addEventListener("DOMContentLoaded", skinableCursor.domReady,
false);
}
if (skinableCursor.IE) {
document.write("<scr" + "ipt id=__ieinit defer=true " +
"src=//:><\/script>");
const script = document.getElementById("__ieinit");
script.onreadystatechange = function() {
if (this.readyState != "complete") return;
this.parentNode.removeChild(this);
skinableCursor.domReady();
};
script = null;
}
},
// privateメソッド。
domReady: function() {
skinableCursor.create();
if (skinableCursor.FF || skinableCursor.OP) {
const s = document.createElement('style');
s.innerHTML =
'* { cursor: inherit; } html { height: 100%; } body, html { cursor: crosshair; }';
document.body.appendChild(s);
document.addEventListener('mousemove', skinableCursor.move, false);
}
if (skinableCursor.IE) {
const s = document.createStyleSheet()
s.addRule("*", "cursor: inherit");
s.addRule("body", "cursor: crosshair");
s.addRule("html", "cursor: crosshair");
document.attachEvent('onmousemove', skinableCursor.move);
}
const anchors = document.getElementsByTagName('a');
for (x = 0; x < anchors.length; x++) {
if (skinableCursor.FF || skinableCursor.OP) {
anchors[x].addEventListener('mousemove', skinableCursor.events.anchor,
false);
anchors[x].addEventListener('mouseout', skinableCursor.events.show, false);
}
if (skinableCursor.IE) {
anchors[x].attachEvent('onmousemove', skinableCursor.events.anchor);
anchors[x].attachEvent('onmouseout', skinableCursor.events.show);
}
}
},
// privateメソッド。カーソルの作成。
create: function() {
function create(el, d) {
el.style.position = 'absolute';
el.style.overflow = 'hidden';
el.style.display = 'none';
el.style.left = d.x;
el.style.top = d.y;
el.style.width = d.w;
el.style.height = d.h;
if (skinableCursor.IE) {
el.innerHTML = '<img src="' + skinableCursor.skinPath +
'" style="margin: -' + d.y + ' 0px 0px -' + d.x + '">';
} else {
el.style.background = 'url(' + skinableCursor.skinPath + ') -' + d.x +
' -' + d.y;
}
return el;
}
const c = skinableCursor.cursor;
c.lt.el = create(document.createElement('div'), c.lt);
c.rt.el = create(document.createElement('div'), c.rt);
c.rb.el = create(document.createElement('div'), c.rb);
c.lb.el = create(document.createElement('div'), c.lb);
document.body.appendChild(c.lt.el);
document.body.appendChild(c.rt.el);
document.body.appendChild(c.rb.el);
document.body.appendChild(c.lb.el);
},
// privateメソッド。カーソルの移動。
move: function(e) {
function pos(el, x, y) {
el.el.style.left = x + el.dx + 'px';
el.el.style.top = y + el.dy + 'px';
}
function hide(el, x, y) {
const w = document.documentElement.clientWidth;
const h = document.documentElement.clientHeight;
const deltaX = w - (x + el.dx + parseInt(el.w) - skinableCursor.cursor.browserDelta);
const deltaY = h - (y + el.dy + parseInt(el.h) - skinableCursor.cursor.browserDelta);
if (!skinableCursor.noSkin) {
el.el.style.display = deltaX > 0 ? (deltaY > 0 ? 'block' : 'none') :
'none';
}
}
const p = skinableCursor.getMousePosition(e);
const s = skinableCursor.getScrollPosition();
const c = skinableCursor.cursor;
const x = p.x + s.x - c.browserDelta;
const y = p.y + s.y - c.browserDelta;
hide(c.lt, p.x, p.y);
hide(c.rt, p.x, p.y);
hide(c.rb, p.x, p.y);
hide(c.lb, p.x, p.y);
pos(c.lt, x, y);
pos(c.rt, x, y);
pos(c.rb, x, y);
pos(c.lb, x, y);
},
// privateメソッド。マウスの位置を返す。
getMousePosition: function(e) {
e = e ? e : window.event;
const position = {
'x': e.clientX,
'y': e.clientY
}
return position;
},
// privateメソッド。ドキュメントのスクロール位置を取得する。
getScrollPosition: function() {
let x = 0;
let y = 0;
if (typeof(window.pageYOffset) == 'number') {
x = window.pageXOffset;
y = window.pageYOffset;
} else if (document.documentElement && (document.documentElement.scrollLeft ||
document.documentElement.scrollTop)) {
x = document.documentElement.scrollLeft;
y = document.documentElement.scrollTop;
} else if (document.body && (document.body.scrollLeft || document.body.scrollTop)) {
x = document.body.scrollLeft;
y = document.body.scrollTop;
}
const position = {
'x': x,
'y': y
}
return position;
},
// privateプロパティ / メソッド。
events: {
anchor: function(e) {
skinableCursor.noSkin = true;
document.body.style.cursor = 'pointer';
const c = skinableCursor.cursor;
c.lt.el.style.display = 'none';
c.rt.el.style.display = 'none';
c.rb.el.style.display = 'none';
c.lb.el.style.display = 'none';
},
show: function() {
skinableCursor.noSkin = false;
document.body.style.cursor = 'crosshair';
}
}
}
skinableCursor.init();
</script>
</head>
<body></body>
</html>
このスクリプトを修正して、デザインや特殊効果を追加することができます。
イメージ(スキン)ファイルを変更することで、マウスカーソルの形状や色を変更することもできます。