共计 4010 个字符,预计需要花费 11 分钟才能阅读完成。
本文简介
点赞 + 关注 + 珍藏 = 学会了
学习 Fabric.js
,我的倡议是看文档不如看 demo。
本文实现的性能:将元素拖进到画布中并生成对应的图形或图片。
成果如下图所示:
思路
要实现以上成果,须要思考以下几点:
- 元素有拖拽性能。
- 能在画布中生成对应的元素。
- 画布有可能缩放。
- 画布有可能挪动。
- 画布的地位可能在页面的某处。
- 在 3 和 4 状况下还能在精确的地位生成元素。
基于以上几点,我得出以下解法。
- 解 1:要让
HTML
元素具备拖拽性能,只有将draggable
属性设置为true
即可。 - 解 2:
Fabric.js
创立元素可看《Fabric.js 从入门到收缩》的根底图形篇,要创立图片能够看 图片篇。 - 解 3:缩放画布我在《Fabric.js 缩放画布》里解说过。
- 解 4:挪动画布我在《Fabric.js 拖拽平移画布》里解说过。
- 解 5:画布的左上角不肯定在 body 的左上角,也就是鼠标以后地位可能和画布对应的坐标不一样,须要通过加减法计算一下。
- 解 6:
Fabric.js
提供了一个办法能够将鼠标以后坐标转换为画布对应的实在坐标,这个办法叫restorePointerVpt
。
入手
我分几个步骤缓缓实现上述性能。我晓得你很急,但你先别急
创立画布及元素
<div class="box">
<div class="data_list">
<div class="data_item rect" draggable="true"></div>
<div class="data_item circle" draggable="true"></div>
<div class="data_item img" draggable="true"></div>
</div>
<canvas id="c" style="border: 1px solid #ccc;"></canvas>
</div>
<script src="https://unpkg.com/fabric@5.2.1/dist/fabric.min.js"></script>
<script>
let canvas = null
// 初始化画布
function initCanvas() {
// 创立画布
canvas = new fabric.Canvas('c', {
width: 800,
height: 600
})
// 矩形
const rect = new fabric.Rect({
top: 30,
left: 30,
width: 60,
height: 60,
fill: 'pink'
})
// 将矩形增加到画布中
canvas.add(rect)
// 接下来 3 个事件监听的次要性能是挪动画布,在按住 alt 后鼠标能够拖拽画布
// 按下鼠标事件
canvas.on('mouse:down', function (opt) {
var evt = opt.e;
if (evt.altKey === true) {
this.isDragging = true
this.lastPosX = evt.clientX
this.lastPosY = evt.clientY
}
})
// 挪动鼠标事件
canvas.on('mouse:move', function (opt) {if (this.isDragging) {
var e = opt.e;
var vpt = this.viewportTransform;
vpt[4] += e.clientX - this.lastPosX
vpt[5] += e.clientY - this.lastPosY
this.requestRenderAll()
this.lastPosX = e.clientX
this.lastPosY = e.clientY
}
})
// 松开鼠标事件
canvas.on('mouse:up', function (opt) {this.setViewportTransform(this.viewportTransform)
this.isDragging = false
})
// 监听鼠标滚轮缩放事件,能够缩放画布
canvas.on('mouse:wheel', opt => {
const delta = opt.e.deltaY // 滚轮,向上滚一下是 -100,向下滚一下是 100
let zoom = canvas.getZoom() // 获取画布以后缩放值
zoom *= 0.999 ** delta
if (zoom > 20) zoom = 20 // 限度最大缩放级别
if (zoom < 0.01) zoom = 0.01 // 限度最小缩放级别
// 以鼠标所在位置为原点缩放
canvas.zoomToPoint(
{ // 关键点
x: opt.e.offsetX,
y: opt.e.offsetY
},
zoom // 传入批改后的缩放级别
)
})
}
initCanvas()
</script>
下面的代码应用了 Fabric.js
绑定了页面上的画布,并发明了一个粉红色的矩形。
按住 alt
后,应用鼠标在画布上能够拖拽画布。
在画布上滚动鼠标滚轮能够缩放画布。
左侧的元素列表也将 draggable
属性设置为 true
,元素具备拖拽性能了。
监听元素放进画布
咱们还须要应用一个变量来记录以后拖拽的是什么元素。
<!-- 省略局部代码 -->
<div class="data_list">
<div class="data_item rect" draggable="true" ondragstart="onDragstart('rect')"></div>
<div class="data_item circle" draggable="true" ondragstart="onDragstart('circle')"></div>
<div class="data_item img" draggable="true" ondragstart="onDragstart('img')"></div>
</div>
<script>
let currentElType = null // 以后要创立的元素类型
// 拖拽开始时就记录以后打算创立的元素类型
function onDragstart(type) {currentType = type}
</script>
后面的代码曾经晓得拖拽时须要生成什么类型的元素了,当初还须要晓得生成到画布的哪个中央(x 和 y 坐标)
松开鼠标时,须要计算鼠标在画布的坐标。这里的坐标是指画布在页面中的地位转换进去的坐标,而且还要计算画布拖拽和缩放过的状况。
我的做法是通过 canvas
元素的 getBoundingClientRect()
办法返回的对象中获取到 top
和 left
两个数据。这两个数据就是 canvas
元素间隔页面顶部和左侧的间隔。
而后通过鼠标以后坐标减去 canvas
间隔页面顶部或左侧的间隔,计算出鼠标点击画布的实在坐标。
但画布有可能拖拽和缩放,所以须要通过 Fabric.js
提供的 restorePointerVpt()
办法将坐标转换一下。
于是有了上面的代码。
// 省略局部代码......
canvas.on('drop', function(opt) {
// 画布元素间隔浏览器左侧和顶部的间隔
let offset = {left: canvas.getSelectionElement().getBoundingClientRect().left,
top: canvas.getSelectionElement().getBoundingClientRect().top
}
// 鼠标坐标转换成画布的坐标(未通过缩放和平移的坐标)let point = {
x: opt.e.x - offset.left,
y: opt.e.y - offset.top,
}
// 转换后的坐标,restorePointerVpt 不受视窗变换的影响
let pointerVpt = canvas.restorePointerVpt(point)
})
生成对应的元素
下面的代码最初得出的 pointerVpt
就是转换后最终的坐标,咱们在这个坐标上生成元素即可。
// 省略局部代码......
canvas.on('drop', function(opt) {
// 省略局部代码......
switch (currentType) {
case 'rect':
createRect(pointerVpt.y, pointerVpt.x)
break
case 'circle':
createCircle(pointerVpt.y, pointerVpt.x)
break
case 'img':
createImg(pointerVpt.y, pointerVpt.x)
break
}
// 创立完元素,把以后操作的元素类型设置回 null
currentElType = null
})
// 创立矩形
function createRect(top, left) {
canvas.add(new fabric.Rect({
top,
left,
width: 60,
height: 60,
fill: 'pink'
}))
}
// 创立圆形
function createCircle(top, left) {
canvas.add(new fabric.Circle({
top,
left,
radius: 30,
fill: 'pink'
}))
}
// 创立图片元素
function createImg(top, left) {
fabric.Image.fromURL('./picture.jpg', oImg => {
oImg.top = top
oImg.left = left
canvas.add(oImg)
})
}
代码仓库
后面都是碎碎念,代码一段一段的。如果须要完整版代码能够关上链接自取。
⭐ Fabric.js 拖拽创立元素
举荐浏览
👍《Fabric.js 橡皮擦的用法(蕴含复原性能)》
👍《Fabric.js 监听元素相交(重叠)》
👍《Fabric.js 自定义子类,创立属于本人的图形》
👍《Fabric.js 自在绘制圆形》
👍《Fabric.js 缩放画布》
👍《Fabric.js 变换视窗》
👍《Fabric.js 拖拽平移画布》
点赞 + 关注 + 珍藏 = 学会了
代码仓库