0530-3433334

网站建设 APP开发 小程序

知识

分享你我感悟

您当前位置>首页 >> 知识 >> 小程序

H5页面小程序如何实现emoji表情?

发表时间:2023-10-05 17:54:16

文章来源:炫佑科技

浏览次数:211

菏泽炫佑科技 菏泽炫佑小程序开发 菏泽炫佑app制作 炫佑科技

H5页面小程序如何实现emoji表情

Emoji表情大家都很熟悉。 例如,微信的对话窗口可以发送表情符号。

但如果你仔细观察,你会发现一个重要的发现。 例如,如果朋友给你发了一个表情符号,你在聊天会话列表页面查看*近的消息,你会发现有些不同,如下所示:

前者是默认的表情符号,后者是自定义的表情符号。 显然,如果你在微博上按住微信的【曰比】,就无法显示微信的【困困】表情。

本文介绍了这两个emoji表情在H5和微信小程序下的实现。

自定义表情符号

定制,顾名思义,就是由你自己定义的表达方式。 它不是一个通用的表达方式。 它是按照你自己系统的一套解析规则来实现的,只能在我的系统中识别。

表达式定义

首先,您需要定义自己的一组正则表达式,它们是绝对路径表达式。 例如:

export default emojiData = {
    "买买买": ["1",true,1]
}

这里我们约定表情图片有统一的路径格式,如:。所以“买买买”其实对应的是

这里定义了表情文案“买买买”对应的表情符号的路径。 当然,自定义表情的文案和图片一定要一一对应。

为了方便区分用户的普通文案,我们通常会在自定义表达方式中添加“[]”。 例如“买买买”*终显示为“[买买买]”。 为了保证之前用过的表情能够正常显示,系统中的【买买买】只能对应这个图片路径。 这里定义了一个数组,接下来的两个参数我们稍后解释。

表达到文本

有了文案和图片的对应关系,根据业务需求,就可以在表情面板上渲染表情了。 这样就可以在页面的表情面板中显示该表情的图片路径了。 然后用户选择一个表达式,相应的表达式就会显示在文本框中。 显示图片的文案,比如【买买买】,当然也是系统数据库中存储的文案【买买买】。

"买买买": ["1",true,1]

这里数组中的true值表示当前表情是否还在使用。 对于离线表情,我们需要在渲染表情面板时将其移除,但是生成的表情如果存在的话仍然需要显示在页面上。

数据中的 1 代表表达式显示在表达式面板的哪个屏幕上。 这里**屏是0,所以1代表第二屏。

function getFaceList(panelIndex) {
    let arr = [];
    for (let txt in emojiData) {
        if (emojiData[txt][2] == panelIndex) { // 找到对应面板的显示。
            if (emojiData[txt][1]) {// 保证该表情未下线
                let s = getFaceUrl(emojiData[txt]);
                s = `${txt}"> ${s}">`;
                arr.push(s);
            }
        }
    }
    return arr;
}

这是渲染表达式面板。 数据根据渲染的面板索引进行渲染。 不离线时,只有表情才能渲染到面板中。

function getFaceUrl(emoji) {
    return `https://wq.360buyimg.com/fd/wx/img/gwq/face/${emoji[0]}.png`
}

文字转图像

后台查询的复制文本可能包含表达式。 当页面显示的时候,我们需要将文字转换成图片。

function text2pic(txt) {
    if (!txt) {
        return '';
    }
    txt = txt.replace(/\[([^\]]+)\]/g, function (v1, v2) {
        //v1: [买买买]   v2:买买买
        let d = emojiData[v2];
        return d ? ' + getFaceUrl(d) + '" />' : v1;
    });
    return txt;
}

这里,需要显示的文字是搜索[xxx]的内容,然后与我们自定义的表情符号进行匹配。 如果匹配,则说明是自定义表情,然后我们输出一个img图像标签。

当然,没有办法区分这个表情是你在面板上选择的表情符号【买买买】还是你在文本框中输入的文案【买买买】。 你还会发现微信的【偰尰】其实是区分表情和文字的。 如果我们也需要这样做的话,我们在传入后台的时候就不能只传入文案【买买买】,比如【买买买】,那么我们之前的识别也需要遵循这个规则。 如果你有兴趣并且需要的话,可以尝试一下。

由于这里将普通文本转换为富文本,所以要特别注意xss的问题。 在转换表达式之前先进行xss处理。 在将富文本内容渲染到页面之前,请确保不存在 xss 问题。

系统默认emoji表情

以上自定义表情可以解决我们系统中对具有特殊含义的emoji表情的需求。 例如,表达方式“买买买”是我们业务的特殊表达方式。 事实上,没有这样的表情符号。

不过,你应该注意系统的表情符号。 它在不同系统中可能显示的样式会略有不同。 不过,不用担心,笑还是笑。 在任何制度下都不会变成哭泣。 如果要求不是那么高的话,问题不大。 大,只知道存在这种显示差异。

代码 emoji 表情

笑吗?:\uD83D\uDE04

当用户在输入法中输入默认的emoji表情时,我们需要对其进行处理,将其转换成代码进行存储,比如调用方法进行转换。

function emoji2Unicode (emoji) {
    let str = '';
    if (emoji && emoji.length > 0) {
        for (const char of emoji) {
            const index = char.codePointAt(0);
            if (index > 65535) {
                const h =
                    '\\u' +
                    (Math.floor((index - 0x10000) / 0x400) + 0xd800).toString(
                        16
                    );
                const c =
                    '\\u' + ((index - 0x10000) % 0x400 + 0xdc00).toString(16);
                str = str + h + c;
            } else {
                str += char;
            }
        }
    }
    return str;
}

如果emoji作为代码存储在后台,返回前端时不需要特殊使用或者vue的v-html来显示。 只需将其显示为普通文本即可。 例如,以下两个都可以显示为表情符号?:

document.getElementById("emojiWrap").innerHTML='\uD83D\uDE04';
document.getElementById("emojiWrap").innerText='\uD83D\uDE04';

如果我们通过传递参数代码来调用后端,比如\uD83D\uDE04,那么前端查询返回时,也需要是文本\uD83D\uDE04。 这里后端数据库需要支持字符存储。 本文暂不讨论。 有兴趣的可以读一下。 。

HTML 实体存储 emoji 表情

除了使用代码来存储emoji表情之外,我们还可以使用html实体存储来实现。

用户使用手机输入法输入表情后,我们需要将其转换为物理存储。

表情符号==> html

function emoji2HtmlEntity (str) {
    const patt = /[\ud800-\udbff][\udc00-\udfff]/g;
    str = str.replace(patt, function (char) {
        let H, L, code;
        if (char.length === 2) {
            H = char.charCodeAt(0); // 取出高位
            L = char.charCodeAt(1); // 取出低位
            code = (H - 0xd800) * 0x400 + 0x10000 + L - 0xdc00; // 转换算法
            return '&#' + code + ';';
        } else {
            return char;
        }
    });
    return str;
}

这里,表达式被转换为实体存储。 这个html对数据库存储没有要求,只要能存储字符串就可以了。 例如:

emoji2HtmlEntity('?')  ==>  😄

把这个html实体&#存储在后台,然后前端查询的时候原样返回。

html ==> 表情符号

通常我们也可以直接渲染html实体,比如:

document.getElementById("emojiWrap").innerHTML='😄';

但是,我们仍然不能用它来显示html。 它只会按原样显示文本。 另外,在微信小程序中很难显示,所以我们可以统一将html转换成代码来显示。

如下:he.js

const regexInvalidEntity = /&#(?:[xX][^a-fA-F0-9]|[^0-9xX])/;
const regexDecode = /&(Gt|GT|ii);|&(gt|lt)(?!;)([=a-zA-Z0-9]?)|&#([0-9]+)(;?)|&#[xX]([a-fA-F0-9]+)(;?)|&([0-9a-zA-Z]+)/g;
const decodeMapNumeric = { '0': '\uFFFD', '128': '\u20AC', '130': '\u201A', '131': '\u0192', '132': '\u201E', '133': '\u2026', '134': '\u2020', '135': '\u2021', '136': '\u02C6', '137': '\u2030', '138': '\u0160', '139': '\u2039', '140': '\u0152', '142': '\u017D', '145': '\u2018', '146': '\u2019', '147': '\u201C', '148': '\u201D', '149': '\u2022', '150': '\u2013', '151': '\u2014', '152': '\u02DC', '153': '\u2122', '154': '\u0161', '155': '\u203A', '156': '\u0153', '158': '\u017E', '159': '\u0178' };
const invalidReferenceCodePoints = [1, 2, 3, 4, 5, 6, 7, 8, 11, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 127, 128, 129, 130, 131, 132, 133, 134, 135, 136, 137, 138, 139, 140, 141, 142, 143, 144, 145, 146, 147, 148, 149, 150, 151, 152, 153, 154, 155, 156, 157, 158, 159, 64976, 64977, 64978, 64979, 64980, 64981, 64982, 64983, 64984, 64985, 64986, 64987, 64988, 64989, 64990, 64991, 64992, 64993, 64994, 64995, 64996, 64997, 64998, 64999, 65000, 65001, 65002, 65003, 65004, 65005, 65006, 65007, 65534, 65535, 131070, 131071, 196606, 196607, 262142, 262143, 327678, 327679, 393214, 393215, 458750, 458751, 524286, 524287, 589822, 589823, 655358, 655359, 720894, 720895, 786430, 786431, 851966, 851967, 917502, 917503, 983038, 983039, 1048574, 1048575, 1114110, 1114111];
const stringFromCharCode = String.fromCharCode;
const object = {};
const hasOwnProperty = object.hasOwnProperty;
const has = function (object, propertyName) {
    return hasOwnProperty.call(object, propertyName);
};
const contains = function (array, value) {
    let index = -1;
    const length = array.length;
    while (++index < length) {
        if (array[index] == value) {
            return true;
        }
    }
    return false;
};
const merge = function (options, defaults) {
    if (!options) {
        return defaults;
    }
    const result = {};
    let key;
    for (key in defaults) {
        // A `hasOwnProperty` check is not needed here, since only recognized
        // option names are used anyway. Any others are ignored.
        result[key] = has(options, key) ? options[key] : defaults[key];
    }
    return result;
};
const parseError = function (message) {
    throw Error('Parse error: ' + message);
};
const codePointToSymbol = function (codePoint, strict) {
    let output = '';
    if ((codePoint >= 0xD800 && codePoint <= 0xDFFF) || codePoint > 0x10FFFF) {
        if (strict) {
            parseError('character reference outside the permissible Unicode range');
        }
        return '\uFFFD';
    }
    if (has(decodeMapNumeric, codePoint)) {
        if (strict) {
            parseError('disallowed character reference');
        }
        return decodeMapNumeric[codePoint];
    }
    if (strict && contains(invalidReferenceCodePoints, codePoint)) {
        parseError('disallowed character reference');
    }
    if (codePoint > 0xFFFF) {
        codePoint -= 0x10000;
        output += stringFromCharCode(codePoint >>> 10 & 0x3FF | 0xD800);
        codePoint = 0xDC00 | codePoint & 0x3FF;
    }
    output += stringFromCharCode(codePoint);
    return output;
};
const decode = function (html, options) {
    options = merge(options, decode.options);
    const strict = options.strict;
    if (strict && regexInvalidEntity.test(html)) {
        parseError('malformed character reference');
    }
    return html.replace(regexDecode, function ($0, $1, $2, $3, $4, $5, $6, $7, $8) {
        let codePoint;
        let semicolon;
        let decDigits;
        let hexDigits;
        if ($4) {
            // Decode decimal escapes, e.g. `𝌆`.
            decDigits = $4;
            semicolon = $5;
            if (strict && !semicolon) {
                parseError('character reference was not terminated by a semicolon');
            }
            codePoint = parseInt(decDigits, 10);
            return codePointToSymbol(codePoint, strict);
        }
        if ($6) {
            // Decode hexadecimal escapes, e.g. `𝌆`.
            hexDigits = $6;
            semicolon = $7;
            if (strict && !semicolon) {
                parseError('character reference was not terminated by a semicolon');
            }
            codePoint = parseInt(hexDigits, 16);
            return codePointToSymbol(codePoint, strict);
        }
        // If we’re still here, `if ($7)` is implied; it’s an ambiguous
        // ampersand for sure. https://mths.be/notes/ambiguous-ampersands
        if (strict) {
            parseError(
                'named character reference was not terminated by a semicolon'
            );
        }
        return $0;
    });
};
decode.options = {
    'isAttributeValue': false,
    'strict': false
};
export default decode;

这个的实现过程我就不详细说了。 有兴趣的同学可以看一下,比较简单。

拿到文本后,我们首先使用he来处理:

import decode from './he';
text = decode(text);

这样html实体就转换成了可以直接显示的emoji表情微信表情制作小程序H5页面小程序如何实现emoji表情?,也可以直接在小程序中显示。 当然,这个强大的库不仅仅只是转换emoji表情,你可以参考:

炫佑科技专注互联网开发小程序开发-app开发-软件开发-网站制作等

相关案例查看更多