使用canvas合成图片并得到的启发

来源:互联网 发布:淘宝网天猫下载 编辑:程序博客网 时间:2024/05/22 19:35

以前我也写过图片合成的简单实现,但是人是不断进步的,经过一系列的学习和研究,终于得到了较好的合成图片的方案。
图片合成本身没什么难点,但是想写好图片合成并不容易,就好像js入门容易,但是想成为大神难。
言归正传:
我的这个版本的代码不仅是图片合成,而且还有模块化编程,图片加载,回调函数等知识点。
首先要讲的是图片加载,为什么先将图片加载,这是因为没有图片的加载,你就没办法完成图片的合成。
你如果自己写过图片操作的代码,就会明白代码执行在图片的加载完成之前,所以想要操作图片第一必须确保图片的加载完成后再进行图片的操作,所以有两种方法(本人的方法)可以实现这项功能,定时器函数和回调函数。
第一种使用回调函数:
推荐使用setInterval(),你需要先在外部定义一个标识,这个标识可以判断图片是否加载完成,例如我的代码中imagesLoaded。为什么可以用,首先你的代码比图片执行的快,但是定时却可以每隔一段时间就会执行一次,一直等到图片加载完成,再停止定时器,这是一种笨方法,但是逻辑简单。
第二种使用回调函数:
推荐这种方式,因为回调本来就是用来执行异步调用的,特别是onload事件,是在所有图片加载完成后执行的,这是一个很清楚的时机,所以使用callback函数可以简单方便的等待图片加载完成后再进行图片合成,但是如果你回调的函数中有this变量的话,你需要了解this的指向,例如我的代码中如果我不将this赋值给_this,那么imagesMerged 函数中的this指向的是handleLoadedImage 而不是MergeImages的原型对象,所以你必须特别注意这一点。
图片的加载必须是有序加载,否则图片合成的顺序会发生错误。

其次要讲的是模块化,为什么要模块话,当你的js文件足够多,足够大,难免有同名变量和同名函数,这时候,就会互相影响,产生极大的隐患,
js本身有命名空间,但是使用起来太过繁琐,所以推荐使用模块,不仅便于管理,而且便于使用,例如如果想使用我的代码,你只需要引入我的MergeImagePlain.js,在你的html文件有一个id=”showMergedImage”的img,最后在你的js文件中调用即可,例如我在自己的js文件中调用:

var imgs = ['imgs/icon3.png', 'imgs/icon1.png', 'imgs/icon2.png', 'imgs/sword.png'];    mergeImagesModule.mergeImages(imgs);

合成的图片的:
这里写图片描述

MergeImagePlain.js:

//将合成图片的功能函数合并为合成图片模块var mergeImagesModule = (function () {    //声明全局变量    var imgs_w = [];            //保存全部图片的宽度    var imgs_h = [];            //保存全部图片的高度    var imgObjs = [];           //保存全部图片的对象    // var mergedImageSrc = '';    //保存合成后图片的src    // var imagesLoaded = false;   //用于判断图片是否全部加载完毕    /*    *定义一个名为formatArray的函数,用于将任意类型的变量转换为数组变量    *@param     Everytype       param       任意类型的变量    *@return    array                       转换后的数组变量    */    function formatArray (param) {        if (!param) {            return [];        }        if (Array.isArray(param)) {            return param;        }        if (Array.from) {            return Array.from(param);        }        return [param];    }    /*    *定义一个名为getArrayMaxValue的函数,用于获取数组变量的最大值    *@param     Everytype       elems       任意类型的变量    *@return    maxVlue                     数组中的最大值    */    function getArrayMaxValue (elems) {        elems = formatArray(elems);        return Math.max.apply(null, elems);    }    /*    *定义一个名为MergeImages的函数,作为合成图片的实例原型    *@param     array           images      图片连接组成的数组    *@param     string          type        合成图片的类型    *@return    void    */    function MergeImages (images, type) {        try {            if (!images) {                throw 'MergeImages的images参数不能为空';            }            this.images = formatArray(images);            if (type && 'string'===typeof(type)) {                this.type = type;            } else {                this.type = "image/png";            }        } catch (err) {            console.log('Error:', err);        }    }    /*    *定义一个名为getImagesRealSizes的函数,作为合成图片的实例原型的函数,获取图片的信息    *@param     void    *@return    void    */    MergeImages.prototype.getImagesRealSize = function (callback) {        var _imgs = this.images,            imgs_len = _imgs.length;        var _this = this;        var count = 0;        //定义一个内部函数对图片进行有序加载        function orderedProloadImages () {            var imgObj = new Image();            imgObj.onload = handleLoadedImage;            imgObj.onerror = handleLoadedImage;            //定义一个函数作为图片的onload和onerror的事件函数            function handleLoadedImage () {                //保存图片的宽和高                imgs_w.push(this.width);                imgs_h.push(this.height);                imgObjs.push(this);                count = Math.min(imgs_len, ++count);                //判断图片是否加载完成                if (count < imgs_len) {                    orderedProloadImages();                } else {                    if ('function'===typeof(callback)) {                        callback.apply(_this);                    }                }            }            imgObj.src = _imgs[count];            imgObj = null;        }        orderedProloadImages();    }    /*    *定义一个名为imagesMerged的函数,作为合成图片的实例原型的函数,用于合成图片    *@param     void    *@return    string      url     合成图片的连接    */    MergeImages.prototype.imagesMerged = function () {        var imgs_len = this.images.length,            maxWidth = 0,            maxHeight = 0,            temp_w = 0,            temp_h = 0,            offset_w = 0,            offset_h = 0,            canvas = null,            cxt = null,            url = '',            srcType = this.type;        try{            //创建画布并设置画布的属性            canvas = document.createElement('canvas');            maxWidth = getArrayMaxValue(imgs_w);            maxHeight = getArrayMaxValue(imgs_h);            canvas.width = maxWidth;            canvas.height = maxHeight;            cxt = canvas.getContext('2d');            for (var i = 0; i < imgs_len; i++) {                //获取每张图片的宽高                temp_w = imgs_w[i];                temp_h = imgs_h[i];                //获取每张图片移动到画布中心需要移动的距离(top和left)                offset_w = Math.abs(maxWidth - temp_w) * 0.5;                offset_h = Math.abs(maxHeight - temp_h) * 0.5;                //在画布上一次将每张图片绘制到画布中                cxt.drawImage(imgObjs[i], 0, 0, temp_w, temp_h, offset_w, offset_h, temp_w, temp_h);            }            url = canvas.toDataURL(srcType);            cxt = null;            canvas = null;            var imgObj = document.getElementById("showMergedImage");            imgObj.src = url;            // return url;        } catch (err) {            console.log('error:', err);        }    }    /*    *定义一个名为init的函数,作为合成图片的实例原型的函数,用于调用原型对象上的函数合成图片    *@param     void    *@return    void    */    MergeImages.prototype.init = function () {        try {            this.getImagesRealSize(this.imagesMerged);            // var imgObj = document.getElementById("showMergedImage");            // console.log(this.getImagesRealSize(this.imagesMerged));            // imgObj.src = this.getImagesRealSize(this.imagesMerged);            //var _this = this;            //使用定时器等待图片加载完成并合成图片,将图片的连接传给一个特定的img元素            // var timer = setInterval(function () {            //     if (imagesLoaded) {            //         mergedImageSrc = _this.imagesMerged();            //         var imgObj = document.getElementById("showMergedImage");            //         imgObj.src = mergedImageSrc;            //         clearInterval(timer);            //         imgObj = null;            //     }            // }, 400);        } catch (err) {            console.log('error:', err);        }    }    return {        mergeImages: function (images, type) {            var mergeImages = new MergeImages(images, type);            mergeImages.init();        }    };})();
阅读全文
'); })();
0 0
原创粉丝点击
热门IT博客
热门问题 老师的惩罚 人脸识别 我在镇武司摸鱼那些年 重生之率土为王 我在大康的咸鱼生活 盘龙之生命进化 天生仙种 凡人之先天五行 春回大明朝 姑娘不必设防,我是瞎子 牛仔裙子太短怎么办 连衣裙买短了怎么办 裙子太短了怎么办 眼睛粘稠分泌物怎么办 黑色蕾丝裙子掉色怎么办 养泰迪屋里的味怎么办 3月泰迪体味重怎么办 狗狗出去溜脚脏怎么办 透明桌垫印了字怎么办 新黑色裤子褪色怎么办 黑衣服一直掉色怎么办 跑步鞋子勒脚脖子怎么办 背心领子大了怎么办 夏天吊带不敢穿怎么办? 黑衣服领子发黄怎么办 白毛衣晒黄了怎么办 英语作文写不好怎么办 领导问业绩不好怎么办 五年级语文不好怎么办 英语总学不好怎么办 蝴蝶翅膀断了怎么办 手机变成黑白色怎么办 想在澳门呆久点怎么办 漩涡鸣人素描怎么办 换盆后的多肉怎么办 多肉繁殖太多怎么办 小店不给退衣服怎么办 君子兰6月开花怎么办 君子兰底叶黄了怎么办 君子兰叶子长斑怎么办 水梅花叶子黄了怎么办 金钱桔掉叶子怎么办 凤仙花叶子掉了怎么办 指甲花不开花怎么办 四季海棠水浇多了怎么办 凤仙花主干枯了怎么办 海棠树叶子枯萎怎么办 海棠浇水多了怎么办 吃梅豆角中毒怎么办 凤仙花叶子发黄发蔫怎么办 新几内亚凤仙蔫了怎么办