// ==UserScript== // @name 必应去广告+粒子消散特效+跟随系统主题 // @namespace http://tampermonkey.net/ // @version 1.0 // @description 清除必应广告,删除时粒子消散动画,自动跟随系统深色浅色 // @author You // @match https://*.bing.com/* // @grant none // ==/UserScript== (function() { 'use strict'; // ===================== 1. 跟随系统明暗主题 ===================== function setBingTheme(isDark) { const theme = isDark ? 'dark' : 'light'; localStorage.setItem('BingTheme', theme); document.documentElement.setAttribute('data-theme', theme); window.dispatchEvent(new StorageEvent('storage', { key: 'BingTheme', newValue: theme })); } function syncSystemTheme() { const mql = window.matchMedia('(prefers-color-scheme: dark)'); setBingTheme(mql.matches); } if (document.readyState === 'loading') document.addEventListener('DOMContentLoaded', syncSystemTheme); else syncSystemTheme(); window.matchMedia('(prefers-color-scheme: dark)').addEventListener('change', e => setBingTheme(e.matches)); // ===================== 2. 粒子消散特效核心 ===================== function createParticleEffect(el) { const rect = el.getBoundingClientRect(); const centerX = rect.left + rect.width / 2; const centerY = rect.top + rect.height / 2; const particleCount = 60; const particles = []; // 创建容器 const canvas = document.createElement('canvas'); const ctx = canvas.getContext('2d'); canvas.style.position = 'fixed'; canvas.style.pointerEvents = 'none'; canvas.style.zIndex = '999999'; canvas.style.left = '0'; canvas.style.top = '0'; canvas.width = window.innerWidth; canvas.height = window.innerHeight; document.body.appendChild(canvas); // 粒子类 class Particle { constructor() { this.x = centerX; this.y = centerY; const angle = Math.random() * Math.PI * 2; const speed = Math.random() * 4 + 2; this.vx = Math.cos(angle) * speed; this.vy = Math.sin(angle) * speed; this.radius = Math.random() * 3 + 1; this.alpha = 1; this.decay = Math.random() * 0.015 + 0.008; } update() { this.x += this.vx; this.y += this.vy; this.vy += 0.05; this.alpha -= this.decay; } draw() { ctx.save(); ctx.globalAlpha = this.alpha; ctx.beginPath(); ctx.arc(this.x, this.y, this.radius, 0, Math.PI * 2); ctx.fillStyle = '#4096ff'; ctx.fill(); ctx.restore(); } } // 生成粒子 for (let i = 0; i < particleCount; i++) particles.push(new Particle()); // 动画循环 function animate() { ctx.clearRect(0, 0, canvas.width, canvas.height); let alive = false; for (let p of particles) { p.update(); p.draw(); if (p.alpha > 0) alive = true; } if (alive) requestAnimationFrame(animate); else canvas.remove(); } animate(); } // ===================== 3. 广告清除逻辑 ===================== const adSelectors = [ // 搜索结果广告 '.b_ad', '.ads-first', '.b_adTop', '.b_adSlate', // 侧边广告 '.bSidebarAd', '.ads-container', // 底部推广、商品广告 '.bProductCarousel', '.bShoppingAd', // 信息流推广卡片 ['.card-with-ad-label'], // 竞价推广标识模块 '[data-ad]', '[data-bm-ad]', '.ad_text' ]; function removeAds() { adSelectors.forEach(sel => { document.querySelectorAll(sel).forEach(ad => { if (!ad.dataset.removed) { ad.dataset.removed = '1'; createParticleEffect(ad); setTimeout(() => ad.remove(), 300); } }); }); } // 初次执行 removeAds(); // 监听动态加载内容(滚动/翻页新广告) const observer = new MutationObserver(muts => { for (let m of muts) { if (m.addedNodes.length) { removeAds(); break; } } }); observer.observe(document.body, { childList: true, subtree: true }); })();