页面无障碍功能

65 阅读5分钟

参考github上组件使用react重写的页面无障碍功能

accessibility-widget.pages.dev/

react+antd+状态管理显示隐藏抽屉

实现全局字体放大缩小,几种字体更换,几种色差更换,居中靠左靠右,大鼠标,阅读尺,阅读标功能

image.png

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;
}