Adds a toggle menu to expand/collapse the drawing canvas on Drawaria.online by hiding/showing side panels, and expands the canvas.
当前为
// ==UserScript==
// @name Drawaria Canvas Expander Toggle
// @namespace http://tampermonkey.net/
// @version 2025-05-23.3 // Incremented version to reflect this crucial fix
// @description Adds a toggle menu to expand/collapse the drawing canvas on Drawaria.online by hiding/showing side panels, and expands the canvas.
// @author YouTubeDrawaria
// @match https://drawaria.online/*
// @icon https://www.google.com/s2/favicons?sz=64&domain=drawaria.online
// @grant none
// @license MIT
// ==/UserScript==
(function() {
'use strict';
const LS_KEY = 'drawaria_expand_canvas_v2'; // localStorage key for state persistence
// --- Helper function to apply/remove canvas expansion styles ---
function setCanvasExpanded(isExpanded) {
const leftbar = document.getElementById('leftbar');
const rightbar = document.getElementById('rightbar');
const canvas = document.getElementById('canvas'); // The actual canvas element
// Ensure main game elements are present before attempting modifications
if (!leftbar || !rightbar || !canvas) {
console.warn("Drawaria core elements (leftbar, rightbar, canvas) not found for expansion/collapse. Will re-attempt when elements are ready.");
return false; // Indicate that elements were not ready
}
if (isExpanded) {
// Apply styles to hide panels
leftbar.style.display = 'none';
rightbar.style.display = 'none';
// Make the canvas element expand to fill the available flex space
canvas.style.flexGrow = '1';
canvas.style.width = 'auto'; // Important for flex items to allow growth
console.log("Canvas expanded.");
} else {
// Restore original styles by clearing inline styles
leftbar.style.display = '';
rightbar.style.display = '';
// Remove flex-grow and width to restore original canvas size
canvas.style.flexGrow = '';
canvas.style.width = '';
console.log("Canvas collapsed.");
}
// Trigger a window resize event. This is crucial for Drawaria to re-render
// its canvas based on the new available space.
window.dispatchEvent(new Event('resize'));
localStorage.setItem(LS_KEY, isExpanded ? 'true' : 'false'); // Save state
return true; // Indicate successful application
}
// --- Inject custom UI (Button and Menu) and its CSS ---
function injectUI() {
// Inject CSS for the custom UI elements to make them look integrated
const style = document.createElement('style');
style.type = 'text/css';
style.innerHTML = `
#drawaria-custom-menu-container {
position: absolute;
top: 5px; /* Position from the top of the viewport */
right: 180px; /* Adjust this value to place it appropriately relative to other top-right elements */
z-index: 10000; /* Ensure it's on top of other elements */
font-family: 'Open Sans', Arial, sans-serif; /* Try to match Drawaria's font */
color: #333;
}
#drawaria-menu-toggle-button {
background-color: #f1f9f5; /* Light background, similar to Drawaria's panels */
border: 1px solid #b0b5b9; /* Soft border */
border-radius: 5px;
padding: 5px 10px;
cursor: pointer;
font-size: 14px;
display: flex;
align-items: center;
gap: 6px; /* Space between icon and text */
box-shadow: 0 1px 3px rgba(0,0,0,0.1); /* Subtle shadow */
transition: background-color 0.2s ease; /* Smooth hover effect */
white-space: nowrap; /* Prevent text wrapping */
}
#drawaria-menu-toggle-button:hover {
background-color: #e0e0e0; /* Slightly darker on hover */
}
#drawaria-menu-toggle-button span {
font-size: 16px; /* Icon size */
}
#drawaria-menu-content {
display: none; /* Hidden by default */
position: absolute;
background-color: #f1f9f5;
border: 1px solid #b0b5b9;
border-radius: 5px;
padding: 10px;
top: 40px; /* Position just below the toggle button */
right: 0;
min-width: 180px; /* Ensure enough width for text */
box-shadow: 0 2px 8px rgba(0,0,0,0.2);
}
#drawaria-menu-content.visible {
display: block; /* Make visible when 'visible' class is added */
}
#drawaria-menu-content label {
display: flex;
align-items: center;
cursor: pointer;
font-size: 14px;
margin-bottom: 0; /* No extra margin if only one item */
}
#drawaria-menu-content input[type="checkbox"] {
margin-right: 8px;
transform: scale(1.2); /* Make checkbox slightly larger for easier clicking */
}
`;
document.head.appendChild(style); // Add CSS to the document's head
// Inject HTML for the button and menu into the body
const uiHtml = `
<div id="drawaria-custom-menu-container">
<button id="drawaria-menu-toggle-button" title="Toggle Canvas Expansion">
<span>🖼️</span> Canvas Options
</button>
<div id="drawaria-menu-content">
<label>
<input type="checkbox" id="expandCanvasCheckbox"> Expand Drawing Area
</label>
</div>
</div>
`;
document.body.insertAdjacentHTML('beforeend', uiHtml); // Insert at the end of the body
// --- Get references to the injected UI elements ---
const menuContainer = document.getElementById('drawaria-custom-menu-container');
const toggleButton = document.getElementById('drawaria-menu-toggle-button');
const menuContent = document.getElementById('drawaria-menu-content');
const expandCanvasCheckbox = document.getElementById('expandCanvasCheckbox');
if (!menuContainer || !toggleButton || !menuContent || !expandCanvasCheckbox) {
console.error("Failed to find Drawaria custom UI elements after injection.");
return;
}
// --- Add Event Listeners ---
// Toggle the visibility of the menu content when the button is clicked
toggleButton.addEventListener('click', (event) => {
event.stopPropagation(); // Prevent document click listener from immediately closing it
menuContent.classList.toggle('visible');
});
// Hide the menu when a click occurs outside of it
document.addEventListener('click', (event) => {
if (!menuContainer.contains(event.target)) {
menuContent.classList.remove('visible');
}
});
// Listen for changes on the "Expand Canvas" checkbox
expandCanvasCheckbox.addEventListener('change', () => {
setCanvasExpanded(expandCanvasCheckbox.checked);
});
// --- Initialize state from localStorage and apply when game is ready ---
const storedState = localStorage.getItem(LS_KEY);
const initialState = storedState === 'true';
expandCanvasCheckbox.checked = initialState; // Set checkbox state visually
// Use a MutationObserver to wait for the #main element to become visible,
// which indicates the game content (leftbar, rightbar, canvas) is ready.
const observer = new MutationObserver((mutationsList, observerInstance) => {
const mainDiv = document.getElementById('main');
// Check if mainDiv exists and its display style is not 'none'
if (mainDiv && mainDiv.style.display !== 'none') {
console.log("#main element became visible. Attempting to apply initial canvas state.");
// Attempt to apply the state. setCanvasExpanded will internally check for sub-elements.
if (setCanvasExpanded(initialState)) { // Only disconnect if successful
observerInstance.disconnect(); // Disconnect observer once the state is applied successfully
}
// If setCanvasExpanded returns false (elements not ready), the observer will continue
// watching for other changes, which might involve the elements becoming available.
}
});
// Start observing the document body for changes, looking for #main to become visible.
// A small delay helps ensure this observer setup runs slightly after initial DOM render
// to avoid conflicts or race conditions with the page's own JS.
setTimeout(() => {
observer.observe(document.body, { childList: true, subtree: true, attributes: true, attributeFilter: ['style'] });
// Also, make an immediate check in case the main content is already loaded/visible
const mainDiv = document.getElementById('main');
if (mainDiv && mainDiv.style.display !== 'none') {
console.log("Immediate check: #main already visible. Attempting to apply initial canvas state.");
if (setCanvasExpanded(initialState)) {
observer.disconnect();
}
}
}, 500); // Wait 500ms before starting observation
// Fallback for window.load just in case, this could also apply the state if observers somehow missed it.
window.addEventListener('load', () => {
const mainDiv = document.getElementById('main');
if (mainDiv && mainDiv.style.display !== 'none') {
console.log("Window loaded and #main is visible (fallback). Applying initial canvas state.");
setCanvasExpanded(initialState);
observer.disconnect(); // Ensure observer is stopped if fallback works
}
});
}
// Execute the UI injection function once the DOM is ready (or shortly after)
// Using DOMContentLoaded for quicker UI appearance, but the core canvas expansion
// logic will wait for the game's #main div to be truly ready.
if (document.readyState === 'loading') {
document.addEventListener('DOMContentLoaded', injectUI);
} else {
injectUI();
}
})();