diff --git a/icon/move.svg b/icon/move.svg
new file mode 100644
index 0000000..688c15d
--- /dev/null
+++ b/icon/move.svg
@@ -0,0 +1 @@
+
\ No newline at end of file
diff --git a/index.html b/index.html
index e8cec6b..818ce73 100644
--- a/index.html
+++ b/index.html
@@ -3,10 +3,11 @@
- 脆皮大学生向你发出请假条条
+ Haihai
+
@@ -28,7 +29,7 @@
感谢导员批假!
-
小树非常开心,导员开心快乐!
+
孩子非常开心,导员开心快乐!
@@ -43,8 +44,8 @@
-
小树有点难过...
-
但小树尊重你的决定,祝你一切顺利!
+
孩子有点难过...
+
但俺尊重你的决定,祝你一切顺利!
diff --git a/script.js b/script.js
index e2827ef..5baa7ee 100644
--- a/script.js
+++ b/script.js
@@ -1,99 +1,159 @@
const confirmSection = document.querySelector('.confirm');
- const acceptedSection = document.querySelector('.accepted');
- const rejectedSection = document.querySelector('.rejected');
- const boi = document.querySelector('.boi');
- const btnDelete = document.querySelector('.confirm-body-button-delete');
- const btnCancel = document.querySelector('.confirm-body-button-cancel');
- const current = {
- happiness: 0.9,
- derp: 1,
- px: 0.5,
- py: 0.5
- };
- const target = { ...current };
- let rejectCount = 0;
+const acceptedSection = document.querySelector('.accepted');
+const rejectedSection = document.querySelector('.rejected');
+const boi = document.querySelector('.boi');
+const btnDelete = document.querySelector('.confirm-body-button-delete');
+const btnCancel = document.querySelector('.confirm-body-button-cancel');
+const current = {
+ happiness: 0.9,
+ derp: 1,
+ px: 0.5,
+ py: 0.5
+};
+const target = { ...current };
+const fakeCursor = document.querySelector('.fake-cursor');
- // 事件监听
- confirmSection.addEventListener('mousemove', onMouseMove);
- confirmSection.addEventListener('mouseleave', onMouseLeave);
+// 页面加载时,将其放在屏幕中心
+window.addEventListener('load', () => {
+ // 设置初始位置为屏幕中心(或者你想要的初始位置)
+ const centerX = window.innerWidth / 2;
+ const centerY = window.innerHeight / 1.4;
+ fakeCursor.style.transition = 'none'; // 先禁用动画
+ fakeCursor.style.transform = `translate(${centerX}px, ${centerY}px)`;
+});
- btnCancel.addEventListener('click', () => {
- confirmSection.classList.add('hidden');
- acceptedSection.classList.remove('hidden');
- target.happiness = 1; // 开心到起飞
- updateBoi();
- });
+document.addEventListener('touchmove', (e) => {
+ const touch = e.touches[0];
+ if (touch) {
+ const { clientX, clientY } = touch;
+ fakeCursor.style.transform = `translate(${clientX}px, ${clientY}px)`;
+ }
+}, { passive: false });
- btnDelete.addEventListener('click', () => {
- rejectCount++;
- if (rejectCount >= 5) {
- btnDelete.style.position = 'absolute';
- btnDelete.style.left = `${Math.random() * 80}%`;
- btnDelete.style.top = `${Math.random() * 80}%`;
- }
- target.happiness = Math.max(0.1, target.happiness - 0.1); // 每次点击拒绝,表情更委屈
- btnCancel.style.transform = `scale(${1 + rejectCount * 0.1})`; // 接受按钮变大
- updateBoi();
- });
+document.addEventListener('touchend', (e) => {
+ const touch = e.changedTouches[0];
+ if (touch) {
+ const { clientX, clientY } = touch;
- acceptedSection.querySelector('a').addEventListener('click', () => {
- acceptedSection.classList.add('hidden');
- confirmSection.classList.remove('hidden');
- resetBoi();
- });
-
- rejectedSection.querySelector('a').addEventListener('click', () => {
- rejectedSection.classList.add('hidden');
- confirmSection.classList.remove('hidden');
- resetBoi();
- });
-
- function onMouseMove({ clientX: x, clientY: y }) {
- let dx1 = x - btnDelete.getBoundingClientRect().x - btnDelete.getBoundingClientRect().width * 0.5;
- let dy1 = y - btnDelete.getBoundingClientRect().y - btnDelete.getBoundingClientRect().height * 0.5;
- let dx2 = x - btnCancel.getBoundingClientRect().x - btnCancel.getBoundingClientRect().width * 0.5;
- let dy2 = y - btnCancel.getBoundingClientRect().y - btnCancel.getBoundingClientRect().height * 0.5;
- let px = (x - confirmSection.getBoundingClientRect().x) / confirmSection.getBoundingClientRect().width;
- let py = (y - confirmSection.getBoundingClientRect().y) / confirmSection.getBoundingClientRect().height;
- let distDelete = Math.sqrt(dx1 * dx1 + dy1 * dy1);
- let distCancel = Math.sqrt(dx2 * dx2 + dy2 * dy2);
- let happiness = Math.pow(distDelete / (distCancel + distDelete), 0.75);
-
- target.happiness = happiness;
- target.derp = 0;
- target.px = px;
- target.py = py;
+ // 模拟点击事件
+ const target = document.elementFromPoint(clientX, clientY);
+ if (target) {
+ const clickEvent = new MouseEvent('click', {
+ bubbles: true,
+ cancelable: true,
+ clientX,
+ clientY,
+ });
+ target.dispatchEvent(clickEvent);
}
+ }
- function onMouseLeave() {
- target.happiness = 0.9;
- target.derp = 1;
- target.px = 0.5;
- target.py = 0.5;
+ // 隐藏箭头
+ fakeCursor.style.transform = 'translate(-1000px, -1000px)';
+});
+
+let rejectCount = 0;
+
+// 鼠标事件
+confirmSection.addEventListener('mousemove', onMouseMove);
+confirmSection.addEventListener('mouseleave', onMouseLeave);
+
+// —— 触屏事件 ——
+// 滑动模拟鼠标移动
+confirmSection.addEventListener('touchstart', onTouchMove, { passive: false });
+confirmSection.addEventListener('touchmove', onTouchMove, { passive: false });
+// 手指离开模拟鼠标离开
+confirmSection.addEventListener('touchend', onMouseLeave);
+
+btnCancel.addEventListener('click', () => {
+ confirmSection.classList.add('hidden');
+ acceptedSection.classList.remove('hidden');
+ target.happiness = 1; // 开心到起飞
+ updateBoi();
+});
+
+btnDelete.addEventListener('click', () => {
+ rejectCount++;
+ if (rejectCount >= 5) {
+ btnDelete.style.position = 'absolute';
+ btnDelete.style.left = `${Math.random() * 80}%`;
+ btnDelete.style.top = `${Math.random() * 80}%`;
+ }
+ target.happiness = Math.max(0.1, target.happiness - 0.1);
+ btnCancel.style.transform = `scale(${1 + rejectCount * 0.1})`;
+ updateBoi();
+});
+
+acceptedSection.querySelector('a').addEventListener('click', () => {
+ acceptedSection.classList.add('hidden');
+ confirmSection.classList.remove('hidden');
+ resetBoi();
+});
+
+rejectedSection.querySelector('a').addEventListener('click', () => {
+ rejectedSection.classList.add('hidden');
+ confirmSection.classList.remove('hidden');
+ resetBoi();
+});
+
+// 将 touch 事件转换为 mousemove 逻辑
+function onTouchMove(e) {
+ e.preventDefault(); // 阻止默认滚动
+ const touch = e.touches[0];
+ if (!touch) return;
+ onMouseMove({ clientX: touch.clientX, clientY: touch.clientY });
+}
+
+function onMouseMove({ clientX: x, clientY: y }) {
+ const rectConfirm = confirmSection.getBoundingClientRect();
+ const rectDel = btnDelete.getBoundingClientRect();
+ const rectCan = btnCancel.getBoundingClientRect();
+
+ const dx1 = x - (rectDel.x + rectDel.width * 0.5);
+ const dy1 = y - (rectDel.y + rectDel.height * 0.5);
+ const dx2 = x - (rectCan.x + rectCan.width * 0.5);
+ const dy2 = y - (rectCan.y + rectCan.height * 0.5);
+
+ const px = (x - rectConfirm.x) / rectConfirm.width;
+ const py = (y - rectConfirm.y) / rectConfirm.height;
+
+ const distDelete = Math.hypot(dx1, dy1);
+ const distCancel = Math.hypot(dx2, dy2);
+ const happiness = Math.pow(distDelete / (distCancel + distDelete), 0.75);
+
+ target.happiness = happiness;
+ target.derp = 0;
+ target.px = px;
+ target.py = py;
+}
+
+function onMouseLeave() {
+ target.happiness = 0.9;
+ target.derp = 1;
+ target.px = 0.5;
+ target.py = 0.5;
+}
+
+function updateBoi() {
+ for (let prop in target) {
+ if (Math.abs(target[prop] - current[prop]) < 0.01) {
+ current[prop] = target[prop];
+ } else {
+ current[prop] += (target[prop] - current[prop]) * 0.1;
}
+ boi.style.setProperty(`--${prop}`, current[prop]);
+ }
+ requestAnimationFrame(updateBoi);
+}
- function updateBoi() {
- for (let prop in target) {
- if (target[prop] === current[prop]) {
- continue;
- } else if (Math.abs(target[prop] - current[prop]) < 0.01) {
- current[prop] = target[prop];
- } else {
- current[prop] += (target[prop] - current[prop]) * 0.1;
- }
- boi.style.setProperty(`--${prop}`, current[prop]);
- }
- requestAnimationFrame(updateBoi);
- }
+function resetBoi() {
+ target.happiness = 0.9;
+ target.derp = 1;
+ target.px = 0.5;
+ target.py = 0.5;
+ rejectCount = 0;
+ btnCancel.style.transform = 'scale(1)';
+ btnDelete.style.position = 'static';
+}
- function resetBoi() {
- target.happiness = 0.9;
- target.derp = 1;
- target.px = 0.5;
- target.py = 0.5;
- rejectCount = 0;
- btnCancel.style.transform = 'scale(1)';
- btnDelete.style.position = 'static';
- }
-
- updateBoi();
\ No newline at end of file
+updateBoi();
\ No newline at end of file
diff --git a/style.css b/style.css
index 3a0b70a..e731cec 100644
--- a/style.css
+++ b/style.css
@@ -1,3 +1,8 @@
+html, body {
+ touch-action: none;
+ overscroll-behavior: contain;
+}
+
* {
box-sizing: border-box;
font: inherit;
@@ -23,6 +28,32 @@ body {
font-family: 'Rubik', sans-serif;
}
+.fake-cursor {
+ position: fixed;
+ width: 2rem;
+ height: 2rem;
+ pointer-events: none;
+ background: url('icon/move.svg') no-repeat center center;
+ background-size: contain;
+ z-index: 9999;
+ opacity: 0.8;
+ transition: transform 0.05s linear;
+}
+
+/* 仅在触摸设备显示虚拟鼠标 */
+@media (pointer: coarse) {
+ .fake-cursor {
+ display: block;
+ }
+}
+
+/* 在精细指针设备(鼠标)隐藏虚拟鼠标 */
+@media (pointer: fine) {
+ .fake-cursor {
+ display: none;
+ }
+}
+
.confirm,
.accepted,
.rejected {