基于Draftjs实现的Electron富文本聊天输入框(二)|基于Draftjs实现的Electron富文本聊天输入框(二) —— 图文输入
图文
显示
- 以Entity的格式添加图片:
// 通过新建一个Entity,插入图片 appendImage(image) { const {editorState} = this.state; const contentState = editorState.getCurrentContent(); const imageSrc = https://www.it610.com/article/image.data || image.file.path; // AtomicBlockUtils插入图片 const contentStateWithEntity = contentState.createEntity('image', 'IMMUTABLE', {src: imageSrc, image}, ); const entityKey = contentStateWithEntity.getLastCreatedEntityKey(); const newEditorState = EditorState.set( editorState, {currentContent: contentStateWithEntity} ); const newEditorStateWithAtomic = AtomicBlockUtils.insertAtomicBlock(newEditorState, entityKey, ' '); this.setState({ editorState: newEditorStateWithAtomic, }); }
通过AtomicBlockUtil
创建的entity有一些问题:当前为空行时,图片会自动插入下一行; focus、删除等操作不是很正常;
- 通过
blockRenderFn
属性传入自定义的图片组件
// 自定义block样式 blockRendererFn(contentBlock) { const type = contentBlock.getType(); let result = null; if (type === 'atomic') { result = { component: DraftImage, editable: false, }; } return result; }
对contentBlock类型为atomic
指定了自定义组件DraftImage
- 在
image.onload()
方法中获取图片原尺寸,根据输入框大小限定显示的图片尺寸
import React from 'react'; import cs from 'classnames'; export default class DraftImage extends React.Component { constructor(props) { super(props); this.state = { src: '', isActive: false, }; }componentDidMount() { this.setImageSrc(this.props); }componentWillReceiveProps(nextProps) { this.setImageSrc(nextProps); }setImageSrc(props) { const {block, contentState} = props; const key = block.getEntityAt(0); if (!key) { return ''; } const entity = contentState.getEntity(key); if (entity && entity.getType() === 'image') { const data = https://www.it610.com/article/entity.getData(); const image = new Image(); const imgSrc = data.src; image.onload = () => { const size = this.getImageSize(image); this.setState({ src: imgSrc, width: size.width + 'px', height: size.height + 'px', }); }; image.src = https://www.it610.com/article/imgSrc; } }handleClick(e) { e.stopPropagation(); this.setState({ isActive: !this.state.isActive, }); }// 根据输入框宽高限制图片 getImageSize(image) { const origWidth = image.width; const origHeight = image.height; const editorWrapperRect = document.getElementsByClassName('chat-draft-editor')[0].getBoundingClientRect(); const maxWidth = editorWrapperRect.width - 10; const maxHeight = editorWrapperRect.height - 10; let newWidth = ''; let newHeight = ''; let ratio = 1; if (origHeight <= maxHeight && origWidth <= maxWidth) { newHeight = origHeight; newWidth = origWidth; } if (origHeight <= maxHeight && origWidth > maxWidth) { ratio = origWidth / maxWidth; newHeight = origHeight / ratio; newWidth = maxWidth; } if (origHeight > maxHeight) { ratio = origHeight / maxHeight; newWidth = origWidth / ratio; newHeight = maxHeight; } return {width: newWidth, height: newHeight}; }render() { const imgCls = cs({ 'draft-editor-image': true, 'img-active': this.state.isActive, }); if (this.state.src !== '' ) { return ( ); } else { return null; } } }
- 通过监听
onPastedFiles(files)
方法处理粘贴的文件
handlePastedFiles(files) { files.forEach((blob) => { if (blob.type.startsWith('image/')) { const image = clipboard.readImage(); const url = image.isEmpty()? '': image.toDataURL(); this.appendImage({ data: url, }); } }); return 'handled'; }
Draftjs这个方法提供的files
对象数据不够,只用来判断type是否为图片,读取数据仍使用的clipboard
;
- 消息发送后,需要将文本框置空
【基于Draftjs实现的Electron富文本聊天输入框(二)|基于Draftjs实现的Electron富文本聊天输入框(二) —— 图文输入】这里有个bug,清空输入框文本时,不能立即Focus,否则内容不会被清空
- 为保证图文消息的发送顺序与输入框编辑时一致,对数组遍历时,设置固定延时:
推荐阅读
- 基于微信小程序带后端ssm接口小区物业管理平台设计
- 关于QueryWrapper|关于QueryWrapper,实现MybatisPlus多表关联查询方式
- MybatisPlus使用queryWrapper如何实现复杂查询
- python学习之|python学习之 实现QQ自动发送消息
- 基于|基于 antd 风格的 element-table + pagination 的二次封装
- 孩子不是实现父母欲望的工具——林哈夫
- opencv|opencv C++模板匹配的简单实现
- Node.js中readline模块实现终端输入
- java中如何实现重建二叉树
- 基于爱,才会有“愿望”当“要求”。2017.8.12