Fabric自定义对象

时间:2017-11-24 11:35:30

标签: fabricjs



fabric.ThreePointArc = fabric.util.createClass(fabric.Circle, {
        type: 'threePointArc',

        points: [], //array of startPoint, intermediatePoint, endPoint

        arcCenter: new fabric.Point(null, null),

        arcBounds: null,

        radius: null,

        initialize: function (points, options) {

            if (!points || points.length === 0) {
                return;
            }

            this.points = points;

            this.callSuper('initialize', options);

            // supports only originX and originY as center
            this.originX = this.originY = 'center';
        },

        _set: function(key, value) {

            this.callSuper('_set', key, value);

            if (key === 'points') {
                this._calcArcCenter();
                this._calcDimensions();
                this.setCoords();
            }
            return this;
        },

        setRadius: function(value) {
            this.radius = value;
            return this;
        },

        _calcDimensions: function() {

            this._calcArcAngles();
            this.setRadius(cMath.getLength(this.arcCenter, this.points[0]));
            this._calcArcBounds();

            this.width = this.arcBounds.width;
            this.height = this.arcBounds.height;
            
            this.top = this.arcBounds.y + this.arcBounds.height / 2;
            this.left = this.arcBounds.x + this.arcBounds.width / 2;
        },

        _calcArcCenter: function() {
            var c1Mp = cMath.getMidPoint(this.points[0], this.points[1]), // chord 1 midpoint
                c2Mp = cMath.getMidPoint(this.points[1], this.points[2]), // chord 2 midpoint
                c1pm = -(1 / cMath.getSlope(this.points[0], this.points[1])), // chord 1 perpendicular bisector slope
                c2pm = -(1 / cMath.getSlope(this.points[1], this.points[2])); // chord 2 perpendicular bisector slope

            // chord perpendicular bisectors meet at the center
            this.arcCenter.x = (c2Mp.y - (c2pm * c2Mp.x) + (c1pm * c1Mp.x) - c1Mp.y) / (c1pm - c2pm);
            this.arcCenter.y = (c2pm * (this.arcCenter.x - c2Mp.x)) + c2Mp.y;
        },

        _calcArcBounds: function() {
            var validPoints = this.buildValidPointsForArc(),
                minX = fabric.util.array.min(validPoints, 'x'),
                minY = fabric.util.array.min(validPoints, 'y'),
                maxX = fabric.util.array.max(validPoints, 'x'),
                maxY = fabric.util.array.max(validPoints, 'y'),
                width = (maxX - minX) || 1,
                height = (maxY - minY) || 1;

            this.arcBounds = {
                x: minX,
                y: minY,
                width: width,
                height: height
            }
        },

        buildValidPointsForArc: function() {
            var direction = this.getRenderingDirection(),
                possibleBoundingPoints = this.points.concat();

            !this.arcAngles && this._calcArcAngles();

            if (direction) {
                for (var i = 1; i <= 4; i++) {
                    var randomAngle = i * (PI / 2);

                    if (this.arcAngles.startAngle < this.arcAngles.endAngle) {
                        !(this.arcAngles.startAngle <= randomAngle && randomAngle <= this.arcAngles.endAngle) &&
                        possibleBoundingPoints.push(this.generateArcPoint(randomAngle));
                    } else {
                        (this.arcAngles.endAngle <= randomAngle && randomAngle <= this.arcAngles.startAngle) &&
                        possibleBoundingPoints.push(this.generateArcPoint(randomAngle));
                    }
                }

            } else {
                for (var i = 4; i >= 1; i--) {
                    var randomAngle = i * (PI / 2);

                    if (this.arcAngles.startAngle < this.arcAngles.endAngle) {
                        (this.arcAngles.startAngle <= randomAngle && randomAngle <= this.arcAngles.endAngle) &&
                        possibleBoundingPoints.push(this.generateArcPoint(randomAngle));
                    } else {
                        !(this.arcAngles.endAngle <= randomAngle && randomAngle <= this.arcAngles.startAngle) &&
                        possibleBoundingPoints.push(this.generateArcPoint(randomAngle));
                    }
                }
            }

            return possibleBoundingPoints;
        },

        generateArcPoint: function(angle) {
            return new fabric.Point(this.arcCenter.x + this.radius * Math.cos(angle), this.arcCenter.y + this.radius * Math.sin(angle));
        },

        _calcArcAngles: function() {

            var angleKeyRepo = ["startAngle", "intermediateAngle", "endAngle"];
            this.arcAngles = this.arcAngles || {};

            this.points.forEach(function(point, index) {
                var a = cMath.getAngle(this.arcCenter, point);

                this.arcAngles[angleKeyRepo[index]] = a < 0 ? ((PI * 2) + a) :
                    a > 2 * PI ? ((PI * 2) - a) : a;
            }, this);
        },

        getRenderingDirection: function() {
            return (((this.points[1].x - this.points[0].x) * (this.points[2].y - this.points[0].y)) -
                ((this.points[1].y - this.points[0].y) * (this.points[2].x - this.points[0].x))) < 0;
        },

        _render: function(ctx, noTransform) {
            if (!this.visible) {
                return;
            }

            ctx.beginPath();
            ctx.arc(
                noTransform ? this.left : 0,
                noTransform ? this.top : 0,
                this.radius,
                this.arcAngles.startAngle,
                this.arcAngles.endAngle,
                this.getRenderingDirection()
            );
            this._renderFill(ctx);
            this._renderStroke(ctx);
        },

        toObject: function (propertiesToInclude) {
           return fabric.util.object.extend(this.callSuper('toObject', propertiesToInclude), {
               points: this.points
           });
       }
    });

fabric.ThreePointArc.fromObject = function(object) {
    return new fabric.ThreePointArc(object.points, object);
};

fabric.ThreePointArc.async = false;

fabric.util.cMath = {
  getSlope : function (startPoint, endPoint) {

        if (!startPoint || !endPoint) {
            console.error('startPoint and endPoint are required to evaluate slope');
            return;
        }

        // hack to get around the indefinte slope problem
        if (endPoint.x == startPoint.x) startPoint.x = startPoint.x + 0.01;
        if (endPoint.y == startPoint.y) endPoint.y = endPoint.y + 0.01;

        return (endPoint.y - startPoint.y) / (endPoint.x - startPoint.x);
    },

    getMidPoint: function (startPoint, endPoint) {

        if (!startPoint || !endPoint) {
            console.error('startPoint and endPoint are required to evaluate slope');
            return;
        }

        return { x: (startPoint.x + endPoint.x) / 2, y: (startPoint.y + endPoint.y) / 2 };
    },

    getAngle: function (startPoint, endPoint, isDegree) {

        if (!startPoint || !endPoint) {
            console.error('startPoint and endPoint are required to evaluate slope');
            return;
        }

        var radians = Math.atan2((endPoint.y - startPoint.y), (endPoint.x - startPoint.x)),
            degrees = fabric.util.radiansToDegrees(radians);

        return isDegree ? degrees < 0 ? 360 + degrees : degrees : radians;
    },

    getLength: function (startPoint, endPoint) {

        if (!startPoint || !endPoint) {
            console.error('startPoint and endPoint are required to evaluate slope');
            return;
        }

        return Math.sqrt(Math.pow(endPoint.y - startPoint.y, 2) + Math.pow(endPoint.x - startPoint.x, 2));
    }
}

var canvas  = new fabric.Canvas('c');

var startPoint = new fabric.Point(47.25423728813553, 56.91525423728814),
    intermediatePoint = new fabric.Point( 76.33898305084739,19.8983050847458 ),
    endPoint = new fabric.Point( 105.42372881355931,86 );

 var arc = new fabric.ThreePointArc([startPoint, intermediatePoint, endPoint] , {
        fill:  "#FF0000",
        stroke: "#000",
        strokeWidth: 10
    });
    
canvas.add(arc);
&#13;
<script src="https://cdnjs.cloudflare.com/ajax/libs/fabric.js/1.4.10/fabric.js"></script>
<canvas id="c" width="800" height="800"></canvas>
&#13;
&#13;
&#13;

我试图在结构js上创建一个三点弧(版本:1.4.10)。我想要的是这样的: - https://www.screencast.com/t/dMLvcOduEF

我有一个点数组,我可以从中计算startAngle,endAngle,arcCenter,radius,bounding boxc height和widht,top和left。当我绘制它时,实际的对象不是绘制鼠标指向的位置。它将arcCenter.x和arcCenter.y分别与left和top值相加并绘制。是否有任何解决方法,以便可以在我的指针所在的位置绘制我的弧?因此,我不需要为移动,旋转和缩放编写任何额外的代码行。

我得到的是这样的: - https://www.screencast.com/t/V9MUgB3pB

添加小提琴!!

这有什么解决办法吗?

0 个答案:

没有答案