Brightness, Contrast, and Saturation Control

Adjust brightness, contrast, and saturation of a webpage with a draggable and user-friendly UI. Settings persist across page reloads.

当前为 2025-01-23 提交的版本,查看 最新版本

  1. // ==UserScript==
  2. // @name Brightness, Contrast, and Saturation Control
  3. // @namespace http://your.namespace.here/
  4. // @version 1.8
  5. // @description Adjust brightness, contrast, and saturation of a webpage with a draggable and user-friendly UI. Settings persist across page reloads.
  6. // @author tae
  7. // @match *://*/*
  8. // @grant none
  9. // @run-at document-end
  10. // ==/UserScript==
  11.  
  12. (function () {
  13. 'use strict';
  14.  
  15. window.addEventListener('load', () => {
  16. if (document.querySelector('.filter-control-toggle')) return;
  17.  
  18. const LOCAL_STORAGE_KEY = 'filter-settings';
  19.  
  20. // Load filter values from localStorage
  21. const loadFilters = () => {
  22. const settings = JSON.parse(localStorage.getItem(LOCAL_STORAGE_KEY)) || { brightness: 100, contrast: 100, saturation: 100 };
  23. return settings;
  24. };
  25.  
  26. // Save filter values to localStorage
  27. const saveFilters = (settings) => {
  28. localStorage.setItem(LOCAL_STORAGE_KEY, JSON.stringify(settings));
  29. };
  30.  
  31. let { brightness, contrast, saturation } = loadFilters();
  32.  
  33. // Create toggle button
  34. const toggleButton = document.createElement('button');
  35. toggleButton.textContent = 'Filters';
  36. toggleButton.className = 'filter-control-toggle';
  37. toggleButton.style.cssText = `
  38. position: fixed;
  39. top: 10px;
  40. left: 10px;
  41. background-color: #333;
  42. color: white;
  43. border: none;
  44. padding: 5px 10px;
  45. z-index: 2147483647;
  46. border-radius: 5px;
  47. cursor: pointer;
  48. `;
  49. document.body.appendChild(toggleButton);
  50.  
  51. // Create control panel
  52. const controlPanel = document.createElement('div');
  53. controlPanel.className = 'filter-control-panel';
  54. controlPanel.style.cssText = `
  55. position: fixed;
  56. top: 50px;
  57. left: 10px;
  58. background-color: rgba(0, 0, 0, 0.85);
  59. color: white;
  60. padding: 15px;
  61. z-index: 2147483646;
  62. border-radius: 10px;
  63. width: 250px;
  64. font-family: Arial, sans-serif;
  65. display: none;
  66. overflow: hidden;
  67. box-shadow: 0 4px 10px rgba(0, 0, 0, 0.5);
  68. `;
  69. document.body.appendChild(controlPanel);
  70.  
  71. // Show/hide control panel
  72. toggleButton.addEventListener('click', () => {
  73. controlPanel.style.display = controlPanel.style.display === 'none' ? 'block' : 'none';
  74. });
  75.  
  76. // Make control panel draggable
  77. makeDraggable(controlPanel);
  78.  
  79. function makeDraggable(element) {
  80. let isDragging = false, startX, startY, initialLeft, initialTop;
  81.  
  82. element.addEventListener('mousedown', (event) => {
  83. isDragging = true;
  84. startX = event.clientX;
  85. startY = event.clientY;
  86. initialLeft = element.offsetLeft;
  87. initialTop = element.offsetTop;
  88. event.preventDefault();
  89. });
  90.  
  91. document.addEventListener('mousemove', (event) => {
  92. if (isDragging) {
  93. const deltaX = event.clientX - startX;
  94. const deltaY = event.clientY - startY;
  95. element.style.left = `${Math.max(0, initialLeft + deltaX)}px`;
  96. element.style.top = `${Math.max(0, initialTop + deltaY)}px`;
  97. }
  98. });
  99.  
  100. document.addEventListener('mouseup', () => {
  101. isDragging = false;
  102. });
  103. }
  104.  
  105. // Create slider function
  106. const createSlider = (labelText, defaultValue, min, max, step, onChange) => {
  107. const container = document.createElement('div');
  108. container.style.marginBottom = '15px';
  109.  
  110. const label = document.createElement('label');
  111. label.textContent = `${labelText}: ${defaultValue}`;
  112. label.style.display = 'block';
  113. label.style.marginBottom = '5px';
  114. container.appendChild(label);
  115.  
  116. const slider = document.createElement('input');
  117. slider.type = 'range';
  118. slider.value = defaultValue;
  119. slider.min = min;
  120. slider.max = max;
  121. slider.step = step;
  122. slider.style.width = '100%';
  123.  
  124. // Stop propagation of the mousedown event
  125. slider.addEventListener('mousedown', (e) => {
  126. e.stopPropagation();
  127. });
  128.  
  129. slider.oninput = (e) => {
  130. const value = e.target.value;
  131. label.textContent = `${labelText}: ${value}`;
  132. onChange(value);
  133. };
  134. container.appendChild(slider);
  135.  
  136. controlPanel.appendChild(container);
  137. return slider;
  138. };
  139.  
  140. // Apply filters
  141. const updateFilters = () => {
  142. document.documentElement.style.filter = `brightness(${brightness}%) contrast(${contrast}%) saturate(${saturation}%)`;
  143. };
  144.  
  145. // Create sliders
  146. createSlider('Brightness', brightness, 50, 150, 1, (value) => {
  147. brightness = value;
  148. saveFilters({ brightness, contrast, saturation });
  149. updateFilters();
  150. });
  151. createSlider('Contrast', contrast, 50, 150, 1, (value) => {
  152. contrast = value;
  153. saveFilters({ brightness, contrast, saturation });
  154. updateFilters();
  155. });
  156. createSlider('Saturation', saturation, 50, 150, 1, (value) => {
  157. saturation = value;
  158. saveFilters({ brightness, contrast, saturation });
  159. updateFilters();
  160. });
  161.  
  162. // Initialize filters
  163. updateFilters();
  164. });
  165. })();