index.vue 5.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254
  1. <template>
  2. <div v-clickoutside="clickoutside">
  3. <div class="biaoqingContent" @click.stop>
  4. <img class="expression" @click.stop="show = !show" src="./expression.png" />
  5. <!-- 表情选择框-->
  6. <div class="box" v-if="show" @click.stop>
  7. <div class="left">
  8. <ul>
  9. <li v-for="(item, index) in biaoqingList" :key="index" :class="['cursor', biaoqingActive === index ? 'active' : '']">
  10. <div @click="bqNameChange(index, item.iconArr)">
  11. {{ item.name }}
  12. </div>
  13. </li>
  14. </ul>
  15. </div>
  16. <div class="right">
  17. <button v-for="(i, index) in rightList" :key="index" class="emoji" @click.stop="insertHtmlAtCaret(i.icon)">
  18. <span>{{ i.icon }}</span>
  19. </button>
  20. </div>
  21. </div>
  22. </div>
  23. </div>
  24. </template>
  25. <script>
  26. // 定义最后光标对象
  27. import { biaoqingArr } from "./biaoqing.js";
  28. export default {
  29. props: {
  30. //表情框宽度
  31. width: {
  32. type: String,
  33. default: "50%",
  34. },
  35. //表情框高度
  36. height: {
  37. type: String,
  38. default: "200px",
  39. },
  40. //表情框ID
  41. id: {
  42. type: String,
  43. default: "text",
  44. },
  45. //内容
  46. value: {
  47. type: String,
  48. default: "",
  49. },
  50. },
  51. data() {
  52. return {
  53. lastEditRange: "",
  54. content: "",
  55. show: false,
  56. biaoqingList: biaoqingArr,
  57. biaoqingActive: 0,
  58. rightList: [],
  59. allList: [],
  60. };
  61. },
  62. watch: {
  63. value() {
  64. this.valueChange();
  65. },
  66. },
  67. methods: {
  68. clickoutside() {
  69. console.log("clickoutside", 111111);
  70. this.show = false;
  71. },
  72. valueChange() {
  73. if (!this.value) return;
  74. let str = this.value;
  75. let newStr = this.forArr(this.forArr(str), "className");
  76. document.getElementById(this.id).innerHTML = newStr;
  77. },
  78. //替换emoji 表情图片
  79. forArr(str, _type) {
  80. for (let j = 0; j < this.allList.length; j++) {
  81. let val = this.allList[j];
  82. let reg = _type === "className" ? `alt${val.className}` : val.icon;
  83. if (_type === "className") {
  84. str = str.replace(new RegExp(reg, "g"), val.icon);
  85. } else {
  86. str = str.replace(
  87. new RegExp(reg, "g"),
  88. `<img style="vertical-align: sub;" src="http://tkeasyemoji.oss-cn-shanghai.aliyuncs.com/images/placeholder.png" class="${val.className}" alt="alt${val.className}">`
  89. );
  90. }
  91. }
  92. return str;
  93. },
  94. // 表情title点击事件
  95. bqNameChange(index, arr) {
  96. this.biaoqingActive = index;
  97. this.rightList = arr;
  98. },
  99. contentClick() {
  100. // 获取选定对象
  101. var selection = getSelection();
  102. // 设置最后光标对象
  103. this.lastEditRange = selection.getRangeAt(0);
  104. },
  105. //表情插入文本框
  106. insertHtmlAtCaret(icon) {
  107. this.$emit("select", icon);
  108. },
  109. },
  110. created() {
  111. this.rightList = biaoqingArr[0].iconArr;
  112. biaoqingArr.forEach((e) => {
  113. this.allList = this.allList.concat(e.iconArr);
  114. });
  115. },
  116. mounted() {
  117. this.valueChange();
  118. window.addEventListener("message", (res) => {
  119. if (Object.prototype.toString.call(res.data) == "[object Object]") {
  120. if (res.data.source === "clickScene") {
  121. if (this.show) {
  122. this.show = false;
  123. }
  124. }
  125. }
  126. });
  127. },
  128. components: {},
  129. };
  130. </script>
  131. <style>
  132. @import "./emoji_sorites.css";
  133. </style>
  134. <style lang="less" scoped>
  135. .contentBox {
  136. border: 1px solid #ccc;
  137. border-radius: 5px;
  138. padding: 10px;
  139. font-size: 16px;
  140. position: relative;
  141. }
  142. .biaoqingContent {
  143. padding: 5px;
  144. width: 30px;
  145. margin: 5px auto;
  146. position: relative;
  147. .expression {
  148. width: 20px;
  149. margin: 5px 0;
  150. cursor: pointer;
  151. }
  152. .box {
  153. border: 1px solid #73a8f9;
  154. width: 400px;
  155. min-height: 400px;
  156. box-shadow: 0px 0px 16px rgba(0, 0, 0, 0.2);
  157. background: #fff;
  158. bottom: 100%;
  159. z-index: 999;
  160. left: 0;
  161. display: flex;
  162. position: absolute;
  163. }
  164. .left {
  165. width: 90px;
  166. height: 100%;
  167. display: table-cell;
  168. border-right: 1px solid #ebebeb;
  169. padding: 4px;
  170. ul {
  171. padding: 0;
  172. margin: 0;
  173. text-align: center;
  174. list-style-type: none;
  175. li {
  176. height: 30px;
  177. line-height: 30px;
  178. cursor: pointer;
  179. font-size: 14px;
  180. overflow: hidden;
  181. text-overflow: ellipsis;
  182. white-space: nowrap;
  183. color: #000;
  184. button {
  185. border: none;
  186. background: none;
  187. width: 100%;
  188. height: 100%;
  189. }
  190. }
  191. }
  192. .active {
  193. background-color: #3171d1;
  194. color: #000;
  195. border-radius: 4px;
  196. button {
  197. color: #000;
  198. }
  199. }
  200. }
  201. .right {
  202. flex: 1;
  203. padding-left: 10px;
  204. padding-top: 15px;
  205. overflow: auto;
  206. text-align: left;
  207. button {
  208. border: none;
  209. padding: 0;
  210. cursor: pointer;
  211. width: 32px;
  212. height: 32px;
  213. }
  214. .emoji {
  215. display: inline-block;
  216. padding: 3px;
  217. border: 1px solid transparent;
  218. cursor: pointer;
  219. background: #fff;
  220. color: #000;
  221. &:hover {
  222. height: 32px;
  223. background-color: #ddded8;
  224. border: 1px solid #b3c1fd;
  225. border-radius: 4px;
  226. }
  227. }
  228. }
  229. //样式一
  230. .box0 {
  231. }
  232. }
  233. @media screen and (max-width: 600px) {
  234. .biaoqingContent {
  235. .box {
  236. width: 80vw;
  237. right: -10vw;
  238. max-height: 26vh;
  239. min-height: unset;
  240. overflow-y: auto;
  241. }
  242. }
  243. }
  244. </style>