Fabric.js进阶自订控制项
2018-11-28 12:57:07
2912次阅读
0个评论
今天要来做更进阶的自订控制项,不只能够修改内建的一些样式,够能够让我们使用自己想要的图示来做控制项,甚至变更每个控制项的功能。
今日就来做把左上控制项改成删除功能。
物件控制一些基础样式调整可以参考
Day 15 - Fabricjs 物件控制项样式调整
透过复写原本的方法
因為 fabricjs 并没有提供 api 能够让我们去改变物件的控制项,所以我们必须透过复写原来 fabricjs 所绘画控制项的方法,来达到自订控制项的目的。
这边讲一下自己再复写的心得,到 fabricjs docs 找有没有对应的方法。可以看到我找到了 Object.drawControls 这个方法。
接著看到的 Source 点选 line 15906 连结可观看 fabricjs 原始码这个方法的所在地。
点选 line 15906
![](http://api.321332211.com/file/topic/2018-11-28/image/bf0a189c93964792a6820b1410876ed9a02f7101c7497468fb0991238464e5669.png)
就能看到 drawControls 原本的样貌啦
![](http://api.321332211.com/file/topic/2018-11-28/image/f7e0cefa83eb4fb7a111be6808cd57c8a02f7101c7497468fb0991238464e5669.png)
复写 fabric.Object.prototype.drawControls
我们想要做的是改变所有產生出来的物件的控制项,所以我们必须要来复写 fabricjs 原本画出控制项的方法。
也就是 fabric.Object.prototype.drawControls,这个方法為 fabricjs 原本画出控制项图示的方法。
再覆盖之前,我们得先去参考原本的写法如何,再来做客製化修改。
Fabricjs 原始码 #line15906 drawControls
// 变更所有物件画出的控制项
fabric.Object.prototype.drawControls = function (ctx, styleOverride) {
// 复写他,改成什麼都不画
}
const rect = new fabric.Rect({
width: 100,
height: 100,
left: 100,
top: 100
})
canvas.add(rect)
可看到因為把 drawControls 覆盖过去了,所以看不到任何控制项。
![](http://api.321332211.com/file/topic/2018-11-28/image/950f68c24948480c948271897d816af0a02f7101c7497468fb0991238464e5669.png)
接著直接将
fabricjs drawControls method source: http://fabricjs.com/docs/fabric.js.html#line15906
整段 call 下来复写,就会正常画出控制项了。
接著分析一下原始码,可以发现控制向都是透过一个名為 _drawControl 的私有函数所画出来的。
// top-left
this._drawControl('tl', ctx, methodName,
left,
top, styleOverride);
把任何一个拿掉就会少掉那一个控制项。
接著我们把原本的 _drawControl 拿掉,换成我们自己的方式画出控制项。
// top-left
const cancel = new Image()
cancel.src = 'https://upload.wikimedia.org/wikipedia/commons/6/65/Crystal_button_cancel.svg'
ctx.drawImage(cancel, left, top, this.cornerSize, this.cornerSize)
OK,这样一来,就能够有自己定义的控制项图示了。
![](http://api.321332211.com/file/topic/2018-11-28/image/6243410d3968415885b0b2df781a7879a02f7101c7497468fb0991238464e5669.png)
不过这时我们是想将左上角的控制向改成删除的功能,但发现只是改变了图示,并没有连功能都一起被改变。
再次来复写 fabric.Object 的 prototype
接下来来改写原本是缩放功能的控制项,改成删除的功能。
一样先看了 fabricjs doc 不过发现好像没有什麼线索,只好透过 google 大神。
大神告诉我 _getActionFromCorner 这个方法,看起来就像是我们所需要的,稍微在看了一下 fabricjs 原始码,大概了解了前因后果。
__onMouseDown 当在 canvas 中点下后触发。其中就判断一些你是否点在物件上,若点选在物件上则触发 _setupCurrentTransform 来设定接下来要转变资讯。
_setupCurrentTransform 设定转变资讯,其中有一个 _getActionFromCorner 方法判断点选的控制项使用什麼方法。
_getActionFromCorner 纪录会做的动作,因為原本的控制项就只有缩放和旋转,都只是在之后 mousemove 发生时会做的动作,所以只有纪录接下来会发生甚麼事情,而我们要改变的删除方法,加在这边就可以了。
复写 fabric.Canvas.prototype._getActionFromCorner
这边很简单就复写 _getActionFromCorner 方法,在 switch case 加上自己自订的方法就可以了。
fabric.Canvas.prototype._getActionFromCorner = function(target, corner, e) {
if (!corner) {
return 'drag';
}
switch (corner) {
case 'mtr':
return 'rotate';
case 'ml':
break;
case 'mr':
return e[this.altActionKey] ? 'skewY' : 'scaleX';
case 'mt':
case 'mb':
return e[this.altActionKey] ? 'skewX' : 'scaleY';
case 'tl': // 增加左上删除动作
canvas.remove(target)
return 'deleted'
default:
return 'scale';
}
}
改变鼠标样式
最后我们将原本缩放的箭头样式,改成手指 pointer 样式。
直接修改 fabric.Canvas.prototype.cursorMap 这个阵列就可以了。
var cursorOffset = {
mt: 0, // n
tr: 1, // ne
mr: 2, // e
br: 3, // se
mb: 4, // s
bl: 5, // sw
ml: 6, // w
tl: 7 // nw
}
fabric.Canvas.prototype.cursorMap[7] = 'pointer'
参考 fabricjs 原始码 #line10929
这样就完成客製化自己的控制项囉,将左上角改為删除功能
![](http://api.321332211.com/file/topic/2018-11-28/image/c8058de7ffef44669cd53bcc952c33ada02f7101c7497468fb0991238464e5669.gif)
本日小结
fabricjs 对使用自订控制项,并没有提供简易的 api 来变换控制项。
但还是能透过修改原本 fabricjs 提供的方法来达到需求。
缺点是若版本不同,作法可能会不同,因為不是正规提供的方法,且要复写必须要深入 fabricjs 原始码了解原本写法,较麻烦。
但有人提供了一个良好的解决方案 - fabricjs-customise-controls-extension
来解决这个问题,明天再来介绍。
价值 $150 的问题
Ability to customize controls $150
有人悬赏了 150 美元為了解决这个问题,其实一些 fabricjs 主要的贡献者也有想要修改此问题,加入能够让开发者好用的 api,从 2015 年就开始讨论此问题 (客製化 controls icon & 功能),不过到现在还没有被完美的被解决。
贡献者表示他还有其他更重要的事情要做 XD
![](http://api.321332211.com/file/topic/2018-11-28/image/9de8e4c444184258ac9510ef1638285ba02f7101c7497468fb0991238464e5669.png)
最新的进展是写上面那个 extension 的人想协助将套件加入 fabricjs 核心,不过因為一直在更新似乎还没有看到结果。
写这篇文章时版本為 2.4.3
00