您需要先安装一个扩展,例如 篡改猴、Greasemonkey 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 Userscripts ,之后才能安装此脚本。
您需要先安装一款用户脚本管理器扩展,例如 Tampermonkey,才能安装此脚本。
您需要先安装用户脚本管理器扩展后才能安装此脚本。
Cyclic gradient with a 'laser' transition effect between colors
// ==UserScript== // @name Drawaria Lazer Gradient // @version 6.1 // @description Cyclic gradient with a 'laser' transition effect between colors // @author лазер дмитрий прайм, YouTubeDrawaria // @match https://drawaria.online/* // @grant none // @icon https://www.google.com/s2/favicons?sz=64&domain=drawaria.online // @license MIT // @namespace https://greasyfork.org/users/1088100 // ==/UserScript== (function() { 'use strict'; // Original ASCII art and comments preserved from v5.1 // ████████████████████████████████████████████████████████████████████████████████████████████████████████████████████ // █▄─█▀▀▀█─▄█─▄▄─█▄─▀█▀─▄█▄─▄▄▀█▄─▄█─▄▄─█─▄─▄─█▄─▄▄─█─▄▄─█▄─▄▄▀█─▄▄─█─▄▄▄▄█─▄─▄─█▄─▄▄─█▄─▀█▄─▄█─▄▄▄▄█─█─█▄─▄█─▄▄─█▄─▀█▀─▄█ // ██─█─█─█─██─██─██─█▄█─███─▄─▄██─██─██─███─████─▄█▀█─██─██─▄─▄█─██─█▄▄▄▄─███─████─▄█▀██─█▄▀─██▄▄▄▄─█─▄─██─██─██─██─█▄█─██ // ▀▀▄▄▄▀▄▄▄▀▄▄▄▄▀▄▄▄▀▄▄▄▀▄▄▀▄▄▀▄▄▄▀▄▄▄▄▀▀▄▄▄▀▀▄▄▄▄▄▀▄▄▄▄▀▄▄▀▄▄▀▄▄▄▄▀▄▄▄▄▄▀▀▄▄▄▀▀▄▄▄▄▄▀▄▄▄▀▀▄▄▀▄▄▄▄▄▀▄▀▄▀▄▄▄▀▄▄▄▄▀▄▄▄▀▄▄▄▀ // Стили панели const panelStyle = ` position: fixed; top: 100px; left: 100px; z-index: 99999; background: rgba(10,10,10,0.96); padding: 15px; border-radius: 8px; border: 2px solid #FF00FF; box-shadow: 0 0 25px rgba(255,0,255,0.7), inset 0 0 15px rgba(0,255,255,0.4); cursor: move; user-select: none; width: 240px; font-family: 'Courier New', monospace; backdrop-filter: blur(5px); `; const gradientStyle = ` position: fixed; top: 0; left: 0; width: 100vw; height: 100vh; z-index: -1; pointer-events: none; opacity: 0; transition: opacity 1.5s cubic-bezier(0.4, 0, 0.2, 1); overflow: hidden; /* Prevent scrollbars if background-size is large */ `; // Создаем элементы const panel = document.createElement("div"); panel.style.cssText = panelStyle; panel.setAttribute('id', 'lazer-gradient-panel'); const gradient = document.createElement("div"); gradient.style.cssText = gradientStyle; gradient.setAttribute('id', 'lazer-gradient-effect'); // █▀▀ █▀█ █▀▀ ▄▀█ ▀█▀ █ █▀█ █▄░█ █▀▀ █▀▀ █▀█ █▄░█ █▀▀ █░█ █▀ █▀▀ █▀▄ █▀▀ █▀▀ █▄░█ █▀▀ █▀█ ▄▀█ █▀▀ █▀▀ ▀█▀ █▀█ █▀█ // █▄▄ █▀▄ ██▄ █▀█ ░█░ █ █▄█ █░▀█ ██▄ █▄▄ █▄█ █░▀█ █▄▄ █▄█ ▄█ ██▄ █▄▀ █▄█ ██▄ █░▀█ ██▄ █▀▄ █▀█ █▄▄ ██▄ ░█░ █▄█ █▀▄ // [КОНТРОЛЛЕРЫ] let speed = 5; let gradientType = 'linear'; // 'linear', 'radial', 'conic' let linearDirection = 'to right'; // 'to right', 'to bottom', '45deg' etc. let conicStartAngle = 0; // 0-360 degrees let globalOpacity = 85; // 0-100 // HTML for new controls const gradientTypeControlHTML = ` <div style="margin-bottom: 15px;"> <div style="color: #00FFFF; font-size: 12px; margin-bottom: 5px;">GRADIENT TYPE:</div> <select id="lazer-gradient-type" style="width: 100%; padding: 5px; border-radius: 3px; background: rgba(0,255,255,0.1); color: white; border: 1px solid #00FFFF;"> <option value="linear">Linear</option> <option value="radial">Radial</option> <option value="conic">Conic</option> </select> </div>`; const linearDirectionControlHTML = ` <div id="lazer-linear-direction-control" style="margin-bottom: 15px;"> <div style="color: #00FFFF; font-size: 12px; margin-bottom: 5px;">LINEAR DIRECTION:</div> <select id="lazer-linear-direction" style="width: 100%; padding: 5px; border-radius: 3px; background: rgba(0,255,255,0.1); color: white; border: 1px solid #00FFFF;"> <option value="to right">Right</option> <option value="to left">Left</option> <option value="to top">Top</option> <option value="to bottom">Bottom</option> <option value="to top right">Top Right</option> <option value="to top left">Top Left</option> <option value="to bottom right">Bottom Right</option> <option value="to bottom left">Bottom Left</option> <option value="0deg">0° (To Top)</option> <option value="45deg">45°</option> <option value="90deg">90° (To Right)</option> <option value="135deg">135°</option> <option value="180deg">180° (To Bottom)</option> <option value="225deg">225°</option> <option value="270deg">270° (To Left)</option> <option value="315deg">315°</option> </select> </div>`; const conicAngleControlHTML = ` <div id="lazer-conic-angle-control" style="margin-bottom: 15px; display: none;"> <div style="display: flex; justify-content: space-between; color: #00FFFF; font-size: 12px; margin-bottom: 5px;"> <span>CONIC START ANGLE:</span> <span id="lazer-conic-angle-value">${conicStartAngle}°</span> </div> <input type="range" min="0" max="360" value="${conicStartAngle}" style="width: 100%; accent-color: #FF00FF; cursor: pointer;" id="lazer-conic-angle-slider"> </div>`; const globalOpacityControlHTML = ` <div style="margin-bottom: 15px;"> <div style="display: flex; justify-content: space-between; color: #00FFFF; font-size: 12px; margin-bottom: 5px;"> <span>GLOBAL OPACITY:</span> <span id="lazer-opacity-value">${globalOpacity}%</span> </div> <input type="range" min="0" max="100" value="${globalOpacity}" style="width: 100%; accent-color: #FF00FF; cursor: pointer;" id="lazer-opacity-slider"> </div>`; // [ИНТЕРФЕЙС] panel.innerHTML = ` <div style="border-bottom: 1px solid #FF00FF; margin-bottom: 15px; padding-bottom: 10px; display: flex; justify-content: space-between; align-items: center;"> <div style="color: #00FFFF; font-weight: bold; text-shadow: 0 0 8px #FF00FF; font-size: 16px;"> ⚡ LAZER GRADIENT v6.0 </div> <div id="lazer-close-btn" style="color: white; cursor: pointer; font-size: 20px; transition: all 0.2s;">×</div> </div> <div id="lazer-color-container" style="display: grid; grid-template-columns: 1fr 1fr; gap: 12px; margin-bottom: 15px; max-height: 250px; overflow-y: auto; padding-right: 5px;"> <!-- Colors will be added here --> </div> <button id="lazer-add-color" style="background: rgba(255,0,255,0.2); color: white; border: 1px dashed #FF00FF; padding: 8px; border-radius: 5px; margin-bottom: 15px; cursor: pointer; width: 100%; font-size: 12px; transition: all 0.2s;"> + ADD LAZER COLOR (MAX 10) </button> ${gradientTypeControlHTML} ${linearDirectionControlHTML} ${conicAngleControlHTML} ${globalOpacityControlHTML} <div style="margin-bottom: 15px;"> <div style="display: flex; justify-content: space-between; color: #00FFFF; font-size: 12px; margin-bottom: 5px;"> <span>LAZER SPEED:</span> <span id="lazer-speed-value">${speed}</span> </div> <input type="range" min="1" max="10" value="${speed}" style="width: 100%; accent-color: #FF00FF; cursor: pointer;" id="lazer-speed-slider"> </div> <button id="lazer-toggle-btn" style="background: linear-gradient(45deg, #FF00FF, #00FFFF); color: black; border: none; padding: 10px; border-radius: 5px; cursor: pointer; font-weight: bold; width: 100%; transition: all 0.3s; font-size: 14px; text-shadow: 0 0 3px rgba(255,255,255,0.5);"> ACTIVATE LAZER </button>`; // █▀▀ █░█ █▀▀ █▀█ █▀▀ █▀▄ █▀▀ █▀█ █▄░█ █▀▀ █░█ █▀ █▀▀ █▀▄ █▀▀ █▀▀ █▄░█ █▀▀ █▀█ ▄▀█ █▀▀ █▀▀ ▀█▀ █▀█ █▀█ // █▄▄ █▀█ ██▄ █▀▄ ██▄ █▄▀ █▄▄ █▄█ █░▀█ █▄▄ █▄█ ▄█ ██▄ █▄▀ █▄█ ██▄ █░▀█ ██▄ █▀▄ █▀█ █▄▄ ██▄ ░█░ █▄█ █▀▄ // Initial setup document.body.appendChild(panel); document.body.appendChild(gradient); let isActive = false; let animationId = null; const colorInputs = []; let colorCount = 2; // Start with 2 colors // Default colors for initialization const defaultColors = [ '#FF00FF', '#00FFFF', '#00FF00', '#FFFF00', '#FF0000', '#0000FF', '#FF8000', '#8000FF', '#0080FF', '#80FF00' ]; // █▀▀ █ ▀█▀ █▀▀ █▀ █▀▀ █▀█ █▄░█ █▀▀ █░█ █▀ █▀▀ █▀▄ █▀▀ █▀█ █▄░█ █▀▀ █▀█ ▄▀█ █▀▀ █▀▀ ▀█▀ █▀█ █▀█ // █▀░ █ ░█░ ██▄ ▄█ █▄▄ █▄█ █░▀█ █▄▄ █▄█ ▄█ ██▄ █▄▀ █▄█ █▄█ █░▀█ ██▄ █▀▄ █▀█ █▄▄ ██▄ ░█░ █▄█ █▀▄ // Function to create color input elements function createColorElement(index) { const wrapper = document.createElement("div"); wrapper.style.cssText = ` display: flex; flex-direction: column; gap: 5px; align-items: center; `; const label = document.createElement("div"); label.textContent = `LAZER ${index + 1}`; label.style.cssText = ` color: #00FFFF; font-size: 10px; text-align: center; width: 100%; font-weight: bold; `; const inputWrapper = document.createElement("div"); inputWrapper.style.cssText = ` display: flex; align-items: center; gap: 5px; width: 100%; justify-content: center; `; const input = document.createElement("input"); input.type = "color"; input.value = defaultColors[index] || '#FFFFFF'; // Fallback if defaultColors runs out input.style.cssText = ` width: 30px; height: 30px; cursor: pointer; flex-shrink: 0; border: 1px solid #00FFFF; border-radius: 50%; `; const deleteBtn = document.createElement("div"); deleteBtn.textContent = "×"; deleteBtn.style.cssText = ` color: white; cursor: pointer; font-size: 14px; opacity: ${index > 1 ? '0.7' : '0'}; pointer-events: ${index > 1 ? 'auto' : 'none'}; background: #FF00FF; width: 18px; height: 18px; border-radius: 50%; display: flex; align-items: center; justify-content: center; transition: all 0.2s; `; // Add handlers input.addEventListener("change", updateGradient); deleteBtn.addEventListener("click", () => removeColor(index, wrapper)); // Store references colorInputs[index] = input; // Assemble component inputWrapper.appendChild(input); if (index > 1) inputWrapper.appendChild(deleteBtn); wrapper.appendChild(label); wrapper.appendChild(inputWrapper); return wrapper; } // Function to remove a color function removeColor(indexToRemove, wrapperToRemove) { if (colorCount <= 2) return; colorContainer.removeChild(wrapperToRemove); colorInputs.splice(indexToRemove, 1); colorCount--; // Re-index remaining colors and update delete button opacity/pointer-events colorInputs.forEach((input, i) => { const parentWrapper = input.closest('div[style*="flex-direction: column"]'); if (parentWrapper) { const label = parentWrapper.querySelector('div[style*="font-size: 10px"]'); if (label) label.textContent = `LAZER ${i + 1}`; const deleteBtn = parentWrapper.querySelector('div[style*="background: rgb(255, 0, 255)"]'); if (deleteBtn) { deleteBtn.style.opacity = i > 1 ? '0.7' : '0'; deleteBtn.style.pointerEvents = i > 1 ? 'auto' : 'none'; } } }); if (isActive) updateGradient(); } // █▀▀ █░█ █▀▀ █▀█ █▀▀ █▀▄ █▀▀ █▀█ █▄░█ █▀▀ █░█ █▀ █▀▀ █▀▄ █▀▀ █▀▀ █▄░█ █▀▀ █▀█ ▄▀█ █▀▀ █▀▀ ▀█▀ █▀█ █▀█ // █▄▄ █▀█ ██▄ █▀▄ ██▄ █▄▀ █▄▄ █▄█ █░▀█ █▄▄ █▄█ ▄█ ██▄ █▄▀ █▄█ ██▄ █░▀█ ██▄ █▀▄ █▀█ █▄▄ ██▄ ░█░ █▄█ █▀▄ // Main gradient update function function updateGradient() { if (colorInputs.length < 2) { gradient.style.background = 'none'; cancelAnimationFrame(animationId); return; } const colors = colorInputs.map(input => input.value); // Add the first color to the end to ensure a seamless loop for repeating gradients const seamlessColors = [...colors, colors[0]]; const stopInterval = 100 / colors.length; // Each color occupies an equal percentage segment // Generate color stops string for CSS gradients const gradientStops = seamlessColors.map((color, i) => `${color} ${i * stopInterval}%`).join(', '); cancelAnimationFrame(animationId); let animationFrameCount = 0; const animate = () => { animationFrameCount++; const animationSpeedFactor = speed * 0.1; // Adjust multiplier for animation speed const currentAnimationOffset = animationFrameCount * animationSpeedFactor; let backgroundCSS = ''; gradient.style.background = ''; // Clear previous background gradient.style.transform = ''; // Clear previous transform (for conic) gradient.style.backgroundSize = ''; // Clear previous background-size (for linear/radial) gradient.style.backgroundPosition = ''; // Clear previous background-position (for linear/radial) if (gradientType === 'linear') { backgroundCSS = `linear-gradient(${linearDirection}, ${gradientStops})`; // Calculate background size and position for animated scrolling effect const stretchFactor = 100 * colors.length; // e.g., 200% for 2 colors, 300% for 3 colors let bgSizeX = '100vw'; // Default to viewport width let bgSizeY = '100vh'; // Default to viewport height let bgPosX = '0px'; let bgPosY = '0px'; // Determine the background-size and position for seamless scrolling based on direction if (linearDirection.includes('right') || linearDirection.includes('left') || linearDirection === '90deg' || linearDirection === '270deg') { bgSizeX = `${stretchFactor}%`; bgPosX = `${-(currentAnimationOffset % stretchFactor)}%`; } if (linearDirection.includes('top') || linearDirection.includes('bottom') || linearDirection === '0deg' || linearDirection === '180deg') { bgSizeY = `${stretchFactor}%`; bgPosY = `${-(currentAnimationOffset % stretchFactor)}%`; } // For diagonal gradients, both dimensions are stretched and moved if ((linearDirection.includes('top') || linearDirection.includes('bottom')) && (linearDirection.includes('left') || linearDirection.includes('right'))) { bgSizeX = `${stretchFactor}%`; bgSizeY = `${stretchFactor}%`; bgPosX = `${-(currentAnimationOffset % stretchFactor)}%`; bgPosY = `${-(currentAnimationOffset % stretchFactor)}%`; } gradient.style.background = backgroundCSS; gradient.style.backgroundSize = `${bgSizeX} ${bgSizeY}`; gradient.style.backgroundPosition = `${bgPosX} ${bgPosY}`; } else if (gradientType === 'radial') { // For radial, animate the center position for a "scanning" effect const offsetAngle = (currentAnimationOffset * 0.5) * (Math.PI / 180); // Slower oscillation const centerX = 50 + Math.sin(offsetAngle) * 40; // Oscillate center X by 40% const centerY = 50 + Math.cos(offsetAngle) * 40; // Oscillate center Y by 40% backgroundCSS = `radial-gradient(circle at ${centerX}% ${centerY}%, ${gradientStops})`; gradient.style.background = backgroundCSS; } else if (gradientType === 'conic') { // For conic, animate the `from` angle for rotation const animatedAngle = (conicStartAngle + currentAnimationOffset * 3.6) % 360; // Rotate by 3.6 degrees per unit of offset backgroundCSS = `conic-gradient(from ${animatedAngle}deg at center, ${colors.join(', ')})`; gradient.style.background = backgroundCSS; } animationId = requestAnimationFrame(animate); }; if (isActive) { // Only start animation if the gradient is active animate(); } } // █▀▀ █░█ █▀▀ █▀█ █▀▀ █▀▄ █▀▀ █▀█ █▄░█ █▀▀ █░█ █▀ █▀▀ █▀▄ █▀▀ █▀▀ █▄░█ █▀▀ █▀█ ▄▀█ █▀▀ █▀▀ ▀█▀ █▀█ █▀█ // █▄▄ █▀█ ██▄ █▀▄ ██▄ █▄▀ █▄▄ █▄█ █░▀█ █▄▄ █▄█ ▄█ ██▄ █▄▀ █▄█ ██▄ █░▀█ ██▄ █▀▄ █▀█ █▄▄ ██▄ ░█░ █▄█ █▀▄ // Initialize interface elements const colorContainer = panel.querySelector("#lazer-color-container"); const addColorBtn = panel.querySelector("#lazer-add-color"); const toggleBtn = panel.querySelector("#lazer-toggle-btn"); const closeBtn = panel.querySelector("#lazer-close-btn"); const speedSlider = panel.querySelector("#lazer-speed-slider"); const speedValue = panel.querySelector("#lazer-speed-value"); // New controls const gradientTypeSelect = panel.querySelector("#lazer-gradient-type"); const linearDirectionControl = panel.querySelector("#lazer-linear-direction-control"); const linearDirectionSelect = panel.querySelector("#lazer-linear-direction"); const conicAngleControl = panel.querySelector("#lazer-conic-angle-control"); const conicAngleSlider = panel.querySelector("#lazer-conic-angle-slider"); const conicAngleValue = panel.querySelector("#lazer-conic-angle-value"); const globalOpacitySlider = panel.querySelector("#lazer-opacity-slider"); const globalOpacityValue = panel.querySelector("#lazer-opacity-value"); // Add initial colors for (let i = 0; i < 2; i++) { colorContainer.appendChild(createColorElement(i)); } // Function to update visibility of gradient-specific controls function updateControlVisibility() { linearDirectionControl.style.display = (gradientType === 'linear') ? 'block' : 'none'; conicAngleControl.style.display = (gradientType === 'conic') ? 'block' : 'none'; } // Set initial visibility updateControlVisibility(); // █▀▀ █░█ █▀▀ █▀█ █▀▀ █▀▄ █▀▀ █▀█ █▄░█ █▀▀ █░█ █▀ █▀▀ █▀▄ █▀▀ █▀▀ █▄░█ █▀▀ █▀█ ▄▀█ █▀▀ █▀▀ ▀█▀ █▀█ █▀█ // █▄▄ █▀█ ██▄ █▀▄ ██▄ █▄▀ █▄▄ █▄█ █░▀█ █▄▄ █▄█ ▄█ ██▄ █▄▀ █▄█ ██▄ █░▀█ ██▄ █▀▄ █▀█ █▄▄ ██▄ ░█░ █▄█ █▀▄ // Event Handlers addColorBtn.addEventListener("click", () => { if (colorCount >= 10) { alert("Maximum 10 LAZER colors!"); return; } colorContainer.appendChild(createColorElement(colorCount)); colorCount++; if (isActive) updateGradient(); // Update gradient immediately after adding a color }); toggleBtn.addEventListener("click", () => { if (colorInputs.length < 2) { alert("Need at least 2 LAZER colors!"); return; } isActive = !isActive; if (isActive) { gradient.style.opacity = globalOpacity / 100; // Use the configured opacity toggleBtn.textContent = "DEACTIVATE LAZER"; toggleBtn.style.background = "linear-gradient(45deg, #FF0000, #990000)"; updateGradient(); // Start animation } else { gradient.style.opacity = 0; toggleBtn.textContent = "ACTIVATE LAZER"; toggleBtn.style.background = "linear-gradient(45deg, #FF00FF, #00FFFF)"; cancelAnimationFrame(animationId); // Stop animation } }); speedSlider.addEventListener("input", () => { speed = parseInt(speedSlider.value); speedValue.textContent = speed; if (isActive) { updateGradient(); // Re-start animation with new speed } }); // New Event Listeners for gradient type, direction, angle, opacity gradientTypeSelect.addEventListener("change", (e) => { gradientType = e.target.value; updateControlVisibility(); // Show/hide relevant controls if (isActive) updateGradient(); }); linearDirectionSelect.addEventListener("change", (e) => { linearDirection = e.target.value; if (isActive) updateGradient(); }); conicAngleSlider.addEventListener("input", () => { conicStartAngle = parseInt(conicAngleSlider.value); conicAngleValue.textContent = `${conicStartAngle}°`; if (isActive) updateGradient(); }); globalOpacitySlider.addEventListener("input", () => { globalOpacity = parseInt(globalOpacitySlider.value); globalOpacityValue.textContent = `${globalOpacity}%`; if (isActive) { // Only change opacity if already active, otherwise it will be set on activation gradient.style.opacity = globalOpacity / 100; } }); closeBtn.addEventListener("click", () => { panel.remove(); gradient.remove(); cancelAnimationFrame(animationId); }); // Panel dragging logic (unchanged) let isDragging = false; let dragOffset = { x: 0, y: 0 }; panel.addEventListener("mousedown", (e) => { // Exclude input fields, selects and buttons from dragging if (e.target.tagName !== "INPUT" && e.target.tagName !== "SELECT" && e.target.tagName !== "BUTTON" && e.target !== closeBtn) { isDragging = true; dragOffset = { x: e.clientX - panel.getBoundingClientRect().left, y: e.clientY - panel.getBoundingClientRect().top }; panel.style.cursor = "grabbing"; panel.style.boxShadow = "0 0 30px rgba(255,0,255,1)"; } }); document.addEventListener("mousemove", (e) => { if (!isDragging) return; panel.style.left = `${e.clientX - dragOffset.x}px`; panel.style.top = `${e.clientY - dragOffset.y}px`; }); document.addEventListener("mouseup", () => { isDragging = false; panel.style.cursor = "move"; panel.style.boxShadow = "0 0 25px rgba(255,0,255,0.8)"; }); // Scrollbar styles (unchanged) const scrollStyle = document.createElement("style"); scrollStyle.textContent = ` #lazer-color-container::-webkit-scrollbar { width: 4px; height: 4px; } #lazer-color-container::-webkit-scrollbar-thumb { background: #FF00FF; border-radius: 2px; } #lazer-color-container::-webkit-scrollbar-track { background: rgba(255,0,255,0.1); } `; document.head.appendChild(scrollStyle); console.log("⚡ LAZER GRADIENT v6.0 activated!"); })();