js生成二维码、合成图片及js压缩图片

近期接到几个功能类似的需求,都是js处理图片相关的,在开发过程中踩了一些坑,现在把过程记录下来。

第一个需求是后端返回包含底图和二维码的数据列表,要将二维码绘制到底图对应的区域,图片使用canvas来进行绘制
首先创建画布

    var width = $('#img_list li').width()
    var height = $('#img_list li').height()
    var canvas= document.createElement("canvas");
    canvas.width = width;
    canvas.height = height;
    var context = canvas.getContext("2d");
    context.rect(0, 0, canvas.width, canvas.height);
    context.fill();

这里就踩了一个坑,因为 $('#img_list li') 是从后端获取数据之后循环的,所以在一开始是无法获取到宽高的,当时绘制完成列表上怎么都不出来图片,后面才发现这个问题,所以在创建画布的时候一定要保证宽高是有值的。
下面是将图片绘制到画布上,这里不能直接使用图片,要先new图片对象,在对象的onload事件里进行绘制,

      var myImage = new Image();
      myImage.setAttribute('crossOrigin', 'anonymous')
      myImage.src = image;
      myImage.onload = function () {
        context.drawImage(myImage, 0, 0, width, height);
        var myImage2 = new Image();
        myImage2.setAttribute('crossOrigin', 'anonymous')
        myImage2.src = qrcode;
        myImage2.onload = function () {
          var x = width * 0.205
          var y = height * 3.39
          var w_ = height / 8
          var h_ = height / 8
          context.drawImage(myImage2, x, y, w_, h_);
        }
      }

context.drawImage(myImage, 0, 0, width, height)是将图片在canvas上进行绘制,方法的五个参数分别是(绘制的文件,绘制起点在画布的X轴坐标,Y轴坐标,绘制图片的宽,高)。
这里又有一个坑,如果图片是非本地图片,将会出现图片跨域的情况不能直接使用,首先要后端先配置好允许图片跨域,我这边是后端给nginx加跨域处理,然后前端需要加

myImage.setAttribute('crossOrigin', 'anonymous')

现在已经绘制完成了,但是现在是canvas,用户不能下载,需求是要用户能下载合成之后的图片,那就将canvas转成base64,再赋值给图片的URL。

var base64 = canvas.toDataURL("image/png");
var img = document.getElementById('avatar');
img.setAttribute('src', base64);

现在就可以进行下载了。

第二个需求是前端生成带logo的二维码,这次的底图是固定的所以就存在前端,不会存在图片跨域的问题,绘制方法跟前面一样,所以只考虑生成二维码的问题,二维码的生成工具很多,但大都不能带二维码,本次生成使用了 jquery.qrcode.js

$("#qrcode").qrcode({ 
    render: "canvas",
    text: val, // 二维码携带的参数
    width : "180", // 二维码的宽度 
    height : "180", // 二维码的高度 
    background : "#ffffff", // 二维码的后景色 
    foreground : "#000000", // 二维码的前景色 
    quiet: 1, // 边距
    mode: 4,
    mSize: 11 * 0.01,
    mPosX: 50 * 0.01,
    mPosY: 50 * 0.01,
    image: $('#logo')[0] // 二维码中间的图片 
}); 

二维码生成完成,然后就是图片合成以及canvas转图片下载,文章前面已经有记录就不在重复。

第三个需求是OCR车牌识别功能,客户在C端进行拍照上传识别车牌号码,现在市面上的手机像素都很高,一张照片小则4、5M,大则10+M,在上传的时候比较慢而且浪费流量,OCR接口也要求图片必须小于3M,所以压缩图片就是非常必要的操作了,压缩还是使用canvas。

<input ref="uploadFile" type="file" @change="checkImg" accept="image/*" capture="camera" class="upload">

let formData = new FormData()
let files = this.$refs.uploadFile.files
let size = files[0].size / 1024 / 1024

根据size来判断大小,小于3M直接走上传流程,大于3M就进行压缩。

let divisor =  Math.ceil(size / 3)  // 文件大于3M,向上取整,倍数压缩
var oFile = files[0];
var reader = new FileReader();
reader.onload=function(){
    var oImg = new Image();
    oImg.src = this.result;
    oImg.style.display = "none"
    document.body.appendChild(oImg);
    oImg.onload = function(){
        var imgWidth = this.width
        var imgHeight = this.height
        var w = imgWidth / divisor;
        var h = imgHeight / divisor;
        var canvas = document.createElement('canvas');
        var ctx = canvas.getContext('2d');
        var anw = document.createAttribute("width");
        anw.nodeValue = w;
        var anh = document.createAttribute("height");
        anh.nodeValue = h;
        canvas.setAttributeNode(anw);
        canvas.setAttributeNode(anh);
        ctx.fillRect(0, 0, w, h);
        ctx.drawImage(oImg, 0, 0, w, h);
        const base64 = canvas.toDataURL('image/jpeg', 0.75); // 压缩后质量
        that.uploadFile(that.dataURLtoFile(base64))  // base64转文件 - 然后上传
    };
};
reader.readAsDataURL(oFile);

dataURLtoFile (dataurl) { // base64转文件
    let arr = dataurl.split(',')
    let mime = arr[0].match(/:(.*?);/)[1]
    let suffix = mime.split('/')[1]
    let bstr = atob(arr[1])
    let n = bstr.length
    let u8arr = new Uint8Array(n)
    while (n--) {
        u8arr[n] = bstr.charCodeAt(n)
    }
    return new File([u8arr], `file.${suffix}`, {
        type: mime
    })
 }

最后将base64转回文件方便上传。

©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 213,928评论 6 493
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 91,192评论 3 387
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 159,468评论 0 349
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 57,186评论 1 286
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 66,295评论 6 386
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 50,374评论 1 292
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 39,403评论 3 412
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 38,186评论 0 269
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 44,610评论 1 306
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 36,906评论 2 328
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 39,075评论 1 341
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 34,755评论 4 337
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 40,393评论 3 320
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 31,079评论 0 21
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,313评论 1 267
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 46,934评论 2 365
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 43,963评论 2 351

推荐阅读更多精彩内容