赞
踩
- 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==);
- }
- }
- }
- }
- }
-
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。