3
0

More than 1 year has passed since last update.

input(TextField)内にペーストした画像を表示する方法 (React, MUI(旧Material UI))

Last updated at Posted at 2022-03-28

目的

SlackやTeamsのように記入欄に画像をペーストし表示するのを目的としています。
ペーストした瞬間にDBに送りそのURLを取得して画像を表示するのではなく、ペーストした画像からデータを取得し表示します。
ただSlack、Teams、Qiitaはペーストした瞬間にDBに送ってるみたいです。

image.png

方法

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

参考

3
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
3
0