canvas教程

TheViper的技术博客

字号+ 作者:H5之家 来源:H5之家 2016-01-15 13:28 我要评论( )

自由拼图? 自由拼图是美图秀秀中的一个功能,它可以让用户在背景图片上插入自己的图片,并可以对插入图片旋转,拖拽,缩放。当然,如果用户对插入的图片不满意,

自由拼图?

自由拼图是美图秀秀中的一个功能,它可以让用户在背景图片上插入自己的图片,并可以对插入图片旋转,拖拽,缩放。当然,如果用户对插入的图片不满意,可以用另一张图片替换选中的图片,或者删除选中图片。

效果

本屌之前用actionscript实现过,参见仿美图秀秀的自由拼图(注意里面基本上没代码说明).
这里用html5的canvas实现。


这个是本屌博客园去年一篇文章的效果,内容也是说的这个,不过很无耻的只贴了代码,没有任何说明。
下面的是录制的效果视频
==.html

布局 <div ms-controller='html5_puzzle'> <div> <ul> <li> <img src='imgs/small_img/1.jpg'> ... </li> </ul> </div ><div> <div> <canvas></canvas> <img> <img> ... <div> <a href='javascript:void(0)'>删除</a> <a href='javascript:void(0)'>更改图片</a> </div> <img src="imgs/1.jpg"/> <canvas></canvas> </div> </div> <div> <a href="javascript:;"> <span>添加</span> <input type="file" multiple=""> </a ><a>上传</a> </div> </div> 读取选中图片 var img_upload_instance=new img_upload({ add_btn:'puzzle_add', onSelect:onSelect//读取图片回调 }); define("html5_imgupload",["avalon-min"], function(avalon){ var html5_img_upload=function(options){ this.init(options); } html5_img_upload.prototype = { init : function(options) { //如果有自定义属性,覆盖默认属性 avalon.mix(html5_img_upload.prototype,options); this.init_events(); }, init_events : function() { var _this=this; avalon.bind($(this.add_btn),'change',function(e) { _this.get_files(e); }); }, file_filter:[], ori_images:[], add_btn:null, upload_btn:null, max_upload_num:9, onSelect:function(file_filter){}, _start:0,//已经读取图片数量 filter:function(files) { var arrFiles=[]; for (var i=0,file;file=files[i];i++){ if(this._start+i<this.max_upload_num){ if(file.type.indexOf("image")==0||(!file.type&&/\.(?:jpg|png|gif)$/. test(file.name))) arrFiles.push(file); else { alert('文件'+file.name+'不是图片'); } }else{ alert('一次最多能上传'+this.max_upload_num+'张图片'); break; } } return arrFiles; }, get_files:function(e) { var files=e.target.files||e.dataTransfer.files; this.file_filter=this.file_filter.concat(this.filter(files)); this.onSelect(this.file_filter); }, destroy_hook:function(){}, _destroy:function(){ this.file_filter=[]; $(this.add_btn).value=''; this.ori_images=[]; this._start=0; this.destroy_hook(); }, upload:function(i,file_filter){} }; return html5_img_upload; });

自定义图片选取回调

<div> <div> <canvas></canvas> <img ms-repeat='middleware_list' ms-attr-src='el'> ... </div> </div> function onSelect(file_filter){ for(var i=this._start,len=file_filter.length;i<len;i++) {//遍历选中图片 var reader=new FileReader(); reader.onload=(function(i){//图片读取的回调 return function(e){ var dataURL=e.target.result,canvas_middleware=$('canvas_middleware'), ctx=canvas_middleware.getContext('2d'),img=new Image(); img.onload = function() {//图片加载的回调 if(img.width>200||img.height>200){//等比例缩放 var prop=Math.min(200/img.width,200/img.height); img.width=img.width*prop; img.height=img.height*prop; } //设置中转canvas尺寸 canvas_middleware.width=img.width; canvas_middleware.height=img.height; ctx.drawImage(img, 0, 0, img.width, img.height); //将读取图片转换成base64,写入.middleware_list的src html5_puzzle.middleware_list.push(canvas_middleware. toDataURL("image/jpeg")); if(!file_filter[i+1]){ //图片延迟加载到canvas,因为canvas有个读取过程,但是没有回调 var t = window.setTimeout(function() { canvas_puzzle.init(); clearTimeout(t); }, 1000); } }; img.src = dataURL; }; delete reader; })(i); reader.readAsDataURL(file_filter[i]);//开始读取图片 } this._start=0; img_upload_instance._destroy(); } canvas初始化 var canvas = new canvasElement.Element(); canvas.init('main_canvas', { width : canvas_w, height : canvas_h }); Canvas.Element.prototype.init = function(el, oConfig) { if (el == '') { return; } this._initElement(el); this._initConfig(oConfig); this._createCanvasBackground(); this._createContainer(); this._initEvents(); this._initCustomEvents(); }; Canvas.Element.prototype._initElement = function(el) { this._oElement = document.getElementById(el); this._oContextTop = this._oElement.getContext('2d'); }; Canvas.Element.prototype._initCustomEvents = function() {//设置自定义事件 this.onRotateStart = new Canvas.CustomEvent('onRotateStart'); this.onRotateMove = new Canvas.CustomEvent('onRotateMove'); this.onRotateComplete = new Canvas.CustomEvent('onRotateComplete'); this.onDragStart = new Canvas.CustomEvent('onDragStart'); this.onDragMove = new Canvas.CustomEvent('onDragMove'); this.onDragComplete = new Canvas.CustomEvent('onDragComplete'); }; Canvas.Element.prototype._initConfig = function(oConfig) { this._oConfig = oConfig; this._oElement.width = this._oConfig.width; this._oElement.height = this._oConfig.height; this._oElement.style.width = this._oConfig.width + 'px'; this._oElement.style.height = this._oConfig.height + 'px'; }; Canvas.Element.prototype._initEvents = function() { var _this=this; avalon.bind(this._oElement,'mousedown',function(e){ _this.onMouseDown(e); }); avalon.bind(this._oElement,'mouseup',function(e){ _this.onMouseUp(e); }); avalon.bind(this._oElement,'mousemove',function(e){ _this.onMouseMove(e); }); }; Canvas.Element.prototype._createContainer = function() { var canvasEl = document.createElement('canvas'); canvasEl.id = this._oElement.id + '-canvas-container'; ... this._oContextContainer = oContainer.getContext('2d'); }; Canvas.Element.prototype._createCanvasBackground = function() { var canvasEl = document.createElement('canvas'); canvasEl.id = this._oElement.id + '-canvas-background'; ... this._oContextBackground = oBackground.getContext('2d'); };

可以看到初始化过程中多次创建<canvas>

从上到下:main_canvas->main_canvas-container-canvas->main_canvas-background-canvas

canvas context:

这下就看到canvas自由拼图的原理了,原来是3个canvas上下重叠起来,操作的时候对不同的canvas进行不同目标的绘制。

canvas绘制图片

 

1.本站遵循行业规范,任何转载的稿件都会明确标注作者和来源;2.本站的原创文章,请转载时务必注明文章作者和来源,不尊重原创的行为我们将追究责任;3.作者投稿可能会经我们编辑修改或补充。

相关文章
  • html5canvas核心技术图形、动画与游戏开发源码

    html5canvas核心技术图形、动画与游戏开发源码

    2017-05-02 17:42

  • 传智播客PHP培训 韩顺平 PHP视频教程 Ajax技术 课堂源代码.zip

    传智播客PHP培训 韩顺平 PHP视频教程 Ajax技术 课堂源代码.zip

    2017-04-26 16:00

  • canvas毛边的问题,大神求救!!!

    canvas毛边的问题,大神求救!!!

    2017-04-16 14:01

  • 使用CamanJS在Web页面上处理图像的技巧【站长博客网】

    使用CamanJS在Web页面上处理图像的技巧【站长博客网】

    2017-04-13 17:02

网友点评
w