当前位置:   article > 正文

学习整理fabric.js自定义选择控制框样式和增加控制图标_fabric mtr

fabric mtr

选择控制框简介

我们以前文中的一个例子作为示例。如下图,当我们点击一个画布中的对象,对象周围就出现了一个控制框,控制框上一共9个控制点。

在这里插入图片描述

控制线

如上图所示,控制框的范围由控制线限定。 自定义时,根据需要,我们一般会修改控制线的以下属性

是否显示
颜色
与框选对象间的内边距

控制点

如上图所示,点击并拖动不同的控制点,会产生不同的交互效果。 下面区分不同的控制点类型分别进行介绍:

1、水平缩放控制点: 即第一列中间和第三列中间两个控制点。点击并进行拖动,会改变对象的水平缩放值(scaleX,初始值为1)

2、竖直缩放控制点: 即第二列第二行和第三行两个控制点。点击并进行拖动,会改变对象的竖直缩放值(scaleY,初始值为1)

3、等比例缩放控制点: 即左上、右上、左下、右下四个控制点。点击并进行拖动,会同时并等比例改变对象的scaleX和scaleY两个值

4、中心旋转控制点: 即第二列最上方的控制点。点击并进行拖动,会改变对象的角度值(angle,初始值为0)

注意

左上的等比例缩放控制点还会改变对象的top和left值。
左中的水平缩放控制点还会改变对象的left值。
中心旋转控制点还会改变对象的top和left值。

自定义控制线样式

上文中提到,我们一般对控制线是否显示、颜色、与框选对象间的内边距这几个属性进行自定义修改。这里用另一个例子,对上述属性逐一进行介绍。

如图所示,其默认的控制线样式如下:

在这里插入图片描述

与框选对象间的内边距

fabric.Object.prototype.padding = 10;
  • 1

代码说明

padding即内边距,目前只支持4个方向的统一设置,不支持单独设置

结果
在这里插入图片描述
是否显示

我们之前见过的编辑器,其旋转控制点和主体之间一般没有那条控制线,这里我们对它进行隐藏。

代码

fabric.Object.prototype.controls.mtr.withConnection = false;
  • 1

代码说明

fabric.Object是所有对象的父类,修改其属性即可对它的子类(Rect、Circle…)都生效。
controls包含了Object类的所有控制点的信息。
mtr是middle top rotation的缩写,即中心旋转控制点。
withConnection即mtr是否和主体有连线,此处设为false。

结果

可见,旋转控制点和主体之间的那条连接线没有了

在这里插入图片描述

修改控制线颜色

我们将控制线默认的浅蓝色改为 #dc143c,一种红色

代码

fabric.Object.prototype.borderColor = 'dodgerblue';
  • 1

效果图
在这里插入图片描述

自定义控制点样式

对于控制点,我们可以自定义修改其形状、大小、边框颜色、填充颜色等属性。这里对于各个属性不再一一介绍,我们用一个综合的例子对它们进行演示。

代码

	// 修改控制点的形状,默认为`rect`矩形,可选的值还有`circle`圆形
    fabric.Object.prototype.cornerStyle = "circle";
    // 修改控制点的填充色为白色
    fabric.Object.prototype.cornerColor = "white";
    // 修改控制点的大小为10px
    fabric.Object.prototype.cornerSize = 10;
    // 设置控制点不透明,即可以盖住其下的控制线
    fabric.Object.prototype.transparentCorners = false;
    // 修改控制点的边框颜色为`gray`灰色
    fabric.Object.prototype.cornerStrokeColor = "gray";
    
    // 单独修改旋转控制点距离主体的纵向距离为-20px
    fabric.Object.prototype.controls.mtr.offsetY = -20;
    // 单独修改旋转控制点,光标移动到该点上时的样式为`pointer`,一个手的形状
    fabric.Object.prototype.controls.mtr.cursorStyle = "pointer";

  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16

自定义控制点贴图

在这里插入图片描述

/*控制选中边框 旋转图标 start*/

// 渲染图标的方法
function renderIcon(image, initialAngle) {
    return function (ctx, left, top, styleOverride, fabricObject) {
        let size = this.cornerSize;
        ctx.save();
        ctx.translate(left, top);
        ctx.rotate(fabric.util.degreesToRadians(fabricObject.angle + initialAngle));
        ctx.drawImage(image, -size / 2, -size / 2, size, size);
        ctx.restore();
    };
}

// 图标的下载链接省略
const iconURL = "../img/xuanzhuan.png";
const callback = (image, isError) => {
    if (!isError) {
        fabric.Object.prototype.controls.ml = new fabric.Control({
            x: 0,
            y: -0.5,
            offsetY: -20,
            cursorStyle: 'pointer',
            actionHandler: fabric.controlsUtils.rotationWithSnapping,
            cursorStyleHandler: fabric.controlsUtils.rotationStyleHandler,
            // 渲染图标
            render: renderIcon(image._element, 0),
            // 设置控制点大小
            cornerSize: 30
        });
    }
};
fabric.Image.fromURL(iconURL, callback);

/*控制选中边框 旋转图标 stop*/
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35

在这里插入图片描述

添加自定义控制点

有的时候,我们可能不满足于默认提供的9个控制点,想要自己添加一些控制点上去,比如用于删除对象的控制点。这个小节,我们使用一个垃圾桶图标来实现它。

首先看一下实现效果:

在这里插入图片描述
代码


/*控制选中边框 增加自对应图标 start*/


// 从画布中删除当前选中的对象
function deleteObject() {
    // 获取画布当前选中的对象
    let activeObject = canvas.getActiveObject();
    if (activeObject) {
        canvas.remove(activeObject);
        canvas.renderAll();
    }
}

// 垃圾桶图标的下载链接
const deleteIconURL = "../img/delete.png";
const deletecallback = (img, isError) => {
    console.log(img);
    if (!isError) {
        fabric.Object.prototype.controls.delete = new fabric.Control({
            // x和y设置该控制点和第二列中间的控制点重合
            x: 0,
            y: -0.5,
            // offsetX和offsetY设置该控制点在水平和竖直两个方向上
            // 偏移的距离(单位px)
            offsetX: 28,
            offsetY: -20,
            // 光标移动到该控制点时变为一个手的图标
            cursorStyle: 'pointer',
            // 自定义的值,可忽略
            actionName: "delete",
            // 设置当点击了该控制点,鼠标弹起是执行的动作处理方法
            mouseUpHandler: () => deleteObject(),
            //渲染图标
            render: renderIcon(img._element, 0),
            cornerSize: 39
        });
    }
};
fabric.Image.fromURL(deleteIconURL, deletecallback);

/*控制选中边框 增加自对应图标 stop*/
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42

注意

renderIcon 方法在上边定义过了,可以直接调用

所有代码

在这里插入图片描述

效果图

在这里插入图片描述

index.html

<!DOCTYPE HTML>
<html>
<head>
    <meta charset="utf-8">


    <title>Fabric.js 上传图片保存</title>


    <script src="../fabric5.2.1.js"></script>

    <style>
        div#container {
            padding: 30px;
            font-family: 'verdana', lucida;
        }

        input {
            background-color: #ccc;
            padding: 0;
            width: 300px;
            color: #777;
        }

        #lnkDownload {

            display: block;

            padding: 0;
            margin-top: 10px;
            text-decoration: none;
        }
    </style>

</head>
<body>

<div id="container">

    <canvas id="imageCanvas" width="300" height="300"></canvas>

    <a id="lnkDownload" href="#">
        <button> 保存图片</button>
    </a>


</div>


<script src="script.js"></script>


</body>
</html>
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42
  • 43
  • 44
  • 45
  • 46
  • 47
  • 48
  • 49
  • 50
  • 51
  • 52
  • 53
  • 54

script.js

var canvas = new fabric.Canvas('imageCanvas', {
    backgroundColor: 'rgb(240,240,240)',
    includeDefaultValues: false,// 指示toObject/toDatalessObject是否应该包含默认值,如果设置为false,则优先于对象值
    perPixelTargetFind: true, //这一句说明选中的时候以图形的实际大小来选择而不是以边框来选择
    hasBorders: false,
});


canvas.setWidth(500);
canvas.setHeight(500);

/*控制选中边框 start*/
//将内边距设置为10px
fabric.Object.prototype.padding = 10;
// 修改控制点的形状,默认为`rect`矩形,可选的值还有`circle`圆形
fabric.Object.prototype.cornerStyle = "circle";
// 修改控制点的填充色为白色
fabric.Object.prototype.cornerColor = "white";

//将控制线默认的浅蓝色改为 #dc143c,
fabric.Object.prototype.borderColor = '#dc143c';


// 修改控制点的大小为10px
fabric.Object.prototype.cornerSize = 10;
// 设置控制点不透明,即可以盖住其下的控制线
fabric.Object.prototype.transparentCorners = false;

// 修改控制点的边框颜色为`gray`灰色
fabric.Object.prototype.cornerStrokeColor = "blue";


// 单独修改旋转控制点距离主体的纵向距离为-20px
fabric.Object.prototype.controls.mtr.offsetY = -20;
// 单独修改旋转控制点,光标移动到该点上时的样式为`pointer`,一个手的形状
fabric.Object.prototype.controls.mtr.cursorStyle = "pointer";
//旋转控制点和主体之间一般没有那条控制线,这里我们对它进行隐藏。
fabric.Object.prototype.controls.mtr.withConnection = false;
/*控制选中边框 stop*/

/*控制选中边框 旋转图标 start*/

// 渲染图标的方法
function renderIcon(image, initialAngle) {
    return function (ctx, left, top, styleOverride, fabricObject) {
        let size = this.cornerSize;
        ctx.save();
        ctx.translate(left, top);
        ctx.rotate(fabric.util.degreesToRadians(fabricObject.angle + initialAngle));
        ctx.drawImage(image, -size / 2, -size / 2, size, size);
        ctx.restore();
    };
}

// 图标的下载链接省略
const iconURL = "../img/xuanzhuan.png";
const callback = (image, isError) => {
    if (!isError) {
        fabric.Object.prototype.controls.ml = new fabric.Control({
            x: 0,
            y: -0.5,
            offsetY: -20,
            cursorStyle: 'pointer',
            actionHandler: fabric.controlsUtils.rotationWithSnapping,
            cursorStyleHandler: fabric.controlsUtils.rotationStyleHandler,
            // 渲染图标
            render: renderIcon(image._element, 0),
            // 设置控制点大小
            cornerSize: 30
        });
    }
};
fabric.Image.fromURL(iconURL, callback);

/*控制选中边框 旋转图标 stop*/


/*控制选中边框 增加自对应图标 start*/


// 从画布中删除当前选中的对象
function deleteObject() {
    // 获取画布当前选中的对象
    let activeObject = canvas.getActiveObject();
    if (activeObject) {
        canvas.remove(activeObject);
        canvas.renderAll();
    }
}

// 垃圾桶图标的下载链接
const deleteIconURL = "../img/delete.png";
const deletecallback = (img, isError) => {
    console.log(img);
    if (!isError) {
        fabric.Object.prototype.controls.delete = new fabric.Control({
            // x和y设置该控制点和第二列中间的控制点重合
            x: 0,
            y: -0.5,
            // offsetX和offsetY设置该控制点在水平和竖直两个方向上
            // 偏移的距离(单位px)
            offsetX: 28,
            offsetY: -20,
            // 光标移动到该控制点时变为一个手的图标
            cursorStyle: 'pointer',
            // 自定义的值,可忽略
            actionName: "delete",
            // 设置当点击了该控制点,鼠标弹起是执行的动作处理方法
            mouseUpHandler: () => deleteObject(),
            //渲染图标
            render: renderIcon(img._element, 0),
            cornerSize: 39
        });
    }
};
fabric.Image.fromURL(deleteIconURL, deletecallback);

/*控制选中边框 增加自对应图标 stop*/


// 矩形
var rect = new fabric.Rect({
    left: 100,
    top: 100,
    fill: 'orange',
    width: 100,
    height: 100,

})
canvas.add(rect);

// 圆角矩形
var rect2 = new fabric.Rect({
    left: 300,
    top: 100,
    fill: 'yellowgreen',
    width: 100,
    height: 100,

    rx: 20,
    ry: 20
})
canvas.add(rect2);

// 圆形
var circle = new fabric.Circle({
    radius: 50,
    fill: 'green',
    left: 200,
    top: 200,
    controls: false, // 不可编辑
    hasControls: false, // 控件将不显示,并且不能用于操作对象
});

canvas.add(circle);


// 使用 IText,可编辑文本
var text = new fabric.IText(
    '奇葩呀,www.qipa250.com',
    {
        top:300,
        fontSize:14,
        fontFamily: 'Comic Sans'
    }
)
canvas.add(text);


var imageSaver = document.getElementById('lnkDownload');
imageSaver.addEventListener('click', saveImage, false);

function saveImage() {

    console.log('toJSON==', canvas.toJSON());

    console.log('toObject==', canvas.toObject()); // 输出序列化的内容

    this.href = canvas.toDataURL({
        format: 'png',
        quality: 0.8
    });
    this.download = 'canvas.png';

}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42
  • 43
  • 44
  • 45
  • 46
  • 47
  • 48
  • 49
  • 50
  • 51
  • 52
  • 53
  • 54
  • 55
  • 56
  • 57
  • 58
  • 59
  • 60
  • 61
  • 62
  • 63
  • 64
  • 65
  • 66
  • 67
  • 68
  • 69
  • 70
  • 71
  • 72
  • 73
  • 74
  • 75
  • 76
  • 77
  • 78
  • 79
  • 80
  • 81
  • 82
  • 83
  • 84
  • 85
  • 86
  • 87
  • 88
  • 89
  • 90
  • 91
  • 92
  • 93
  • 94
  • 95
  • 96
  • 97
  • 98
  • 99
  • 100
  • 101
  • 102
  • 103
  • 104
  • 105
  • 106
  • 107
  • 108
  • 109
  • 110
  • 111
  • 112
  • 113
  • 114
  • 115
  • 116
  • 117
  • 118
  • 119
  • 120
  • 121
  • 122
  • 123
  • 124
  • 125
  • 126
  • 127
  • 128
  • 129
  • 130
  • 131
  • 132
  • 133
  • 134
  • 135
  • 136
  • 137
  • 138
  • 139
  • 140
  • 141
  • 142
  • 143
  • 144
  • 145
  • 146
  • 147
  • 148
  • 149
  • 150
  • 151
  • 152
  • 153
  • 154
  • 155
  • 156
  • 157
  • 158
  • 159
  • 160
  • 161
  • 162
  • 163
  • 164
  • 165
  • 166
  • 167
  • 168
  • 169
  • 170
  • 171
  • 172
  • 173
  • 174
  • 175
  • 176
  • 177
  • 178
  • 179
  • 180
  • 181
  • 182
  • 183
  • 184
  • 185
声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/IT小白/article/detail/98132
推荐阅读
相关标签
  

闽ICP备14008679号