灵感来自微博@bangbang93

大佬写了个记仇生成器,作为表情包大王的我不禁想学习一番。

然而菜鸡如我,写的还是有些不尽如人意,比如canvas图片跨域问题还是没有解决明白,图片大的话保存速度会很慢,代码有些地方略显冗余等。希望有大佬指教一下。

<html>
<head>
<title>文件上传</title>
<style>
#bigImg{
width:300px;
height:239.31px;
}
#write{
width: 300px;
border: none;
overflow-y:visible;
font-size: 15px;
margin-top: 10px;
}
#canvas{
width:300px;
height:300px;
display: none;
}
#form{
display: none;
}
#sub{
margin-top: 20px;
}
</style>
</head>
<body>
<div id="container">
</div>
<script>
var jc = new jichou({
container:"container",//容器
initImg:"", //初始图片,不能跨域
initText:"", //初始文字,没有默认“请输入”
method:"/upload",//提交位置
canvasWidth:300,
canvasHeight:300,
canvasFont:"normal normal normal 15px Microsoft YaHei UI",
fontSize:12,
lineHeight:20
})
//构造函数
function jichou(jcObject){
let that = this;
//默认文字
if(!jcObject.initText){
jcObject.initText = "请输入"
}
//获取id
this.getId=function(id){
return document.getElementById(id)
}
//填充内容
var innerHTML = "<img id = 'bigImg' src="+jcObject.initImg+"><br />";
innerHTML += "<div id='write' contenteditable='true'/>"+jcObject.initText+"</div>";
innerHTML += "<form action="+jcObject.method+" method='post' enctype='multipart/form-data' id = 'form'>";
innerHTML += "<input type='file' name='image' id='image'>";
innerHTML += "<br />";
innerHTML += "<input type='hidden' name='base' id='base'>";
innerHTML += "</form>";
innerHTML += "<input type='button' value='保存' id='sub' />";
innerHTML += "<br/>";
innerHTML += "<canvas id='canvas' width='"+jcObject.canvasWidth+"' height='"+jcObject.canvasHeight+"'>";
innerHTML += "</canvas>";
this.getId(jcObject.container).innerHTML = innerHTML;
//上传文件的input
var image = this.getId('image');
//显示文件的img
var bigImg = this.getId('bigImg');
//显示文字的div
var write = this.getId('write');
//表单
var form = this.getId('form');
//保存base64的input
var base = this.getId('base');
//画布
var canvas = this.getId('canvas');
var context = canvas.getContext('2d');
//填充颜色
this.drawCanvas = function(canvas,left,top,width,height,color)
{
context.fillStyle=color;
context.fillRect(left,top,width,height);
}
//清空画布
this.clearCanvas = function(canvas,left,top,width,height,color)
{
context.clearRect(left,top,width,height);
//再填充一下
that.drawCanvas(canvas,left,top,width,height,color);
}
//初始化
if(jcObject.initImg||jcObject.initText){
//初始化canvas
window.onload=function(){
that.saveImg(jcObject.initImg);
that.saveText(jcObject.initText);
}
}
//保存图片
this.saveImg = function(imgUrl){
//创建image对象
var img = new Image;
img.src = imgUrl;
img.crossOrigin = 'anonymous';
img.onload = function(){
//画图
canvas.height = bigImg.clientHeight + write.clientHeight + 10;
canvas.style.height = bigImg.clientHeight + write.clientHeight + 10 +"px";
context.drawImage(img,0,0,jcObject.canvasWidth,bigImg.height);
}
context.stroke();
}
//先填充白色防止透明色块
this.drawCanvas(canvas,0,0,canvas.width,canvas.height,"#ffffff");
//canvas文字换行
this.canvasTextAutoLine = function(str,canvas,initX,initY,lineHeight,context){
var context = canvas.getContext('2d');
context.fillStyle="#000000";
var lineWidth = 0;
var canvasWidth = canvas.width;
var lastSubStrIndex= 0;
for(let i=0;i<str.length;i++){
lineWidth+=context.measureText(str[i]).width;
if(lineWidth>canvasWidth-initX){//减去initX,防止边界出现的问题
context.fillText(str.substring(lastSubStrIndex,i),initX,initY);
initY+=lineHeight;
lineWidth=0;
lastSubStrIndex=i;
}
if(i==str.length-1){
context.fillText(str.substring(lastSubStrIndex,i+1),initX,initY);
}
}
}
//换图时修改路径
image.onchange = function(){
var imgUrl = window.URL.createObjectURL(this.files[0]);
bigImg.src = imgUrl;
bigImg.style.height = "auto";
image.onload = that.saveImg(imgUrl)
}
//点击图片换图
bigImg.onclick = function(){
image.click();
}
//点击保存
sub.onclick = function(){
var text = write.innerHTML;
that.saveText(text);
//提交表单
window.setTimeout(function(){
var strDataURI = canvas.toDataURL();
base.value = strDataURI;
form.submit();
},1000)
}
//存文字
this.saveText = function(text){
//文字样式
context.font=jcObject.canvasFont;
//清空文字
that.clearCanvas(canvas,0,bigImg.clientHeight+jcObject.fontSize,canvas.width,write.clientHeight+jcObject.lineHeight,"#ffffff");
//文字换行
that.canvasTextAutoLine(text,canvas,0,bigImg.clientHeight+jcObject.lineHeight,jcObject.lineHeight,content)
context.stroke();
}
}
</script>
</body>
</html>

upload.js

var express = require('express');
var app = express();
var fs = require('fs');
var router = express.Router();
//用于解析数据
var bodyParser = require('body-parser');
//上传文件中间件
var multer = require('multer');
app.use(express.static('static'));
app.use(bodyParser.urlencoded({extended:false}));
app.use(multer({dest:'/tmp/'}).array('image'));
app.get('/upload.html',function(req,res){
res.sendFile(__dirname + '/' + "upload.html")
})
//设置跨域访问
app.all('*', function(req, res, next) {
res.header("Access-Control-Allow-Origin", "*");
res.header("Access-Control-Allow-Headers", "X-Requested-With");
res.header("Access-Control-Allow-Methods", "PUT,POST,GET,DELETE,OPTIONS");
res.header("X-Powered-By", ' 3.2.1');
res.header("Content-Type", "application/json;charset=utf-8");
next();
});
app.post('/upload',function(req,res){
var imgData = req.body.base.replace(/^data:image\/\w+;base64,/, '');
var imageName = imgData.substr(0,10) + Math.random().toString(16);
console.log(imageName)
var dataBuffer = new Buffer(imgData, 'base64');
//写入文件
fs.writeFile('D:/my/node/static/images/'+imageName+'.png', dataBuffer, function(err){
if(err){
res.end(err);
}else{
res.end(JSON.stringify('保存成功'));
}
});
})
var server = app.listen(3300,function(req,res){
var host = server.address().address;
var port = server.address().port;
console.log('running at http://%s:%s',host,port)
})

傻吊表情包加文字功能(canvas+node)相关推荐

  1. python表情换头_使用Python制作表情包实现换脸功能

    "表情包"是现在非常流行的交流方式,通过一张图片就能把文字不能表达或不便于表达的情感给表示出来,表情包一经诞生,就统治了中国人的社交圈,尤其是年轻人,他们的社交方式是所谓" ...

  2. python制作表情包教程_使用Python制作表情包实现换脸功能

    "表情包"是现在非常流行的交流方式,通过一张图片就能把文字不能表达或不便于表达的情感给表示出来,表情包一经诞生,就统治了中国人的社交圈,尤其是年轻人,他们的社交方式是所谓" ...

  3. 怎么在动态表情包上添加文字,gif添加文字

    怎么在动态表情包上添加文字,我们经常看到微信表情包里很多非常有趣的表情包,很多图片或者gif表情包,让简单的图片添加动效文字,视觉效果和传播效果非常好,其实这种图片制作很简单. 下面就给大家演示一下, ...

  4. 流量主系列|独立表情包壁纸喝酒神器功能微信小程序源码

    简介: 相信玩小程序的朋友对这款小程序应该也不陌生,  这是前半年很火的一款微信表情包小程序功能.  之前的版本内置了表情包还有壁纸功能  ,这一期的版本给优化了一下UI和新增加了一些喝酒神器功能 具 ...

  5. 表情包 AI 生成器:识别人脸情绪,自动配文字

    code小生 一个专注大前端领域的技术平台 公众号回复Android加入安卓技术群 Meme表情包,兴盛于各大社交网站,但自己动手制作费时耗力. "急民之所急",表情包自动生成器出 ...

  6. 表情包AI生成器:识别人脸情绪,自动配文字

    梅宁航 发自 凹非寺  量子位 报道 | 公众号 QbitAI Meme表情包,兴盛于各大社交网站,但自己动手制作费时耗力. "急民之所急",表情包自动生成器出现了. 以往的此类生 ...

  7. python 实现表情包+文字拼接demo

    同一目录下: 1.2张事先准备好图片: 2.一段显示表情包上文字: 3.代码,run,生成表情包. 代码如下: from PIL import Image, ImageDraw, ImageFont ...

  8. 表情包壁纸独立后台美化二开版本新增加神器功能微信小程序源码下载+教程自动采集

    相信玩小程序的朋友对这款小程序应该也不陌生 这是前半年很火的一款微信表情包小程序功能 之前的版本内置了表情包还有壁纸功能 这一期的版本给优化了一下UI和新增加了一些喝酒神器功能 具体新增加的喝酒神器功 ...

  9. 小程序源码:新款最火表情包壁纸独立后台美化二开版本新增加喝酒神器功能

    相信玩小程序的朋友对这款小程序应该也不陌生 这是前半年很火的一款微信表情包小程序功能 之前的版本内置了表情包还有壁纸功能 这一期的版本给优化了一下UI和新增加了一些喝酒神器功能 具体新增加的喝酒神器功 ...

最新文章

  1. 算法工程师必须要知道的面试技能雷达图
  2. go语言学习(3)面向对象,结构体和方法
  3. c# 多线程 执行事件 并发_C#.NET Thread多线程并发编程学习与常见面试题解析-1、Thread使用与控制基础...
  4. CSS hr修改样式
  5. BZOJ 3304: [Shoi2005]带限制的最长公共子序列( LCS )
  6. 小米无线网卡驱动_小米air笔记本蓝屏故障排除,一个匪夷所思的故障原因。
  7. Why Helm? - 每天5分钟玩转 Docker 容器技术(160)
  8. C# 父类代码动态转换子类
  9. idea lombok插件安装_开发效率不高?墙裂推荐这十款精选 IntelliJ IDEA 插件
  10. React入门---组件-4
  11. 数据库JDBC的基本内容
  12. [动态规划]ACM预选赛F题 侠客行
  13. springboot2 oauth2 jwt认证服务器和资源服务器
  14. Non-managed pom.xml file found
  15. 作为面试官,如何甄别应聘者的包装程度?
  16. 一文读懂微软转型秘诀
  17. 世界十大名言是什么?
  18. win10运行calc计算器报错 win10无法打开这个应用。请与你的系统管理员联系,以了解有关修复或重新安装该应用的信息。
  19. Fzu 2206 函数求解【规律】
  20. 江苏省普通高校“专转本”选拔考试 计算机专业大类专业综合基础理论考试大纲

热门文章

  1. maven打包springboot项目的jar包的时候出现报错There are test failures.
  2. 能阅读计算机英语,全阅读英语电脑版
  3. GRID K1、K2测试的初步总结
  4. vue3.0-axios拦截器、proxy跨域代理
  5. Solaris配置多个IP
  6. 怎么在自己的电脑上录音,电脑录音的软件有哪些
  7. 打破云和端的那堵墙,​Midway Serverless 带你感受云端一体应用研发
  8. Win7 wifi热点设置
  9. 模式识别技术,目前主要应用于哪几方面?
  10. 职称考试计算机需要带什么,职称计算机考试考前需要准备什么