您需要先安装一个扩展,例如 篡改猴、Greasemonkey 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 Userscripts ,之后才能安装此脚本。
您需要先安装一款用户脚本管理器扩展,例如 Tampermonkey,才能安装此脚本。
您需要先安装用户脚本管理器扩展后才能安装此脚本。
outils d'accessibilité pour les malvoyants
- // ==UserScript==
- // @name AccesSight Pro
- // @namespace http://tampermonkey.net/
- // @version 5.0
- // @description outils d'accessibilité pour les malvoyants
- // @author Yglsan
- // @include *
- // @grant GM_getValue
- // @grant GM_setValue
- // @grant GM_addStyle
- // @license GPL-3.0
- // ==/UserScript==
- (function() {
- 'use strict';
- // Configuration initiale
- const defaultConfig = {
- textSize: 16,
- contrastMode: 'normal',
- speechRate: 1,
- highlightLinks: true,
- darkMode: false,
- savedPosition: { x: 20, y: 20 }
- };
- // État courant
- let config = {
- ...defaultConfig,
- ...GM_getValue('accessightConfig', {})
- };
- // Création de l'interface utilisateur
- function createAccessibilityPanel() {
- const panel = document.createElement('div');
- panel.id = 'accessight-panel';
- panel.style.cssText = `
- position: fixed;
- top: ${config.savedPosition.y}px;
- left: ${config.savedPosition.x}px;
- background: ${config.darkMode ? '#333' : '#FFF'};
- color: ${config.darkMode ? '#FFF' : '#000'};
- padding: 1rem;
- border-radius: 8px;
- box-shadow: 0 4px 12px rgba(0,0,0,0.2);
- z-index: 10000;
- font-family: Arial, sans-serif;
- min-width: 250px;
- cursor: move;
- `;
- // Header avec titre et bouton de fermeture
- const header = document.createElement('div');
- header.innerHTML = `
- <h2 style="margin: 0 0 1rem 0; font-size: 1.2rem;">AccesSight</h2>
- <button aria-label="Fermer" style="position: absolute; top: 5px; right: 5px; background: none; border: none; cursor: pointer;">×</button>
- `;
- panel.appendChild(header);
- // Contrôles principaux
- const controls = [
- { type: 'range', label: 'Taille du texte', min: 12, max: 24, value: config.textSize, key: 'textSize' },
- { type: 'select', label: 'Contraste', options: ['Normal', 'Élevé', 'Inversé'], value: config.contrastMode, key: 'contrastMode' },
- { type: 'button', label: 'Lecture vocale', action: 'toggleSpeech' },
- { type: 'toggle', label: 'Mode sombre', value: config.darkMode, key: 'darkMode' },
- { type: 'toggle', label: 'Surbrillance liens', value: config.highlightLinks, key: 'highlightLinks' }
- ];
- controls.forEach(control => {
- const controlGroup = document.createElement('div');
- controlGroup.style.marginBottom = '0.5rem';
- switch (control.type) {
- case 'range':
- controlGroup.innerHTML = `
- <label style="display: block; margin-bottom: 0.3rem;">
- ${control.label}: <output>${control.value}px</output>
- </label>
- <input type="range"
- min="${control.min}"
- max="${control.max}"
- value="${control.value}"
- style="width: 100%;"
- data-key="${control.key}">
- `;
- break;
- case 'select':
- controlGroup.innerHTML = `
- <label style="display: block; margin-bottom: 0.3rem;">${control.label}</label>
- <select style="width: 100%;" data-key="${control.key}">
- ${control.options.map(opt =>
- `<option value="${opt.toLowerCase()}" ${opt.toLowerCase() === control.value ? 'selected' : ''}>${opt}</option>`
- ).join('')}
- </select>
- `;
- break;
- case 'toggle':
- controlGroup.innerHTML = `
- <label style="display: flex; align-items: center; gap: 0.5rem;">
- <input type="checkbox" ${control.value ? 'checked' : ''} data-key="${control.key}">
- ${control.label}
- </label>
- `;
- break;
- case 'button':
- controlGroup.innerHTML = `
- <button style="width: 100%; padding: 0.5rem;" data-action="${control.action}">
- ${control.label}
- </button>
- `;
- break;
- }
- panel.appendChild(controlGroup);
- });
- // Gestion des événements
- panel.querySelectorAll('input, select').forEach(element => {
- element.addEventListener('change', handleSettingChange);
- });
- panel.querySelector('[data-action="toggleSpeech"]').addEventListener('click', toggleTextToSpeech);
- // Déplacement du panel
- let isDragging = false;
- let initialX, initialY, currentX, currentY;
- panel.addEventListener('mousedown', startDragging);
- document.addEventListener('mousemove', dragPanel);
- document.addEventListener('mouseup', stopDragging);
- function startDragging(e) {
- isDragging = true;
- initialX = e.clientX - panel.offsetLeft;
- initialY = e.clientY - panel.offsetTop;
- }
- function dragPanel(e) {
- if (isDragging) {
- e.preventDefault();
- currentX = e.clientX - initialX;
- currentY = e.clientY - initialY;
- panel.style.left = `${currentX}px`;
- panel.style.top = `${currentY}px`;
- }
- }
- function stopDragging() {
- isDragging = false;
- GM_setValue('accessightConfig', {
- ...config,
- savedPosition: { x: currentX, y: currentY }
- });
- }
- document.body.appendChild(panel);
- applyAccessibilitySettings();
- }
- // Appliquer les paramètres d'accessibilité
- function applyAccessibilitySettings() {
- // Taille du texte
- document.documentElement.style.fontSize = `${config.textSize}px`;
- // Contraste
- switch (config.contrastMode) {
- case 'élevé':
- GM_addStyle(`
- body {
- filter: contrast(150%);
- }
- `);
- break;
- case 'inversé':
- GM_addStyle(`
- body {
- filter: invert(1) hue-rotate(180deg);
- }
- `);
- break;
- }
- // Mode sombre
- if (config.darkMode) {
- GM_addStyle(`
- body {
- background: #111 !important;
- color: #FFF !important;
- }
- `);
- }
- // Surbrillance des liens
- if (config.highlightLinks) {
- GM_addStyle(`
- a {
- outline: 2px solid #FF0000 !important;
- padding: 2px !important;
- }
- `);
- }
- }
- // Gestion des changements de paramètres
- function handleSettingChange(e) {
- const key = e.target.dataset.key;
- let value = e.target.type === 'checkbox' ? e.target.checked : e.target.value;
- if (key === 'textSize') value = parseInt(value);
- config[key] = value;
- GM_setValue('accessightConfig', config);
- applyAccessibilitySettings();
- if (key === 'textSize') {
- e.target.parentNode.querySelector('output').textContent = `${value}px`;
- }
- }
- // Synthèse vocale
- let speech = null;
- function toggleTextToSpeech() {
- if (!speech) {
- speech = new window.SpeechSynthesisUtterance();
- speech.text = document.body.textContent;
- speech.rate = config.speechRate;
- window.speechSynthesis.speak(speech);
- } else {
- window.speechSynthesis.cancel();
- speech = null;
- }
- }
- // Initialisation
- function init() {
- if (!document.getElementById('accessight-panel')) {
- createAccessibilityPanel();
- }
- }
- // Démarrage
- if (document.readyState === 'loading') {
- document.addEventListener('DOMContentLoaded', init);
- } else {
- init();
- }
- })();