d3js transforming nested group images

2020-04-02 08:42发布

I am working on [this][1] d3 project. Basically I am trying to create a SQL like query builder. I can drop boxes to the drawing area & other operators inside the box. Then I should be able to connect them all. I am trying to translate 2 images which are nested in groups. I want to move the small items inside the big box. I can transform the big box and small operators separately. Problem happens When I try to move the small operators first. I want to move the small operators, then big boxes. meanwhile I want to keep the relative position of small operators and big box same. But when I try to move the large box after moving one of the small box it resets its location. Here is a demo of my work in jsfiddle

<g id="draw">

    <rect class="container" height="400" width="400" x="0" y="0" style="fill:gray"></rect>

    <g class="qbox" id="qbox">

        <line id="dummyLine" x1="0" x2="0" y1="0" y2="0" visibility="hidden"
              style='stroke:red; stroke-width:4px'></line>

        <image x="10" y="10" class="container" initial-x="10" initial-y="10" xlink:href="http://i60.tinypic.com/20ic9e.png"
               width="110"
               height="110"></image>
        <circle class="left" id="qbox-left" initial-cx="10" initial-cy="65" cx="10" cy="65" r="5"
                style="fill:red"></circle>
        <circle class="right" id="qbox-right" initial-cx="120" initial-cy="65" cx="120" cy="65" r="5"
                style="fill:red"></circle>

        <g id="op1" class="op">
            <image class="opim" x="10" y="10" class="container" initial-x="10" initial-y="10"
                   xlink:href="http://i58.tinypic.com/imlzs9.png" width="50"
                   height="50"></image>
            <circle id="op1-left" class="left" initial-cx="10" initial-cy="35" cx="10" cy="35" r="5"
                    style="fill:red"></circle>
            <circle id="op1-right" class="right" initial-cx="60" initial-cy="35" cx="60" cy="35" r="5"
                    style="fill:red"></circle>
        </g>

        <g id="op2" class="op">
            <image class="opim" x="60" y="60" initial-x="60" initial-y="60"
                   xlink:href="http://i58.tinypic.com/imlzs9.png" width="50"
                   height="50"></image>
            <circle id="op2-left" class="left" initial-cx="60" initial-cy="85" cx="60" cy="85" r="5"
                    style="fill:red"></circle>
            <circle id="op2-right" class="right" initial-cx="110" initial-cy="85" cx="110" cy="85" r="5"
                    style="fill:red"></circle>
        </g>

    </g>

    <g class="qbox" id="qbox2" >

        <line id="dummyLine" x1="0" x2="0" y1="0" y2="0" visibility="hidden"
              style='stroke:red; stroke-width:4px'></line>

        <image x="110" y="110" class="container" initial-x="110" initial-y="110" xlink:href="http://i60.tinypic.com/20ic9e.png"
               width="110"
               height="110"></image>
        <circle class="left" id="qbox-left" initial-cx="110" initial-cy="165" cx="110" cy="165" r="5"
                style="fill:red"></circle>
        <circle class="right" id="qbox-right" initial-cx="220" initial-cy="265" cx="220" cy="165" r="5"
                style="fill:red"></circle>

        <g id="op3" class="op">
            <image class="opim" x="110" y="110" class="container" initial-x="110" initial-y="110"
                   xlink:href="http://i58.tinypic.com/imlzs9.png" width="50"
                   height="50"></image>
            <circle id="op1-left" class="left" initial-cx="110" initial-cy="135" cx="110" cy="135" r="5"
                    style="fill:red"></circle>
            <circle id="op1-right" class="right" initial-cx="160" initial-cy="135" cx="160" cy="135" r="5"
                    style="fill:red"></circle>
        </g>
        <g id="op4" class="op">
            <image class="opim" x="160" y="160" initial-x="160" initial-y="160"
                   xlink:href="http://i58.tinypic.com/imlzs9.png" width="50"
                   height="50"></image>
            <circle id="op2-left" class="left" initial-cx="160" initial-cy="185" cx="160" cy="185" r="5"
                    style="fill:red"></circle>
            <circle id="op2-right" class="right" initial-cx="210" initial-cy="185" cx="210" cy="185" r="5"
                    style="fill:red"></circle>
        </g>



    </g>


</g>

    var qBox = d3.selectAll('.qbox')
            .on('dblclick', function () {
                var g = d3.select(this);
                var scale = 'scale(1.2,1.2)';
                g.attr('transform', g.attr('transform') + ' ' + scale);
            });
    var opBox = d3.selectAll('.op');
    var circles = d3.selectAll('circle');


    var cDrag = d3.behavior.drag()

                    .on('dragstart', function () {
                        d3.event.sourceEvent.stopPropagation();
                    })
                    .on('drag', function () {

                        var dummyLine = d3.select('#dummyLine');
                        var me = d3.select(this);

                        var transForm = me.node().getCTM();
                        var t2 = me.select(function () {
                            return this.parentNode;
                        }).select(function () {
                            return this.parentNode;
                        }).select('circle').node().getCTM();

                        var tC = d3.transform(d3.select(this).attr('transform')).translate;
                        var tP = d3.transform(d3.select(this).select(function () {
                            return this.parentNode;
                        }).attr('transform')).translate;

                        console.log(transForm);

                        var meX = t2['e'];
                        var meY = t2['f'];


                        dummyLine
                                .style('visibility', 'visible')
                                .attr('tx1', Number(me.attr('cx')))
                                .attr('x1', Number(me.attr('cx')) + (Number(transForm['e'] - Number(meX))))
                                .attr('ty1', Number(me.attr('cy')))
                                .attr('y1', Number(me.attr('cy')) + (Number(transForm['f'] - Number(meY))))
                                .attr('x2', Number(d3.event.x) )
                                .attr('tx2', Number(d3.event.x) + Number(tP[0]) - Number(tC[0]))
                                .attr('y2', Number(d3.event.y) )
                                .attr('ty2', Number(d3.event.y) + Number(tP[1]) - Number(tC[0]))
                                .attr('start', me.attr('id'))

                        ;

                    })
                    .on('dragend', function () {

                        var g = d3.select(this).select(function () {
                            return this.parentNode;
                        }).select(function () {
                            return this.parentNode;
                        });


                        var dummyLine = d3.select('#dummyLine');

                        dummyLine.style('visibility', 'hidden');

                        d3.select('.qbox')
                                .append('line')
                                .attr('id', function () {
                                    return dummyLine.attr('start') + '__' + circleID;
                                })

                                .attr('x1', dummyLine.attr('x1'))
                                .attr('ix1', dummyLine.attr('tx1'))
                                .attr('x2', dummyLine.attr('x2'))
                                .attr('ix2', d3.select('#' + circleID).attr('cx'))
                                .attr('y1', dummyLine.attr('y1'))
                                .attr('iy1', dummyLine.attr('ty1'))
                                .attr('y2', dummyLine.attr('y2'))
                                .attr('iy2', d3.select('#' + circleID).attr('cy'))
                                .attr('start', dummyLine.attr('start'))
                                .attr('end', circleID)
                                .style('stroke', 'green')
                                .style('stroke-width', '2px')

                        ;
                    })
            ;

    var svg = d3.select('svg').node();

    var drag = d3.behavior.drag()
                    .origin(function () {
                        var t = d3.transform(d3.select(this).attr("transform")).translate;
                        return {x: t[0], y: t[1]};
                    }).on('dragstart', function () {
                        d3.event.sourceEvent.stopPropagation();
                    }).on('drag', function () {

                        var g = d3.select(this);

                        var mouse = {dx: d3.event.x, dy: d3.event.y};
                        var currentObj = {
                            x: g.select('image').attr('x'),
                            y: g.select('image').attr('y'),
                            width: g.select('image').attr('width'),
                            height: g.select('image').attr('height')
                        };
                        var parentObj = {
                            x: (Number(g.select(function () {
                                return this.parentNode;
                            }).select('.container').attr('x'))), // + Number(d3.transform(parent.attr('transform')).translate[0])),
                            y: (Number(g.select(function () {
                                return this.parentNode;
                            }).select('.container').attr('y'))), // + Number(d3.transform(parent.attr('transform')).translate[1])),
                            width: g.select(function () {
                                return this.parentNode;
                            }).select('.container').attr('width'),
                            height: g.select(function () {
                                return this.parentNode;
                            }).select('.container').attr('height')
                        };


                        var loc = getXY(mouse, currentObj, parentObj);
                        d3.select(this).attr('transform', 'translate(' + loc.x + ',' + loc.y + ')');
//                        d3.select(this).attr('transform', 'translate(' + d3.event.x + ',' + d3.event.y + ')');

                        var groupId = d3.select(this).attr('id');
                        var groupClass = d3.select(this).attr('class');

                        d3.selectAll('line')[0].forEach(function (e1) {

                            var line = d3.select(e1);
//                            console.log('groupId: ', groupId);


                            if (line.attr('id') != 'dummyLine' && groupClass != 'qbox') {

//                                console.log('--------------');
//                                console.log('lineId: ', line.attr('id'));

                                var lineStart = line.attr('start').split('-')[0];
                                var lineEnd = line.attr('end').split('-')[0];
//                                console.log('lineStatr : ', lineStart);
//                                console.log('lineEnd : ', lineEnd);

                                var t = d3.transform(d3.select('#' + groupId).attr('transform')).translate;
                                var t2 = d3.transform(d3.select('#' + groupId).select(function () {
                                    return this.parentNode;
                                }).attr('transform')).translate;

                                console.log('groupID ', groupId);

                                if (lineStart == groupId) {
                                    var t = d3.transform(d3.select('#' + lineStart).attr('transform')).translate;

                                    line.attr('x1', Number(line.attr('ix1')) + (Number(t[0])));
                                    line.attr('y1', Number(line.attr('iy1')) + Number(t[1]));
//                                    line.attr('x1', Number(line.attr('ix1')) - (-Number(t[0])+Number(t2[0])));
//                                    line.attr('y1', Number(line.attr('iy1')) - (-Number(t[1]+Number(t2[1]))));

                                }

                                if (lineEnd == groupId) {
                                    var t = d3.transform(d3.select('#' + lineEnd).attr('transform')).translate;

                                    line.attr('x2', Number(line.attr('ix2')) + Number(t[0]));
                                    line.attr('y2', Number(line.attr('iy2')) + Number(t[1]));
//                                    line.attr('x2', Number(line.attr('ix2')) - Number(t[0]));
//                                    line.attr('y2', Number(line.attr('iy2')) - Number(t[1]));
//                                    line.attr('x2', Number(line.attr('ix2')) - (Number(t[0]+Number(t2[0]))));
//                                    line.attr('y2', Number(line.attr('iy2')) - (Number(t[1]+Number(t2[1]))));

                                }

                            }


                        });


                    })

            ;

    opBox.call(drag);
    qBox.call(drag);
    circles.call(cDrag);

    var circleID;

    circles.on('mouseover', function () {
        circleID = d3.select(this).attr('id');
    }).on('mouseout', function () {
        circleID = null;
    })

PS : I connect two elements by dragging the circles and dropping into another circle.

Can anyone point out my mistake?

2条回答
smile是对你的礼貌
2楼-- · 2020-04-02 08:59

From my experience developing visual editors, I can say that relative positions (such as x,y in Operator) can and shoud be managed as data.

Try changing that data (and not directly the x,y attributes of the svg element), and binding the data in a d3js way. It will be much more idiomatic and fast.

PS: I know about separation of model and view, and I know about the bad side of storing visual properties along the model, but if it will be only a view for that model, it is for sure the best approach.

查看更多
做个烂人
3楼-- · 2020-04-02 09:10

After all sort of troubles, I found my answer. Actually it is all about the coordinate system and where to put stuff and how to organize it. Once I fugured that out, Answer is pretty obvious.

<svg width="500" height="500" style="background-color: blue">


    <g id="draw">

        <rect class="container" height="500" width="500" x="0" y="0" style="fill:yellow"></rect>

        <line class="dummyLineOutsideQbox"></line>

        <g class="qbox" id="qbox">

            <line class="dummyLineInsideQbox"></line>


            <image x="10" y="10" class="container" initial-x="10" initial-y="10" xlink:href="images/query.png"
                   width="110"
                   height="110"></image>
            <circle class="left" id="qbox-left" initial-cx="10" initial-cy="65" cx="10" cy="65" r="5"
                    style="fill:red"></circle>
            <circle class="right" id="qbox-right" initial-cx="120" initial-cy="65" cx="120" cy="65" r="5"
                    style="fill:red"></circle>

            <g id="op1" class="op">
                <image class="opim" x="10" y="10" class="container" initial-x="10" initial-y="10"
                       xlink:href="images/filter.png" width="50"
                       height="50"></image>
                <circle id="op1-left" class="left" initial-cx="10" initial-cy="35" cx="10" cy="35" r="5"
                        style="fill:red"></circle>
                <circle id="op1-right" class="right" initial-cx="60" initial-cy="35" cx="60" cy="35" r="5"
                        style="fill:red"></circle>
            </g>

            <g id="op2" class="op">
                <image class="opim" x="60" y="60" initial-x="60" initial-y="60"
                       xlink:href="images/filter.png" width="50"
                       height="50"></image>
                <circle id="op2-left" class="left" initial-cx="60" initial-cy="85" cx="60" cy="85" r="5"
                        style="fill:red"></circle>
                <circle id="op2-right" class="right" initial-cx="110" initial-cy="85" cx="110" cy="85" r="5"
                        style="fill:red"></circle>
            </g>

        </g>

        <g class="qbox" id="qbox2">

            <line class="dummyLineInsideQbox"></line>

            <image x="110" y="110" class="container" initial-x="110" initial-y="110" xlink:href="images/query.png"
                   width="110"
                   height="110"></image>
            <circle class="left" id="qbox2-left" initial-cx="110" initial-cy="165" cx="110" cy="165" r="5"
                    style="fill:red"></circle>
            <circle class="right" id="qbox2-right" initial-cx="220" initial-cy="265" cx="220" cy="165" r="5"
                    style="fill:red"></circle>

            <g id="op3" class="op">
                <image class="opim" x="110" y="110" class="container" initial-x="110" initial-y="110"
                       xlink:href="images/filter.png" width="50"
                       height="50"></image>
                <circle id="op3-left" class="left" initial-cx="110" initial-cy="135" cx="110" cy="135" r="5"
                        style="fill:red"></circle>
                <circle id="op3-right" class="right" initial-cx="160" initial-cy="135" cx="160" cy="135" r="5"
                        style="fill:red"></circle>
            </g>
            <g id="op4" class="op">
                <image class="opim" x="160" y="160" initial-x="160" initial-y="160"
                       xlink:href="images/filter.png" width="50"
                       height="50"></image>
                <circle id="op4-left" class="left" initial-cx="160" initial-cy="185" cx="160" cy="185" r="5"
                        style="fill:red"></circle>
                <circle id="op4-right" class="right" initial-cx="210" initial-cy="185" cx="210" cy="185" r="5"
                        style="fill:red"></circle>
            </g>


        </g>


    </g>

</svg>

<script>
    var qBox = d3.selectAll('.qbox')
            .on('dblclick', function () {
                var g = d3.select(this);
                var scale = 'scale(1.2,1.2)';
                g.attr('transform', g.attr('transform') + ' ' + scale);
            });
    var opBox = d3.selectAll('.op');
    var circles = d3.selectAll('circle');


    var cDrag = d3.behavior.drag()

                    .on('dragstart', function () {
                        d3.event.sourceEvent.stopPropagation();
                    })
                    .on('drag', function () {

                        var thisCircle = d3.select(this);
                        var thisGroup = thisCircle.select(function () {
                            return this.parentNode;
                        });
                        var thisGroupTransform = d3.transform(thisGroup.attr('transform')).translate;

                        var thisGroupParent = d3.select(this).select(function () {
                            return this.parentNode;
                        }).select(function () {
                            return this.parentNode;
                        });

                        var thisGroupParentId = thisGroupParent.attr('id');
                        var thisGroupParentClass = thisGroupParent.attr('class');


                        if (thisGroupParentClass == 'qbox') {
                            dummyLine = d3.select('#' + thisGroupParentId).select('.dummyLineInsideQbox');
                        }
                        else {
                            dummyLine = d3.select('#' + thisGroupParentId).select('.dummyLineOutsideQbox');

                        }

                        console.log('dummyLine ', dummyLine.attr('class'));


                        dummyLine
                                .style('visibility', 'visible')
                                .style('stroke', 'red')
                                .style('stroke-width', '3px')
                                .attr('x1', Number(thisCircle.attr('cx')) + thisGroupTransform[0])
                                .attr('real-x1', thisCircle.attr('cx'))
                                .attr('y1', Number(thisCircle.attr('cy')) + thisGroupTransform[1])
                                .attr('real-y1', thisCircle.attr('cy'))
                                .attr('x2', d3.mouse(this)[0] + thisGroupTransform[0])
                                .attr('y2', d3.mouse(this)[1] + thisGroupTransform[1])
                                .attr('startGroup', thisGroup.attr('id'))
                                .attr('startCircleClass', thisCircle.attr('class'))
                        ;


                    })
                    .on('dragend', function () {


                        var thisCircle = d3.select('#' + circleID);
                        var thisCircleClass = thisCircle.attr('class');
                        var thisGroup = thisCircle.select(function () {
                            return this.parentNode;
                        });

                        var thisGroupTransform = d3.transform(thisGroup.attr('transform')).translate;

                        var thisGroupParent = d3.select(this).select(function () {
                            return this.parentNode;
                        }).select(function () {
                            return this.parentNode;
                        });

                        var thisGroupParentId = thisGroupParent.attr('id');
                        var thisGroupParentClass = thisGroupParent.attr('class');


                        var sourceCircleClass = dummyLine.attr('startCircleClass');
                        var sourceGroup = d3.select('#' + dummyLine.attr('startGroup'));

                        console.log('SOURCE GROUP :', sourceGroup.attr('id'));

                        var targetLineGroup;
                        var lineClass;

                        var t = [0, 0];
                        var x1, x2, y1, y2;

                        if (( sourceGroup.attr('class') == 'op') || (thisGroup.attr('class') == 'op')) {

                            if (sourceGroup.attr('class') == 'op') {
                                targetLineGroup = sourceGroup.select(function () {
                                    return this.parentNode;
                                });
//                                console.log('I am on line 185');
                            } else {
                                targetLineGroup = thisGroup.select(function () {
                                    return this.parentNode;
                                });
//                                console.log('I am on line 190');

                            }
                            lineClass = 'in';
                            x1 = startCircle.attr('cx');
                            y1 = startCircle.attr('cy');
                            x2 = thisCircle.attr('cx');
                            y2 = thisCircle.attr('cy');

                        }

                        if ((sourceGroup.attr('class') == 'qbox') && (thisGroup.attr('class') == 'qbox')) {

                            targetLineGroup = sourceGroup.select(function () {
                                return this.parentNode;
                            });
                            lineClass = 'out';

                            x1 = dummyLine.attr('x1');
                            x2 = dummyLine.attr('x2');
                            y1 = dummyLine.attr('y1');
                            y2 = dummyLine.attr('y2');
                        }

                        targetLineGroup
                                .append('line')
                                .attr('class', lineClass)
                                .attr('id', function () {
                                    return sourceCircleClass + '--' + sourceGroup.attr('id') + '__' + thisCircleClass + '--' + thisGroup.attr('id');
                                })
                                .attr('x1', dummyLine.attr('x1'))
                                .attr('real-x1', dummyLine.attr('x1'))
                                .attr('y1', dummyLine.attr('y1'))
                                .attr('real-y1', dummyLine.attr('y1'))
                                .attr('x2', dummyLine.attr('x2'))
                                .attr('real-x2', dummyLine.attr('x2'))
                                .attr('y2', dummyLine.attr('y2'))
                                .attr('real-y2', dummyLine.attr('y2'))
                                .attr('startGroup', dummyLine.attr('startGroup'))
                                .attr('endGroup', thisGroup.attr('id'))
                                .style('stroke', 'green')
                                .style('stroke-width', '3px')

                        ;
                        dummyLine.style('visibility', 'hidden');


                        console.log('DRAWING LINE ON : ', targetLineGroup.attr('id'))

                    })
            ;

    var svg = d3.select('svg').node();

    var drag = d3.behavior.drag()
                    .origin(function () {
                        var t = d3.transform(d3.select(this).attr("transform")).translate;
                        return {x: t[0], y: t[1]};
                    }).on('dragstart', function () {
                        d3.event.sourceEvent.stopPropagation();
                    }).on('drag', function () {

                        var g = d3.select(this);

                        var mouse = {dx: d3.event.x, dy: d3.event.y};
                        var currentObj = {
                            x: g.select('image').attr('x'),
                            y: g.select('image').attr('y'),
                            width: g.select('image').attr('width'),
                            height: g.select('image').attr('height')
                        };
                        var parentObj = {
                            x: (Number(g.select(function () {
                                return this.parentNode;
                            }).select('.container').attr('x'))), // + Number(d3.transform(parent.attr('transform')).translate[0])),
                            y: (Number(g.select(function () {
                                return this.parentNode;
                            }).select('.container').attr('y'))), // + Number(d3.transform(parent.attr('transform')).translate[1])),
                            width: g.select(function () {
                                return this.parentNode;
                            }).select('.container').attr('width'),
                            height: g.select(function () {
                                return this.parentNode;
                            }).select('.container').attr('height')
                        };


                        var loc = getXY(mouse, currentObj, parentObj);
                        d3.select(this).attr('transform', 'translate(' + loc.x + ',' + loc.y + ')');
//                        d3.select(this).attr('transform', 'translate(' + d3.event.x + ',' + d3.event.y + ')');

                        var thisGroupId = d3.select(this).attr('id');
                        var groupClass = d3.select(this).attr('class');

                        var thisGroupClass = d3.select(this).attr('class');
                        var tLineClass;
                        if (thisGroupClass == 'qbox') {
                            tLineClass = 'out'
                        } else {
                            tLineClass = 'in'
                        }

                        d3.selectAll('line.' + tLineClass)[0].forEach(function (e1) {

                            var line = d3.select(e1);

                            var lineId = line.attr('id');




                            var lineStartGroup = lineId.split('__')[0].split('--')[1];
                            var lineStartSide = lineId.split('__')[0].split('--')[0];
                            var lineEndGroup = lineId.split('__')[1].split('--')[1];
                            var lineEndSide = lineId.split('__')[1].split('--')[0];

                            console.log('-------------------');
                            console.log(lineId);
                            console.log(lineStartGroup);
                            console.log(lineEndGroup);
                            console.log('-------------------');

                            var c;
                            var ctm;

                            if (thisGroupId == lineStartGroup) {
                                var t = d3.transform(d3.select('#' + thisGroupId).attr('transform')).translate;

                                if (lineStartSide == 'left') {
                                    c = d3.select('#' + lineStartGroup).select('.left');
                                    ctm = c.node().getCTM();
                                } else {
                                    c = d3.select('#' + lineStartGroup).select('.right');
                                    ctm = c.node().getCTM();
                                }

                                var x = d3.transform(c.select(function () {
                                    return this.parentNode;
                                }).attr('transform')).translate;


                                console.log('START e'+ctm['e']);
                                console.log('START ex'+x[0]);
                                console.log('START f'+ctm['f']);
                                console.log('START fx'+x[0]);
                                line.attr('x1', Number(c.attr('cx')) + Number(x[0]));
                                line.attr('y1', Number(c.attr('cy')) + Number(x[1]));
                            }

                            if (thisGroupId == lineEndGroup) {
//                                var t = d3.transform(d3.select('#' + thisGroupId).attr('transform')).translate;
//
//                                line.attr('x2', Number(line.attr('real-x2')) + Number(t[0]));
//                                line.attr('y2', Number(line.attr('real-y2')) + Number(t[1]));

                                if (lineEndSide == 'left') {
                                    c = d3.select('#' + lineEndGroup).select('.left');

                                } else {
                                    c = d3.select('#' + lineEndGroup).select('.right');

                                }

                                var x = d3.transform(c.select(function () {
                                    return this.parentNode;
                                }).attr('transform')).translate;

                                ctm = c.node().getCTM();
                                console.log('END circleId'+c.attr('id'));

                                line.attr('x2', Number(c.attr('cx')) + Number(x[0]));
                                line.attr('y2', Number(c.attr('cy')) + Number(x[1]));

                            }


                        });


                    })

            ;

    opBox.call(drag);
    qBox.call(drag);
    circles.call(cDrag);

    var circleID;

    var dummyLine;

    circles.on('mouseover', function () {
        circleID = d3.select(this).attr('id');
    }).on('mouseout', function () {
        circleID = null;
    })

function getXY(mouse, current, parent) {

    var obj = {
        x: 0,
        y: 0
    };

    var dx = mouse.dx;
    var dy = mouse.dy;

    obj.x = dx;
    obj.y = dy;

    var xGap = current.x - parent.x;
    var yGap = current.y - parent.y;

    if (dx < 0) {
        if ((dx + xGap) < 0) {
            obj.x = -1 * xGap + 10;
        }
    } else {
        if ((dx + xGap) > parent.width) {
            obj.x = parent.width - xGap - current.width - 10;
        }
    }

    if (dy < 0) {
        if ((dy + yGap) < 0) {
            obj.y = -1 * yGap + 10;
        }

    } else {
        if ((dy + yGap) > parent.height) {
            obj.y = parent.height - yGap - current.height - 10;
        }
    }


    return obj;
}

</script>
查看更多
登录 后发表回答