123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447 |
- <!DOCTYPE html>
- <html>
- <head>
- <meta charset="UTF-8">
- <title>Interactive Pet Widget</title>
- <style>
- /* Main container styles */
- #vpet-container {
- position: fixed;
- bottom: 20px;
- left: 50%;
- transform: translateX(-50%);
- cursor: pointer;
- z-index: 9999;
- display: flex;
- flex-direction: column;
- align-items: center;
- user-select: none;
- }
- /* Pet image container */
- #vpet {
- width: 180px;
- height: 180px;
- overflow: hidden;
- image-rendering: pixelated;
- position: relative;
- }
- #vpet img {
- width: 100%;
- height: 100%;
- object-fit: contain;
- pointer-events: none;
- }
- /* Corner trigger button */
- #corner-trigger {
- position: absolute;
- top: 5px;
- right: 5px;
- width: 20px;
- height: 20px;
- background-image: url('images/边角/vpeticon.png');
- background-size: contain;
- background-repeat: no-repeat;
- cursor: pointer;
- z-index: 10000;
- opacity: 0.7;
- transition: opacity 0.2s;
- }
- #corner-trigger:hover {
- opacity: 1;
- }
- /* System button */
- #system-btn {
- position: absolute;
- top: 5px;
- left: 5px;
- width: 20px;
- height: 20px;
- background-color: rgba(255,255,255,0.2);
- border-radius: 50%;
- display: flex;
- align-items: center;
- justify-content: center;
- color: white;
- font-size: 12px;
- cursor: pointer;
- z-index: 10000;
- transition: all 0.2s;
- border: none;
- }
- #system-btn:hover {
- background-color: rgba(255,255,255,0.3);
- transform: scale(1.1);
- }
- /* Settings panel */
- #settings-panel {
- display: none;
- background: rgba(50, 50, 50, 0.9);
- border-radius: 4px;
- padding: 1px 4px;
- margin-top: 4px;
- backdrop-filter: blur(4px);
- box-shadow: 0 1px 4px rgba(0, 0, 0, 0.1);
- z-index: 10001;
- flex-direction: row;
- align-items: center;
- width: 33.33vw;
- max-width: 200px;
- height: calc((100vh / 16) / 3);
- min-height: 10px;
- justify-content: space-around;
- box-sizing: border-box;
- }
- /* Button styles */
- .settings-btn {
- display: inline-flex;
- padding: 0 4px;
- background: none;
- border: none;
- color: #fff;
- cursor: pointer;
- transition: all 0.1s;
- position: relative;
- overflow: hidden;
- margin: 0 1px;
- text-align: center;
- border-radius: 2px;
- white-space: nowrap;
- font-size: 0.6em;
- min-width: 30px;
- height: calc((100% - 2px) * 5 / 4);
- align-items: center;
- justify-content: center;
- border-bottom: calc(((100% - 2px) * 5 / 4) / 5) solid transparent;
- }
- .settings-btn:hover:not(.task-btn) {
- background: rgba(255, 255, 255, 0.05);
- border-bottom-color: rgba(255, 255, 255, 0.2);
- }
- /* Ripple effect */
- .ripple {
- position: absolute;
- border-radius: 50%;
- background: rgba(255, 255, 255, 0.2);
- transform: scale(0);
- animation: ripple 0.4s linear;
- pointer-events: none;
- }
- @keyframes ripple {
- to {
- transform: scale(2);
- opacity: 0;
- }
- }
- /* Task button styles */
- .task-btn {
- background: linear-gradient(45deg, #2ed573, #1e90ff);
- padding: 0 3px;
- font-size: 0.55em;
- border-bottom: calc(((100% - 2px) * 5 / 4) / 5) solid rgba(0, 0, 0, 0.15);
- display: flex;
- align-items: center;
- height: calc((100% - 2px) * 5 / 4);
- }
- .task-btn:hover {
- transform: scale(1.01) !important;
- border-bottom-color: rgba(255, 255, 255, 0.3);
- }
- /* Task counter */
- .task-counter {
- font-size: 0.4em;
- background: rgba(0,0,0,0.3);
- padding: 0 2px;
- border-radius: 4px;
- margin-left: 2px;
- line-height: normal;
- display: inline-flex;
- align-items: center;
- height: 66.67%;
- transform: translateY(2px);
- }
- .task-badge {
- position: absolute;
- top: -2px;
- right: -2px;
- width: 6px;
- height: 6px;
- background: #ff4757;
- border-radius: 50%;
- animation: taskPulse 1.5s infinite;
- display: none;
- border: 1px solid rgba(50, 50, 50, 0.9);
- }
- @keyframes taskPulse {
- 0% { transform: scale(1); }
- 50% { transform: scale(1.1); }
- 100% { transform: scale(1); }
- }
- </style>
- </head>
- <body>
- <div id="vpet-container">
- <div id="vpet">
- <img id="pet-sprite" src="images/待机/待机_001.png">
- <div id="corner-trigger"></div>
- <div id="system-btn">⚙</div>
- </div>
- <div id="settings-panel">
- <div class="task-badge"></div>
- <button class="settings-btn" id="scale-btn">🔄尺寸</button>
- <button id="assistant-btn" class="settings-btn">💡助手</button>
- <button class="settings-btn task-btn" id="task-btn">📝任务</button>
- <button class="settings-btn" id="settings-btn">⚙设置</button>
- </div>
- </div>
- <script>
- // Animation configuration
- const frames = Array.from({length: 13}, (_, i) =>
- `images/待机/待机_${String(i+1).padStart(3, '0')}.png`);
- const dragFrames = Array.from({length: 22}, (_, i) =>
- `images/提起/提起_${String(i+1).padStart(3, '0')}.png`);
-
- // System state
- let currentFrame = 0;
- let currentScale = 1.0;
- let isDragging = false;
- let dragFrameIndex = 0;
- const petImage = document.getElementById('pet-sprite');
- const container = document.getElementById('vpet-container');
- const cornerTrigger = document.getElementById('corner-trigger');
- // Store original position
- let originalPosition = {
- bottom: '20px',
- left: '50%',
- transform: 'translateX(-50%)'
- };
- // Auto-play animation
- let idleAnimation;
- function startIdleAnimation() {
- idleAnimation = setInterval(() => {
- if (!isDragging) {
- petImage.src = frames[currentFrame];
- currentFrame = (currentFrame + 1) % frames.length;
- }
- }, 100);
- }
- startIdleAnimation();
- // Ripple effect function
- function createRipple(event) {
- const button = event.currentTarget;
- const circle = document.createElement("span");
- const diameter = Math.max(button.clientWidth, button.clientHeight);
- const radius = diameter / 2;
-
- circle.style.width = circle.style.height = `${diameter}px`;
- circle.style.left = `${event.clientX - button.getBoundingClientRect().left - radius}px`;
- circle.style.top = `${event.clientY - button.getBoundingClientRect().top - radius}px`;
- circle.classList.add("ripple");
-
- const ripple = button.getElementsByClassName("ripple")[0];
- if (ripple) {
- ripple.remove();
- }
-
- button.appendChild(circle);
- }
- // Size toggle
- function toggleScale() {
- currentScale = currentScale === 1.0 ? 0.8 : 1.0;
- container.style.transform = `translateX(-50%) scale(${currentScale})`;
- originalPosition.transform = `translateX(-50%) scale(${currentScale})`;
- }
- // Assistant button feedback
- function assistantHint() {
- const btn = document.getElementById('assistant-btn');
- btn.style.color = '#ffdd00';
- setTimeout(() => {
- btn.style.color = '#fff';
- }, 200);
- }
- // System button function
- function systemHint() {
- const btn = document.getElementById('system-btn');
- btn.style.backgroundColor = 'rgba(100, 200, 255, 0.3)';
- setTimeout(() => {
- btn.style.backgroundColor = 'rgba(255,255,255,0.2)';
- }, 200);
- }
- // Settings button function
- function settingsHint() {
- const btn = document.getElementById('settings-btn');
- btn.style.borderBottomColor = 'rgba(100, 200, 255, 0.4)';
- setTimeout(() => {
- btn.style.borderBottomColor = 'transparent';
- }, 200);
- }
- // Daily task system
- let taskCount = 0;
- const taskElements = {
- badge: document.querySelector('.task-badge'),
- counter: document.querySelector('.task-counter')
- };
- function showTaskReminder() {
- taskElements.badge.style.display = 'block';
- setTimeout(() => {
- taskElements.badge.style.display = 'none';
- }, 2000);
- }
- function dailyTaskHint() {
- const btn = document.getElementById('task-btn');
-
- // Button animation
- btn.style.transform = 'scale(0.96)';
- setTimeout(() => {
- btn.style.transform = 'scale(1)';
- }, 150);
- // Update progress
- taskCount = (taskCount + 1) % 4;
-
- // Completion effect
- if(taskCount === 3) {
- showTaskReminder();
- setTimeout(() => {
- taskCount = 0;
- }, 1000);
- }
- }
- // Initialize task reminder (every 30 seconds)
- setInterval(showTaskReminder, 30000);
- // Corner trigger right-click control
- document.getElementById('corner-trigger').addEventListener('contextmenu', (e) => {
- e.preventDefault();
- const panel = document.getElementById('settings-panel');
- panel.style.display = panel.style.display === 'flex' ? 'none' : 'flex';
- });
- // System button click
- document.getElementById('system-btn').addEventListener('click', function(e) {
- createRipple(e);
- systemHint();
- });
- // Hide menu when clicking outside
- document.addEventListener('click', (e) => {
- if (!e.target.closest('#settings-panel') &&
- !e.target.closest('#corner-trigger') &&
- !e.target.closest('#system-btn')) {
- document.getElementById('settings-panel').style.display = 'none';
- }
- });
- // Button event listeners
- document.getElementById('scale-btn').addEventListener('click', function(e) {
- createRipple(e);
- toggleScale();
- });
- document.getElementById('assistant-btn').addEventListener('click', function(e) {
- createRipple(e);
- assistantHint();
- });
- document.getElementById('task-btn').addEventListener('click', function(e) {
- createRipple(e);
- dailyTaskHint();
- });
- document.getElementById('settings-btn').addEventListener('click', function(e) {
- createRipple(e);
- settingsHint();
- });
- // Drag functionality
- let offsetX, offsetY;
- let longPressTimer;
- let dragAnimation;
- const LONG_PRESS_DELAY = 300;
- container.addEventListener('mousedown', (e) => {
- // Prevent text selection during drag
- e.preventDefault();
-
- longPressTimer = setTimeout(() => {
- isDragging = true;
- clearInterval(idleAnimation);
- const containerRect = container.getBoundingClientRect();
-
- // Calculate offset to position cursor at 1/4 from top and 1/2 from left
- offsetX = e.clientX - containerRect.left - containerRect.width / 2;
- offsetY = e.clientY - containerRect.top - containerRect.height / 4;
-
- // Adjust the container position
- container.style.left = (e.clientX - offsetX) + 'px';
- container.style.top = (e.clientY - offsetY) + 'px';
- container.style.bottom = 'auto';
- container.style.transform = `scale(${currentScale})`;
- container.style.cursor = 'grabbing';
-
- dragFrameIndex = 0;
- dragAnimation = setInterval(() => {
- petImage.src = dragFrames[dragFrameIndex];
- dragFrameIndex = (dragFrameIndex + 1) % dragFrames.length;
- }, 100);
-
- document.addEventListener('mousemove', drag);
- }, LONG_PRESS_DELAY);
- });
- document.addEventListener('mouseup', () => {
- clearTimeout(longPressTimer);
- if (isDragging) {
- isDragging = false;
- clearInterval(dragAnimation);
- startIdleAnimation();
- document.removeEventListener('mousemove', drag);
- container.style.cursor = 'pointer';
- }
- });
- function drag(e) {
- if (isDragging) {
- e.preventDefault();
- container.style.left = (e.clientX - offsetX) + 'px';
- container.style.top = (e.clientY - offsetY) + 'px';
- }
- }
- // Reset to original position function (if needed)
- function resetPosition() {
- container.style.bottom = originalPosition.bottom;
- container.style.left = originalPosition.left;
- container.style.top = 'auto';
- container.style.transform = originalPosition.transform;
- }
- </script>
- </body>
- </html>
|