用图像替换一列表情符号

14

我有一个数组,其中包含:

emoticons = {
   ':-)' : 'smile1.gif',
   ':)'  : 'smile2.gif',
   ':D'  : 'smile3.gif'     
}

然后我有一个包含文本的变量。

var text = 'this is a simple test :)';

同时创建一个变量来存储网站的URL

var url = "http://www.domain.com/";

如何编写一个函数,将符号替换为它们对应的图像?

<img> 标签的结果应该是:

<img src="http://www.domain.com/simple2.gif" />

我必须将URL变量连接到图像名称。

非常感谢!

3个回答

33

另一种方法:

function replaceEmoticons(text) {
  var emoticons = {
    ':-)' : 'smile1.gif',
    ':)'  : 'smile2.gif',
    ':D'  : 'smile3.gif'
  }, url = "http://www.domain.com/";
  // a simple regex to match the characters used in the emoticons
  return text.replace(/[:\-)D]+/g, function (match) {
    return typeof emoticons[match] != 'undefined' ?
           '<img src="'+url+emoticons[match]+'"/>' :
           match;
  });
}

replaceEmoticons('this is a simple test :)');
// "this is a simple test <img src="http://www.domain.com/smile2.gif"/>"

编辑:@pepkin88提出了一个很好的建议,即基于表情符(emoticons)对象的属性名称构建正则表达式。

这很容易实现,但我们必须转义元字符(meta-characters)以使其正常工作。

转义后的模式存储在数组中,稍后使用RegExp构造函数构建正则表达式,基本上是将所有模式用|元字符分隔并连接起来。

function replaceEmoticons(text) {
  var emoticons = {
    ':-)' : 'smile1.gif',
    ':)'  : 'smile2.gif',
    ':D'  : 'smile3.gif',
    ':-|'  : 'smile4.gif'
  }, url = "http://www.domain.com/", patterns = [],
     metachars = /[[\]{}()*+?.\\|^$\-,&#\s]/g;

  // build a regex pattern for each defined property
  for (var i in emoticons) {
    if (emoticons.hasOwnProperty(i)){ // escape metacharacters
      patterns.push('('+i.replace(metachars, "\\$&")+')');
    }
  }

  // build the regular expression and replace
  return text.replace(new RegExp(patterns.join('|'),'g'), function (match) {
    return typeof emoticons[match] != 'undefined' ?
           '<img src="'+url+emoticons[match]+'"/>' :
           match;
  });
}

replaceEmoticons('this is a simple test :-) :-| :D :)');

1
如果emoticons中的键值决定了正则表达式,那就更好了。 - pepkin88
1
@pepkin88:非常好的建议 :), 我添加了一个可以实现这个功能的函数。 - Christian C. Salvadó
1
这可以进一步增强,通过闭包replace()(类似于这个答案…) - 这将加速对该函数的重复调用。 - Tomalak
@CMS 对我的一个应用程序来说非常有帮助。 - redV
1
@redV 很高兴能帮到你! - Christian C. Salvadó
太棒了!特别是第二部分 :) 第一部分匹配所有类型的符号(如':',')'甚至'D'),我认为在大量文本中会非常慢。第二个很棒,稍作修改,正如@Tomalak建议的那样-每次创建所有模式都不值得。无论如何-仍然是一个很好的答案!干杯! :) - Andrey Popov

4
for ( smile in emoticons )
{
   text = text.replace(smile, '<img src="' + url + emoticons[smile] + '" />');
}

1
由于replace仅替换匹配字符串的第一个出现,因此它无法正常工作。 - mati
仅适用于替换每个笑脸的第一次出现。在像“这被替换了:)但不是这个:)”这样的字符串中,第二个笑脸保持不变。 - Guffa
1
还要确保在for...in语句中使用var,否则如果代码位于未在该范围内声明smile变量的函数中,则它将变为全局变量,并在循环内部使用if (emoticons.hasOwnProperty(smile))是个好主意。 - Christian C. Salvadó
好的,那么如何使用.replace()来替换多个出现次数? - Damiano
要替换多个出现次数,请将 smile 更改为 new RegExp(smile, 'g') - pepkin88
或者你也可以 /微笑/ :P - Jacek Pietal

0

使用正则表达式与查找替换元素数组配合使用效果很好。

var emotes = [
    [':\\\)', 'happy.png'],
    [':\\\(', 'sad.png']
];

function applyEmotesFormat(body){
    for(var i = 0; i < emotes.length; i++){
        body = body.replace(new RegExp(emotes[i][0], 'gi'), '<img src="emotes/' + emotes[i][1] + '">');
    }
    return body;
}

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接