// ==UserScript==
// @name MC-Skin
// @namespace https://viayoo.com/
// @version 2.4
// @description 在网页里添加一个MC小人
// @author undefined303
// @license MIT
// @run-at document-end
// @match *
// @include *
// @grant GM_registerMenuCommand
// @grant GM_unregisterMenuCommand
// @grant GM_getValue
// @grant GM_setValue
// @grant GM_deleteValue
// @grant GM_xmlhttpRequest
// @require data:text/javascript,const%20origdef%20%3D%20window.define%3B
// @require data:text/javascript,window.define%20%3D%20undefined%3B
// @require https://fastly.jsdelivr.net/npm/[email protected]/bundles/skinview3d.bundle.min.js
// @require https://fastly.jsdelivr.net/npm/[email protected]/build/three.min.js
// @require data:text/javascript,window.define%20%3D%20origdef%3B
// ==/UserScript==
(function() {
'use strict'
var skin = GM_getValue("skin", null);
if (self != top) {
return;
}
console.log("%cMcSkin.js", "color:orange");
var defaultRotation = GM_getValue("defaultRotation", -0.25);
const box = document.createElement("div");
document.documentElement.append(box);
const shadow = box.attachShadow({
mode: "closed"
});
const inner = document.createElement("main");
shadow.append(inner);
var dialog = inner.appendChild(document.createElement("dialog"));
dialog.setAttribute("style", `border:none !important;
border-radius:10px !important;
width:min(70vw,350px) !important;
max-width:100vw !important;
text-align:center !important;
padding:40px 0px !important;
box-shadow:0px 0px 7px 1px rgba(0,0,0,.3) !important;
backdrop-filter: blur(50px);
background-color: rgba(255, 255, 255, 0.8);
outline:none !important;
font-size:0px;
`)
var span = document.body.appendChild(document.createElement("span"));
span.setAttribute("style", "font-size:1.2em");
var fontSize = window.getComputedStyle(span).fontSize;
document.body.removeChild(span);
dialog.addEventListener("click", e => {
const dialogDimensions = dialog.getBoundingClientRect()
if (
e.clientX < dialogDimensions.left ||
e.clientX > dialogDimensions.right ||
e.clientY < dialogDimensions.top ||
e.clientY > dialogDimensions.bottom
) {
dialog.close()
}
})
var removeAllChild = function(node) {
while (node.hasChildNodes()) {
node.removeChild(node.lastChild);
}
}
skin = GM_getValue("skin", skin);
var uploadSkin = function(isSave) {
dialog.close();
return new Promise((resolve, reject) => {
let input = document.createElement('input');
input.type = 'file';
input.accept = 'image/png';
input.style.display = 'none';
input.multiple = false;
input.addEventListener('change', (event) => {
let file = event.target.files[0];
if (!file) {
reject(new Error('No file selected'));
return;
}
if (file.type !== 'image/png') {
reject(new Error('Only PNG files are allowed'));
return;
}
let reader = new FileReader();
reader.onload = (e) => {
try {
const base64 = e.target.result;
skinViewer.loadSkin(base64);
skin = base64;
if (isSave) {
GM_setValue("skin", base64);
}
resolve(base64);
} catch (error) {
reject(error);
}
};
reader.onerror = (error) => reject(error);
reader.readAsDataURL(file);
});
document.body.appendChild(input);
input.click();
setTimeout(() => {
document.body.removeChild(input);
}, 200)
});
}
var createSkinPickerDialog = function(isSave, info) {
removeAllChild(dialog);
let span = dialog.appendChild(document.createElement("span"));
span.style.fontSize = fontSize;
span.innerText = info;
span.style.display = "block";
let wrap = dialog.appendChild(document.createElement("div"));
wrap.style.display = "block";
let nameInp = wrap.appendChild(document.createElement("input"));
nameInp.placeholder = "使用正版ID获取皮肤";
nameInp.setAttribute("style", `
outline:none;
border:none;
border-bottom:2px solid black;
background:transparent;
margin-right:10px;
`)
nameInp.addEventListener("input", function() {
if (nameInp.value != "") {
uploadBtn.innerText = "获取皮肤";
uploadBtn.onclick = function() {
let span1 = dialog.appendChild(document.createElement("span"));
span1.style.fontSize = fontSize;
span1.innerText = `获取中 ...`;
span1.style.display = "block";
const username = nameInp.value.trim();
GM_xmlhttpRequest({
method: 'GET',
url: `https://api.mojang.com/users/profiles/minecraft/${username}`,
onload: function(uuidResponse) {
try {
const uuidData = JSON.parse(uuidResponse.responseText);
const uuid = uuidData.id;
GM_xmlhttpRequest({
method: 'GET',
url: `https://sessionserver.mojang.com/session/minecraft/profile/${uuid}`,
onload: function(profileResponse) {
try {
const profileData = JSON.parse(profileResponse.responseText);
const texturesProp = profileData.properties.find(p => p.name === 'textures');
if (!texturesProp) {
alert('未获取到皮肤');
dialog.close();
}
const texturesJson = atob(texturesProp.value);
const texturesData = JSON.parse(texturesJson);
const skinUrl = texturesData.textures.SKIN.url;
GM_xmlhttpRequest({
method: "GET",
url: skinUrl,
responseType: "blob",
onload: function(response) {
const reader = new FileReader();
reader.onloadend = function() {
skinViewer.loadSkin(reader.result);
skin = reader.result;
if (isSave) {
GM_setValue("skin", reader.result);
}
dialog.close();
}
reader.readAsDataURL(response.response);
},
onerror: function(e) {
alert("皮肤加载错误")
dialog.close();
}
});
} catch (e) {
alert(`
${ e.message.includes('default') ? e.message : 'API请求失败,无法获取皮肤信息,请检查ID是否正确,或者检查网络连接'}`);
dialog.close();
}
},
onerror: function(e) {
alert(`API请求失败,无法获取皮肤信息,请检查ID是否正确,或者检查网络连接`);
dialog.close();
}
});
} catch (e) {
alert(`${e.responseText ? JSON.parse(e.responseText).errorMessage : 'API请求失败,无法获取皮肤信息,请检查ID是否正确,或者检查网络连接'}
`);
dialog.close();
}
},
onerror: function(e) {
alert(`${e.responseText ? JSON.parse(e.responseText).errorMessage : 'API请求失败无法获取皮肤信息,请检查ID是否正确,或者检查网络连接'}`);
dialog.close();
}
});
}
} else {
uploadBtn.innerText = "上传皮肤";
uploadBtn.onclick = function() {
uploadSkin(isSave);
};
}
})
let uploadBtn = wrap.appendChild(document.createElement("button"));
uploadBtn.onclick = uploadSkin;
uploadBtn.setAttribute("style", `
color:white;
background:#6F8DE1;
border:none;
outline:none;
padding:5px 10px;
border-radius:10px;
margin-top:20px;
`)
uploadBtn.style.fontSize = fontSize;
uploadBtn.innerText = "上传皮肤";
}
if (!skin) {
createSkinPickerDialog(true, `[MC Skin] 初次使用需要上传皮肤文件`);
dialog.showModal();
dialog.focus();
dialog.blur();
}
var opacity = GM_getValue("opacity", "0.85");
var positionLeft;
var positionTop;
var w = 130;
var h = 200;
var positionSetting = {
top: {
top: 0
},
bottom: {
top: `calc(100vh - ${h}px)`,
}
}
var position = positionSetting.bottom;
var canvas = document.createElement("canvas");
canvas.style.position = "fixed";
positionLeft = GM_getValue("positionLeft", `calc(100vw - ${w}px)`);
positionTop = GM_getValue("positionTop", position.top);
canvas.style.top = positionTop;
canvas.style.left = positionLeft;
canvas.style.zIndex = 999999999999;
canvas.style.pointerEvents = "none";
canvas.style.opacity = opacity;
document.body.appendChild(canvas);
let skinViewer = new skinview3d.SkinViewer({
canvas: canvas,
width: w,
height: h,
skin: skin
});
var addAnimation = function() {}
var idleAnimation = new skinview3d.FunctionAnimation((player, pr) => {
const t = pr * 2;
// Arm swing
const basicArmRotationZ = Math.PI * 0.02;
player.skin.leftArm.rotation.z = Math.cos(t) * 0.03 + basicArmRotationZ;
player.skin.rightArm.rotation.z = Math.cos(t + Math.PI) * 0.03 - basicArmRotationZ;
// Always add an angle for cape around the x axis
const basicCapeRotationX = Math.PI * 0.06;
player.cape.rotation.x = Math.sin(t) * 0.01 + basicCapeRotationX;
player.rotation.y = defaultRotation;
addAnimation(player, pr)
});
skinViewer.animation = idleAnimation;
skinViewer.controls.enablePan = false;
skinViewer.controls.enableZoom = false;
skinViewer.controls.enableRotate = false;
const plane = new THREE.Plane(new THREE.Vector3(0, 0, 1), -10);
const raycaster = new THREE.Raycaster();
const mouse = new THREE.Vector2();
const pointOfIntersection = new THREE.Vector3();
const head = skinViewer.playerObject.skin.head;
var isPlayingAfkAnimation;
var timeout0;
var AfkAnimation = () => {
head.rotation.x = 0;
head.rotation.y = 0;
head.rotation.z = 0;
addAnimation = (pl, pr) => {
var kT = 13.5;
var sin0 = (x) => {
var r = Math.pow(Math.abs(Math.sin(x)), 1 / 1.5)
return Math.sin(x) > 0 ? r : -r
}
var kD = 0.25;
var t1 = Math.abs(sin0(pr / 2 * kT))
pl.skin.body.rotation.x = 0.4537860552 * (1 - kD * t1);
pl.skin.body.position.z = 1.3256181 * (1 - kD * t1) - 3.4500310377 * (1 - kD * t1);
pl.skin.body.position.y = -6 - 2.103677462 * (1 - kD * t1);
pl.skin.head.position.y = -3.618325234674 * (1 - kD * t1);
pl.skin.leftArm.position.z = 3.618325234674 * (1 - kD * t1) - 3.4500310377 * (1 - kD * t1);
pl.skin.rightArm.position.z = pl.skin.leftArm.position.z;
pl.skin.leftArm.rotation.x = 0.510367746202 * (1 - kD * t1);
pl.skin.rightArm.rotation.x = pl.skin.leftArm.rotation.x;
pl.skin.leftArm.rotation.z = 0.1 * (1 - kD * t1);
pl.skin.rightArm.rotation.z = -pl.skin.leftArm.rotation.z;
pl.skin.leftArm.position.y = -2 - 2.53943318 * (1 - kD * t1);
pl.skin.rightArm.position.y = pl.skin.leftArm.position.y;
pl.skin.rightLeg.position.z = -3.4500310377 * (1 - kD * t1);
pl.skin.leftLeg.position.z = pl.skin.rightLeg.position.z;
var mD = 1.5
var t = sin0(pr * kT) * mD
pl.skin.leftLeg.rotation.z = -Math.asin((pl.skin.leftLeg.position.x - 1.9) / 12)
pl.skin.leftLeg.position.x = t + 1.9
pl.skin.rightLeg.rotation.z = pl.skin.leftLeg.rotation.z
pl.skin.rightLeg.position.x = t - 1.9
pl.skin.body.position.x = t / 2
pl.skin.leftArm.position.x = t / 2 + 5 - 0.5 * sin0(Math.max(pr - 0.25 / kT, 0) * kT)
pl.skin.rightArm.position.x = t / 2 - 5 - 0.5 * sin0(Math.max(pr - 0.25 / kT, 0) * kT)
pl.skin.body.rotation.z = -pl.skin.rightLeg.rotation.z
pl.skin.leftArm.rotation.z = Math.asin(sin0(Math.max(pr - 0.25 / kT, 0) * kT) * mD / 12) + Math.PI / 18
pl.skin.rightArm.rotation.z = pl.skin.leftArm.rotation.z - 2 * Math.PI / 18
pl.skin.leftArm.position.y = -2.5 * Math.sin(pl.skin.leftLeg.rotation.z) - 2 - 2.53943318 * (1 - kD * Math.abs(sin0(pr / 2 * kT)));
pl.skin.rightArm.position.y = 2.5 * Math.sin(pl.skin.rightLeg.rotation.z) - 2 - 2.53943318 * (1 - kD * Math.abs(sin0(pr / 2 * kT)));
pl.skin.head.rotation.z = pl.skin.body.rotation.z * 1 / 3
}
}
isPlayingAfkAnimation = false;
timeout0 = setTimeout(() => {
AfkAnimation();
isPlayingAfkAnimation = true;
}, 300000)
var handleAfkAnimation = () => {
clearTimeout(timeout0);
if (isPlayingAfkAnimation) {
addAnimation = () => {}
var pl = skinViewer.playerObject;
pl.skin.head.rotation.set(0, 0, 0);
pl.skin.leftArm.rotation.set(0, 0, 0);
pl.skin.rightArm.rotation.set(0, 0, 0);
pl.skin.leftLeg.rotation.set(0, 0, 0);
pl.skin.rightLeg.rotation.set(0, 0, 0);
pl.skin.body.rotation.set(0, 0, 0);
pl.skin.head.position.y = 0;
pl.skin.body.position.y = -6;
pl.skin.body.position.z = 0;
pl.skin.rightArm.position.x = -5;
pl.skin.rightArm.position.y = -2;
pl.skin.rightArm.position.z = 0;
pl.skin.leftArm.position.x = 5;
pl.skin.leftArm.position.y = -2;
pl.skin.leftArm.position.z = 0;
pl.skin.rightLeg.position.x = -1.9;
pl.skin.rightLeg.position.y = -12;
pl.skin.rightLeg.position.z = -0.1;
pl.skin.leftLeg.position.x = 1.9;
pl.skin.leftLeg.position.y = -12;
pl.skin.leftLeg.position.z = -0.1;
isPlayingAfkAnimation = false;
}
timeout0 = setTimeout(() => {
AfkAnimation();
isPlayingAfkAnimation = true;
}, 300000)
}
function clamp(num, min, max) {
return num <= min ? min : num >= max ? max : num;
}
function stopAddedAnimation() {
_t0 = undefined;
_t1 = undefined;
z0 = undefined;
progress1 = undefined;
progress2 = undefined;
progress3 = undefined;
endRotationX = undefined;
progress4 = undefined;
progress5 = undefined;
endRotationXR = undefined;
endRotationXL = undefined;
isTimeoutSetted = true;
clearTimeout(waveTimeout);
addAnimation = () => {}
}
var waveTimeout;
var isTimeoutSetted = false;
var _t0;
var _t1;
var z0;
function handleWaveAnimation() {
function wave() {
addAnimation = (player, progress) => {
_t0 = !_t0 ? progress : _t0;
const t = (progress - _t0) * 2.1 * Math.PI;
if (t <= Math.PI * 4) {
player.skin.leftArm.rotation.x = -2.21;
player.skin.leftArm.rotation.z = Math.cos(t) * 0.5;
} else {
_t1 = _t1 == undefined ? progress : _t1;
z0 = z0 == undefined ? player.skin.leftArm.rotation.z : z0;
var t1 = Math.cos((progress - _t1) * 15);
if (t1 < 0) {
t1 = 0;
stopAddedAnimation();
return;
}
player.skin.leftArm.rotation.x = -2.21 * t1
player.skin.leftArm.rotation.z = z0 * t1;
}
}
}
if (!isTimeoutSetted) {
waveTimeout = setTimeout(wave, 800);
}
isTimeoutSetted = true;
}
function handleMove(x, y) {
handleAfkAnimation();
const canvasRect = canvas.getBoundingClientRect();
mouse.x = (((x - canvasRect.left) / canvasRect.width) * 2 - 1) / (window.innerWidth / canvasRect.width);
mouse.y = clamp((-((y - canvasRect.top) / canvasRect.height) * 2 + 1) / (window.innerHeight / canvasRect.height) + 0.4 - 0.52 / (window.innerHeight / canvasRect.height), -0.5, 0.9);
raycaster.setFromCamera(mouse, skinViewer.camera);
raycaster.ray.intersectPlane(plane, pointOfIntersection);
head.lookAt(pointOfIntersection);
}
window.addEventListener("mousemove", e => {
var x = e.clientX;
var y = e.clientY;
handleMove(x, y);
const canvasRect = canvas.getBoundingClientRect();
if (x >= canvasRect.left && x <= canvasRect.left + canvasRect.width && y >= canvasRect.top && y <= canvasRect.top + canvasRect.height) {
handleWaveAnimation();
} else {
clearTimeout(waveTimeout);
isTimeoutSetted = false;
}
});
window.addEventListener("touchstart", e => {
handleMove(e.targetTouches[0].clientX, e.targetTouches[0].clientY)
});
window.addEventListener("touchmove", e => {
handleMove(e.targetTouches[0].clientX, e.targetTouches[0].clientY)
});
var progress1;
var progress2;
var progress3;
var endRotationX;
var ws;
function handleMouseWheelEvent(event) {
handleAfkAnimation();
try {
clearTimeout(ws)
} catch (e) {}
event = event || window.event;
let delta = event.wheelDelta || -event.detail;
var k = Math.pow(Math.abs(delta / 120), 1 / 3);
if (delta > 0) {
addAnimation = function(player, progress) {
if (!progress1) {
progress1 = progress;
isTimeoutSetted = true;
clearTimeout(waveTimeout);
}
progress2 = undefined;
player.skin.rightArm.rotation.x = -0.1 + (Math.floor((progress - progress1) / (Math.PI / (13 * k))) % 2 == 0 ? (-Math.acos(Math.cos((k * 13 * (progress - progress1 - Math.PI / (13 * k))))) * 0.5) : -0.5);
player.skin.leftArm.rotation.x = 0;
}
} else {
addAnimation = function(player, progress) {
if (!progress2) {
progress2 = progress;
isTimeoutSetted = true;
clearTimeout(waveTimeout);
}
progress1 = undefined;
player.skin.rightArm.rotation.x = -0.1 + ((Math.floor((progress - progress2) / (Math.PI / (6 * 2 * k))) % 2 == 0) ? (-Math.abs(Math.asin(Math.sin(6 * k * (progress - progress2)))) * 0.8) : 0);
player.skin.leftArm.rotation.x = 0;
}
}
ws = setTimeout(() => {
addAnimation = function(player, progress) {
if (!endRotationX) {
endRotationX = player.skin.rightArm.rotation.x;
progress3 = progress;
}
player.skin.rightArm.rotation.x = Math.min(4 * (progress - progress3) + endRotationX, 0);
if (player.skin.rightArm.rotation.x == 0) {
progress3 = undefined;
endRotationX = undefined;
stopAddedAnimation();
}
}
progress1 = undefined;
progress2 = undefined;
}, 300)
}
window.onmousewheel = document.onmousewheel = handleMouseWheelEvent;
window.onmousedown = function() {
handleAfkAnimation();
var progress0
addAnimation = function(player, progress) {
if (!progress0) {
progress0 = progress;
isTimeoutSetted = true;
clearTimeout(waveTimeout);
}
player.rotation.y = defaultRotation;
const t = (progress - progress0) * 20;
player.skin.rightArm.rotation.x = -0.4537860552 * 2 + 2 * Math.sin(t + Math.PI) * 0.3;
const basicArmRotationZ = 0.01 * Math.PI + 0.06;
player.skin.rightArm.rotation.z = -Math.cos(t) * 0.403 + basicArmRotationZ;
player.skin.body.rotation.y = -Math.cos(t) * 0.06;
player.skin.leftArm.rotation.x = Math.sin(t + Math.PI) * 0.077;
player.skin.leftArm.rotation.z = -Math.cos(t) * 0.015 + 0.13 - 0.05;
player.skin.leftArm.position.z = Math.cos(t) * 0.3;
player.skin.leftArm.position.x = 5 - Math.cos(t) * 0.05;
if (t >= Math.PI * 2) {
player.skin.rightArm.rotation.x = 0;
stopAddedAnimation();
}
}
}
var timeout;
var progress4;
var progress5;
var time0 = -1;
var endRotationXL;
var endRotationXR;
function handleInputEvent() {
try {
clearTimeout(timeout)
} catch (e) {}
var deltaTime;
if (time0 == -1) {
time0 = Date.now();
} else {
let t = Date.now();
deltaTime = t - time0;
time0 = t;
}
let k = 5 / Math.pow(deltaTime + 1, 1 / 3.6)
k = Number.isNaN(k) ? 1 : k;
addAnimation = function(player, progress) {
if (!progress4) {
progress4 = progress;
isTimeoutSetted = true;
clearTimeout(waveTimeout);
}
var pr = progress - progress4;
player.skin.leftArm.rotation.z = -0.27;
player.skin.rightArm.rotation.z = 0.27;
player.skin.leftArm.rotation.x = -Math.abs(Math.PI / 6 * Math.sin(pr * 5 * k)) - 0.6;
player.skin.rightArm.rotation.x = -Math.abs(Math.PI / 6 * Math.cos(pr * 5 * k)) - 0.6;
}
timeout = setTimeout(() => {
addAnimation = function(player, progress) {
if (!progress5) {
progress5 = progress;
endRotationXL = player.skin.leftArm.rotation.x;
endRotationXR = player.skin.rightArm.rotation.x;
}
player.skin.leftArm.rotation.z = 0;
player.skin.rightArm.rotation.z = 0;
player.skin.rightArm.rotation.x = Math.min(4 * (progress - progress5) + endRotationXR, 0);
player.skin.leftArm.rotation.x = Math.min(4 * (progress - progress5) + endRotationXL, 0);
player.skin.rightArm.rotation.z = Math.min(4 * (progress - progress5) + 0.27, 0);
player.skin.leftArm.rotation.z = Math.max(-4 * (progress - progress5) - 0.27, 0);
if (player.skin.rightArm.rotation.x == 0 && player.skin.leftArm.rotation.x == 0 && player.skin.rightArm.rotation.z == 0 && player.skin.leftArm.rotation.z == 0) {
stopAddedAnimation();
}
}
progress4 = undefined;
}, 600)
}
document.addEventListener('keydown', () => {
handleAfkAnimation();
handleInputEvent();
});
GM_registerMenuCommand("调整透明度", function() {
removeAllChild(dialog)
var d1 = dialog.appendChild(document.createElement("div"))
d1.setAttribute("style", `padding-bottom:15px !important;
font-size:` + fontSize)
var inp = dialog.appendChild(document.createElement("input"));
inp.min = 0;
inp.max = 1;
inp.step = 0.01;
inp.type = "range";
inp.setAttribute("style", `height:5px !important;
width:85% !important;
webkit-appearance: none !important;
accent-color:#6F8DE1 !important;
vertical-align:middle !important;
outline:none !important;
margin-left:7.5% !important;
display:block !important;
`)
inp.addEventListener("input", () => {
d1.innerHTML = (inp.value * 100).toFixed() + "%";
canvas.style.opacity = inp.value;
opacity = inp.value;
})
var d2 = dialog.appendChild(document.createElement("div"))
d2.setAttribute("style", `
margin-top:20px !important;
font-size:` + fontSize.replace(/px/, "") / 1.3 + "px")
d2.innerText = "设置仅对本次当前网页生效,保存设置请单击菜单中 保存当前设置";
dialog.showModal();
dialog.focus();
dialog.blur();
inp.value = canvas.style.opacity;
d1.innerHTML = (inp.value * 100).toFixed() + "%";
})
var moveListeners = [];
var moveMenuId;
var finishMoveMenuId;
function move() {
GM_unregisterMenuCommand(moveMenuId);
finishMoveMenuId = GM_registerMenuCommand("完成移动", finishMove);
function makeDraggable(element) {
element.style.pointerEvents = "auto";
let isDragging = false;
let startX, startY, initialLeft, initialTop;
const parsePosition = (type) => {
var originalPosition = (type == "left" ? (getComputedStyle(element).left.replace(/px/, "") / window.innerWidth) * 100 + "vw" : (getComputedStyle(element).top.replace(/px/, "") / window.innerHeight) * 100 + "vh")
const value = originalPosition;
const match = value.match(/(-?\d+\.?\d*)v[w|h]/);
return match ? parseFloat(match[1]) : 0;
};
const pxToVW = (px) => (px / window.innerWidth) * 100;
const pxToVH = (px) => (px / window.innerHeight) * 100;
const startDrag = (clientX, clientY) => {
isDragging = true;
initialLeft = parsePosition('left');
initialTop = parsePosition('top');
startX = clientX;
startY = clientY;
};
const handleMove = (clientX, clientY) => {
if (!isDragging) return;
const deltaX = clientX - startX;
const deltaY = clientY - startY;
element.style.left = `${initialLeft + pxToVW(deltaX)}vw`;
element.style.top = `${initialTop + pxToVH(deltaY)}vh`;
if ((initialLeft + pxToVW(deltaX)) + pxToVW(0.5 * (getComputedStyle(element).width.replace(/px/, ""))) >= 50) {
defaultRotation = -Math.abs(defaultRotation);
} else {
defaultRotation = Math.abs(defaultRotation);
}
};
const addEvent = (target, type, handler) => {
moveListeners.push({
target: target,
type: type,
handler: handler
})
target.addEventListener(type, handler);
}
addEvent(element, 'mousedown', e => startDrag(e.clientX, e.clientY));
addEvent(element, 'touchstart', e => startDrag(e.touches[0].clientX, e.touches[0].clientY));
addEvent(document, 'mousemove', e => handleMove(e.clientX, e.clientY));
addEvent(document, 'touchmove', e => handleMove(e.touches[0].clientX, e.touches[0].clientY));
['mouseup', 'touchend'].forEach(type => addEvent(document, type, () => isDragging = false));
}
makeDraggable(canvas)
canvas.style.border = "5px solid red";
}
function finishMove() {
moveListeners.forEach((item) => {
item.target.removeEventListener(item.type, item.handler);
canvas.style.border = "none";
positionLeft = canvas.style.left;
positionTop = canvas.style.top;
})
moveMenuId = GM_registerMenuCommand("移动", move);
GM_unregisterMenuCommand(finishMoveMenuId);
canvas.style.pointerEvents = "none";
}
moveMenuId = GM_registerMenuCommand("移动", move);
GM_registerMenuCommand("保存当前设置", () => {
GM_setValue("positionLeft", positionLeft);
GM_setValue("positionTop", positionTop);
GM_setValue("opacity", opacity);
GM_setValue("skin", skin);
GM_setValue("defaultRotation", defaultRotation);
alert(`[MC Skin]
保存成功,当前参数为:
${GM_getValue("positionLeft")?"位置:left "+GM_getValue("positionLeft")+" top:"+GM_getValue("positionTop")+"\n":""}${GM_getValue("opacity")?"透明度"+GM_getValue("opacity")+"\n":""}${GM_getValue("skin")?"皮肤"+GM_getValue("skin"):""}`)
})
GM_registerMenuCommand("重置当前设置", () => {
GM_deleteValue("positionLeft");
GM_deleteValue("positionTop");
GM_deleteValue("opacity");
GM_deleteValue("skin");
GM_deleteValue("defaultRotation");
})
GM_registerMenuCommand("更换皮肤", function() {
createSkinPickerDialog(false, `选择皮肤 如需保存请点击菜单中 保存当前设置`)
dialog.showModal();
dialog.focus();
dialog.blur();
})
})();