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

Preface

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

问题原因

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

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

解决问题

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

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

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

.input {
	user-select: none;
}

效果:
请添加图片描述

源代码

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

<head>
  <meta http-equiv="Content-Type" content="text/html;charset=UTF-8">
  <title>Document</title>
  <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>
	<!-- tabindex: 让元素可聚焦, 拥有focus方法、可用tab切换焦点; -->
  <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 += `<span class="emoji" data-type="EMOJI" style="cursor: pointer">${emoji}</span>`
	    ul.innerHTML += `<div data-type="EMOJI" data-url="${url}" style="display: inline-block;width: 22px; height: 22px; background: url(${url}) no-repeat center / 18px;cursor: pointer;"></div>`
	  })
	  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>

svg 表情

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

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

在这里插入图片描述

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

之前一直不知道 xxNS 的作用, 这下知道用途了
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)
}
  • 0
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值