1、需要

实现Canvas绘制多边形。

2、成果

3、代码

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

// Copyright 2021 zhaoardenimport 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...