a11y-magnifier
v2.0.3
Published
Zero-dependency, cursor-following screen magnifier widget for the web — built for low-vision accessibility on news sites and content-heavy pages.
Maintainers
Readme
🇹🇷 Türkçe · 🇬🇧 English
a11y-magnifier
Bağımlılıksız, mouse takipli büyüteç (magnifier) widget'ı. Haber siteleri ve metin ağırlıklı sayfalarda görme zorluğu yaşayan kullanıcılar için tasarlandı — tek bir script etiketiyle eklenir, build adımı ya da framework gerektirmez.
📖 Canlı Storybook demosu — tüm seçenekleri deneyin
Neden bu proje var?
Görme zorluğu yaşayan kullanıcılar, web'in büyük ve genelde göz ardı edilen bir kesimi; çoğu site tarayıcının kendi zoom özelliği dışında bir büyütme seçeneği sunmuyor — o da sayfa düzenini bozup okunan noktayı kaybettiriyor. Alternatif genelde pahalı bir SaaS overlay widget'ı oluyor. Bu kütüphane, ücretsiz ve açık olan orta yol: imleci takip eden, metni net tutan ve build sürecine dahi müdahale etmeden tek satırla herhangi bir sayfaya eklenebilen bir büyüteç.
Tam bir erişilebilirlik denetiminin yerini tutmaz, ama imleç odaklı bir büyüteç bugün görme zorluğu yaşayan kullanıcılar için somut bir fayda sağlar — ve her site, satın alma sürecine girmeden bunu ekleyebilmeli.
Mevzuat bağlamı (AB & Türkiye)
Erişilebilirlik, web'in giderek büyüyen bir kesimi için "olsa iyi olur"dan "yasal zorunluluk"a doğru kayıyor — bu kütüphanenin hedeflediği hem kamu hem özel sektör cephesinde:
- AB — kamu sektörü: Web Erişilebilirliği Direktifi (AB) 2016/2102, kamu kurumlarının web sitesi ve uygulamalarında WCAG 2.1 AA uyumluluğunu 2019-2021 arasında (sitenin yaşına göre değişen tarihlerde) zorunlu kıldı.
- AB — özel sektör: Avrupa Erişilebilirlik Yasası (AB) 2019/882, 28 Haziran 2025'ten itibaren yürürlükte; EN 301 549 standardı üzerinden WCAG 2.1 AA'ya denk gereklilikleri e-ticaret, bankacılık, telekomünikasyon ve AB'de tüketiciye sunulan diğer dijital hizmetlere genişletiyor — uyumsuzluk durumunda para cezaları öngörülüyor.
- Türkiye: 5378 sayılı Engelliler Hakkında Kanun ve Erişilebilirlik İzleme ve Denetleme Yönetmeliği (Resmî Gazete 20.07.2013, Sayı 28713; değişiklik 21.09.2016, Sayı 29834), kamu kurumlarının dijital hizmetlerinin erişilebilirlik açısından izlenmesini zaten zorunlu kılıyor.
Bunların hiçbiri "ekranda büyüteç bulunmalı" diye özel bir gereklilik saymıyor ve kapsam detayları önemli — herhangi birini uyumluluk tavsiyesi olarak görmeden önce orijinal metni okuyun. Ama yön net: WCAG 2.1 AA, hem kamu hem özel sektörde giderek daha fazla sitenin taban çizgisi haline geliyor ve imleç odaklı büyütme, 1.4.4 Metni Yeniden Boyutlandırma ve 1.4.10 Reflow gibi WCAG başarı ölçütlerini doğrudan destekliyor. Bir denetimden ya da yasal son tarihten önce böyle bir araç eklemek, gereksiz mühendislik değil ucuz bir sigorta.
Özellikler
- ⚙️ Sıfır runtime bağımlılığı, TypeScript ile yazıldı, minified ~11 KB
- 🎯 Mouse cursor'unu takip eder; isteğe bağlı olarak aktifken native cursor'u gizler
- 🔵 Daire, kare veya dikdörtgen lens şekli
- 🖼️ Varsayılan olarak canvas tabanlı render (SVG
foreignObjectsnapshot →<canvas>) — canlı DOM'a dokunmaz, GPU hızlandırmalıdrawImageile büyütür - 🎚️ Her seçenek
setOptions()ile runtime'da anlık değiştirilebilir - ⌨️ Yapılandırılabilir klavye kısayolu (varsayılan
Alt+M) - 🔁 Bir butondan tetiklenebilir veya
autoStart: trueile otomatik açılır - 📰
excludeSelectorsile reklam alanları, video oynatıcılar veya belirttiğiniz herhangi bir bölgede lens gizlenir - 📝 Tip tanımları (
dist/magnifier.d.ts) doğrudan kaynak koddan otomatik üretilir — ayrı bir@typespaketine gerek yok - 📚 Her constructor seçeneğini kapsayan, tamamen interaktif bir Storybook
Kurulum
npm install a11y-magnifier// CommonJS
const Magnifier = require('a11y-magnifier');
// ESM / bundler'lar (webpack, Vite, Rollup, Next.js, ...)
import Magnifier from 'a11y-magnifier';Ya da hiç build adımına gerek kalmadan doğrudan CDN'den yükleyin — bu bundle herhangi bir modül formatına ihtiyaç duymaz, sadece window.Magnifier'ı tanımlar:
<script src="https://cdn.jsdelivr.net/npm/a11y-magnifier/dist/magnifier.global.min.js"></script>
<script>
const mag = new Magnifier({ shape: 'circle', zoom: 2 });
mag.enable();
</script>Hızlı Kullanım
// Buton kontrolü
const mag = new Magnifier({ shape: 'circle', size: 220, zoom: 2 });
document.getElementById('magBtn').addEventListener('click', () => mag.toggle());
// Sayfa açılır açılmaz aktif
new Magnifier({ autoStart: true, shape: 'circle', zoom: 2.5 });API
new Magnifier(options)
| Seçenek | Tip | Varsayılan | Açıklama |
|---|---|---|---|
| shape | 'circle' \| 'square' \| 'rectangle' | 'circle' | Büyüteç şekli |
| size | number | 220 | circle ve square için çap/kenar (px) |
| width | number | 360 | rectangle için genişlik |
| height | number | 220 | rectangle için yükseklik |
| zoom | number | 2 | Büyütme oranı |
| borderWidth | number | 3 | Kenar kalınlığı |
| borderColor | string | rgba(255,255,255,.95) | Kenar rengi |
| borderStyle | string | 'solid' | CSS border-style |
| borderRadius | number | 8 | square/rectangle köşe yumuşatma |
| shadow | string | '0 10px 40px ...' | CSS box-shadow |
| background | string | '#ffffff' | Lens arkaplanı |
| crosshair | boolean | false | Merkezde nokta göstergesi |
| crosshairColor | string | rgba(255,0,0,.6) | Crosshair rengi |
| autoStart | boolean | false | Sayfa yüklenince otomatik aç |
| hideCursor | boolean | true | Sayfa cursor'unu gizle |
| smooth | boolean | true | Yumuşak hareket |
| smoothDuration | number | 50 | Transition süresi (ms) |
| offsetX / offsetY | number | 0 | Lens'in cursor'a göre ofseti |
| zIndex | number | 2147483646 | Lens z-index |
| renderMode | 'canvas' \| 'clone' \| 'auto' | 'canvas' | Render yöntemi (aşağıya bakın) |
| excludeSelectors | string[] | [] | Bu seçicilerin üzerinde lens gizlenir (örn. ['.ad-slot', '.video-ad']) |
| refreshIntervalMs | number | 500 | Snapshot/clone yenileme aralığı (ms) |
| keyboardShortcut | string \| false | 'm' | Toggle için tuş; false ile kapatılır |
| shortcutWithCtrl | boolean | false | Ctrl/Cmd gereksin mi |
| shortcutWithAlt | boolean | true | Alt gereksin mi |
| shortcutWithShift | boolean | false | Shift gereksin mi |
| onEnable | function | null | Aktif olunca çağrılır |
| onDisable | function | null | Kapanınca çağrılır |
| onMove | function | null | (x, y) mouse koordinatlarıyla çağrılır |
renderMode seçeneği
| Değer | Açıklama |
|---|---|
| 'canvas' | Sayfa, SVG foreignObject aracılığıyla bir <canvas> snapshot'ına yazdırılır. Lens içinde ikinci bir DOM ağacı oluşmaz; büyütme drawImage ile GPU hızlandırmalı yapılır. Önerilen. |
| 'clone' | document.body klonlanarak lens içine yerleştirilir ve CSS transform: scale() ile büyütülür. Cross-origin görsel içeren sayfalarda daha güvenilir. |
| 'auto' | canvas destekleniyorsa canvas, değilse clone kullanılır. |
Metodlar
| Metod | Açıklama |
|---|---|
| .enable() | Büyüteci aç |
| .disable() | Büyüteci kapat |
| .toggle() | Aç/kapat |
| .isEnabled() | Açık mı? |
| .setOptions(opts) | Runtime'da seçenekleri güncelle |
| .getOptions() | Mevcut seçenekleri döner |
| .destroy() | Tüm event listener'ları kaldır |
Klavye kısayolları
| Kısayol | Eylem |
|---|---|
| Alt + M | Büyüteci aç/kapat (varsayılan) |
| Esc | (yerleşik değil — kendiniz bağlayın, aşağıya bakın) |
Kısayol; input, textarea veya contenteditable bir öğeye odaklanılmışken tetiklenmez.
Gerçek senaryo: haber sitesi
const mag = new Magnifier({
shape: 'circle',
size: 240,
zoom: 2.2,
renderMode: 'canvas',
autoStart: false,
excludeSelectors: ['.ad-slot', '.gpt-ad', '.video-player', '[data-ad]'],
keyboardShortcut: 'm',
shortcutWithAlt: true,
});
// Erişilebilirlik menüsünden açma
document.querySelector('#accessibility-magnifier-toggle')
.addEventListener('click', () => mag.toggle());
// İsteğe bağlı: Esc ile de kapatılabilsin
document.addEventListener('keydown', (e) => {
if (e.key === 'Escape' && mag.isEnabled()) mag.disable();
});Notlar / Sınırlamalar
- Canvas modu (varsayılan): Sayfa içeriği SVG
foreignObjectile bir canvas'a yazdırılır; lens içinde ikinci bir DOM ağacı oluşmaz.drawImageile büyütme GPU hızlandırmalıdır. Cross-origin<img>veya<iframe>öğeleri snapshot'a dahil edilemez (tarayıcı güvenlik kısıtlaması); bu durum haber sitelerinin kendi makale içeriği için nadiren sorun çıkarır. - Clone modu: Sayfanın DOM clone'u üzerinde CSS scale uygular.
<canvas>ve cross-origin<iframe>içerikleri bu modda da büyütülmüş görünmeyebilir. Cross-origin görseller sunuyorsanız bu mod tercih edilebilir. refreshIntervalMsçok düşürülürse CPU kullanımı artar; varsayılan 500ms çoğu sayfa için uygundur.- Klavye kısayolu input/textarea/contenteditable alanlarında hiçbir zaman tetiklenmez.
Geliştirme
Kaynak kod TypeScript'tir (src/), tsup ile dört dist/ bundle'ına derlenir: magnifier.js (CJS), magnifier.mjs (ESM), magnifier.global.js / magnifier.global.min.js (IIFE, window.Magnifier'ı tanımlar — yukarıdaki CDN örneğinde kullanılan budur), ve otomatik üretilen .d.ts tipleri.
npm install
npm run storybook # interaktif oyun alanı — her seçenek, canlı
npm run typecheck # tsc --noEmit
npm run build # yukarıda açıklanan dist/ bundle'larını üretir
npm run build-storybook # statik Storybook build'i (CI/Pages deploy'da kullanılır)Katkılar, issue'lar ve fikirler memnuniyetle karşılanır — GitHub üzerinden bir PR ya da issue açabilirsiniz.
Lisans
MIT © Umut Yaldız
Yazar
Umut Yaldız — github.com/umutyaldiz
