几乎每次我在 Twitter 订阅源中看到新的表情包时,我都会想到一个机智的版本来创建。我并不是唯一一个这样想的人。表情包通常是承认共同经历或想法的一种方式。在一个在线流传的“这是鸽子吗”表情包的变体中,一位设计师 Daryl Ginn 嘲笑了大多数声称使用人工智能的应用程序的 基础性质。
https://twitter.com/darylginn/status/996541055192453120
一些人回复了他的推文,说了一些类似“用这个替换这个”的话。Daryl 的版本让他们想到了其他可能的变体。像 imgFlip 这样的平台存在是为了使表情包生成快速且容易。但是,它们所能允许的自定义程度是有限的。对于许多表情包,创建新版本只能由具有 Photoshop 知识的人完成。但事实并非如此!对于一些需要在图像上使用 Impact 字体以外内容的表情包,可以使用 HTML Canvas API 创建表情包生成器。在本教程中,我们将为 #saltbae 表情包制作一个生成器。
但首先…
让我们看看一些有趣交互式表情包示例!
网站 pablo.life 允许您通过更改文本和图像来创建您自己的 Kanye West TLOP 专辑封面。

这是我最喜欢的之一

数字代理机构 R/GA 创建了 Straight Outta Somewhere 活动,用户“通过上传自己的照片并在‘Straight Outta ____’之后填写空白来向世界展示他们的出身”。用户可以下载和分享表情包。

开发人员 Isaac Hepworth 创建了 特朗普行政命令生成器。

Spotify 与 Migos 合作创建了一系列 可下载的情人节卡片,可以通过更改姓名进行自定义。

让我们构建我们自己的表情包生成器!
现在,教程。在 #saltbae 表情包的一个流行版本中,Salt Bae(真名 Nusret Gökçe)撒的不是盐,而是其他东西。

加载图像
我们首先要做的是将原始图像加载到画布上。您可以通过两种方式之一加载图像:从 URL 加载或从 DOM 中存在的 <img>
标签加载,但该标签是隐藏的。
以下是如何使用隐藏的图像标签进行操作
<canvas id="canvas" width="1024" height="1024">
Canvas requires a browser that supports HTML5.
</canvas>
<img crossOrigin="Anonymous" id="salt-bae" src="http://res.cloudinary.com/dlwnmz6lr/image/upload/v1520011253/170203-salt-bae-mn-1530_060e5898cdcf7b58f97126d3cfbfdf71.nbcnews-ux-2880-1000_kllh1d.jpg"/>
我在 Cloudinary 上托管图像,并添加了 crossOrigin
属性,因此我们不会遇到任何 CORS 问题。
function drawImage(text) {
const canvas = document.getElementById('canvas');
const ctx = canvas.getContext('2d');
ctx.clearRect(0, 0, canvas.width, canvas.height);
const img = document.getElementById('salt-bae');
ctx.drawImage(img, 0, 0, canvas.width, canvas.height);
}
window.onload = function() {
drawImage();
}
我们正在使用画布 drawImage
函数将图像绘制到画布上。它也可以用于绘制视频或图像的一部分。该方法提供了不同的执行方式。我们通过指示图像的位置以及图像的宽度和高度来绘制图像。
ctx.drawImage(img, x, y, width, height);
或者,我们可以从 URL 加载图像
function loadAndDrawImage(src) {
// Create an image object. (Not part of the dom)
const image = new Image();
// After the image has loaded, draw it to the canvas
image.onload = () => {
// draw image
};
// Then set the source of the image that we want to load
image.src = src;
}
现在我们加载一个图像来替换 Salt Bae 撒的盐。首先,我们使用前面提到的其中一项技术加载图像,然后像对 Salt Bae 基础图像一样将其绘制到屏幕上。
function getRandomInt(min, max) {
min = Math.ceil(min);
max = Math.floor(max);
return Math.floor(Math.random() * (max - min)) + min; //The maximum is exclusive and the minimum is inclusive
}
function drawBackgroundImage(canvas, ctx) {
ctx.clearRect(0, 0, canvas.width, canvas.height);
const img = document.getElementById('salt-bae');
ctx.drawImage(img, 0, 0, canvas.width, canvas.height);
}
function getRandomImageSize(min, max, width, height) {
const ratio = width / height; // Used for aspect ratio
width = getRandomInt(min, max);
height = width / ratio;
return { width, height };
}
function drawSalt(src, canvas, ctx) {
// Create an image object. (Not part of the dom)
const image = new Image();
image.src = src;
// After the image has loaded, draw it to the canvas
image.onload = function() {
for (let i = 0; i < 8; i++) {
const randomX = getRandomInt(10, canvas.width/2);
const randomY = getRandomInt(canvas.height-300, canvas.height);
const dimensions = getRandomImageSize(20, 100, image.width, image.height);
ctx.drawImage(image, randomX, randomY, dimensions.width, dimensions.height);
}
}
return image;
}
onload = function() {
const canvas = document.getElementById('canvas');
const ctx = canvas.getContext('2d');
drawBackgroundImage(canvas, ctx);
const saltImage = drawSalt('http://res.cloudinary.com/dlwnmz6lr/image/upload/v1526005050/chadwick-boseman-inspired-workout-program-wide_phczey.webp', canvas, ctx);
};
现在我们可以让用户撒一些除了盐以外的东西了。
上传图像
我们将添加一个触发图像上传的按钮,并包含一个事件监听器来监听更改。
<input type="file" class="upload-image">`
function updateImage(file, img){
img.src = URL.createObjectURL(file);
}
onload = function() {
const canvas = document.getElementById('canvas');
const ctx = canvas.getContext('2d');
drawBackgroundImage(canvas, ctx);
const saltImage = drawSalt('http://res.cloudinary.com/dlwnmz6lr/image/upload/v1526005050/chadwick-boseman-inspired-workout-program-wide_phczey.webp', canvas, ctx);
const input = document.querySelector("input[type='file']");
/*
* Add event listener to the input to listen for changes to its selected
* value, i.e when files are selected
*/
input.addEventListener('change', function() {
drawBackgroundImage(canvas, ctx); // clear canvas and re-draw
updateImage(this.files[0], saltImage);
});
};
URL.createObjectURL()
创建一个包含 URL 的 DOMString
,该 URL 表示参数中给定的对象,在本例中为上传的文件。

我们甚至可以稍微提高一下游戏水平,例如提供一些默认选项。我添加了一些表情符号,您可以作为起点进行尝试。
下载最终图像
生成新表情包后,我们希望用户能够下载和分享它。通常的做法是使用 toDataURL
方法在新标签页中打开画布,但是用户必须右键单击才能从该标签页保存图像,这很不方便。
因此,我们可以利用 HTML5 中添加到链接的 download
属性。我们创建一个链接,单击该链接时,将 download
属性设置为 canvas.toDataURL
的结果。toDataURL()
方法“返回一个包含以指定格式表示的图像的 data URI。”
function addLink() {
var link = document.createElement('a');
link.innerHTML = 'Download!';
link.addEventListener('click', function(e) {
link.href = canvas.toDataURL();
link.download = "salt-bae.png";
}, false);
link.className = "instruction";
document.querySelectorAll('section')[1].appendChild(link);
}
就是这样!我们的表情包生成器完成了。
一些很酷的链接
- Darius Kazemi 一直在制作许多生成表情包的 Twitter 机器人。
- Vox Media 有一个名为 meme 的表情包生成器,它是开源的。
尽情创作表情包吧!
很棒的东西