Greasy Fork

Greasy Fork is available in English.

MC-Skin

在网页里添加一个MC小人

当前为 2025-06-10 提交的版本,查看 最新版本

您需要先安装一款用户脚本管理器扩展,例如 Tampermonkey 篡改猴Greasemonkey 油猴子Violentmonkey 暴力猴,才能安装此脚本。

您需要先安装一款用户脚本管理器扩展,例如 Tampermonkey 篡改猴,才能安装此脚本。

您需要先安装一款用户脚本管理器扩展,例如 Tampermonkey 篡改猴Violentmonkey 暴力猴,才能安装此脚本。

您需要先安装一款用户脚本管理器扩展,例如 Tampermonkey 篡改猴Userscripts ,才能安装此脚本。

您需要先安装一款用户脚本管理器扩展,例如 Tampermonkey 篡改猴,才能安装此脚本。

您需要先安装一款用户脚本管理器扩展后才能安装此脚本。

(我已经安装了用户脚本管理器,让我安装!)

您需要先安装一款用户样式管理器扩展,比如 Stylus,才能安装此样式。

您需要先安装一款用户样式管理器扩展,比如 Stylus,才能安装此样式。

您需要先安装一款用户样式管理器扩展,比如 Stylus,才能安装此样式。

您需要先安装一款用户样式管理器扩展后才能安装此样式。

您需要先安装一款用户样式管理器扩展后才能安装此样式。

您需要先安装一款用户样式管理器扩展后才能安装此样式。

(我已经安装了用户样式管理器,让我安装!)

// ==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();
	})

})();