库:GitHub - guanwanxiao/simplest-ts-environment at syq/canvasGitHub - fabricjs/fabric.js: Javascript Canvas Library, SVG-to-Canvas (& canvas-to-SVG) ParserGitHub - guanwanxiao/simplest-ts-environment at syq/canvas
官网:Fabric.js Javascript Canvas Library
中文文档:http://funcion_woqu.gitee.io/fabric-doc/api/#circle
问题list:
- npm/yarn安装后引入报错
- 控制器删除、旋转图标修改,边框样式修改
- 缩放最大最小倍数限制
- 添加图片跨域报错
- 调用canvas.toDataURl()报错
解决方案:
npm/yarn安装后引入报错
不管我用npm还是yarn安装,都报各种eslint或者webpack的错误,因为我的项目是服务端渲染,且项目配置都在别的库,不好修改,我用了github上两种导入方式都报错。
const fabric = require("fabric").fabric;
import { fabric } from "fabric";所以我最终用的bootcdn的线上地址来加载
<script
type="text/javascript"
src="https://cdn.bootcdn.net/ajax/libs/fabric.js/521/fabric.js"
/>
控制器删除、旋转图标修改,边框样式修改
看看fabric原生效果,和我们UI设计的效果对比
代码实现:
//删除图标实现代码
var delimg = document.createElement('img')
delimg.src = deletepng //deleteIcon
function renderDelIcon(ctx, left, top, styleOverride, fabricObject) {
var size = this.cornerSize
ctx.save()
ctx.translate(left, top)
ctx.rotate(fabric.util.degreesToRadians(fabricObject.angle))
ctx.drawImage(delimg, -size / 2, -size / 2, size, size)
ctx.restore()
}
fabric.Object.prototype.controls.deleteControl = new fabric.Control({
x: -0.5,
y: -0.5,//这里x y 的正负值代表4个角
cursorStyle: 'pointer',
mouseUpHandler: this.deleteObject,//点击事件
render: renderDelIcon,//渲染函数
cornerSize: 22,//这里是图片大小
})
//----------------------------------
//旋转图标的实现
var rotaeimg = document.createElement('img')
rotaeimg.src = xuanzhuanpng
function renderRotaIcon(ctx, left, top, styleOverride, fabricObject) {
var size = 22 //this.cornerSize
ctx.save()
ctx.translate(left, top)
ctx.rotate(fabric.util.degreesToRadians(fabricObject.angle))
ctx.drawImage(rotaeimg, -size / 2, -size / 2, size, size)
ctx.restore()
}
//因为旋转这个功能他本身就有,只是把位置变了,所以不用重新写方法
fabric.Object.prototype.controls.br.actionHandler =
fabric.Object.prototype.controls.mtr.actionHandler
fabric.Object.prototype.controls.br.render = renderRotaIcon
原理分析:
fabric.Object.prototype.controls是fabric的控制器对象,在添加之前打个log看下:
正好是8个方向点,加一个旋转点
加一个删除按钮后打个log看下:
原型链上多了一个deleteControl,就是我们刚才添加的删除按钮。由此可见,通过原型链还可以添加更多的内容到控制器上,同时也可以修改控制器的样式、方法,等
缩放最大最小倍数限制
同样用修改原型链方法实现:
//限制元素放大的倍数
fabric.Object.prototype.on('scaling', function () {
const maxScaleX = 2
if (this.scaleX > maxScaleX) {
this.scaleX = maxScaleX
this.left = this.lastGoodLeft
this.top = this.lastGoodTop
}
if (this.scaleY > maxScaleX) {
this.scaleY = maxScaleX
this.left = this.lastGoodLeft
this.top = this.lastGoodTop
}
this.lastGoodTop = this.top
this.lastGoodLeft = this.left
})
添加图片跨域报错
调用canvas.toDataURl()报错
这两个问题可以一起讲,获取canvas的base64数据的时候,可能会报错
Access to image at ‘file:‘ from origin ‘null‘ has been blocked by CORS policy
那是因为canvas里面加载了跨图片,导致画布被污染,看看mdn怎么说
启用了 CORS 的图片 - HTML(超文本标记语言) | MDN
在fabric里面加载图片,且需要导出数据的,需要图片所在域名的域名加 Access-Control-Allow-Origin:*,并且在加载的时候要设置跨域模式,比如:
//fabric加载跨域图片
let imgbg = new Image()//可以不new Image()的,因为我要计算倍数,所以这么写
imgbg.src = url
imgbg.onload = () => {
let scale = window.innerWidth / 3 / imgbg.width
fabric.Image.fromURL(url, (img) => {
img.set({
left: 50,
top: 50,
scaleX: scale,
scaleY: scale,
})
canvas.add(img)
})
}
我的其他设置可以参考一下:
fabricConfig = () => {
fabric.Object.prototype.set({
borderColor: 'white',
cornerColor: 'white', //激活状态角落图标的填充颜色
cornerStrokeColor: '', //激活状态角落图标的边框颜色
borderOpacityWhenMoving: 1,
borderScaleFactor: 2,
cornerSize: 8, //操作点的像素
cornerStyle: 'circle', //rect,circle,操作点是圆点还是小方块
centeredScaling: false, //角落放大缩小是否是以图形中心为放大原点
centeredRotation: false, //旋转按钮旋转是否是左上角为圆心旋转
transparentCorners: false, //激活状态角落的图标是否透明
rotatingPointOffset: 2, //旋转距旋转体的距离
originX: 'left',
originY: 'top',
// scaleX: 2,//不起作用
// scaleY: 2,
lockScalingFlip: true,
lockUniScaling: true, //当设置为true,Object将无法被锁定比例进行缩放。默认值为false
hasRotatingPoint: true, //是否显示旋转按钮
selectionDashArray: [5, 5],
// minScaleLimit: 0.5,//对整个画布生效
})
fabric.Object.prototype.setControlsVisibility({
ml: false, //中左,中下,中右,中上、旋转五个点隐藏
mb: false,
mr: false,
mt: false,
mtr: false,
})