接着图片选取完成后canvas_puzzle.init()
var canvas_img=[];
...
var canvas_puzzle= function() {
return {
init : function() {
var img_list=document.querySelectorAll('.middleware_img');
//第一张作为背景图片
canvas_img[0]=new canvasImg.Img($('puzzle_bg'), {});
avalon.each(img_list,function(i,el){
canvas_img.push(new canvasImg.Img(el, {}));
canvas.addImage(canvas_img[i+1]);
});
canvas.setCanvasBackground(canvas_img[0]);
...
}
};
}();
Canvas.Element.prototype.addImage = function(oImg) {
if(isEmptyObject(this._aImages))
this._aImages = [];
this._aImages.push(oImg);
this.renderAll(false,true);
};
_aImages是保存canvas图片封装的数组,renderAll()方法很重要,后面会说到。
canvas.setCanvasBackground(canvas_img[0])将背景图片绘制到canvas
Canvas.Element.prototype.setCanvasBackground = function(oImg) {
this._backgroundImg = oImg;
var originalImgSize = oImg.getOriginalSize();
this._oContextBackground.drawImage(oImg._oElement, 0, 0, originalImgSize.width,
originalImgSize.height);
};
Canvas.Img.prototype.getOriginalSize = function() {//获得canvas尺寸
return { width: this._oElement.width, height: this._oElement.height }
};
canvas事件操作
mousedown
Canvas.Element.prototype.onMouseDown = function(e) {
$('canvas_menu').style.display="none";
var mp = this.findMousePosition(e);//鼠标相对位置
if (this._currentTransform != null || this._aImages == null) {
return;
}
var oImg = this.findTargetImage(mp, false);//获取目标图片
//事件触发位置是不是在4个角上
var action = (!this.findTargetCorner(mp, oImg)) ? 'drag' : 'rotate';
if (action == "rotate") {
this.onRotateMove.fire(e);//触发自定义事件
} else if (action == "drag") {
this.onDragMove.fire(e);
}
this._prevTransform=this._currentTransform = {
target: oImg,
action: action,
scalex: oImg.scalex,
offsetX: mp.ex - oImg.left,
offsetY: mp.ey - oImg.top,
ex: mp.ex, ey: mp.ey,
left: oImg.left, top: oImg.top,
theta: oImg.theta
};
//设置菜单位置
$('canvas_menu').style.transform='rotate('+oImg.theta*180/3.14+'deg)';
$('canvas_menu').style.left=oImg.left+"px";
$('canvas_menu').style.top=oImg.top+"px";
this.renderAll(false,false);
};
this._prevTransform保存当前目标图片状态,替换图片时会用到这个变量
renderAll()方法是整个绘制的核心方法
Canvas.Element.prototype.renderAll=function(allOnTop,allowCorners) {
var containerCanvas=allOnTop?this._oContextTop:this._oContextContainer;
this._oContextTop.clearRect(0,0,parseInt(this._oConfig.width),parseInt(this._oConfig.height));
containerCanvas.clearRect(0,0,parseInt(this._oConfig.width),parseInt(this._oConfig.height));
if(allOnTop){//所有图片都要在最上面
var originalImgSize=this._backgroundImg.getOriginalSize();
//在最上层canvas绘制背景图片
this._oContextTop.drawImage(this._backgroundImg._oElement, 0, 0,
originalImgSize.width,originalImgSize.height);
}
for(var i=0,l=this._aImages.length-1;i<l;i+=1){
this.drawImageElement(containerCanvas,this._aImages[i],allowCorners);
}
var last_aImages=this._aImages[this._aImages.length-1];
this.drawImageElement(this._oContextTop,last_aImages ,allowCorners);
};
可以看到,如果allOnTop=false,从_aImages封装图片的数组的第一个元素到倒数第二个元素,会绘制到中间一层container-canvas,而_aImages数组的最后一个元素,即当前操作的图片,会绘制到最上面一层top-canvas,当然如果改变操作对象,_aImages数组也会相应的变化,保证当前操作的图片在_aImages数组的最后一个位置。
如果allOnTop=true,_aImages数组中的所有图片还有背景图片都会被绘制到最上面一层top-canvas.
设置allOnTop参数的目的在于上传时只有所有图片都在一个canvas context上,调用toDataURL()方法,就能获得整个拼图的base64字符串。
第二个参数allowCorners表示绘制时是否添加边框,边角。
前面将选中图片及背景图片绘制到canvas,最后this.renderAll(false,true)让边框,边角可见,是为了让用户知道图片可以进行操作。
Canvas.Element.prototype.addImage = function(oImg) {
...
this.renderAll(false,true);
};