参考github上组件使用react重写的页面无障碍功能
accessibility-widget.pages.dev/
react+antd+状态管理显示隐藏抽屉
实现全局字体放大缩小,几种字体更换,几种色差更换,居中靠左靠右,大鼠标,阅读尺,阅读标功能
import React, {useEffect} from 'react';
import {Drawer, Row, Col} from 'antd';
import {useDispatch, useSelector} from 'react-redux';
import icon_invert from '../../assets/icons/icon-invert.svg';
import icon_dark from '../../assets/icons/icon-dark.svg';
import icon_hue from '../../assets/icons/icon-hue.svg';
import icon_desaturate from '../../assets/icons/icon-desaturate.svg';
import icon_left from '../../assets/icons/icon-left.svg';
import icon_center from '../../assets/icons/icon-center.svg';
import icon_right from '../../assets/icons/icon-right.svg';
import icon_mouse from '../../assets/icons/icon-mouse.svg';
import icon_readMark from '../../assets/icons/icon-readMark.svg';
import icon_readGui from '../../assets/icons/icon-readGui.svg';
import icon_rightArrow from '../../assets/icons/icon-rightArrow.svg';
import {MinusOutlined, PlusOutlined} from '@ant-design/icons';
import {setCurrentDrawerModule} from '../../store/slices/drawerModuleSlice.tsx';
import './index.scss';
import {useState, useRef} from 'react';
function Accessibility() {
const dispatch = useDispatch();
const [open, setOpen] = React.useState(false);
const {currentDrawerModule} = useSelector((state: {
drawerModule: { currentDrawerModule: boolean }
}) => state.drawerModule);
const [selectedObject, setSelectedObject] = useState({
contrast: '',
lang: '',
align: '',
cursor: ''
});
const [highlightStyle, setHighlightStyle] = useState({
rgBottom: toString(),
rgTop: toString()
});
const [guideStyle, setGuideStyle] = useState({
rgBottom: toString(),
rgTop: toString(),
arrow: toString()
});
const guideStyleRef = useRef({
rgBottom: toString(),
rgTop: toString(),
arrow: toString()
});
const [isReadMask, setIsReadMask] = useState(false);
const [isReadGuide, setIsReadGuide] = useState(false);
interface SawObjects {
cursor?: string;
contrast?: string;
lang?: string;
align?: string;
}
interface RequiredSawObject {
contrast: string;
lang: string;
align: string;
cursor: string;
}
// 启动或停止监听鼠标移动事件
const toggleListening = () => {
setIsReadMask(!isReadMask);
};
// 启动或停止监听鼠标移动事件
const openReadGuide = () => {
setIsReadGuide(!isReadGuide);
};
// 删除样式
const deleteClass = (e: string) => {
// const className: string = 'custom-cursor-style';
const className: string = e;
const styles: NodeListOf<Element> = document.querySelectorAll(`style.${className}`);
styles.forEach(style => {
style.parentNode?.removeChild(style);
});
};
const adjustFontSize = (multiply: number = 1) => {
document
.querySelectorAll<HTMLElement>('div,h1,h2,h3,h4,h5,h6,p,a,dl,dt,li,ol,th,td,span,blockquote,.asw-text')
.forEach((el) => {
if (!el.classList.contains('drawerDiv') && !el.classList.contains('ant-drawer-title')
) {
let orgFontSize = Number(el.getAttribute('data-asw-orgFontSize') ?? 0);
if (!orgFontSize) {
orgFontSize = parseInt(window.getComputedStyle(el).getPropertyValue('font-size'));
el.setAttribute('data-asw-orgFontSize', String(orgFontSize));
}
const newFontSize: number = orgFontSize * multiply;
el.style.fontSize = newFontSize + 'px';
}
});
};
useEffect(() => {
console.log(currentDrawerModule, 'currentDrawerModule');
if (!currentDrawerModule) {
setOpen(false);
} else {
setOpen(true);
}
}, [currentDrawerModule]);
useEffect(() => {
const handleMouseMove = (event: { clientY: number, x: number, y: number }) => {
if (isReadMask) {
const margin = 20;
const rgTop: string = (event.clientY - margin) + 'px';
const rgBottom: string = (window.innerHeight - event.clientY - (margin * 2)) + 'px';
const highlightStyles = {
rgTop: `${rgTop}`,
rgBottom: `${rgBottom}`
};
setHighlightStyle(highlightStyles);
} else {
const arrow = '50%';
// div的宽度
const divWidth: number = Math.floor((window.innerWidth * 0.4) * 100) / 100;
// 箭头相对于页面的距离
const containerWidth = window.innerWidth;
// div一半的距离
const halfLineWidth = divWidth / 2;
// 鼠标距离右边的距离
const newLeft: number = containerWidth - event.x;
const lineLeft: number = halfLineWidth - newLeft;
if (halfLineWidth + event.x > containerWidth || event.x - halfLineWidth < 0) {
const rgTop: string = event.y + 'px';
const readGuideStyles = {
...guideStyleRef.current,
rgTop: `${rgTop}`,
};
if (halfLineWidth + event.x > containerWidth && event.x < containerWidth - 20) {
readGuideStyles.arrow = `${(halfLineWidth + lineLeft) + 'px'}`;
}
if (event.x - halfLineWidth < 0 && event.x > 12) {
readGuideStyles.arrow = `${event.x + 'px'}`;
}
setGuideStyle(readGuideStyles);
guideStyleRef.current = {...readGuideStyles};
} else {
const rgTop: string = event.y + 'px';
const rgBottom: string = event.x + 'px';
const readGuideStyles: {
rgTop: string, rgBottom: string, arrow: string
} = {
rgTop: `${rgTop}`,
rgBottom: `${rgBottom}`,
arrow: `${arrow}`
};
readGuideStyles.arrow = '50%';
setGuideStyle(readGuideStyles);
guideStyleRef.current = {...readGuideStyles};
}
}
};
document.addEventListener('mousemove', handleMouseMove);
return () => {
document.removeEventListener('mousemove', handleMouseMove);
};
}, [isReadMask, isReadGuide]);
useEffect(() => {
const sawItem = sessionStorage.getItem('saw') || '{}';
const sawObject: SawObjects = JSON.parse(sawItem);
// 提供默认值以确保所有必需的属性都存在
const defaultSawObject: RequiredSawObject = {
contrast: sawObject.contrast ?? '',
lang: sawObject.lang ?? '',
align: sawObject.align ?? '',
cursor: sawObject.cursor ?? ''
};
if (!sawObject) {
sessionStorage.setItem('saw', JSON.stringify({ fontSize: 1 }));
} else {
setSelectedObject(defaultSawObject);
}
}, []);
return (
<>
<Drawer
className='drawerDiv'
keyboard={true}
mask={false}
title="Accessibility Features"
placement='left'
onClose={() => {
setOpen(false);
dispatch(setCurrentDrawerModule(false));
}}
width={640}
open={open}
key={'left'}
styles={{
header: {
backgroundColor: '#E9EDED',
color: '#3F6580'
},
body: {
backgroundColor: '#E9EDED'
}
}}
>
<Row gutter={12}>
<Col className="gutter-row" span={24}>
<div className='colTitle drawerDiv'>
Font Size
</div>
</Col>
</Row>
<Row className='fontContent'>
<Col className="gutter-row drawerDiv" span={8}>
<div className='fontContentLeft drawerDiv'>
Adjust Font Size
</div>
</Col>
<Col className="gutter-row" span={8} offset={8}>
<div className='fontContentRight'>
<Row>
<Col className='drawerDiv' span={4} onClick={() => {
const margin = 0.1;
let fontSize: number = 0;
const sawItem : string | object = sessionStorage.getItem('saw') || '{}';
const sawObject: { fontSize?: string } = JSON.parse(sawItem) as { fontSize?: string };
if ('fontSize' in sawObject) {
fontSize = Number(sawObject.fontSize) - Number(margin);
adjustFontSize(fontSize);
sessionStorage.setItem('saw', JSON.stringify({
...sawObject,
fontSize: fontSize
}));
} else {
adjustFontSize(1.1);
sessionStorage.setItem('saw', JSON.stringify({
...sawObject,
fontSize: 1.1
}));
}
}}>
<MinusOutlined className='drawerDiv' style={{cursor: 'pointer'}}/>
</Col>
<Col span={4}>
<p className='drawerDiv' style={{fontSize: '15px', lineHeight: '20px'}}>A</p>
</Col>
<Col span={4}>
<p className='drawerDiv' style={{fontSize: '20px', lineHeight: '20px'}}>A</p>
</Col>
<Col span={4}>
<p className='drawerDiv' style={{fontSize: '25px', lineHeight: '20px'}}>A</p>
</Col>
<Col span={4}>
<p className='drawerDiv' style={{fontSize: '30px', lineHeight: '20px'}}>A</p>
</Col>
<Col span={4} className='drawerDiv'>
<PlusOutlined className='drawerDiv' style={{cursor: 'pointer'}}
onClick={() => {
const margin:number = 0.1;
let fontSizes: number = 0;
const sawItem : string | object = sessionStorage.getItem('saw') || '{}';
const sawObject: { fontSize?: string } = JSON.parse(sawItem) as { fontSize?: string };
if ('fontSize' in sawObject) {
if (sawObject.fontSize !== undefined) {
fontSizes = Number(sawObject.fontSize) + margin;
}
adjustFontSize(fontSizes);
sessionStorage.setItem('saw', JSON.stringify({
...sawObject,
fontSize: fontSizes
}));
} else {
adjustFontSize(1.1);
sessionStorage.setItem('saw', JSON.stringify({
...sawObject,
fontSize: 1.1
}));
}
}}/>
</Col>
</Row>
</div>
</Col>
</Row>
<Row gutter={16}>
<Col className="gutter-row" span={24}>
<div className='colTitle drawerDiv'>
Contrast
</div>
</Col>
</Row>
<Row gutter={16}>
<Col className='gutter-row clickClass' span={6} onClick={() => {
const sawItem : string | object = sessionStorage.getItem('saw') || '{}';
const sawObject: { contrast?: string } = JSON.parse(sawItem) as { contrast?: string };
deleteClass('contrast-style');
if ('contrast' in sawObject && sawObject?.contrast == 'Invert Colors') {
sessionStorage.setItem('saw', JSON.stringify({
...sawObject,
contrast: ''
}));
setSelectedObject({...selectedObject, contrast: ''});
} else {
const style: HTMLStyleElement = document.createElement('style');
style.className = 'contrast-style';
style.innerHTML = 'html { filter: invert(100%);-webkit-filter: invert(100%); }';
document.head.appendChild(style);
sessionStorage.setItem('saw', JSON.stringify({
...sawObject,
contrast: 'Invert Colors'
}));
setSelectedObject({...selectedObject, contrast: 'Invert Colors'});
}
}}>
<div
className={`ContrastClass ${selectedObject?.contrast == 'Invert Colors' ? 'selectedStutas' : ''}`}>
<Row className='ContrastClassRow'>
<Col span={24}>
<img className="w-[24px] h-[24px] drawerDiv" src={icon_invert} alt=""/>
</Col>
</Row>
<Row>
<Col span={24} className='drawerDiv'>
<div className='drawerDiv'>
Invert Colors
</div>
</Col>
</Row>
</div>
</Col>
<Col className='gutter-row clickClass' span={6} onClick={() => {
const sawItem : string | object = sessionStorage.getItem('saw') || '{}';
const sawObject: { contrast?: string } = JSON.parse(sawItem) as { contrast?: string };
deleteClass('contrast-style');
if ('contrast' in sawObject && sawObject?.contrast == 'Dark Contrast') {
sessionStorage.setItem('saw', JSON.stringify({
...sawObject,
contrast: ''
}));
setSelectedObject({...selectedObject, contrast: ''});
} else {
const style: HTMLStyleElement = document.createElement('style');
style.className = 'contrast-style';
style.innerHTML = 'html p,svg,png,span,img,h1,h2,h3,h4,h5,button {\n' +
' color: #FFF !important;\n' +
' fill: #FFF !important;\n' +
' background-color: #000 !important;\n' +
'}';
document.head.appendChild(style);
sessionStorage.setItem('saw', JSON.stringify({
...sawObject,
contrast: 'Dark Contrast'
}));
setSelectedObject({...selectedObject, contrast: 'Dark Contrast'});
}
}}>
<div
className={`ContrastClass ${selectedObject?.contrast == 'Dark Contrast' ? 'selectedStutas' : ''}`}>
<Row className='ContrastClassRow'>
<Col span={24}>
<img className="w-[24px] h-[24px]" src={icon_dark} alt=""/>
</Col>
</Row>
<Row>
<Col span={24} className='drawerDiv'>
<div className='drawerDiv'>
Dark Contrast
</div>
</Col>
</Row>
</div>
</Col>
<Col className='gutter-row clickClass' span={6}
onClick={() => {
const sawItem : string | object = sessionStorage.getItem('saw') || '{}';
const sawObject: { contrast?: string } = JSON.parse(sawItem) as { contrast?: string };
deleteClass('contrast-style');
if ('contrast' in sawObject && sawObject?.contrast == 'Hue Rotate') {
sessionStorage.setItem('saw', JSON.stringify({
...sawObject,
contrast: ''
}));
setSelectedObject({...selectedObject, contrast: ''});
} else {
const style: HTMLStyleElement = document.createElement('style');
style.className = 'contrast-style';
style.innerHTML = 'html { filter:hue-rotate(100deg);!important; }';
document.head.appendChild(style);
sessionStorage.setItem('saw', JSON.stringify({
...sawObject,
contrast: 'Hue Rotate'
}));
setSelectedObject({...selectedObject, contrast: 'Hue Rotate'});
}
}}>
<div
className={`ContrastClass ${selectedObject?.contrast == 'Hue Rotate' ? 'selectedStutas' : ''}`}>
<Row className='ContrastClassRow'>
<Col span={24}>
<img className="w-[24px] h-[24px]" src={icon_hue} alt=""/>
</Col>
</Row>
<Row>
<Col span={24} className='drawerDiv'>
<div className='drawerDiv'>
Hue Rotate
</div>
</Col>
</Row>
</div>
</Col>
<Col className='gutter-row clickClass' span={6} onClick={() => {
const sawItem : string | object = sessionStorage.getItem('saw') || '{}';
const sawObject: { contrast?: string } = JSON.parse(sawItem) as { contrast?: string };
deleteClass('contrast-style');
if ('contrast' in sawObject && sawObject?.contrast == 'Desaturate') {
sessionStorage.setItem('saw', JSON.stringify({
...sawObject,
contrast: ''
}));
setSelectedObject({...selectedObject, contrast: ''});
} else {
const style: HTMLStyleElement = document.createElement('style');
style.className = 'contrast-style';
style.innerHTML = 'html { filter:saturate(0);!important; }';
document.head.appendChild(style);
sessionStorage.setItem('saw', JSON.stringify({
...sawObject,
contrast: 'Desaturate'
}));
setSelectedObject({...selectedObject, contrast: 'Desaturate'});
}
}}>
<div
className={`ContrastClass ${selectedObject?.contrast == 'Desaturate' ? 'selectedStutas' : ''}`}>
<Row className='ContrastClassRow'>
<Col span={24}>
<img className="w-[24px] h-[24px]" src={icon_desaturate} alt=""/>
</Col>
</Row>
<Row>
<Col span={24} className='drawerDiv'>
<div className='drawerDiv'>
Desaturate
</div>
</Col>
</Row>
</div>
</Col>
</Row>
<Row gutter={16}>
<Col className="gutter-row" span={24}>
<div className='colTitle drawerDiv'>
Change Font
</div>
</Col>
</Row>
<Row gutter={2}>
<Col className="gutter-row clickClass" span={6} onClick={() => {
const sawItem : string | object = sessionStorage.getItem('saw') || '{}';
const sawObject: { lang?: string } = JSON.parse(sawItem) as { lang?: string };
deleteClass('custom-font-style');
if ('lang' in sawObject && sawObject?.lang == 'Helvetica Neue') {
sessionStorage.setItem('saw', JSON.stringify({
...sawObject,
lang: ''
}));
setSelectedObject({...selectedObject, lang: ''});
} else {
const style: HTMLStyleElement = document.createElement('style');
style.className = 'custom-font-style';
style.innerHTML = '* { font-family: "Helvetica Neue", Arial, sans-serif;!important }';
document.head.appendChild(style);
sessionStorage.setItem('saw', JSON.stringify({
...sawObject,
lang: 'Helvetica Neue'
}));
setSelectedObject({...selectedObject, lang: 'Helvetica Neue'});
}
}}>
<div
className={`changeContent drawerDiv ${selectedObject?.lang == 'Helvetica Neue' ? 'selectedStutas' : ''}`}>
Helvetica Neue
</div>
</Col>
<Col className="gutter-row clickClass" span={6} onClick={() => {
const sawItem : string | object = sessionStorage.getItem('saw') || '{}';
const sawObject: { lang?: string } = JSON.parse(sawItem) as { lang?: string };
deleteClass('custom-font-style');
if ('lang' in sawObject && sawObject?.lang == 'SF Pro') {
sessionStorage.setItem('saw', JSON.stringify({
...sawObject,
lang: ''
}));
setSelectedObject({...selectedObject, lang: ''});
} else {
const style: HTMLStyleElement = document.createElement('style');
style.className = 'custom-font-style';
style.innerHTML = '* { font-family: -apple-system, BlinkMacSystemFont, sans-serif;!important }';
document.head.appendChild(style);
sessionStorage.setItem('saw', JSON.stringify({
...sawObject,
lang: 'SF Pro'
}));
setSelectedObject({...selectedObject, lang: 'SF Pro'});
}
}}>
<div
className={`changeContent drawerDiv ${selectedObject?.lang == 'SF Pro' ? 'selectedStutas' : ''}`}>
SF Pro
</div>
</Col>
<Col className="gutter-row clickClass" span={6} onClick={() => {
const sawItem : string | object = sessionStorage.getItem('saw') || '{}';
const sawObject: { lang?: string } = JSON.parse(sawItem) as { lang?: string };
deleteClass('custom-font-style');
if ('lang' in sawObject && sawObject?.lang == 'Roboto') {
sessionStorage.setItem('saw', JSON.stringify({
...sawObject,
lang: ''
}));
setSelectedObject({...selectedObject, lang: ''});
} else {
const style: HTMLStyleElement = document.createElement('style');
style.className = 'custom-font-style';
style.innerHTML = '* { font-family: "Roboto", sans-serif;!important }';
document.head.appendChild(style);
sessionStorage.setItem('saw', JSON.stringify({
...sawObject,
lang: 'Roboto'
}));
setSelectedObject({...selectedObject, lang: 'Roboto'});
}
}}>
<div
className={`changeContent drawerDiv ${selectedObject?.lang == 'Roboto' ? 'selectedStutas' : ''}`}>
Roboto
</div>
</Col>
<Col className="gutter-row clickClass" span={6} onClick={() => {
const sawItem : string | object = sessionStorage.getItem('saw') || '{}';
const sawObject: { lang?: string } = JSON.parse(sawItem) as { lang?: string };
deleteClass('custom-font-style');
if ('lang' in sawObject && sawObject?.lang == 'DA Kufi') {
sessionStorage.setItem('saw', JSON.stringify({
...sawObject,
lang: ''
}));
setSelectedObject({...selectedObject, lang: ''});
} else {
const style: HTMLStyleElement = document.createElement('style');
style.className = 'custom-font-style';
style.innerHTML = '* { font-family: "DA Kufi", sans-serif;!important }';
document.head.appendChild(style);
sessionStorage.setItem('saw', JSON.stringify({
...sawObject,
lang: 'DA Kufi'
}));
setSelectedObject({...selectedObject, lang: 'DA Kufi'});
}
}}>
<div
className={`changeContent drawerDiv ${selectedObject?.lang == 'DA Kufi' ? 'selectedStutas' : ''}`}>
DA Kufi
</div>
</Col>
</Row>
<Row gutter={16}>
<Col className="gutter-row" span={24}>
<div className='colTitle drawerDiv'>
Text Alignment
</div>
</Col>
</Row>
<Row className='fontContent'>
<Col className="gutter-row clickClass" span={8} onClick={() => {
const sawItem : string | object = sessionStorage.getItem('saw') || '{}';
const sawObject: { align?: string } = JSON.parse(sawItem) as { align?: string };
deleteClass('custom-Alignment-style');
if ('align' in sawObject && sawObject?.align == 'Align left') {
sessionStorage.setItem('saw', JSON.stringify({
...sawObject,
align: ''
}));
setSelectedObject({...selectedObject, align: ''});
} else {
const style: HTMLStyleElement = document.createElement('style');
style.className = 'custom-Alignment-style';
style.innerHTML = 'html { text-align: left !important; }';
document.head.appendChild(style);
sessionStorage.setItem('saw', JSON.stringify({
...sawObject,
align: 'Align left'
}));
setSelectedObject({...selectedObject, align: 'Align left'});
}
}}>
<div className='textContent'>
<Row
className={`${selectedObject?.align == 'Align left' ? 'textContentSelectedStutas' : ''}`}
style={{width: '95%'}}>
<Col span={24} className='drawerDiv'
style={{display: 'flex', justifyContent: 'space-evenly'}}>
<img className="w-[24px] h-[20px] drawerDiv" src={icon_left} alt=""/>
<div className='drawerDiv'>
Align left
</div>
</Col>
</Row>
</div>
</Col>
<Col className="gutter-row clickClass" span={8} onClick={() => {
const sawItem : string | object = sessionStorage.getItem('saw') || '{}';
const sawObject: { align?: string } = JSON.parse(sawItem) as { align?: string };
deleteClass('custom-Alignment-style');
if ('align' in sawObject && sawObject?.align == 'Center Align') {
sessionStorage.setItem('saw', JSON.stringify({
...sawObject,
align: ''
}));
setSelectedObject({...selectedObject, align: ''});
} else {
const style: HTMLStyleElement = document.createElement('style');
style.className = 'custom-Alignment-style';
style.innerHTML = 'html { text-align: center !important; }';
document.head.appendChild(style);
sessionStorage.setItem('saw', JSON.stringify({
...sawObject,
align: 'Center Align'
}));
setSelectedObject({...selectedObject, align: 'Center Align'});
}
}}>
<div className='textContent'>
<Row
className={`${selectedObject?.align == 'Center Align' ? 'textContentSelectedStutas' : ''}`}
style={{width: '95%'}}>
<Col span={24} className='drawerDiv'
style={{display: 'flex', justifyContent: 'space-evenly'}}>
<img className="w-[24px] h-[20px] drawerDiv" src={icon_center} alt=""/>
<div className='drawerDiv'>
Center Align
</div>
</Col>
</Row>
</div>
</Col>
<Col className="gutter-row clickClass" span={8} onClick={() => {
const sawItem : string | object = sessionStorage.getItem('saw') || '{}';
const sawObject: { align?: string } = JSON.parse(sawItem) as { align?: string };
deleteClass('custom-Alignment-style');
if ('align' in sawObject && sawObject?.align == 'Align right') {
sessionStorage.setItem('saw', JSON.stringify({
...sawObject,
align: ''
}));
setSelectedObject({...selectedObject, align: ''});
} else {
const style: HTMLStyleElement = document.createElement('style');
style.className = 'custom-Alignment-style';
style.innerHTML = 'html { text-align: right !important; }';
document.head.appendChild(style);
sessionStorage.setItem('saw', JSON.stringify({
...sawObject,
align: 'Align right'
}));
setSelectedObject({...selectedObject, align: 'Align right'});
}
}}>
<div className='textContent'>
<Row
className={`${selectedObject?.align == 'Align right' ? 'textContentSelectedStutas' : ''}`}
style={{width: '95%'}}>
<Col span={24} className='drawerDiv'
style={{display: 'flex', justifyContent: 'space-evenly'}}>
<img className="w-[24px] h-[20px] drawerDiv" src={icon_right} alt=""/>
<div className='drawerDiv'>
Align right
</div>
</Col>
</Row>
</div>
</Col>
</Row>
<Row gutter={16}>
<Col className="gutter-row" span={24}>
<div className='colTitle drawerDiv'>
Cursor
</div>
</Col>
</Row>
<Row gutter={16}>
<Col className="gutter-row" span={8}>
<div
className={`cursorContent ${selectedObject?.cursor == 'Big Cursor' ? 'selectedStutas' : ''}`}
onClick={() => {
const sawItem : string | object = sessionStorage.getItem('saw') || '{}';
const sawObject: { cursor?: string } = JSON.parse(sawItem) as { cursor?: string };
deleteClass('custom-cursor-style');
setIsReadMask(false);
setIsReadGuide(false);
if (sawObject.cursor == 'Big Cursor') {
sessionStorage.setItem('saw', JSON.stringify({
...sawObject,
cursor: ''
}));
setSelectedObject({...selectedObject, cursor: ''});
} else {
const style: HTMLStyleElement = document.createElement('style');
style.className = 'custom-cursor-style';
style.innerHTML = '* { cursor: url(https://cdn.userway.org/widgetapp/images/arrow_w.svg), auto !important; }';
document.head.appendChild(style);
sessionStorage.setItem('saw', JSON.stringify({
...sawObject,
cursor: 'Big Cursor'
}));
setSelectedObject({...selectedObject, cursor: 'Big Cursor'});
}
}}>
<Row>
<Col span={24}>
<img className="w-[25px] h-[32px] drawerDiv" src={icon_mouse} alt=""/>
</Col>
</Row>
<Row style={{marginTop: '10px'}}>
<Col span={24} className='drawerDiv'>
<div className='drawerDiv'>
Big Cursor
</div>
</Col>
</Row>
</div>
</Col>
<Col className="gutter-row" span={8} onClick={() => {
const sawItem : string | object = sessionStorage.getItem('saw') || '{}';
const sawObject: { cursor?: string } = JSON.parse(sawItem) as { cursor?: string };
deleteClass('custom-cursor-style');
if ('cursor' in sawObject && sawObject?.cursor == 'Reading Mask') {
sessionStorage.setItem('saw', JSON.stringify({
...sawObject,
cursor: ''
}));
setSelectedObject({...selectedObject, cursor: ''});
setIsReadMask(false);
} else {
setIsReadGuide(false);
toggleListening();
sessionStorage.setItem('saw', JSON.stringify({
...sawObject,
cursor: 'Reading Mask'
}));
setSelectedObject({...selectedObject, cursor: 'Reading Mask'});
}
}}>
<div
className={`cursorContent ${selectedObject?.cursor == 'Reading Mask' ? 'selectedStutas' : ''}`}>
<Row>
<Col span={24}>
<img className="w-[32px] h-[32px] drawerDiv" src={icon_readMark} alt=""/>
</Col>
</Row>
<Row style={{marginTop: '10px'}}>
<Col span={24} className='drawerDiv'>
<div className='drawerDiv'>
Reading
</div>
</Col>
</Row>
<Row>
<Col span={24} className='drawerDiv'>
<div className='drawerDiv'>
Mask
</div>
</Col>
</Row>
</div>
</Col>
<Col className="gutter-row" span={8} onClick={() => {
const sawItem : string | object = sessionStorage.getItem('saw') || '{}';
const sawObject: { cursor?: string } = JSON.parse(sawItem) as { cursor?: string };
deleteClass('custom-cursor-style');
if ('cursor' in sawObject && sawObject?.cursor == 'Reading Guide') {
sessionStorage.setItem('saw', JSON.stringify({
...sawObject,
cursor: ''
}));
setSelectedObject({...selectedObject, cursor: ''});
setIsReadGuide(false);
} else {
setIsReadMask(false);
openReadGuide();
sessionStorage.setItem('saw', JSON.stringify({
...sawObject,
cursor: 'Reading Guide'
}));
setSelectedObject({...selectedObject, cursor: 'Reading Guide'});
}
}}>
<div
className={`cursorContent ${selectedObject?.cursor == 'Reading Guide' ? 'selectedStutas' : ''}`}>
<Row>
<Col span={24}>
<img className="w-[32px] h-[30px] drawerDiv" src={icon_readGui} alt=""/>
</Col>
</Row>
<Row style={{marginTop: '10px'}}>
<Col span={24} className='drawerDiv'>
<div className='drawerDiv'>
Reading
</div>
</Col>
</Row>
<Row>
<Col span={24} className='drawerDiv'>
<div className='drawerDiv'>
Guide
</div>
</Col>
</Row>
</div>
</Col>
</Row>
<Row gutter={16}>
<Col className="gutter-row clickClass drawerDiv" span={12} offset={12} onClick={() => {
deleteClass('contrast-style');
deleteClass('custom-font-style');
deleteClass('custom-Alignment-style');
deleteClass('custom-cursor-style');
sessionStorage.setItem('saw', JSON.stringify({
fontSize: 1
}));
setSelectedObject({
contrast: '',
lang: '',
align: '',
cursor: ''
});
setIsReadMask(false);
setIsReadGuide(false);
adjustFontSize(1);
document?.querySelectorAll('.asw-selected')?.forEach(el => el?.classList?.remove('asw-selected'));
}}>
<div className='resetClass clickClass drawerDiv'>
RESET SETTINGS <img className="w-[14px] h-[14px] drawerDiv" style={{marginLeft: '7px'}}
src={icon_rightArrow} alt=""/>
</div>
</Col>
</Row>
</Drawer>
{
isReadMask &&
<>
<div className="asw-rg-container">
<div className="asw-rg asw-rg-top" style={{height: highlightStyle?.rgTop}}></div>
<div className="asw-rg asw-rg-bottom"
style={{top: 'auto', bottom: '0px', height: highlightStyle?.rgBottom}}></div>
</div>
</>
}
{
isReadGuide &&
<>
<div className="bottomRulerGuide"
style={{top: guideStyle.rgTop, left: guideStyle.rgBottom}}></div>
<div className="rightRulerGuide guideClassMidd"
style={{top: guideStyle.rgTop, left: guideStyle.rgBottom}}></div>
<div className="leftRulerGuide guideClassMidd"
style={{top: guideStyle.rgTop, left: guideStyle.rgBottom}}></div>
<div className="readingGuide guideClassMidd"
style={{top: guideStyle.rgTop, left: guideStyle.rgBottom}}>
<div className="readingGuide__arrow" style={{left: guideStyle.arrow}}></div>
</div>
</>
}
</>
)
;
}
export default Accessibility;
css部分
.colTitle{
color: #3F6580;
margin: 15px 0;
font-size: 20px;
}
.fontContent{
color: #3F6580;
background-color: #FAFAFA;
border-radius: 10px;
height: 62px;
display: flex;
align-items: center;
text-align: center;
}
.changeContent{
color: #3F6580;
background-color: #FAFAFA;
border-radius: 5px;
height: 46px;
width: 142px;
display: flex;
align-items: center;
justify-content: center;
font-size: 16px;
}
.cursorContent{
color: #3F6580;
height: 113px;
width: 182px;
display: flex;
justify-content: center;
align-items: center;
flex-direction: column;
background-color: #FAFAFA;
border-radius: 10px;
cursor: pointer;
}
.textContent{
height: 62px;
color: #3F6580;
display: flex;
justify-content: center;
align-items: center;
flex-direction: column;
background-color: #FAFAFA;
border-radius: 10px;
}
.ContrastClass{
color: #3F6580;
height: 129px;
display: flex;
justify-content: center;
align-items: center;
flex-direction: column;
background-color: #FAFAFA;
border-radius: 10px;
font-size: 16px;
}
.ContrastClassRow{
margin-bottom: 19px;
}
.resetClass{
height: 37px;
border-radius: 10px;
background-color: #A3D2E7;
width: 100%;
display: flex;
justify-content: center;
align-items: center;
margin-top: 20px;
font-weight: 700;
}
.clickClass{
cursor: pointer;
}
.ant-drawer-close{
position: absolute;
right: 10px;
border: 1px solid red;
border-radius: 14px;
}
.asw-rg{
position: fixed;
top: 0;
left: 0;
right: 0;
width: 100%;
height: 0;
pointer-events: none;
background-color: rgba(0,0,0,.8);
z-index: 1000000;
}
.readingGuide{
box-sizing: border-box;
background: #000;
width: 40vw !important;
min-width: 200px !important;
position: absolute !important;
height: 12px !important;
border: solid 3px #fff300;
border-radius: 5px;
top: 20px;
z-index: 2147483647;
transform: translateX(-50%);
}
.bottomRulerGuide{
width: 36px;
height: 16px;
background: 0 0;
position: absolute !important;
z-index: 2147483647;
transform: translateX(-50%);
}
.leftRulerGuide, .RightRulerGuide {
width: 16px;
height: 9px;
background: 0 0;
position: absolute !important;
z-index: 2147483647;
transform: translateY(-50%);
}
.bottomRulerGuide,.leftRulerGuide,.readingGuide,.rightRulerGuide {
display: block;
pointer-events: none;
}
.readingGuide__arrow {
bottom: 100%;
left: 50%;
transform: translateX(-50%);
width: 20px;
height: 0;
position: absolute;
}
.readingGuide__arrow:before {
border-bottom-color: #fff300;
border-top-color: transparent;
border-left-color: transparent;
border-right-color: transparent;
border-width: 17px;
margin-left: -17px;
}
.readingGuide__arrow:after {
border-bottom-color: #000;
border-top-color: transparent;
border-left-color: transparent;
border-right-color: transparent;
border-width: 14px;
margin-left: -14px;
}
.readingGuide__arrow:after, .readingGuide__arrow:before {
content: "";
bottom: 100%;
left: 50%;
height: 0;
width: 0;
position: absolute;
pointer-events: none;
}
.guideClassMidd{
zoom: 1!important;
}
.selectedStutas{
border: 2px solid #0848ca !important;
color: #0848ca;
}
.selectedStutas img{
fill: #0848ca !important;
color: #0848ca !important;
}
.textContentSelectedStutas{
height: 54px;
display: flex;
width: 180px;
background: #96D4EA;
border-radius: 10px;
align-content: center;
}