什么是Fabric.js?
Fabric.js是一个可以简化Canvas程序编写的库。 Fabric.js为Canvas提供所缺少的对象模型, svg parser, 交互和一整套其他不可或缺的工具。由于Fabric.js为国外框架,官方API杂乱繁多,相关文档大多为英文文档,而且数量不多,这里是为了记录使用中遇到到的问题和解决办法。我所使用的场景是定制商品的编辑。网址http://www.dingbar.cn/mobiles/distributionsranks/index/18995.html
为什么要使用Fabric.js?
Canvas提供一个好的画布能力, 但是Api不够友好。绘制简单图形其实还可以, 不过做一些复杂的图形绘制, 编写一些复杂的效果,就不是那么方便了。Fabric.js就是为此而开发,它主要就是用对象的方式去编写代码。
Fabric.js能做的事情
在Canvas上创建、填充图形(包括图片、文字、规则图形和复杂路径组成图形)。
给图形填充渐变颜色。
组合图形(包括组合图形、图形文字、图片等)。
设置图形动画集用户交互。
生成JSON, SVG数据等。
生成Canvas对象自带拖拉拽功能。
1、定义canvas整体的属性
canvas.centeredScaling=true;//控制选中的对象缩放时原点为中心点。
canvas.controlsAboveOverlay=true;//指明对象的控制器(borders/controls)是否渲染在前景图片之上
canvas.preserveObjectStacking=true;//选中对象不会到最高层。
这些是比较常用的。
2、自定义对象控制边角的图标。
var O = new Image, N= new Image,Z = new Image,L = new Image;
L.src="";//使用base64格式图片赋值。
N.src = “”;
Z.src = “”;
O.src = “”;
分为设置了tr、br、tl、mtr
fabric.Canvas.prototype.cursorMap = [“default”, “default”, “default”, “default”, “default”, “default”, “default”, “default”];
fabric.Object.prototype._drawControl = function(e, t, i, a, r) {
var n = this.cornerSize;
if (this.isControlVisible(e)) {
this.transparentCorners || t.clearRect(a, r, n, n);
if (e == “tr” || e == “br” || e == “mtr”||e == “tl”) {
var o;
switch (e) {
case “tr”:
o = N;
break;
case “br”:
o = O;
break;
case “mtr”:
o = Z;
break;
case “tl”:
o = L;
break;
}
if (o !== false) {
t.drawImage(o, a, r,20, 20);
//t[i](a, r, n, n);
}
}
}
};
**3 事件**
canvas.on({//通用事件
"mouse:down": function(e) {
if (e.target != undefined) {
var ob = canvas.getActiveObject();
if(ob){
var i = e.transform.corner;
var text_img=0;
var imgsarr="";
if (i == "tr") {
this.del();
}
ob.set({
borderColor: "#ff4200",//设置边框颜色
cornerSize: 20,//设置大小
rotatingPointOffset: 5,
padding: 10,
borderDashArray: [3, 3],
snapAngle:45,//在45度时自动保持到45的倍数
snapThreshold: 15,
centeredRotation: true
});
}
}
}
});
snapAngle: 45,//在45度时自动保持到45的倍数
snapThreshold: 15,
centeredRotation: true
是否开启极轴追踪,就是在45度整数倍时会有停顿效果。类似于cad的极轴追踪功能。这个设置对于编辑设计有很大帮助,角度可以已实际项目来定。
4、canvas处理跨域问题需要
1、url=url+ ‘?v=’ + Math.random(); // 链接后加随机字符串处理缓存;
2、背景设置canvas.setBackgroundImage(url,
canvas.renderAll.bind(canvas),
{crossOrigin: ‘anonymous’}
);
3、对于苹果不支持crossOrigin: ‘anonymous’,需要先把图像转换成blob的格式才能使用。
var reader = new FileReader();
var that=this;
getImageBlob( url , function(blob){
reader.readAsDataURL(blob);
});
reader.onload = function(e) {
pugImg.src =e.target.result;
}
5对于json数据加载进来的对象,进行缩放
缩放
function zoomIt(factor) {
canvas.setHeight(canvas.getHeight() * factor);
canvas.setWidth(canvas.getWidth() * factor);
if (canvas.backgroundImage) {
// Need to scale background images as well
var bi = canvas.backgroundImage;
bi.width = bi.width * factor; bi.height = bi.height * factor;
}
var objects = canvas.getObjects();
for (var i in objects) {
var scaleX = objects[i].scaleX;
var scaleY = objects[i].scaleY;
var left = objects[i].left;
var top = objects[i].top;
var tempScaleX = scaleX * factor;
var tempScaleY = scaleY * factor;
var tempLeft = left * factor;
var tempTop = top * factor;
objects[i].scaleX = tempScaleX;
objects[i].scaleY = tempScaleY;
objects[i].left = tempLeft;
objects[i].top = tempTop;
objects[i].setCoords();
}
canvas.renderAll();
canvas.calcOffset();
}
6、选中对象,知道是在第几层。
选中的对象在canvas里的第几层canvas.getObjects().indexOf(ob);用于层的显示和修改。
7、当修改obj位置后,obj上无法选中问题。
是因为编辑框没有更新。使用.setCoords();更新编辑框的位置信息。
使用举例;ob.set({
top:200,
}).setCoords(); canvas.requestRenderAll();
7、替换图片src
var options = canvas.getActiveObject().toObject();
delete options.filters;
options.crossOrigin = true;
canvas.getActiveObject().setSrc(‘img/5.jpg’, function(){
canvas.renderAll();
}, options);
8、自定义属性在loadFromJSON的时候可以保留自定义属性
logo.toObject = (function (toObject) {
return function () {
return fabric.util.object.extend(toObject.call(this), {
dingversion: price,
});
};
})(logo.toObject);
canvas.add(logo);
logo为定义的对象。
在加入json对象的时候也需要再次绑定自定义属性,防止再次保存的时候丢失。
9、canvas.discardActiveObject();取消全部选中。
10、根据obj层数据,获取obj
var canvarObj=canvas.item(sortNums);
canvarObj.opacity=0.8;
canvas.setActiveObject(canvarObj);//设置选中
11、给canvas对象起名,然后名称找到对应canvas对象。自定义方法,通过名称在canvas中过滤出相应名称对象
fabric.StaticCanvas.prototype.getObjectByName = function(name){
if(!name || typeof name === ‘undefined’){
return [];
}
return this._objects.filter(function(o) {
return o.name === name;
});
}
var objectByName = canvas.getObjectByName(objectName); objectName为对象名称,objectByName为对应的canvas对象