文本框插入表情包

原生js写文本框插入表情

  1. 背景
    聊天软件要支持发送表情包

  2. 思想
    传统的textarea无法支持插入图片,所以我们应该使用可编辑的div进行操作,监听div的按键事件和点击事件,记录上一次的光标位置,插入表情是获取上次的光标位置进行插入,插入后再次记录光标位置
    <div contenteditable = "true" ></div>

  3. 实现原理–复制demo

<!DOCTYPE html>
<html lang="en">

<head>
  <meta charset="UTF-8">
  <meta http-equiv="X-UA-Compatible" content="IE=edge">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <title>Document</title>
</head>
<style>
  body {
    display: flex;
    justify-content: center;
    align-items: center;
  }

  .app {
    width: 400px;
    height: 700px;
    border: 1px solid #000;
    display: flex;
    flex-direction: column;

  }

  .app .content {
    flex: 1;
  }

  .app .input {
    height: 150px;
    border: 1px solid #000;
    margin: 4px;
    padding: 10px;
    outline: none;
  }

  .input img {
    width: 20px;
    height: 20px;
  }

  .left {
    width: 400px;
    height: 400px;
    position: fixed;
    left: 20px;
    border: 1px solid #000;
    right: 100px;
  }

  .left img {
    width: 40px;
    height: 40px;
    cursor: pointer;
  }
</style>

<body>

  <div class="app">
    <div class="content"></div>
    <div>
      <button>表情</button>
      <button>字体</button>
    </div>
    <div class="input" id="input" contenteditable="true">
    </div>
  </div>
  <div class="left" id="left">
    <img src="https://img-blog.csdnimg.cn/69ffefde15a545ef80d586bfe9a35223.gif#pic_center" alt="">
    <img src="https://img-blog.csdnimg.cn/e4c25b7128c148e5ad254eda4a929262.gif#pic_center)" alt="">
    <img src="https://img-blog.csdnimg.cn/375fa86b0cd24e4a8e1140d6d0c08e03.gif#pic_center" alt="">
    <img src="https://img-blog.csdnimg.cn/4bea28810e934c7da4f6923a29abe26b.gif#pic_center" alt="">
  </div>
</body>

</html>
<script>
  var lastEditRange;
  const div = document.getElementById('input')
  const left = document.getElementById('left')
  // 编辑框点击事件
  div.onclick = (e) => {
    const childNodes = Array.from(div.childNodes)
    // // // 获取选定对象
    const selection = getSelection()
    const {
      focusNode
    } = selection
    // 点击图片
    if (!e.target.innerHTML) {
      selection.removeAllRanges()
      const index = childNodes.findIndex((v) => v === e.target)
      selection.collapse(div, index === -1 ? childNodes.length : index)
    }
    lastEditRange = selection.getRangeAt(0)
  }
  div.onkeyup = () => {
    // 获取选定对象
    var selection = getSelection()
    // 设置最后光标对象
    lastEditRange = selection.getRangeAt(0)
  }
  left.onclick = (e) => {
    // var edit = document.getElementById('edit')
    // // 获取输入框对象
    // var emojiInput = document.getElementById('emojiInput')
    // div.focus()
    const childNodes = Array.from(div.childNodes)
    var selection = getSelection()
    selection.removeAllRanges()
    selection.addRange(lastEditRange)
    // div.innerHTML += `<img src="${e.target.src}" />`
    var range = selection.getRangeAt(0)
    // 获取光标位置
    var rangeStartOffset = range.startOffset;
    var img = document.createElement('img')
    img.src = e.target.src
    // 判断选定对象范围是编辑框还是文本节点
    if (selection.anchorNode.nodeName != '#text') {
      if (div.childNodes.length > 0) {
        // 如果文本框的子元素大于0,则表示有其他元素,则按照位置插入表情节点
        for (var i = 0; i < div.childNodes.length; i++) {
          if (i == selection.anchorOffset) {
            div.insertBefore(img, div.childNodes[i])
          }
        }
      } else {
        // 否则直接插入一个表情元素
        div.appendChild(img)
      }
      // 创建新的光标对象
      var range = document.createRange()
      // 光标对象的范围界定为新建的表情节点
      range.selectNodeContents(img)
      // 光标位置定位在表情节点的最大长度
      range.setStart(div, Array.from(div.childNodes).findIndex(v => v === img) + 1)
      // 使光标开始和光标结束重叠
      range.collapse(true)
      // 清除选定对象的所有光标对象
      selection.removeAllRanges()
      // 插入新的光标对象
      selection.addRange(range)
    } else {
      // 如果是文本节点则先获取光标对象
      // 获取光标对象的范围界定对象,一般就是textNode对象
      var textNode = range.startContainer;
      // 获取光标位置
      const { textContent } = textNode
      // 分割开始值
      const startStr = textContent.substr(0, rangeStartOffset)
      // 分割结束值
      const endStr = textContent.substr(rangeStartOffset)
      // 当前节点的索引
      const index = childNodes.findIndex(v => v === textNode)
      // 移除当前文本节点
      const startStrNode = document.createTextNode(startStr)
      const endStrNode = document.createTextNode(endStr)

      div.removeChild(textNode)
      if (index === childNodes.length - 1) {
        // 最后一个节点处理
        div.appendChild(startStrNode)
        div.appendChild(img)
        div.appendChild(endStrNode)
        selection.collapse(div, index + 2)
      } else {
        // 不是最后一个
        div.insertBefore(startStrNode, childNodes[index + 1])
        div.insertBefore(img, childNodes[index + 1])
        div.insertBefore(endStrNode, childNodes[index + 1])
        selection.collapse(div, Array.from(div.childNodes).findIndex(v => v === img) + 1)
      }
   
      // 光标开始和光标结束重叠
      range.collapse(true)
      // // 清除选定对象的所有光标对象
      // selection.removeAllRanges()
      // // 插入新的光标对象
      selection.addRange(range)

    }
    // 无论如何都要记录最后光标对象
    lastEditRange = selection.getRangeAt(0)
  }
</script>

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
快去试一试看看效果吧

  • 11
    点赞
  • 12
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
以下是一个使用 C++ 和 VBA 代码将数学公式插入 PowerPoint 文本框的示例: ``` #include <windows.h> #include <ole2.h> #include <atlbase.h> #include <comutil.h> #include <cstdio> #pragma comment(lib, "ole32.lib") #pragma comment(lib, "comsuppw.lib") int main() { HRESULT hr = CoInitialize(NULL); if (FAILED(hr)) { printf("Failed to initialize COM library\n"); return 1; } hr = CoCreateInstance(CLSID_PowerPointApplication, NULL, CLSCTX_LOCAL_SERVER, IID_IDispatch, (void**)&app); if (FAILED(hr)) { printf("Failed to create PowerPoint application instance\n"); CoUninitialize(); return 1; } // 打开一个演示文稿 IDispatch* pres = NULL; _variant_t vtName("C:\\example.pptx"); hr = app->Presentations->Open(vtName, VARIANT_FALSE, VARIANT_FALSE, VARIANT_FALSE, &pres); if (FAILED(hr)) { printf("Failed to open presentation\n"); app->Release(); CoUninitialize(); return 1; } // 在幻灯片上插入一个文本框 IDispatch* slide = NULL; hr = pres->Slides->Item(1, &slide); if (FAILED(hr)) { printf("Failed to get slide\n"); pres->Close(); app->Release(); CoUninitialize(); return 1; } IDispatch* txtBox = NULL; hr = slide->Shapes->AddTextbox(msoTextOrientationHorizontal, 100, 100, 400, 100, &txtBox); if (FAILED(hr)) { printf("Failed to add text box\n"); slide->Release(); pres->Close(); app->Release(); CoUninitialize(); return 1; } // 将数学公式插入文本框 _bstr_t formula(L"y = mx + b"); // 更改此处的公式 IDispatch* txtRange = NULL; hr = txtBox->GetItem(_variant_t(2), &txtRange); if (FAILED(hr)) { printf("Failed to get text range\n"); txtBox->Release(); slide->Release(); pres->Close(); app->Release(); CoUninitialize(); return 1; } hr = txtRange->CallMethod(DISPID_VALUE, NULL, 1, &formula); if (FAILED(hr)) { printf("Failed to insert formula\n"); txtRange->Release(); txtBox->Release(); slide->Release(); pres->Close(); app->Release(); CoUninitialize(); return 1; } // 保存并关闭演示文稿 pres->Save(); pres->Close(); // 释放 COM 对象 txtRange->Release(); txtBox->Release(); slide->Release(); pres->Release(); app->Release(); CoUninitialize(); return 0; } ``` 这是一个使用 C++ 和 VBA 代码向 PowerPoint 文本框插入数学公式的简单示例。它使用 PowerPoint 对象模型和 VBA 代码来打开演示文稿、插入文本框插入数学公式并保存演示文稿。请注意,您需要将代码的公式更改为您要插入的实际公式。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值