目的
SlackやTeamsのように記入欄に画像をペーストし表示するのを目的としています。
ペーストした瞬間にDBに送りそのURLを取得して画像を表示するのではなく、ペーストした画像からデータを取得し表示します。
ただSlack、Teams、Qiitaはペーストした瞬間にDBに送ってるみたいです。
方法
React, Material UIを使っています。
index.tsx
import * as React from 'react';
import TextField from '@mui/material/TextField';
import { Button, Stack } from '@mui/material';
import ImageList from '@mui/material/ImageList';
import ImageListItem from '@mui/material/ImageListItem';
import ImageListItemBar from '@mui/material/ImageListItemBar'
import IconButton from '@mui/material/IconButton';
import Box from '@mui/material/Box';
import DeleteIcon from '@mui/icons-material/Delete';
type imageDataType = {
src:string;
imageFile:File;
}
export default function TextFieldImg() {
const [newPostValue, setNewPostValue] = React.useState('');
const [imageData, setImageData] = React.useState<imageDataType[]>([])
const handleChange = (event: React.ChangeEvent<HTMLInputElement>) => {
setNewPostValue(event.target.value);
};
const handlePasteImage = async(event: React.ClipboardEvent<HTMLDivElement>) => {
const isImage = event.clipboardData.items[0].type.indexOf("image") != -1
if(isImage){
const imageFile = event.clipboardData.items[0].getAsFile()
if(imageFile!==null){
const URLObj = window.URL || window.webkitURL
const imgSrc = URLObj.createObjectURL(imageFile)
setImageData([...imageData, {
src:imgSrc,
imageFile
}])
}
}
}
const handleClickDeleteImg = (imgSrc:string) => () => {
setImageData(imageData.filter(img=>img.src !== imgSrc))
}
return (
<>
<TextField
sx={{margin:8,width:490}}
multiline
rows={8}
onChange={handleChange}
onPaste={handlePasteImage}
/>
<Box>
<ImageList cols={3} gap={8}>
{imageData.map((item) =>
<ImageListItem key={item.src}>
<img src={item.src}/>
<ImageListItemBar
position="below"
actionIcon={
<IconButton onClick={handleClickDeleteImg(item.src)}>
<DeleteIcon />
</IconButton>
}
/>
</ImageListItem>
)}
</ImageList>
</Box>
<Stack direction="row" spacing={2}>
<Button variant="contained">Post</Button>
</Stack>
</>
);
}
ブラウザーの互換性
Chrome, Edge, FireFoxは確認済み
ClipboardEvent.clipboardData
がすべて対応してるみたいなので大体動くと思います。
環境
React v16.9.0
node v12.22.1
MUI(旧Material UI) v5.5.1
参考