let speakEditor = {};
if (process.env.TARO_ENV === 'h5') {
speakEditor = require('./quill-editor');
}
const SpeakEditor = speakEditor.default || <View />;
// 外层back使用相对定位,这样SpeakEditor使用绝对定位时位置就没问题了
<View className={style.back}>
<SpeakEditor onInput={handleInputChange} value={''} />
</View>
// SpeakEditor组件index.jsx
import {createRef, useCallback, useEffect, useImperativeHandle, useRef} from 'react';
import {Events} from '@tarojs/taro';
import {View} from '@tarojs/components';
import ReactQuill from 'react-quill';
import 'react-quill/dist/quill.snow.css';
import 'tippy.js/dist/tippy.css';
import style from './style.less';
export const events = new Events();
const oneSelfRef = createRef();
export default function SpeakEditor(props) {
const {value, onInput} = props;
const reactQuillRef = useRef();
const quillRef = useRef();
useImperativeHandle(oneSelfRef, () => ({
getText() {
return quillRef.current.getText();
},
getContents() {
return quillRef.current.getContents();
},
loadContents(contents) {
quillRef.current.setContents(contents);
},
editorEvent(eventName, handler) {
quillRef.current.root.addEventListener(eventName, handler);
},
editorOffEvent(eventName, handler) {
quillRef.current.root.removeEventListener(eventName, handler);
},
call(method, ...args) {
return quillRef.current[method](...args);
},
focusOnSelection() {
// 滚动到光标处
const editor = quillRef.current; // quill编辑器实例
const selection = editor.getSelection(); // 获取选中范围
if (selection) {
const [line] = editor.getLines(selection.index, 1);
if (line) {
editor.scrollIntoView(line);
}
}
}
}));
useEffect(() => {
quillRef.current = reactQuillRef.current.getEditor();
}, []);
const handleChange = useCallback(
(_value, delta, source, editor) => {
// console.log('Change: ', {_value, delta, source, editor}, editor.getContents());
onInput({detail: {value: _value}});
},
[onInput]
);
return (
<View className={style.quill_editor}>
<ReactQuill theme="snow" value={value} onChange={handleChange} ref={reactQuillRef} />
</View>
);
}
export function event(eventName, handler) {
if (oneSelfRef.current) {
oneSelfRef.current.call('on', eventName, handler);
} else if (event.counter < 20) {
event.counter++;
setTimeout(()=> {
event(eventName, handler);
}, 200);
}
}
event.counter = 0;
export function offEvent(eventName, handler) {
oneSelfRef.current?.call('off', eventName, handler);
}
export function editorEvent(eventName, handler) {
if (oneSelfRef.current) {
oneSelfRef.current.editorEvent(eventName, handler);
} else if (editorEvent.counter < 20) { editorEvent.counter++; setTimeout(()=> {
oneSelfRef.current.editorEvent(eventName, handler);
}, 200);
}
}
editorEvent.counter = 0;
export function editorOffEvent(eventName, handler) {
oneSelfRef.current.editorOffEvent(eventName, handler);
}
export function on(eventName, handler) {
events.on(eventName, handler);
}
export function off(eventName, handler) {
if (!eventName || !handler) {
events.off();
} else {
events.off(eventName, handler);
}
}
export function getText() {
return oneSelfRef.current?.getText();
}
export function getContents() {
return oneSelfRef.current?.getContents();
}
export function loadContents(contents) {
return oneSelfRef.current?.loadContents(contents);
}
export function doBlur() {
console.log('doBlur');
return oneSelfRef.current?.call('blur');
}
export function doFocus() {
console.log('doFocus');
return oneSelfRef.current?.call('focus');
}
export function focusOnSelection() {
oneSelfRef.current?.focusOnSelection();
}
// SpeakEditor组件style.less
.quill_editor {
position: absolute;
top: 0;
right: 0;
bottom: 0;
left: 0;
width: 100%;
:global {
.quill {
width: 100%;
height: 100%;
user-select: text;
}
.ql-toolbar {
display: none;
}
.ql-container {
font-size: 28px;
color: white;
border: none;
}
.ql-editor {
padding: 0;
line-height: 38px;
letter-spacing: 4px;
}
.pause_embed {
display: inline-block;
margin: 6px 0;
margin-right: 3px;
font-size: 28px !important;
color: #468df7;
pointer-events: auto;
}
.reading_method {
display: inline-block;
padding: 0;
padding-left: 4px;
margin: 6px 0;
margin-right: 3px;
font-size: inherit !important;
font-weight: inherit !important;
pointer-events: none;
// background: rgb(66, 44, 54);
background: rgba(239, 161, 56, 0.32);
border-radius: 4px;
&::after {
display: inline-block;
height: 100%;
padding: 3px 4px;
margin-left: 4px;
font-size: 22px;
color: #efa138;
pointer-events: auto;
background: rgba(239, 161, 56, 0.16);
content: attr(data-str);
}
}
.shift_speed {
display: inline-block;
margin: 6px 0;
margin-right: 3px;
font-size: inherit !important;
font-weight: inherit !important;
pointer-events: none;
&::before {
color: #468df7;
content: '【';
}
&::after {
color: #468df7;
pointer-events: auto;
content: '】' attr(data-value) 'x';
}
}
.chars_check {
display: inline-block;
padding: 0;
padding-left: 4px;
margin: 6px 0;
margin-right: 3px;
font-size: inherit !important;
font-weight: inherit !important;
// pointer-events: none;
background: rgba(82, 196, 26, 0.16);
border-radius: 4px;
&::after {
display: inline-block;
padding: 3px 4px;
margin-bottom: 5px;
margin-left: 4px;
font-size: 22px;
vertical-align: middle;
// pointer-events: auto;
content: attr(data-str);
}
&[data-str=''] {
&::after {
width: 24px;
height: 24px;
margin-right: 7px;
margin-left: 3px;
background: center no-repeat;
background-size: contain;
background-image: url(data:image/svg+xml;base64,PHN2ZyB3aWR0aD0iMzIiIGhlaWdodD0iMzIiIHZpZXdCb3g9IjAgMCAzMiAzMiIgZmlsbD0ibm9uZSIgeG1sbnM9Imh0dHA6Ly93d3cudzMub3JnLzIwMDAvc3ZnIj4KPHBhdGggZD0iTTE5LjYxMDUgMTEuODcwMkMxOS42MTA1IDExLjM4OTYgMjAuMDAwMSAxMSAyMC40ODA2IDExSDIzLjk2MTNDMjQuNDQxOCAxMSAyNC44MzE0IDExLjM4OTYgMjQuODMxNCAxMS44NzAyVjExLjg3MDJDMjQuODMxNCAxMi4zNTA3IDI0LjQ0MTggMTIuNzQwMyAyMy45NjEzIDEyLjc0MDNIMjAuNDgwNkMyMC4wMDAxIDEyLjc0MDMgMTkuNjEwNSAxMi4zNTA3IDE5LjYxMDUgMTEuODcwMlYxMS44NzAyWiIgZmlsbD0id2hpdGUiLz4KPHBhdGggZmlsbC1ydWxlPSJldmVub2RkIiBjbGlwLXJ1bGU9ImV2ZW5vZGQiIGQ9Ik0yMS41NTU4IDI0LjI5NzJDMjEuNjk1NSAyNC4zMDk5IDIxLjg0MDggMjQuMzE2MiAyMS45OTE1IDI0LjMxNjJDMjIuNzc3OCAyNC4zMTYyIDIzLjQ2MTYgMjQuMTYyNCAyNC4wNDI4IDIzLjg4ODlDMjQuNTU1NiAyMy42MzI1IDI0Ljk4MjkgMjMuMjczNSAyNS4zMjQ4IDIyLjgyOTFWMjQuMDc2OUgyN1YxOC40MzU5QzI3IDE3LjM1OSAyNi43MjY1IDE2LjUzODUgMjYuMTk2NiAxNS45NzQ0QzI1LjU4MTIgMTUuMzI0OCAyNC42MjQgMTUgMjMuMzI0OCAxNUMyMi4yMzA4IDE1IDIxLjM0MTkgMTUuMTg4IDIwLjY5MjMgMTUuNTk4M0MyMC4yMTMzIDE1Ljg4MTMgMTkuODQ1MyAxNi4yNzUzIDE5LjU5MjUgMTYuNzcxNEwxOS44NTI0IDE3Ljc2NzZMMjEuMDY4NCAxNy44NzE4QzIxLjE3MSAxNy4zNzYxIDIxLjQyNzQgMTcuMDE3MSAyMS44Mzc2IDE2Ljc3NzhDMjIuMTc5NSAxNi41NzI2IDIyLjY0MSAxNi40NzAxIDIzLjIwNTIgMTYuNDcwMUMyNC41Mzg1IDE2LjQ3MDEgMjUuMjA1MiAxNy4wODU1IDI1LjIwNTIgMTguMzE2MlYxOC42NzUyTDIzLjIyMjIgMTguNzI2NUMyMS45ODk2IDE4Ljc1ODkgMjEuMDAzMSAxOC45OTE0IDIwLjI5MjEgMTkuNDUzMkwyMC44NjU2IDIxLjY1MTdDMjAuOTE1MSAyMC42MjI1IDIxLjczNTMgMjAuMDc1OSAyMy4zNDE5IDIwLjA0MjdMMjUuMjA1MiAxOS45OTE1VjIwLjUwNDNDMjUuMjA1MiAyMS4xODggMjQuOTE0NiAyMS43NjkyIDI0LjM2NzUgMjIuMjMwOEMyMy44MjA1IDIyLjY5MjMgMjMuMTcxIDIyLjkzMTYgMjIuNDAxNyAyMi45MzE2QzIxLjk0MDIgMjIuOTMxNiAyMS41NjQxIDIyLjgxMiAyMS4yOTA2IDIyLjU4OTdDMjEuMTkxNCAyMi41MTM5IDIxLjExMDIgMjIuNDMyMSAyMS4wNDYxIDIyLjM0MzZMMjEuNTU1OCAyNC4yOTcyWiIgZmlsbD0id2hpdGUiLz4KPHBhdGggZmlsbC1ydWxlPSJldmVub2RkIiBjbGlwLXJ1bGU9ImV2ZW5vZGQiIGQ9Ik0xNS4yMTc0IDI2TDE2IDI5TDI2IDI5QzI4LjIwOTIgMjkgMzAgMjcuMjA5MSAzMCAyNUwzMCAxMEMzMCA3Ljc5MDg2IDI4LjIwOTIgNiAyNiA2SDE2Ljc4MjZMMTcuMzA0NCA4TDI2IDhDMjcuMTA0NiA4IDI4IDguODk1NDMgMjggMTBMMjggMjVDMjggMjYuMTA0NiAyNy4xMDQ2IDI3IDI2IDI3TDE3LjU0NTIgMjdMMTcuMjg0MyAyNkgxNS4yMTc0WiIgZmlsbD0id2hpdGUiLz4KPHBhdGggZmlsbC1ydWxlPSJldmVub2RkIiBjbGlwLXJ1bGU9ImV2ZW5vZGQiIGQ9Ik0xNC40NTQ4IDVINkM0Ljg5NTQzIDUgNCA1Ljg5NTQzIDQgN1YyMkM0IDIzLjEwNDYgNC44OTU0MyAyNCA2IDI0SDE5LjQxMTNMMTQuNDU0OCA1Wk0xNiAzSDZDMy43OTA4NiAzIDIgNC43OTA4NiAyIDdWMjJDMiAyNC4yMDkxIDMuNzkwODYgMjYgNiAyNkgyMkwxNiAzWiIgZmlsbD0id2hpdGUiLz4KPHBhdGggZmlsbC1ydWxlPSJldmVub2RkIiBjbGlwLXJ1bGU9ImV2ZW5vZGQiIGQ9Ik0xMS4wMTYzIDEwLjA5ODdDMTAuNzMyOCAxMC4xNjUyIDEwLjQyMjUgMTAuMDg3OSAxMC4yMDE1IDkuODY2ODlMOC4zNTU1OSA4LjAyMTAxQzguMDE1NzcgNy42ODExOSA4LjAxNTc3IDcuMTMwMjQgOC4zNTU1OSA2Ljc5MDQyQzguNjk1NDEgNi40NTA2MSA5LjI0NjM2IDYuNDUwNjEgOS41ODYxOCA2Ljc5MDQyTDEwLjgxNjggOC4wMjEwMkwxMi4wNDc0IDYuNzkwNDFDMTIuMzg3MiA2LjQ1MDYgMTIuOTM4MiA2LjQ1MDYgMTMuMjc4IDYuNzkwNDFDMTMuNjE3OCA3LjEzMDIzIDEzLjYxNzggNy42ODExOCAxMy4yNzggOC4wMjFMMTEuNDMyMSA5Ljg2Njg4QzExLjMxMzMgOS45ODU2OSAxMS4xNjg3IDEwLjA2MyAxMS4wMTYzIDEwLjA5ODdaIiBmaWxsPSJ3aGl0ZSIvPgo8cGF0aCBkPSJNMTAuODc2OCAxMS45NzE5QzEyLjE3NTkgMTEuOTcxOSAxMy4xMzMyIDEyLjI5NjYgMTMuNzQ4NiAxMi45NDYyQzE0LjI3ODUgMTMuNTEwMyAxNC41NTIgMTQuMzMwOCAxNC41NTIgMTUuNDA3OFYyMS4wNDg4SDEyLjg3NjhWMTkuODAwOUMxMi41MzQ5IDIwLjI0NTQgMTIuMTA3NiAyMC42MDQzIDExLjU5NDcgMjAuODYwOEMxMS4wMTM1IDIxLjEzNDMgMTAuMzI5OCAyMS4yODgxIDkuNTQzNDUgMjEuMjg4MUM4LjYyMDM4IDIxLjI4ODEgNy45MDI0MyAyMS4wNDg4IDcuMzg5NjEgMjAuNTg3MkM2LjgyNTUxIDIwLjEyNTcgNi41NTIgMTkuNTI3NCA2LjU1MiAxOC43OTI0QzYuNTUyIDE3LjgwMDkgNi45NDUxNiAxNy4wMzE3IDcuNzMxNDkgMTYuNTAxOEM4LjQ0OTQ0IDE1Ljk4OSA5LjQ3NTA4IDE1LjczMjUgMTAuNzc0MiAxNS42OTg0TDEyLjc1NzEgMTUuNjQ3MVYxNS4yODgxQzEyLjc1NzEgMTQuMDU3MyAxMi4wOTA1IDEzLjQ0MTkgMTAuNzU3MSAxMy40NDE5QzEwLjE5MyAxMy40NDE5IDkuNzMxNDkgMTMuNTQ0NSA5LjM4OTYxIDEzLjc0OTZDOC45NzkzNSAxMy45ODkgOC43MjI5NCAxNC4zNDc5IDguNjIwMzggMTQuODQzN0w2LjgyNTUxIDE0LjY4OThDNy4wMTM1NCAxMy43MzI1IDcuNDkyMTcgMTMuMDE0NiA4LjI0NDMxIDEyLjU3MDJDOC44OTM4OCAxMi4xNTk5IDkuNzgyNzcgMTEuOTcxOSAxMC44NzY4IDExLjk3MTlaTTEyLjc1NzEgMTYuOTYzM0wxMC44OTM5IDE3LjAxNDZDOS4yMzU3NiAxNy4wNDg4IDguNDE1MjUgMTcuNjMgOC40MTUyNSAxOC43MjRDOC40MTUyNSAxOS4wNjU5IDguNTUyIDE5LjMzOTQgOC44NDI2IDE5LjU2MTZDOS4xMTYxIDE5Ljc4MzggOS40OTIxNyAxOS45MDM1IDkuOTUzNzEgMTkuOTAzNUMxMC43MjI5IDE5LjkwMzUgMTEuMzcyNSAxOS42NjQyIDExLjkxOTUgMTkuMjAyNkMxMi40NjY1IDE4Ljc0MTEgMTIuNzU3MSAxOC4xNTk5IDEyLjc1NzEgMTcuNDc2MVYxNi45NjMzWiIgZmlsbD0id2hpdGUiLz4KPC9zdmc+Cg==);
}
}
}
}
}
小程序H5页面使用富文本quill
最新推荐文章于 2024-04-16 14:30:40 发布