How to determine size of Raphael object after scaling & rotating it?

前端 未结 2 922
灰色年华
灰色年华 2020-12-03 20:33

If I were to create an image as a Raphael.js object with the initial size [w1,h1], then scale it using the transform() method, how would I afte

2条回答
  •  心在旅途
    2020-12-03 20:45

    The Matt Esch's example may work with only some (rectangular) elements, but to get metrics of all possible elements (and also in cases where element is affected by nested transformations of parent groups) we have to use an other approach. To get various metrics (width, height, bbox width, bbox height, corner coordinates, side lengths etc.) of whichever transformed SVG element I made a get_metrics()-function:

    Full functional example: http://output.jsbin.com/zuvuborehe/

    The following image shows one possible use case of get_metrics():

    Metrics example

    The function get_metrics() uses pure javascript, no libraries. But it can OC be used with libraries, like Raphaël. It is based on native element1.getTransformToElement(element2) which can get relation matrix between two elements, which are in this case the transformed element (eg. ) and SVG root element (). Of course you can use other elements also, like image, polygon, rectangle etc. By the way, the getTransformToElement is very powerful and versatile, it can be used eg. to flatten transforms of path consisting of whichever path commands ( even arcs if they are first converted to Cubics using Raphaël's path2curve) this way: http://jsbin.com/atidoh/9.

    SVGElement.prototype.getTransformToElement = 
    SVGElement.prototype.getTransformToElement || function(elem)
    { 
      return elem.getScreenCTM().inverse().multiply(this.getScreenCTM()); 
    };
    
    function get_metrics(el) {
        function pointToLineDist(A, B, P) {
            var nL = Math.sqrt((B.x - A.x) * (B.x - A.x) + (B.y - A.y) * (B.y - A.y));
            return Math.abs((P.x - A.x) * (B.y - A.y) - (P.y - A.y) * (B.x - A.x)) / nL;
        }
    
        function dist(point1, point2) {
            var xs = 0,
                ys = 0;
            xs = point2.x - point1.x;
            xs = xs * xs;
            ys = point2.y - point1.y;
            ys = ys * ys;
            return Math.sqrt(xs + ys);
        }
        var b = el.getBBox(),
            objDOM = el,
            svgDOM = objDOM.ownerSVGElement;
        // Get the local to global matrix
        var matrix = svgDOM.getTransformToElement(objDOM).inverse(),
            oldp = [[b.x, b.y], [b.x + b.width, b.y], [b.x + b.width, b.y + b.height], [b.x, b.y + b.height]],
            pt, newp = [],
            obj = {},
            i, pos = Number.POSITIVE_INFINITY,
            neg = Number.NEGATIVE_INFINITY,
            minX = pos,
            minY = pos,
            maxX = neg,
            maxY = neg;
    
        for (i = 0; i < 4; i++) {
            pt = svgDOM.createSVGPoint();
            pt.x = oldp[i][0];
            pt.y = oldp[i][1];
            newp[i] = pt.matrixTransform(matrix);
            if (newp[i].x < minX) minX = newp[i].x;
            if (newp[i].y < minY) minY = newp[i].y;
            if (newp[i].x > maxX) maxX = newp[i].x;
            if (newp[i].y > maxY) maxY = newp[i].y;
        }
        // The next refers to the transformed object itself, not bbox
        // newp[0] - newp[3] are the transformed object's corner
        // points in clockwise order starting from top left corner
        obj.newp = newp; // array of corner points
        obj.width = pointToLineDist(newp[1], newp[2], newp[0]) || 0;
        obj.height = pointToLineDist(newp[2], newp[3], newp[0]) || 0;
        obj.toplen = dist(newp[0], newp[1]);
        obj.rightlen = dist(newp[1], newp[2]);
        obj.bottomlen = dist(newp[2], newp[3]);
        obj.leftlen = dist(newp[3], newp[0]);
        // The next refers to the transformed object's bounding box
        obj.BBx = minX;
        obj.BBy = minY;
        obj.BBx2 = maxX;
        obj.BBy2 = maxY;
        obj.BBwidth = maxX - minX;
        obj.BBheight = maxY - minY;
        return obj;
    }
    

提交回复
热议问题