关于fabric:Day-19100-React-Fabricjs-实现可拖拽变化的多边形

36次阅读

共计 4157 个字符,预计需要花费 11 分钟才能阅读完成。

1、需要

实现 Canvas 绘制多边形。

2、成果

3、代码

官网 Demo 是 HTML 版本的,我改写了 React 版本。

// Copyright 2021 zhaoarden
import React, {useState,useCallback} from 'react';
import {fabric} from "fabric";
import {Button} from 'antd';
class Polygon extends React.Component {constructor(props) {super(props);
        this.state={canvas:{}
        }
    }
    componentDidMount(){console.log('componentDidMount');
        const canvas =  new fabric.Canvas('c');
        console.log('canvas',canvas);
        this.setState({canvas:canvas})
        // console.log('state-canvas',this.state.canvas);
        var points = [{x: 3, y: 4}, {x: 16, y: 3}, {x: 30, y: 5}, {x: 25, y: 55}, {x: 19, y: 44}, {x: 15, y: 30}, {x: 15, y: 55}, {x: 9, y: 55}, {x: 6, y: 53}, {x: -2, y: 55}, {x: -4, y: 40}, {x: 0, y: 20}]
        var polygon = new fabric.Polygon(points, {
            left: 100,
            top: 50,
            fill: '#D81B60',
            strokeWidth: 4,
            stroke: 'green',
            scaleX: 4,
            scaleY: 4,
            objectCaching: false,
            transparentCorners: false,
            cornerColor: 'blue',
        });
        canvas.viewportTransform = [0.7, 0, 0, 0.7, -50, 50];
        canvas.add(polygon);
    }
    render() {
        const controls={display: 'inline-block'};
        const {canvas}=this.state

        // define a function that can locate the controls.
        // this function will be used both for drawing and for interaction.
        function polygonPositionHandler(dim, finalMatrix, fabricObject) {var x = (fabricObject.points[this.pointIndex].x - fabricObject.pathOffset.x),
                y = (fabricObject.points[this.pointIndex].y - fabricObject.pathOffset.y);
            return fabric.util.transformPoint({ x: x, y: y},
                fabric.util.multiplyTransformMatrices(
                    fabricObject.canvas.viewportTransform,
                    fabricObject.calcTransformMatrix())
            );
        }

        // define a function that will define what the control does
        // this function will be called on every mouse move after a control has been
        // clicked and is being dragged.
        // The function receive as argument the mouse event, the current trasnform object
        // and the current position in canvas coordinate
        // transform.target is a reference to the current object being transformed,
        function actionHandler(eventData, transform, x, y) {
            var polygon = transform.target,
                currentControl = polygon.controls[polygon.__corner],
                mouseLocalPosition = polygon.toLocalPoint(new fabric.Point(x, y), 'center', 'center'),
                polygonBaseSize = polygon._getNonTransformedDimensions(),
                size = polygon._getTransformedDimensions(0, 0),
                finalPointPosition = {
                    x: mouseLocalPosition.x * polygonBaseSize.x / size.x + polygon.pathOffset.x,
                    y: mouseLocalPosition.y * polygonBaseSize.y / size.y + polygon.pathOffset.y
                };
            polygon.points[currentControl.pointIndex] = finalPointPosition;
            return true;
        }

        // define a function that can keep the polygon in the same position when we change its
        // width/height/top/left.
        function anchorWrapper(anchorIndex, fn) {return function (eventData, transform, x, y) {
                var fabricObject = transform.target,
                    absolutePoint = fabric.util.transformPoint({x: (fabricObject.points[anchorIndex].x - fabricObject.pathOffset.x),
                        y: (fabricObject.points[anchorIndex].y - fabricObject.pathOffset.y),
                    }, fabricObject.calcTransformMatrix()),
                    actionPerformed = fn(eventData, transform, x, y),
                    newDim = fabricObject._setPositionDimensions({}),
                    polygonBaseSize = fabricObject._getNonTransformedDimensions(),
                    newX = (fabricObject.points[anchorIndex].x - fabricObject.pathOffset.x) / polygonBaseSize.x,
                    newY = (fabricObject.points[anchorIndex].y - fabricObject.pathOffset.y) / polygonBaseSize.y;
                fabricObject.setPositionByOrigin(absolutePoint, newX + 0.5, newY + 0.5);
                return actionPerformed;
            }
        }
        function Edit() {console.log('canvas',canvas);
            console.log('Edit');
            // clone what are you copying since you
            // may want copy and paste on different moment.
            // and you do not want the changes happened
            // later to reflect on the copy.
            var poly = canvas.getObjects()[0];
            canvas.setActiveObject(poly);
            poly.edit = !poly.edit;
            if (poly.edit) {
                var lastControl = poly.points.length - 1;
                poly.cornerStyle = 'circle';
                poly.cornerColor = 'rgba(0,0,255,0.5)';
                poly.controls = poly.points.reduce(function (acc, point, index) {acc['p' + index] = new fabric.Control({
                        positionHandler: polygonPositionHandler,
                        actionHandler: anchorWrapper(index > 0 ? index - 1 : lastControl, actionHandler),
                        actionName: 'modifyPolygon',
                        pointIndex: index
                    });
                    return acc;
                }, {});
            } else {
                poly.cornerColor = 'blue';
                poly.cornerStyle = 'rect';
                poly.controls = fabric.Object.prototype.controls;
            }
            poly.hasBorders = !poly.edit;
            canvas.requestRenderAll();}
        return <div>
            <h1>Learn, {this.props.name}</h1>
            <div className={controls}>
                <p>
                    <Button id="edit" onClick={Edit}>Toggle editing polygon</Button>
                </p>
            </div>
            <canvas id="c" width="500" height="400" style={{border:'1px solid #ccc'}}></canvas>
        </div>;
    }
}
export default Polygon;

参考文档

http://fabricjs.com/docs/fabr…

正文完
 0