这是17年的第一篇博文,话说这天又是产品同学跑过来问我说:hi,lenny,你看现在市面上流行各种装逼H5,随便输入点名字啥的就给我生成房产证了,这种还可以分享出去,传播率可高了,或者你再看这里,一键生成邀请函,牛逼吧,要不你也帮我做一个这个功能,我去玩点传播手段。
我看见效果后第一反映就是,肯定canvas进行的图片拼接,现在市面上流行的效果具体是如何实现的我没有去看源码,思路很清晰,于是晚饭后没有下班,开始我的插件制作之旅了。
首先,我们需要思考,既然是图片处理,那么就必然存在图片下载,我们知道图片的onload是异步回调,所有的资源必须在下载完成后才可以进行接下来的逻辑,前置资源下载的逻辑就很关键,我们不仅需要在onload事件回调后去处理我们后续的流程,同时需要在所有必须资源加载完成后才执行,所以我们需要构建一个资源数组大致如下:
[{ { name: 'bg', src: '../img/bg.jpg' }, { name: 'z', src: '../img/z.png' }]
为了获得最终的complete事件,我们需要利用一个全局变量监听onload或者onerror次数:
var i = 1; arr.forEach(function(obj, index, array) { function onLoad() { _self[obj.name] = img; if (i < array.length) { ++i; } else { console.log('complete'); }; } var img = new Image(); img.onload = onLoad; img.onerror = onLoad; img.src = obj.src;
好了,资源加载完成事件我们得到了,可以继续下面的逻辑,既然是基于canvas,当然需要创建并初始化我们的canvas,我根据自己的需求,这个功能在我所使用的项目中不论初始化多少次,只会存在一个,所以我做了如下的控制:
init: function() { var LCanvasImg_canvas = document.querySelector('#LCanvasImg_canvas'); if (LCanvasImg_canvas) { LCanvasImg_canvas.width = this.params.cw; LCanvasImg_canvas.height = this.params.ch; LCanvasImg_canvas.style.display = this.params.display; this.canvas = LCanvasImg_canvas; } else { var canvas = document.createElement('canvas'); canvas.id = 'LCanvasImg_canvas'; canvas.width = this.params.cw; canvas.height = this.params.ch; canvas.style.display = this.params.display; document.body.appendChild(canvas); this.canvas = canvas; } this.clear(); },
canvas创建好了,接下来我们需要实现图片渲染的能力,canvas的图片渲染使用的是drawImage方法,根据官方文档,该方法有3种传参方式:
JavaScript 语法 1
在画布上定位图像:
context.drawImage(img,x,y);
JavaScript 语法 2
在画布上定位图像,并规定图像的宽度和高度:
context.drawImage(img,x,y,width,height);
JavaScript 语法 3
剪切图像,并在画布上定位被剪切的部分:
context.drawImage(img,sx,sy,swidth,sheight,x,y,width,height);
于是,我们也充分的判断好我们调用的drawImage参数:
addImg: function(obj, callback) { var _self = this; var canvas = _self.canvas; var ctx = canvas.getContext("2d"); if (obj.hasOwnProperty('sx') && obj.hasOwnProperty('sy') && obj.hasOwnProperty('sw') && obj.hasOwnProperty('sh') && obj.hasOwnProperty('x') && obj.hasOwnProperty('y') && obj.hasOwnProperty('width') && obj.hasOwnProperty('height')) { ctx.drawImage(_self[obj.name], obj.sx, obj.sy, obj.sw, obj.sh, obj.x, obj.y, obj.width, obj.height); } else if (obj.hasOwnProperty('x') && obj.hasOwnProperty('y') && obj.hasOwnProperty('width') && obj.hasOwnProperty('height')) { ctx.drawImage(_self[obj.name], obj.x, obj.y, obj.width, obj.height); } else if (obj.hasOwnProperty('x') && obj.hasOwnProperty('y')) { ctx.drawImage(_self[obj.name], obj.x, obj.y); } else { ctx.drawImage(_self[obj.name], 0, 0); } _self.showImg(); },
接下来我们需要开发文字生成的能力,这个比较简单,如果对canvas相关api熟悉点的,这部分没有难度:
addFont: function(obj) { var _self = this; var canvas = _self.canvas; var ctx = canvas.getContext("2d"); ctx.font = obj.fontsize + "px " + obj.fontfamily; //文字的字体大小和字体系列 var ftop = obj.ftop; //文字top var fleft = obj.fleft; //文字left ctx.textBaseline = "top"; //设置绘制文本时的文本基线。 ctx.fillText(obj.txt, fleft, ftop); ctx.lineWidth = 1; ctx.fillStyle = "#000"; ctx.strokeStyle = "rgba(255,255,255,0.4)"; ctx.strokeText(obj.txt, fleft, ftop); },
最后一步是二维码的生成,这个有点坑,自己开发肯定来不及了,我选用的是一个开源插件:qrcode,根据这个插件,我们可以在一个img中动态生成二维码的base64字串,而有了这个字串,我们也很方便的将内容输出到我们的canvas中,为了保证体验,这个插件的最外层div直接display:none,避免它干扰到我们的实际项目。
<div id="qrcode" style="display: none;"></div>
/** * * 初始化二维码生成插件 * */ var qrdata = ''; var myqr = document.querySelector('#myqr'); var qrcode = document.querySelector('#qrcode'); var qr = new QRCode(qrcode, { width: 300, height: 300, colorDark: "#000000", colorLight: "#ffffff", correctLevel: QRCode.CorrectLevel.L });
由于这个img是动态变化的,我们获取base64字串的时候一定要在该img的onload事件的回调内去获取,这点非常重要:
function buildQr () { var img = qrcode.querySelector('img'); img.onload = function() { qrdata = img.src; main(); }; qr.makeCode(myqr.value); }
ok,准备工作都完成了,接下来我们需要开始初始化我们的插件了,我预先埋下了很多可配置的参数:
var canvasImg = null; function main() { //初始化 canvasImg = new LCanvasImg({ cw: 768,//canvas width ch: 1163,//canvas height iw: '100%',//output img width ih: 'auto',//output img height display:'none'//canvas display }); //资源加载 canvasImg.load([{ name: 'qr', src: qrdata }, { name: 'bg', src: '../img/bg.jpg' }, { name: 'z', src: '../img/z.png' }], build); };
看见上面的build变量了吗?我们将图片生成逻辑全部写在这个build方法中,在load资源complete后,会执行build;
function build() { var farr = [{ txt: document.querySelector('#mytxt1').value, fontsize: 26, fontfamily: 'fzjt', ftop: 140, fleft: 194 }, { txt: '胡鑫', fontsize: 26, fontfamily: 'fzjt', ftop: 220, fleft: 394 }, { txt: '邓逸昕', fontsize: 26, fontfamily: 'fzjt', ftop: 220, fleft: 294 }, { txt: document.querySelector('#mytxt1').value, fontsize: 26, fontfamily: 'fzjt', ftop: 220, fleft: 194 }]; canvasImg.addImg({ name: 'bg', x: 0, y: 0, width: 768, height: 1163 }); farr.forEach(function(obj) { canvasImg.addFont(obj); }); canvasImg.addImg({ name: 'z', x: 0, y: 0, width: 100, height: 100 }); canvasImg.addImg({ name: 'z', sx: 0, sy: 0, sw: 150, sh: 150, x: 100, y: 100, width: 100, height: 100 }); canvasImg.addImg({ name: 'qr', x: 400, y: 800, width: 200, height: 200 }); }; window.onload = buildQr;
最后一句话非常重要,为什么这里我需要用window.onload事件,如果你使用的是webfont,当webfont下载成功后,其实还有一小段时间需要将font字体载入进浏览器中,只有在window.onload事件时,webfont字体文件才能生效。
最后奉上效果截图:
整个demo已经上传至github上了,如果需要做类似需求的同学可以下载该插件,可以节约大家许多时间
资源地址:https://github.com/xfhxbb/LCanvasImg
以上就是本文的全部内容,希望本文的内容对大家的学习或者工作能带来一定的帮助,同时也希望多多支持!
免责声明:本站资源来自互联网收集,仅供用于学习和交流,请遵循相关法律法规,本站一切资源不代表本站立场,如有侵权、后门、不妥请联系本站删除!
P70系列延期,华为新旗舰将在下月发布
3月20日消息,近期博主@数码闲聊站 透露,原定三月份发布的华为新旗舰P70系列延期发布,预计4月份上市。
而博主@定焦数码 爆料,华为的P70系列在定位上已经超过了Mate60,成为了重要的旗舰系列之一。它肩负着重返影像领域顶尖的使命。那么这次P70会带来哪些令人惊艳的创新呢?
根据目前爆料的消息来看,华为P70系列将推出三个版本,其中P70和P70 Pro采用了三角形的摄像头模组设计,而P70 Art则采用了与上一代P60 Art相似的不规则形状设计。这样的外观是否好看见仁见智,但辨识度绝对拉满。
更新日志
- 凤飞飞《我们的主题曲》飞跃制作[正版原抓WAV+CUE]
- 刘嘉亮《亮情歌2》[WAV+CUE][1G]
- 红馆40·谭咏麟《歌者恋歌浓情30年演唱会》3CD[低速原抓WAV+CUE][1.8G]
- 刘纬武《睡眠宝宝竖琴童谣 吉卜力工作室 白噪音安抚》[320K/MP3][193.25MB]
- 【轻音乐】曼托凡尼乐团《精选辑》2CD.1998[FLAC+CUE整轨]
- 邝美云《心中有爱》1989年香港DMIJP版1MTO东芝首版[WAV+CUE]
- 群星《情叹-发烧女声DSD》天籁女声发烧碟[WAV+CUE]
- 刘纬武《睡眠宝宝竖琴童谣 吉卜力工作室 白噪音安抚》[FLAC/分轨][748.03MB]
- 理想混蛋《Origin Sessions》[320K/MP3][37.47MB]
- 公馆青少年《我其实一点都不酷》[320K/MP3][78.78MB]
- 群星《情叹-发烧男声DSD》最值得珍藏的完美男声[WAV+CUE]
- 群星《国韵飘香·贵妃醉酒HQCD黑胶王》2CD[WAV]
- 卫兰《DAUGHTER》【低速原抓WAV+CUE】
- 公馆青少年《我其实一点都不酷》[FLAC/分轨][398.22MB]
- ZWEI《迟暮的花 (Explicit)》[320K/MP3][57.16MB]