• JavaScript聊天框插入表情: 点击表情时输入框失焦, 无法插入到输入框.


    Preface

    最近在尝试做一个聊天框,但是在我做表情插入的时候被一个问题卡住了。
    表情是使用的 img 标签;
    本次最大问题就是: 点击表情时输入框失焦, 无法插入到输入框.

    问题原因

    当点击表情的时候, 输入框失去焦点, 聚焦到点击的标清处或失去焦点.

    我尝试过点击的时候, 聚焦到输入框, 但是又出现了聚焦位置问题...  真是一波三折
    
    • 1

    解决问题

    一开始做的时候, 我一直有个简单的解决思路, 但是我就是没去尝试. 就去搜索各种问题和解决办法.
    最后还是妥协了
    
    • 1
    • 2

    解决思路 : 既然是因为点击表情的时候, 焦点聚焦到表情选择了, 那我就不让表情选择框不能选中. 👍🏻 还真管用了.

    给输入框加这个样式就可以解决, 如果要做兼容 记得添加属性前缀 -webkit- 等…

    .input {
    	user-select: none;
    }
    
    • 1
    • 2
    • 3

    效果:
    请添加图片描述

    源代码

    doctype html>
    <html lang="en">
    
    <head>
      <meta http-equiv="Content-Type" content="text/html;charset=UTF-8">
      <title>Documenttitle>
      <link rel="stylesheet" href="/index.css" />
      <style>
        .emoji-box {
    	  width: 300px;
    	  user-select: none;
    	}
    	.emoji-box .emoji {
    	  display: inline-block;
    	  padding: 3px;
    	}
    	._emoji {
    	  display: inline-block;
    	  width: 18px;
    	  height: 18px;
    	  margin: 0 1px;
    	  vertical-align: middle;
    	}
    	.input {
    	  border: 1px solid orange;
    	  width: 300px;
    	  height: 120px;
    	  outline: none;
    	  display: inline-block;
    	  font-size: 14px;
    	}
      style>
    head>
    
    <body>
    	
      <pre id="input" class="input" tabindex="0" contenteditable>pre>
      <script>
      	// 获取表情 url, 我这里demo使用的是固定的图片.
    	function getImgUrl() {
    	  return [
    	    '1', 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 'sun'
    	  ].map((x) => `/image/weather/${x}.png`)
    	}
    
        // 插入表情列表
    	function insertUl() {
    	  let ul = document.createElement('div')
    	  ul.className = 'emoji-box'
    	  // 也可以使用 emoji 来作为表情, 但是我觉得太单一, 所以改用了 img方式来做.
    	  // let emojis = '😀 🥹 ☺️ 😉 😗 😝 🤓 😏 😕 😫 😤 😳 😃 😅 😊 😌 😙 😜 😎 😒 😶‍🌫️ 🫥 🫢 🫢 🫣 🫣 🫠 🤔 🤫 😯 😵'.split(' ')
    	  getImgUrl().forEach((url) => {
    	    // ul.innerHTML += `${emoji}`
    	    ul.innerHTML += `
    ${url}" style="display: inline-block;width: 22px; height: 22px; background: url(${url}) no-repeat center / 18px;cursor: pointer;">
    `
    }) document.body.appendChild(ul) ul.onclick = tapUl } // 点击表情事件 function tapUl(event) { let e = event.target insertImg(e.dataset.url) } // 插入表情到输入框 function insertImg(src) { if (window.getSelection) { var sel = window.getSelection(); var range = sel.getRangeAt(0); var img = new Image(); img.className = '_emoji' range.deleteContents() img.src = src; range.insertNode(img); range.collapse(false); } }
    script> body> html>
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49
    • 50
    • 51
    • 52
    • 53
    • 54
    • 55
    • 56
    • 57
    • 58
    • 59
    • 60
    • 61
    • 62
    • 63
    • 64
    • 65
    • 66
    • 67
    • 68
    • 69
    • 70
    • 71
    • 72
    • 73
    • 74
    • 75
    • 76
    • 77
    • 78
    • 79
    • 80
    • 81

    svg 表情

    我还使用svg来测试插入表情, 存在一个大问题:

    svg 不能够选中, 光标也不能移动到svg标签后.
    
    • 1

    在这里插入图片描述

    svg标签的创建方式也比较特殊.
    以下为 ts 代码

    之前一直不知道 xxNS 的作用, 这下知道用途了
    
    • 1
    private onClickIcon(iconName: string) {
      const ns: string = "http://www.w3.org/2000/svg"
      const cNs: string = 'http://www.w3.org/1999/xlink'
    
      // NS 的第一个参数是svg的命名空间URI, svg 和 use 标签都有不同的 URI 注意区分.
      const oSvg: any = document.createElementNS(ns, 'svg')
      const use: any = document.createElementNS(ns, 'use')
      oSvg.setAttribute('style', 'width: 1em;height: 1em;') 
      oSvg.setAttribute('class', `svg-icon ${iconName}`)
    
      use.setAttributeNS(cNs, 'xlink:href', `#icon-${iconName}`)
      oSvg.appendChild(use)
    
      Insert.insertContent(oSvg)
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
  • 相关阅读:
    Metabase学习教程:系统管理-5
    HDFS-FSCK命令输出
    矢量化的步骤
    CalBioreagents超全Id 蛋白兔单克隆抗体,助力科研
    打字通小游戏制作教程:用HTML5和JavaScript提升打字速度
    电影太大怎么压缩变小?
    Windows电脑部署Jellyfin服务端并进行远程访问配置详细教程
    机器学习算法:线性回归、逻辑回归、决策树和随机森林解析
    关于Hbase使用出现java.io.IOException: java.lang.reflect.InvocationTargetException解决
    Redis哨兵模式(Docker)
  • 原文地址:https://blog.csdn.net/qq_40314318/article/details/126605887