抓拍Svg边框并转换坐标

时间:2022-08-22 13:54:50

I can't figure how to place a path relative to its sibling path's bounding box. Imagine a box like a window and I want to put a close button to the top right corner of it. Here is the box and close button grouped together after transforming the window (scaling it 3x):

我不知道如何将路径相对于它的兄弟路径的边界框放置。想象一个像窗口一样的盒子,我想在它的右上角放一个关闭按钮。这是转换窗口后分组的方框和关闭按钮(缩放到3x):

<g id="group24">
        <path id="path24" fill="#00aa00" stroke="#00ff00" stroke-width="4" stroke-miterlimit="10" d="M301,585.08v47h45.834l-0.134-21.8
            l12.3-0.2l-1-239H253v216c0,0,22,0.2,22,0c0-41,26-31.357,26-31.357V585.08L301,585.08z" transform="matrix(3,0,0,3,-612,-1003.16)"></path>

<path id="close-button" fill="#B40000" d="M256,232c-13.255,0-24,10.745-24,24s10.745,24,24,24s24-10.745,24-24
    S269.255,232,256,232z M265.102,270.277l-8.985-8.984l-8.985,8.985l-4.826-4.829l8.983-8.984l-8.984-8.984l4.829-4.826l8.983,8.982
    l8.981-8.983l4.83,4.827l-8.983,8.983l8.984,8.983L265.102,270.277z"></path>
</g>

I just append the button after transforming the box (animate callback) to the group24 group dynamically and close button appears like this:

我只是在将方框(动画回调)转换为group24组后追加按钮,动态和关闭按钮如下:

抓拍Svg边框并转换坐标

And after when I get the bounding box of the path24 element in group and try to position the close button to the top right:

当我在组中得到path24元素的边界框并试图将关闭按钮定位到右上角时:

var p = this.SvgButton.select("path");
var bbox = myBox.getBBox();
var coordString = (bbox.x2 - 10) + " " + (bbox.y);
p.transform("T" + coordString);

the coordinates are always wrong. How can I position the close button to the top right corner of the lightgreen box?

坐标总是错的。如何将关闭按钮定位到亮绿色框的右上角?

An example of what I'm trying to achieve is here: http://jsfiddle.net/savpm8w3/1/ Note that scale animation doesn't work in jsfiddle and thats why the example in fiddle works.

我要实现的一个示例是:http://jsfiddle.net/savpm8w3/1/注意,scale animation在jsfiddle不起作用,这就是fiddle的示例起作用的原因。

1 个解决方案

#1


4  

I've managed to solve the issue by adding a plugin to Snap.Svg which positions elements relative to other Snap objects' bounding boxes. It can be further worked on to provide more transformation types. If anyone's interested here is the code:

我通过添加插件来解决这个问题。Svg,将元素相对于其他快照对象的边框放置。它还可以进一步提供更多的转换类型。如果有人感兴趣的话,这里是代码:

    Snap.plugin( function( Snap, Element, Paper, global ) {
    Element.prototype.getCenter = function() {
        var bbox = this.getBBox();
        return {x: bbox.cx, y:bbox.cy};
    };
    Element.prototype.getSize = function() {
        var bbox = this.getBBox();
        return {w: bbox.width, h:bbox.height};
    };
    Element.prototype.getPos = function() {
        var bbox = this.getBBox();
        return {x: bbox.x, y:bbox.y};
    };
    Element.prototype.getTransformRelative = function(relativeObj, type, absolute, xadjust, yadjust) {
        var movex = 0;
        var movey = 0;
        switch (type) {
            case "center":
                var c = relativeObj.getCenter();
                var elpos = this.getPos();
                var elsize = this.getSize();
                var movex = c.x - (elsize.w / 2);
                var movey = c.y - (elsize.h / 2);

                movex = (elpos.x > movex ? 0 - (elpos.x - movex) : movex - elpos.x);
                movey = (elpos.y > movey ? 0 - (elpos.y - movey) : movey - elpos.y);
                break;
            case "topleft":
                var movepos = relativeObj.getPos();
                var elpos = this.getPos();

                movex = (elpos.x > movepos.x ? 0 - (elpos.x - movepos.x) : movepos.x - elpos.x);
                movey = (elpos.y > movepos.y ? 0 - (elpos.y - movepos.y) : movepos.y - elpos.y);
                break;
            case "bottomleft":
                var movepos = relativeObj.getBBox();
                var elpos = this.getPos();

                movex = (elpos.x > movepos.x ? 0 - (elpos.x - movepos.x) : movepos.x - elpos.x);
                movey = (elpos.y > movepos.y2 ? 0 - (elpos.y - movepos.y2) : movepos.y2 - elpos.y);
                break;
            case "topright":
                var movepos = relativeObj.getPos();
                var rsize = relativeObj.getSize();
                var elsize = this.getSize();
                var elpos = this.getPos();

                movex = (elpos.x > movepos.x ? 0 - (elpos.x - movepos.x) : movepos.x - elpos.x);
                movey = (elpos.y > movepos.y ? 0 - (elpos.y - movepos.y) : movepos.y - elpos.y);
                movex += rsize.w - elsize.w;
                break;
            case "bottomright":
                var movepos = relativeObj.getBBox();
                var rsize = relativeObj.getSize();
                var elsize = this.getSize();
                var elpos = this.getPos();

                movex = (elpos.x > movepos.x2 ? 0 - (elpos.x - movepos.x2) : movepos.x2 - elpos.x);
                movey = (elpos.y > movepos.y2 ? 0 - (elpos.y - movepos.y2) : movepos.y2 - elpos.y);
                break;
            case "topcenter":
                var c = relativeObj.getCenter();
                var rpos = relativeObj.getPos();
                var elpos = this.getPos();
                var elsize = this.getSize();
                var movex = c.x - (elsize.w / 2);

                movex = (elpos.x > movex ? 0 - (elpos.x - movex) : movex - elpos.x);
                movey = (elpos.y > rpos.y ? 0 - (elpos.y - rpos.y) : rpos.y - elpos.y);
                break;
            case "bottomcenter":
                var c = relativeObj.getCenter();
                var rpos = relativeObj.getBBox();
                var elpos = this.getPos();
                var elsize = this.getSize();
                var movex = c.x - (elsize.w / 2);

                movex = (elpos.x > movex ? 0 - (elpos.x - movex) : movex - elpos.x);
                movey = (elpos.y > rpos.y2 ? 0 - (elpos.y - rpos.y2) : rpos.y2 - elpos.y);
                break;
            case "leftcenter":
                var c = relativeObj.getCenter();
                var rpos = relativeObj.getPos();
                var elpos = this.getPos();
                var elsize = this.getSize();
                var movey = c.y - (elsize.h / 2);

                movex = (elpos.x > rpos.x ? 0 - (elpos.x - rpos.x) : rpos.x - elpos.x);
                movey = (elpos.y > movey ? 0 - (elpos.y - movey) : movey - elpos.y);
                break;
            case "rightcenter":
                var c = relativeObj.getCenter();
                var rbox = relativeObj.getBBox();
                var elpos = this.getPos();
                var elsize = this.getSize();
                var movey = c.y - (elsize.h / 2);

                movex = (elpos.x > rbox.x2 ? 0 - (elpos.x - rbox.x2) : rbox.x2 - elpos.x);
                movey = (elpos.y > movey ? 0 - (elpos.y - movey) : movey - elpos.y);
                break;
            default:
                console.log("ERROR: Unknown transform type in getTransformRelative!");
                break;
        }

        if (typeof(xadjust) === 'undefined') xadjust = 0;
        if (typeof(yadjust) === 'undefined') yadjust = 0;
        movex = movex + xadjust;
        movey = movey + yadjust;

        return (absolute ? "T"+movex+","+movey : "t"+movex+","+movey);
    };
});

#1


4  

I've managed to solve the issue by adding a plugin to Snap.Svg which positions elements relative to other Snap objects' bounding boxes. It can be further worked on to provide more transformation types. If anyone's interested here is the code:

我通过添加插件来解决这个问题。Svg,将元素相对于其他快照对象的边框放置。它还可以进一步提供更多的转换类型。如果有人感兴趣的话,这里是代码:

    Snap.plugin( function( Snap, Element, Paper, global ) {
    Element.prototype.getCenter = function() {
        var bbox = this.getBBox();
        return {x: bbox.cx, y:bbox.cy};
    };
    Element.prototype.getSize = function() {
        var bbox = this.getBBox();
        return {w: bbox.width, h:bbox.height};
    };
    Element.prototype.getPos = function() {
        var bbox = this.getBBox();
        return {x: bbox.x, y:bbox.y};
    };
    Element.prototype.getTransformRelative = function(relativeObj, type, absolute, xadjust, yadjust) {
        var movex = 0;
        var movey = 0;
        switch (type) {
            case "center":
                var c = relativeObj.getCenter();
                var elpos = this.getPos();
                var elsize = this.getSize();
                var movex = c.x - (elsize.w / 2);
                var movey = c.y - (elsize.h / 2);

                movex = (elpos.x > movex ? 0 - (elpos.x - movex) : movex - elpos.x);
                movey = (elpos.y > movey ? 0 - (elpos.y - movey) : movey - elpos.y);
                break;
            case "topleft":
                var movepos = relativeObj.getPos();
                var elpos = this.getPos();

                movex = (elpos.x > movepos.x ? 0 - (elpos.x - movepos.x) : movepos.x - elpos.x);
                movey = (elpos.y > movepos.y ? 0 - (elpos.y - movepos.y) : movepos.y - elpos.y);
                break;
            case "bottomleft":
                var movepos = relativeObj.getBBox();
                var elpos = this.getPos();

                movex = (elpos.x > movepos.x ? 0 - (elpos.x - movepos.x) : movepos.x - elpos.x);
                movey = (elpos.y > movepos.y2 ? 0 - (elpos.y - movepos.y2) : movepos.y2 - elpos.y);
                break;
            case "topright":
                var movepos = relativeObj.getPos();
                var rsize = relativeObj.getSize();
                var elsize = this.getSize();
                var elpos = this.getPos();

                movex = (elpos.x > movepos.x ? 0 - (elpos.x - movepos.x) : movepos.x - elpos.x);
                movey = (elpos.y > movepos.y ? 0 - (elpos.y - movepos.y) : movepos.y - elpos.y);
                movex += rsize.w - elsize.w;
                break;
            case "bottomright":
                var movepos = relativeObj.getBBox();
                var rsize = relativeObj.getSize();
                var elsize = this.getSize();
                var elpos = this.getPos();

                movex = (elpos.x > movepos.x2 ? 0 - (elpos.x - movepos.x2) : movepos.x2 - elpos.x);
                movey = (elpos.y > movepos.y2 ? 0 - (elpos.y - movepos.y2) : movepos.y2 - elpos.y);
                break;
            case "topcenter":
                var c = relativeObj.getCenter();
                var rpos = relativeObj.getPos();
                var elpos = this.getPos();
                var elsize = this.getSize();
                var movex = c.x - (elsize.w / 2);

                movex = (elpos.x > movex ? 0 - (elpos.x - movex) : movex - elpos.x);
                movey = (elpos.y > rpos.y ? 0 - (elpos.y - rpos.y) : rpos.y - elpos.y);
                break;
            case "bottomcenter":
                var c = relativeObj.getCenter();
                var rpos = relativeObj.getBBox();
                var elpos = this.getPos();
                var elsize = this.getSize();
                var movex = c.x - (elsize.w / 2);

                movex = (elpos.x > movex ? 0 - (elpos.x - movex) : movex - elpos.x);
                movey = (elpos.y > rpos.y2 ? 0 - (elpos.y - rpos.y2) : rpos.y2 - elpos.y);
                break;
            case "leftcenter":
                var c = relativeObj.getCenter();
                var rpos = relativeObj.getPos();
                var elpos = this.getPos();
                var elsize = this.getSize();
                var movey = c.y - (elsize.h / 2);

                movex = (elpos.x > rpos.x ? 0 - (elpos.x - rpos.x) : rpos.x - elpos.x);
                movey = (elpos.y > movey ? 0 - (elpos.y - movey) : movey - elpos.y);
                break;
            case "rightcenter":
                var c = relativeObj.getCenter();
                var rbox = relativeObj.getBBox();
                var elpos = this.getPos();
                var elsize = this.getSize();
                var movey = c.y - (elsize.h / 2);

                movex = (elpos.x > rbox.x2 ? 0 - (elpos.x - rbox.x2) : rbox.x2 - elpos.x);
                movey = (elpos.y > movey ? 0 - (elpos.y - movey) : movey - elpos.y);
                break;
            default:
                console.log("ERROR: Unknown transform type in getTransformRelative!");
                break;
        }

        if (typeof(xadjust) === 'undefined') xadjust = 0;
        if (typeof(yadjust) === 'undefined') yadjust = 0;
        movex = movex + xadjust;
        movey = movey + yadjust;

        return (absolute ? "T"+movex+","+movey : "t"+movex+","+movey);
    };
});