Day 181/200 React Fabric.js 实现可拖拽变化的多边形

20 篇文章 0 订阅

1、需求

实现Canvas绘制多边形。

2、效果

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-6owgqbr1-1640231560854)(/img/bVcWTw1)]

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/fabric.Polygon.html

  • 1
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
React Fabric.js是一个用于在React应用中使用Fabric.js库的封装。Fabric.js是一个强大的JavaScript库,用于创建和操作基于HTML5 Canvas的图形对象。通过使用React Fabric.js,您可以轻松地在React应用中创建和操作图形对象,如圆形、矩形、文本等。 要在React应用中使用React Fabric.js,您需要引入Fabric.jsReact Fabric.js的依赖,并在应用程序中创建相应的组件。首先,您需要在您的HTML文件中引入Fabric.js的库文件。然后,您可以使用React的组件生命周期方法,比如componentDidMount,来初始化Fabric.js并在Canvas上绘制图形对象。您还可以使用React的状态管理来更新图形对象的属性。 在React Fabric.js中,您可以使用Fabric.js的API来创建和操作图形对象。例如,您可以使用Fabric.js的Circle类来创建一个圆形对象,并设置其属性,如半径、位置和颜色。然后,您可以将该圆形对象添加到Canvas上,并在React组件中进行渲染。 下面是一个简单的示例代码,展示了如何在React应用中使用React Fabric.js来创建一个圆形对象: ```jsx import React, { Component } from 'react'; import { fabric } from 'fabric'; import './App.css'; class App extends Component { componentDidMount() { const canvas = new fabric.Canvas('canvas'); const circle = new fabric.Circle({ radius: 50, left: 100, top: 100, fill: 'red', }); canvas.add(circle); } render() { return ( <div className="App"> <canvas id="canvas" width={500} height={500}></canvas> </div> ); } } export default App; ``` 在上面的代码中,我们在组件的componentDidMount方法中初始化了Fabric.js的Canvas,并创建了一个半径为50、位于(100,100)的红色圆形对象。然后,我们将该圆形对象添加到Canvas上,并在组件的render方法中渲染Canvas。 通过使用React Fabric.js,您可以方便地在React应用中创建和操作图形对象,实现丰富的可视化效果和交互性。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值