Study background
In the daily use of social software such as Qiuqiu and wechat, we can often use their expression function, which is very convenient and quick. A good set of emojis can give users a good experience, like this screenshot of QQ emojis. Recently there has been a need to add this little expression to small programs, after trying and learning various methods, here is a summary.
The implementation process
- Storage and acquisition of facial expressions
- Make the marquee box
- rendering
1. Storage and acquisition of facial expressions
Premise: The emoticons mentioned in this article are mainly pictures in common formats such as.jpg.png.
This part is relatively simple, about the image storage, either locally or on the network. Although the ordinary little yellow face facial expressions 2x@png format is up to 1KB or so, but if you want to increase the different facial expressions later set of words also have dozens or even hundreds of KB, for the small program is still some unbearable.
So how do you get the web image to show up on the selection page? For example, [haha] is displayed as 😄 on the selection panel. We can use a function to generate the corresponding network address or create a mapping table to map the identifier to the corresponding image network address.
Function form implementation reference:
/ * * *@param {string[]} BaseUrl Header of the network address *@param {string[]} Sign Specifies the image identifier *@param {string[]} Ext image format *@return {string[]} * /
const imgAddMap = (baseUrl, sign, ext) = > {
// Here you can further customize the sign.slice result to get the desired path
return baseUrl + sign.slice(1, -1) + ext;
};
console.log(
imgAddMap('http://localhost:8080/abc/'.'[haha]'.'.png'));// http://localhost:8080/abc/haha.png
Copy the code
Table implementation form reference:
// Implement an img util
const baseUrl = 'http://localhost:8080/abc';
const imgName = ['[haha]'.'[wuwu]' /*more ... * /];
const imgMap = {
'[haha]': 'lalala.png'.'[wuwu]': 'yingyingying.png'.// more ...
};
/ * * *@param {string[]} ImgSign Identifies the image *@return {string[]}* /
const imgDisplay = (imgSign) = > {
const _img = imgMap[imgSign];
return _img ? baseUrl + _img : ' ';
};
console.log(imgDisplay('[haha]'));
// http://localhost:8080/abclalala.png
// export { imgName, imgMap, imgDisplay }; Finally, export the module
Copy the code
A brief comparison:
- Function implementations do not need to declare other related variables or objects to store, but they need to be evaluated each time.
- Table implementations are more efficient at lookups, but require additional objects to store addresses, formats, and so on.
2. Make a selection box
Before we use emojis we have to have a display page, a layout that you can easily think of and you just have to draw a square and put emojis in it.
// My personal habits are as follows#outer {
position: relative;
width: 12.5%;
height: 0;
padding-top: 12.5%;
}
// aspect-ratio: 1/1; inh5In the normal use, there seems to be a compatibility problem in wechat small program.inner {
position: absolute;
width: 100%;
height: 100%;
left: 0;
top: 0;
}
Copy the code
The expression chooses the display part (here the expression is repeated several times in order to show the effect, which is actually lazy)
<div id="outer">
<div class="inner" v-for="item in imgName">
<span class="img">
<img
:src="_imgDisplay(item)"
alt=""
style="width: 60%; height: 60%"
/>
</span>
</div>
</div>
Copy the code
Sample picture: (12.5% / picture)
Here we add an input box and add the specified click event to the emoticon to add the emoticon identifier to the input box for later rendering.
Here, input value = current value + expression identifier is directly used for simple addition. No insert operation is implemented. H5, all kinds of small procedures to achieve different methods, you can try to insert in the cursor.
At this point, we are halfway there, and now we have to do the main rendering.
3. Rendering method
Now that we have the message, we need to consider how to render it into the message. Here are two reference methods:
- Use regular expressions to replace the contents in parentheses with images that are displayed with innerHTML
- Encapsulate a function to generate a string into a virtual DOM node
A. Regular expression replacement
/ * * *@param {string[]} MSG Content to be replaced *@return {string[]}* /
const imgTextReplacer = (msg) = > {
return msg.replace(/\[([a-z0-9]+?)\]/g.(name) = > {
// The regular expression replaces ~ according to its own needs
if (imgDisplay(name)) {
return `<img src="${imgDisplay(name)}"
class="imgText"></img>`;ImgText is the style of the final image
} else {
returnname; }}); };Copy the code
Display in HTML:
<div v-html="_imgTextReplace(inputContent)" class="_display"></div>
You can add imgText as mentioned earlier, or you can replace it with style, but don’t forget to align the image with the text. You can add the vertically centered align-items:baseline to the parent element._display, or you can add the style vertical-align: text-bottom to the image.imgText.
The updated hook adds the corresponding secondary processing to the element or removes the scoped attribute in the style
B.r ender function
/ * * *@param {string[]} MSG The message to render@return {string[]}* /
const imgTextParser = (msg) = > {
const res = [];
let left = -1;
let right = -1;
while (msg.length) {
left = msg.indexOf('[');
right = msg.indexOf('] ');
if (left === 0) {
if (right === -1) {
res.push({ tag: 'text'.text: msg });
break;
}
// find img in the table
const _img = imgMap[msg.slice(0, right + 1)];
if (_img) {
res.push({
tag: 'image'.src: baseUrl + _img,
});
msg = msg.slice(right + 1);
} else {
res.push({
tag: 'text'.text: '['}); msg = msg.slice(1); }}else {
// Check if left is found
constifFindLeft = left ! = = -1;
res.push({
tag: 'text'.text: ifFindLeft ? msg.slice(0, left) : msg,
});
msg = ifFindLeft ? msg.slice(left) : ' '; }}return res;
};
Copy the code
Code in the page structure (H5):
// A message<div class="_display">
<div class="" v-for="_d in msg">
<span v-if="_d.tag === 'text'"> {{ _d.text }} </span>
<img :src="_d.src" alt="bq" style=""
class="_img" v-if="msg.tag === 'image'"
/>
</div>
</div>
Copy the code
Final display effect
Sometimes it’s better to be centered
Regardless of which method you choose, pay attention to the timing of the rendering. Don’t call functions on the HTML like the one above, as frequent DOM manipulation can cause pages to get jammed. You should replace what you need in advance.
conclusion
Here we have achieved a simple expression selector, we can strengthen the function according to their preferences or needs, shortcomings or mistakes welcome to point out 🤗🤗🤗~