可编辑div粘贴图片的案例分享

html文件

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>聊天框</title>
    <style>
        body,
        html {
            text-align: center;
        }

        #editDiv {
            width: 600px;
            display: inline-block;
            min-height: 100px;
            background: #fff;
            border-radius: 10px;
            line-height: 20px;
            padding: 10px;
            font-size: 14px;
            color: #666;
            resize: none;
            outline: none;
            overflow-y: auto;
        }

        #editDiv {
            border: 1px solid #333;
            border-color: rgba(169, 169, 169, 1);
            text-align: left;
        }

        /* 隐藏 Chrome、Safari 和 Opera 的滚动条 */
        #editDiv::-webkit-scrollbar {
            display: none;
        }

        /* 隐藏 IE、Edge 和 Firefox 的滚动条 */
        #editDiv {
            -ms-overflow-style: none;
            /* IE and Edge */
            scrollbar-width: none;
            /* Firefox */
        }

        #msg {
            width: 1024px;
            min-height: 100px;
            overflow: hidden;
            border: 1px solid #000;
            margin: 10px auto;
        }

        p {
            border: 1px solid #666;
            background-color: #666;
            width: 50%;
            margin: 5px auto;
        }

        img {
            /* border: 1px solid #666; */
            margin: 5px auto;
        }
    </style>
    <script src="./paste.js"></script>
</head>
<body>
    <div id="editDiv" contenteditable="true"></div>
    <button onclick="send()">发送</button>
    <div id="msg"></div>

    <script>
        var edit = document.getElementById('editDiv');
        edit.focus()
        // 监听粘贴事件
        document.querySelector('#editDiv').addEventListener('paste', (e) => {
            onPaste(e).then((res) => {
                console.log(res)
            })
        }, false);

        function send() {
            // 获取输入框的内容,发送消息
            var edit = document.getElementById('editDiv');
            var msg = document.getElementById('msg');
            // 分离出图片和文字
            let children = edit.childNodes;
            if (children.length == 0) return alert("消息不能为空");

            // 为每个子元素创建一个 Promise
            let promises = [];
            let text = "";
            children.forEach(item => {
                console.log(item.nodeName)
                if (item.tagName && item.tagName.toLowerCase() === 'img') {
                    promises.push(sendImg(msg, item.src));
                } else if (item.nodeName == '#text') {
                    //promises.push(sendText(msg, item.data));
                     text += item.data
                }
            });
        if (typeof text == 'string' && text.length > 0) promises.push(sendText(msg, text));

            // 使用 Promise.all 等待所有消息发送完成
            Promise.all(promises)
                .then(() => {
                    // 清空输入框
                    edit.innerHTML = "";
                })
                .catch(error => {
                    console.error('发送消息出错:', error);
                });
        }

        function sendImg(msg, src) {
            return new Promise((resolve, reject) => {
                let img = document.createElement('img');
                img.onload = function () {
                    msg.appendChild(img);
                    resolve();
                };
                img.onerror = function () {
                    reject(new Error('图片加载失败'));
                };
                img.src = src;
            });
        }

        function sendText(msg, text) {
            return new Promise((resolve, reject) => {
                var para = document.createElement("p");
                para.innerText = text;
                msg.appendChild(para);
                resolve();
            });
        }
    </script>
</body>
</html>

paste.js代码

// 定义粘贴函数
const onPaste = (e) => {
  e.preventDefault();//拦截默认粘贴操作
  e.stopPropagation();//防止冒泡

  // var editDiv = document.getElementById('editDiv');
  var cbd = e.clipboardData;
  var ua = window.navigator.userAgent;
  // 剪贴板没数据,则直接返回
  if (!e.clipboardData || !e.clipboardData.items) {
    return;
  }
  // Mac平台下Chrome49版本以下 复制Finder中的文件的Bug Hack掉
  if (cbd.items && cbd.items.length === 2 && cbd.items[0].kind === "string" && cbd.items[1].kind === "file" &&
    cbd.types && cbd.types.length === 2 && cbd.types[0] === "text/plain" && cbd.types[1] === "Files" &&
    ua.match(/Macintosh/i) && Number(ua.match(/Chrome\/(\d{2})/i)[1]) < 49) {
    return;
  }

  return new Promise((resovle, reject) => {
    for (let i = 0; i < cbd.items.length; i++) {
      const item = cbd.items[i];
      if (item.kind === 'file') {
        const file = item.getAsFile();
        if (item.type.match('^image/')) {
          // 处理图片
          handleImage(file, (data) => {
            resovle(data)
          })
        } else {
          // 其他文件直接返回
          resovle({
            data: file,
            type: 'file'
          })
        }
      } else if (item.kind === 'string') {
        let str = cbd.getData('text')
         // 处理文字
        handleText(str, (data) => {
          resovle(data)
        })
      } else {
        reject(new Error('不支持粘贴该类型'));
      }
    }
  })
}
// 处理图片
function handleImage(file, callback, maxWidth = 50, maxHeight = 50) {
  if (!file || !/(?:png|jpg|jpeg|gif)/i.test(file.type)) {
    callback('图片格式不支持')
    return;
  }

  const reader = new FileReader();
  reader.readAsDataURL(file);
  reader.onload = function () {
    const result = this.result;
    let img = new Image();
    img.onload = function () {
      let compressedDataUrl = compressImage(img, file.type, maxWidth, maxHeight, true);
      let url = compressImage(img, file.type, maxWidth, maxHeight, false);
      addImageToPage(compressedDataUrl);
      img = null;
      callback({
        data: file,
        compressedDataUrl,
        url,
        type: 'image'
      })
    };
    img.src = result;
  };
}
// 压缩图片函数
function compressImage(img, type, maxWidth, maxHeight, flag = true) {
  let canvas = document.createElement('canvas');
  let ctx = canvas.getContext('2d');

  // 计算压缩后的宽高比例
  let ratio = 1;
  if (flag && (img.width > maxWidth || img.height > maxHeight)) {
    ratio = Math.min(maxWidth / img.width, maxHeight / img.height);
  }

  // 设置canvas的宽高
  canvas.width = img.width * ratio;
  canvas.height = img.height * ratio;

  // 绘制图片到canvas
  // ctx.fillStyle = '#fff';
  // ctx.fillRect(0, 0, canvas.width, canvas.height);
  ctx.drawImage(img, 0, 0, canvas.width, canvas.height);

  // 将canvas转换为base64格式的图片数据
  let base64Data = canvas.toDataURL(type, 0.75);

  if (type === 'image/gif') {
    let regx = /(?<=data:image).*?(?=;base64)/; // 正则表示时在用于replace时,根据浏览器的不同,有的需要为字符串
    base64Data = base64Data.replace(regx, '/gif');
  }
  canvas = null;
  ctx = null;
  return base64Data;
}
//粘贴压缩后的图片到输入框
function addImageToPage(dataUrl) {
  let img = document.createElement('img');
  img.src = dataUrl;
  insertHtmlAtCaret(img)
}
// 粘贴文字
function handleText(str, callback) {
  let textNode = document.createTextNode(str)
  insertHtmlAtCaret(textNode)
  callback({
    data: str,
    type: 'string'
  })
}

/**
 * 
 * @param {*} textNode 插入的node
 */
function insertHtmlAtCaret(textNode) {
  let sel, range;
  if (window.getSelection) {
    // IE9 and non-IE
    sel = window.getSelection();
    if (sel.getRangeAt && sel.rangeCount) {
      range = sel.getRangeAt(0);
      range.deleteContents();

      let frag = document.createDocumentFragment();
      let lastNode = frag.appendChild(textNode);
      range.insertNode(frag);

      if (lastNode) {
        range = range.cloneRange();
        range.setStartAfter(lastNode);
        range.collapse(true);
        sel.removeAllRanges();
        sel.addRange(range);
      }
    }
  } else if (document.selection && document.selection.type != "Control") {
    // IE < 9
    document.selection.createRange().pasteHTML(textNode);
  }
}

支持粘贴图片和文字,粘贴后,光标默认到末尾。点击发送,会将图片文字新增到id为msg的div并清空输入框。案例已调试好,可以根据自己的需求更改

--5.7--

优化:在中间插入内容时,文字应该粘贴到光标位置,光标移到粘贴文本末尾

  • 4
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

DytLisa

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值