fabric.js 功能封装记录

目录

前言

一、绘制直线

二、绘制矩形

三、绘制圆

四、添加文字

五、添加图片

六、绘制折线

七、绘制多边形



前言

业务需求 查了很多资料,在这里仅是个人功能记录

很多代码参考https://gitee.com/k21vin/front-end-data-visualization

特别感谢


一、绘制直线


/** 直线
 * 
 * @param {*} data 
 * @param {*} stroke 颜色
 * @param {*} strokeWidth 宽度
 * @param {*} id id
 * @param {*} zIndex 层级
 * @returns 
 */
export function drawLine (data) {
    let currentLine
    let downPoint
    let upPoint
    let currentType = 'line'

    let canvas = data.map
    let stroke = data.stroke
    let strokeWidth = data.strokeWidth
    let id = data.id
    let zIndex = data.zIndex

    return new Promise((resolve, reject) => {

        canvas.on('mouse:down', canvasMouseDown)   // 鼠标在画布上按下
        canvas.on('mouse:move', canvasMouseMove)   // 鼠标在画布上移动
        canvas.on('mouse:up', canvasMouseUp)       // 鼠标在画布上松开

        // 鼠标在画布上按下
        function canvasMouseDown (e) {

            downPoint = e.absolutePointer

            if (currentType === 'line') {
                currentLine = new fabric.Line(
                    [
                        downPoint.x, downPoint.y, // 起始点坐标
                        downPoint.x, downPoint.y // 结束点坐标
                    ],
                    {
                        stroke: 'rgba(0, 0, 0, 0.2)', // 笔触颜色
                        selectable: isevented,
                        selection: true,
                    }
                )
                canvas.moveTo(currentLine, zIndex);
                canvas.add(currentLine)
                canvas.remove(currentLine)
                canvas.renderAll()
            }
        }

        // 鼠标在画布上移动
        function canvasMouseMove (e) {
            if (currentType === 'line' && currentLine) {
                const currentPoint = e.absolutePointer

                currentLine.set('x2', currentPoint.x)
                currentLine.set('y2', currentPoint.y)

                canvas.requestRenderAll()
            }
        }

        // 鼠标在画布上松开
        function canvasMouseUp (e) {
            upPoint = e.absolutePointer

            if (currentType === 'line') {

                let line = new fabric.Line(
                    [currentLine.get('x1'), currentLine.get('y1'), currentLine.get('x2'), currentLine.get('y2')],
                    {
                        selectable: isevented,
                        selection: true,
                        stroke: stroke,
                        strokeWidth: strokeWidth,
                        id: id,

                        scaleX: 1,
                        scaleY: 1,
                        scale: 1,
                    }
                )
                canvas.moveTo(line, zIndex);
                canvas.add(line)
                canvas.remove(currentLine)
                canvas.renderAll()
                stopDraw(canvas)
                console.log(currentLine);
                data.points = [line.get('x1'), line.get('y1'), line.get('x2'), line.get('y2')]
                data.dleft = line.get('left')
                data.dtop = line.get('top')
                data.scaleX = line.get('scaleX')
                data.scaleY = line.get('scaleY')
                data.scale = line.get('scale')
                resolve(data)
            }
        }
    })
}

二、绘制矩形


/**矩形
 * 
 * @param {*} map  画布
 * @param {*} id  用于判断的id
 * @param {*} fill  填充色
 * @param {*} stroke  边框填充色
 * @param {*} strokeWidth  边框宽度
 * @param {*} rx  圆角大小
 * @param {*} ry  圆角大小
 * @param {*} zIndex  层级
 * @param {*} angle  旋转
 */
export function drawRect (data) {
    let canvas = data.map
    let id = data.id
    let fill = data.fill
    let stroke = data.stroke
    let strokeWidth = data.strokeWidth
    let rx = data.rx
    let ry = data.ry
    let angle = data.angle
    let zIndex = data.zIndex
    let currentType = 'rect'


    return new Promise((resolve, reject) => {


        canvas.on('mouse:down', canvasMouseDown)   // 鼠标在画布上按下
        canvas.on('mouse:up', canvasMouseUp)       // 鼠标在画布上松开


        let downPoint = null // 鼠标按下的坐标

        // 鼠标在画布上按下
        function canvasMouseDown (e) {
            downPoint = e.absolutePointer
        }

        // 鼠标在画布上松开
        function canvasMouseUp (e) {
            if (currentType === 'rect') {
                // 创建矩形
                createRect(e.absolutePointer)
            }
        }

        // 创建矩形
        function createRect (pointer) {
            // 点击事件,不生成矩形
            if (JSON.stringify(downPoint) === JSON.stringify(pointer)) {
                return
            }

            // 创建矩形
            // 矩形参数计算
            let top = Math.min(downPoint.y, pointer.y)
            let left = Math.min(downPoint.x, pointer.x)
            let width = Math.abs(downPoint.x - pointer.x)
            let height = Math.abs(downPoint.y - pointer.y)

            // 矩形对象
            const rect = new fabric.Rect({
                top,
                left,
                width,
                height,
                rx: rx,
                ry: ry,
                id: id,
                fill: fill,
                stroke: stroke,
                strokeWidth: strokeWidth,
                angle: angle,
                selection: true,
                selectable: isevented,
                scaleX: 1,
                scaleY: 1,
                scale: 1,
            })

            // 将矩形添加到画布上
            canvas.add(rect)
            canvas.moveTo(rect, zIndex);
            stopDraw(canvas)
            data.dleft = left
            data.dtop = top
            data.width = width
            data.height = height
            data.scaleX = 1
            data.scaleY = 1
            data.scale = 1
            resolve(data)
            downPoint = null
        }

    })



}

三、绘制圆


/**圆
 * 
 * @param {*} canvas  画布
 * @param {*} id  用于判断的id
 * @param {*} fill  填充色
 * @param {*} stroke  边框填充色
 * @param {*} strokeWidth  边框宽度
 */
export function drawCircle (data) {
    let canvas = data.map
    let id = data.id
    let fill = data.fill
    let stroke = data.stroke
    let strokeWidth = data.strokeWidth
    let zIndex = data.zIndex

    let currentCircle
    let downPoint
    let upPoint
    let currentType = 'circle'
    //Setting the mouse events
    return new Promise((resolve, reject) => {



        canvas.on('mouse:down', canvasMouseDown)   // 鼠标在画布上按下
        canvas.on('mouse:move', canvasMouseMove)   // 鼠标在画布上移动
        canvas.on('mouse:up', canvasMouseUp)       // 鼠标在画布上松开

        // 鼠标在画布上按下
        function canvasMouseDown (e) {
            console.log(e);
            downPoint = e.absolutePointer

            if (currentType === 'circle') {
                currentCircle = new fabric.Circle({
                    top: downPoint.y,
                    left: downPoint.x,
                    radius: 0,
                    fill: 'transparent',
                    stroke: 'rgba(0, 0, 0, 0.2)',

                })

                canvas.add(currentCircle)
            }
        }

        // 鼠标在画布上移动
        function canvasMouseMove (e) {
            if (currentType === 'circle' && currentCircle) {
                const currentPoint = e.absolutePointer

                let radius = Math.min(Math.abs(downPoint.x - currentPoint.x), Math.abs(downPoint.y - currentPoint.y)) / 2
                let top = currentPoint.y > downPoint.y ? downPoint.y : downPoint.y - radius * 2
                let left = currentPoint.x > downPoint.x ? downPoint.x : downPoint.x - radius * 2

                currentCircle.set('radius', radius)
                currentCircle.set('top', top)
                currentCircle.set('left', left)

                canvas.requestRenderAll()
            }
        }

        // 鼠标在画布上松开
        function canvasMouseUp (e) {
            upPoint = e.absolutePointer

            if (currentType === 'circle') {
                if (JSON.stringify(downPoint) === JSON.stringify(upPoint)) {
                    canvas.remove(currentCircle)
                } else {
                    if (currentCircle) {
                        currentCircle.set('id', id)

                        let circle = new fabric.Circle({
                            top: currentCircle.get('top'),
                            left: currentCircle.get('left'),
                            radius: currentCircle.get('radius'),
                            fill: fill,
                            strokeWidth: strokeWidth,
                            stroke: stroke,
                            selectable: isevented,
                            id: id,
                            selection: true,
                            scaleX: 1,
                            scaleY: 1,
                            scale: 1,
                        })

                        data.radius = circle.get('radius');
                        data.dtop = circle.get('top')
                        data.dleft = circle.get('left')
                        data.scaleX = circle.get('scaleX')
                        data.scaleY = circle.get('scaleY')
                        data.scale = circle.get('scale')
                        canvas.remove(currentCircle)
                        canvas.add(circle)
                        canvas.moveTo(circle, zIndex);
                        resolve(data)
                        stopDraw(canvas)
                        canvas.renderAll();
                    }
                }
                currentCircle = null
            }
        }

    });


}

四、添加文字


/**添加文字
 * 
 * @param {*} data 
 * @param {*} canvas 
 * @param {*} fontSize 文字大小
 * @param {*} textFill 文字颜色
 * @param {*} zIndex 层级
 * @param {*} backgroundColor 背景色
 * @param {*} id 
 * @returns 
 */
export function setText (data) {
    let canvas = data.map
    let fontSize = data.fontSize
    let textFill = data.textFill
    let zIndex = data.zIndex
    let backgroundColor = data.backgroundColor
    let dleft
    let dtop
    let textObject
    let id = data.id

    return new Promise((resolve, reject) => {
        canvas.on('mouse:down', options => {
            console.log('mouse-down:', options, options.e.clientY);
            // 注意减去偏移量
            dleft = options.e.layerX
            dtop = options.e.layerY
            if (!textObject) {
                textObject = new fabric.Textbox('', {
                    left: dleft,
                    top: dtop,
                    fontSize: fontSize,
                    fill: textFill,
                    scaleX: 1,
                    scaleY: 1,
                    scale: 1,
                    hasControls: true, // 设置为false时,选中的时候不出现旋转缩放标识
                    hasBorders: true, // 设置为false时,选中的时候不出现边框
                    width: 30,
                    backgroundColor: backgroundColor,
                    id: id,
                    selectable: isevented,
                    selection: true,
                })
                canvas.add(textObject)
                canvas.moveTo(textObject, zIndex)
                // 文本打开编辑模式
                textObject.enterEditing()
                // 文本编辑框获取焦点
                textObject.hiddenTextarea.focus()
            } else {
                stopDraw(canvas)
                stopText(textObject, canvas)
                data.text = textObject.get('text')
                data.left = dleft
                data.top = dtop
                data.scaleX = 1
                data.scaleY = 1
                data.scale = 1
                resolve(data)
            }


        });

    })
}

五、添加图片


/** 设置图片
 * 
 * @param {*} url  地址 
 * @param {*} angle   旋转角度
 * @param {*} opacity  透明度
 * @param {*} scaleX  宽度百分比
 * @param {*} scaleY  高度百分比
 * @param {*} zIndex  层级
 * @param {*} id 标识
 * @returns 
 */
export function setImg (data) {
    let canvas = data.map
    let url = data.url
    let angle = data.angle
    let opacity = data.opacity
    let scaleX = data.scaleX
    let scaleY = data.scaleY
    let zIndex = data.zIndex
    let id = data.id
    let dleft
    let image
    let dtop
    return new Promise((resolve, reject) => {
        canvas.on('mouse:down', options => {
            console.log('mouse-down:', options, options.e.clientY);
            // 注意减去偏移量
            dleft = options.e.layerX
            dtop = options.e.layerY

            fabric.Image.fromURL(url, (img) => {
                img.set({
                    left: dleft, // 图片相对画布的左侧距离
                    top: dtop, // 图片相对画布的顶部距离
                    angle: angle, // 图片旋转角度
                    opacity: opacity, // 图片透明度
                    scaleX: scaleX,
                    scaleY: scaleY,
                    id: id,
                    selection: true,
                    selectable: isevented, // 是否允许当前对象被选中
                    scaleX: 1,
                    scaleY: 1,
                    scale: 1,
                });
                // 添加对象
                image = img
                canvas.add(img);
                canvas.moveTo(img, zIndex);
                stopDraw(canvas)
                data.left = dleft
                data.top = dtop
                data.width = image.get('width')
                data.height = image.get('height')
                data.scaleX = 1
                data.scaleY = 1
                data.scale = 1
                resolve(data)
            });

        });


    })


}

六、绘制折线


/** 折线
 * 
 * @param {*} data 
 * @param {*} stroke  颜色
 * @param {*} strokeWidth  宽度
 * @param {*} zIndex  层级
 * @param {*} id id
 * @returns 
 */
export function drawPolyline (data) {
    let canvas = data.map
    let stroke = data.stroke
    let strokeWidth = data.strokeWidth
    let zIndex = data.zIndex
    let id = data.id


    let currentType = 'polyline'

    let currentPolyline = null
    return new Promise((resolve, reject) => {
        canvas.on('mouse:down', canvasMouseDown)         // 鼠标在画布上按下
        canvas.on('mouse:move', canvasMouseMove)         // 鼠标在画布上移动
        canvas.on('mouse:dblclick', canvasMouseDblclick) // 鼠标在画布上双击

        // 创建折线
        function createPolyline (e) {
            const currentPoint = e.absolutePointer
            currentPolyline = new fabric.Polyline(
                [
                    { x: currentPoint.x, y: currentPoint.y },
                    { x: currentPoint.x, y: currentPoint.y }
                ],
                {
                    fill: 'transparent',
                    stroke: 'rgba(0, 0, 0, 0.2)',
                    objectCaching: false
                }
            )
            canvas.add(currentPolyline)
        }

        // 修改当前正在创建的折线
        function changeCurrentPolyline (e) {
            const currentPoint = e.absolutePointer

            let points = currentPolyline.points

            points.push({
                x: currentPoint.x,
                y: currentPoint.y
            })
            canvas.requestRenderAll()
        }

        // 折线橡皮带
        function changePolylineBelt (e) {
            const currentPoint = e.absolutePointer
            let points = currentPolyline.points

            points[points.length - 1].x = currentPoint.x
            points[points.length - 1].y = currentPoint.y

            canvas.requestRenderAll()
        }

        // 完成折线绘制
        function finishPolyline (e) {
            const currentPoint = e.absolutePointer
            console.log(e, currentPoint, 12313);
            let points = currentPolyline.points
            points[points.length - 1].x = currentPoint.x
            points[points.length - 1].y = currentPoint.y

            points.pop()
            points.pop()
            canvas.remove(currentPolyline)
            let polyline
            if (points.length > 1) {
                polyline = new fabric.Polyline(points, {
                    stroke: stroke,
                    fill: 'transparent',
                    strokeWidth: strokeWidth,
                    id: id,
                    selectable: isevented,
                    selection: true,
                    scaleX: 1,
                    scaleY: 1,
                    scale: 1,
                })

                canvas.add(polyline)
                canvas.moveTo(polyline, zIndex);

            }
            currentPolyline = null
            data.points = points
            data.dleft = polyline.get('left')
            data.dtop = polyline.get('top')
            data.scaleX = polyline.get('scaleX')
            data.scaleY = polyline.get('scaleY')
            data.scale = polyline.get('scale')
            canvas.requestRenderAll()
            stopDraw(canvas)
            resolve(data)
        }

        // 鼠标在画布上按下
        function canvasMouseDown (e) {
            if (currentType === 'polyline') {
                if (currentPolyline === null) {
                    createPolyline(e)
                } else {
                    changeCurrentPolyline(e)
                }
            }
        }

        // 鼠标在画布上移动
        function canvasMouseMove (e) {
            if (currentType === 'polyline' && currentPolyline) {
                changePolylineBelt(e)
            }
        }

        // 鼠标在画布上双击
        function canvasMouseDblclick (e) {
            if (currentType === 'polyline') {
                finishPolyline(e)

            }
        }
    })
}

七、绘制多边形


/**绘制多边形
 * 
 * @param {*} data 
 * @param {*} stroke  颜色
 * @param {*} strokeWidth  宽度
 * @param {*} zIndex  层级
 * @param {*} id id
 * @param {*} fill 填充色
 * @returns 
 */
export function drawPolygon (data) {
    let currentPolygon = null

    let currentType = 'polygon'

    let canvas = data.map
    let stroke = data.stroke
    let strokeWidth = data.strokeWidth
    let id = data.id
    let fill = data.fill
    let zIndex = data.zIndex
    return new Promise((resolve, reject) => {

        canvas.on('mouse:down', canvasMouseDown)         // 鼠标在画布上按下
        canvas.on('mouse:move', canvasMouseMove)         // 鼠标在画布上移动
        canvas.on('mouse:dblclick', canvasMouseDblclick) // 鼠标在画布上双击

        // 创建多边形
        function createPolygon (e) {
            const currentPoint = e.absolutePointer
            currentPolygon = new fabric.Polygon(
                [
                    { x: currentPoint.x, y: currentPoint.y },
                    { x: currentPoint.x, y: currentPoint.y }
                ],
                {
                    fill: 'transparent',
                    stroke: 'rgba(0, 0, 0, 0.2)',
                    objectCaching: false
                }
            )
            canvas.add(currentPolygon)
        }

        // 修改当前正在创建的多边形
        function changeCurrentPolygon (e) {
            const currentPoint = e.absolutePointer

            let points = currentPolygon.points

            points.push({
                x: currentPoint.x,
                y: currentPoint.y
            })
            canvas.requestRenderAll()
        }

        // 多边形橡皮带
        function changePolygonBelt (e) {
            const currentPoint = e.absolutePointer
            let points = currentPolygon.points

            points[points.length - 1].x = currentPoint.x
            points[points.length - 1].y = currentPoint.y

            canvas.requestRenderAll()
        }

        // 完成多边形绘制
        function finishPolygon (e) {
            const currentPoint = e.absolutePointer
            let points = currentPolygon.points
            points[points.length - 1].x = currentPoint.x
            points[points.length - 1].y = currentPoint.y

            points.pop()
            points.pop()
            canvas.remove(currentPolygon)
            let polygon
            if (points.length > 1) {
                polygon = new fabric.Polygon(points, {
                    stroke: stroke,
                    fill: fill,
                    strokeWidth: strokeWidth,
                    id: id,
                    selectable: isevented,
                    selection: true,
                    scaleX: 1,
                    scaleY: 1,
                    scale: 1,
                })
                canvas.moveTo(polygon, zIndex);
                canvas.add(polygon)
            }

            currentPolygon = null
            canvas.requestRenderAll()
            stopDraw(canvas)
            data.points = points
            data.dleft = polygon.get('left')
            data.dtop = polygon.get('top')
            data.scaleX = polygon.get('scaleX')
            data.scaleY = polygon.get('scaleY')
            data.scale = polygon.get('scale')

            resolve(data)
        }

        // 鼠标在画布上按下
        function canvasMouseDown (e) {
            if (currentType === 'polygon') {
                if (currentPolygon === null) {
                    createPolygon(e)
                } else {
                    changeCurrentPolygon(e)
                }
            }
        }

        // 鼠标在画布上移动
        function canvasMouseMove (e) {
            if (currentType === 'polygon' && currentPolygon) {
                changePolygonBelt(e)
            }
        }

        // 鼠标在画布上双击
        function canvasMouseDblclick (e) {
            if (currentType === 'polygon') {
                finishPolygon(e)
            }
        }
    })
}


总结

以上只是个人功能代码,欢迎大佬们提意见

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值