React工程写一个HTML富文本编辑器,顺带上传图片功能。基于react-draft-wysiwyg、draftjs、antd使用

公司项目要求要写一个富文本编辑器,好像之前一直都没有写过这个稀奇古怪的东西。不多说看方法!
使用npm安装 :react-draft-wysiwyg、draftjs-to-html、antd;
安装好了之后,我的组件是这样写的;
ps:{
react-draft-wysiwyg : 是开元的,
GitHub地址 : https://github.com/jpuri/react-draft-wysiwyg
API文档地址 : https://jpuri.github.io/react-draft-wysiwyg/#/docs
}

import React from "react";
import {Button,Card,Modal} from 'antd';
import {Editor} from 'react-draft-wysiwyg';
import 'react-draft-wysiwyg/dist/react-draft-wysiwyg.css';
import draftjs from 'draftjs-to-html';

export class RichText extends React.Component{
    constructor(props) {
        super(props);
        this.state = {
            ...props,
            editorState: '',
        };
    }
    
    onEditorStateChange = (editorState) => {
        this.setState({
            editorState
        });
    };

    imageUploadCallBack = file => new Promise(
        (resolve, reject) => {
            let reader = new FileReader();
            reader.readAsDataURL(file);
            let img = new Image();
            // let url = ''
            reader.onload = function (e) {
                img.src = this.result
            };

            img.onload = function () {
                //console.log(img); // 获取图片
                // console.log(img.src.length)
                // 缩放图片需要的canvas(也可以在DOM中直接定义canvas标签,这样就能把压缩完的图片不转base64也能直接显示出来)
                let canvas = document.createElement('canvas');
                let context = canvas.getContext('2d');

                // 图片原始尺寸
                let originWidth = this.width;
                let originHeight = this.height;

                // 最大尺寸限制,可通过设置宽高来实现图片压缩程度
                let maxWidth = 400,
                    maxHeight = 500;
                // 目标尺寸
                let targetWidth = originWidth,
                    targetHeight = originHeight;
                // 图片尺寸超过300x300的限制
                if(originWidth > maxWidth || originHeight > maxHeight) {
                    if(originWidth / originHeight > maxWidth / maxHeight) {
                        // 更宽,按照宽度限定尺寸
                        targetWidth = maxWidth;
                        targetHeight = Math.round(maxWidth * (originHeight / originWidth));
                    } else {
                        targetHeight = maxHeight;
                        targetWidth = Math.round(maxHeight * (originWidth / originHeight));
                    }
                }
                // canvas对图片进行缩放
                canvas.width = targetWidth;
                canvas.height = targetHeight;
                // 清除画布
                context.clearRect(0, 0, targetWidth, targetHeight);
                // 图片压缩
                context.drawImage(img, 0, 0, targetWidth, targetHeight);
                /*第一个参数是创建的img对象;第二三个参数是左上角坐标,后面两个是画布区域宽高*/

                //压缩后的图片转base64 url
                /*canvas.toDataURL(mimeType, qualityArgument),mimeType 默认值是'image/png';
                  * qualityArgument表示导出的图片质量,只有导出为jpeg和webp格式的时候此参数才有效,默认值是0.92*/
                let newUrl = canvas.toDataURL('image/jpeg', 0.92);//base64 格式

                resolve({
                    data: {
                        link: newUrl
                    }
                })

                //也可以把压缩后的图片转blob格式用于上传
                // canvas.toBlob((blob)=>{
                //     console.log(blob)
                //     //把blob作为参数传给后端
                // }, 'image/jpeg', 0.92)
            }
        }
    );

    render(){
        const { editorContent, editorState } = this.state;
        return (
            <div style={{marginBottom:'20px'}}>
                <Card title="富文本编辑器">
                    <Editor
                        editorState={editorState}
                        toolbarClassName="home-toolbar"
                        wrapperClassName="home-wrapper"
                        editorClassName="home-editor"
                        onEditorStateChange={this.onEditorStateChange}
                        toolbar={{ //Editor富文本组件功能控制
                            history: { inDropdown: true },
                            inline: { inDropdown: false },
                            list: { inDropdown: true },
                            textAlign: { inDropdown: true },
                            image: {
                                urlEnabled: true,
                                uploadEnabled: true,
                                alignmentEnabled: true,   // 是否显示排列按钮 相当于text-align
                                uploadCallback: this.imageUploadCallBack,  //图片的处理 (但是仅限于本地上传的,url方式不经过此函数)
                                previewImage: true,
                                inputAccept: 'image/*',
                                alt: {present: false, mandatory: false}
                            }
                        }}
                        onContentStateChange={this.props.onEditorChange.bind(this)}//引用父组件的函数
                        placeholder="请输文章内容" //输入框中默认内容
                        spellCheck
                        localization={{ locale: 'zh', translations: { 'generic.add': '添加' } }}
                    />
                </Card>
            </div>
        );
    }
}

//使用组件  ==>子组件中要找到父组件onEditorChange函数,直接将这个函数写在子组件中也可以,根据个人需要自行修改
export default class extends React.Component{
    constructor(props) {
        super(props);
        this.state = {
            editorContent: '',
        };
    }

    onEditorChange = (editorContent) => {
        console.log('父组件' + draftjs(editorContent)); //实时根据输入进行更新
        //editorContent = '<html lang="en"><head><meta charset="UTF-8"><title></title></head><body>' + draftjs(editorContent) + '</body></html>'
        this.setState({
            editorContent,
        });
    };//获取html富文本

    render() {
        let {editorContent} = this.state;
        //传递给子组件的函数
        return <RichText onEditorChange={this.onEditorChange.bind(this)} editorContent={editorContent}/>
    }
}

猜你喜欢

转载自blog.csdn.net/qq_40524880/article/details/85272926