抓住&从中心移动元素

时间:2017-02-24 16:39:12

标签: javascript svg drag-and-drop viewbox

我想知道我在使用以下代码时遇到了什么问题。

SVG已经放大并翻译,元素垂直拖动,但是,它仍然很疯狂。

https://jsbin.com/gahoseneyu/edit?js,output

const svg = document.getElementsByTagName( "svg" )[ 0 ];
const w = svg.getAttribute( "width" );
const h = svg.getAttribute( "height" );
const cry = document.getElementById( "cry" );
const reg = /\d*\.\d[^\s]/g;
const viewBox = svg.getAttribute( "viewBox" ).match( reg );
const wRatio = w / viewBox[ 2 ];
const hRatio = h / viewBox[ 3 ];
console.log( "viewbox is...", viewBox, wRatio, hRatio );
cry.addEventListener( "mousedown", function(){
    this.addEventListener( "mousemove", function( e ){
        let newX = (e.pageX / wRatio) + parseFloat( viewBox[ 0 ]) - 22,
             newY = (e.pageY / hRatio) + parseFloat( viewBox[ 1 ]) - 22;
        this.setAttribute( "transform", `translate(${ newX },${ newY })`);
    });
});

1 个答案:

答案 0 :(得分:1)

问题是viewBox与视口不同,后者是实际使用的视口。例如,你的viewBox以191个单位开始,但你可以看到你的cry元素的x坐标为0.如果你添加一个矩形来查看视口,这会有所帮助:

<rect x="191.37" y="15.73" width="212.59" height="393.23"/>

您可以使用preserveAspectRatio来保留宽高比,具体取决于您尝试做的事情(本教程应该有所帮助:http://tutorials.jenkov.com/svg/svg-viewport-view-box.html

或者,您可以计算真正的viewBox是什么:

const svg = document.getElementsByTagName( "svg" )[ 0 ];
const cry = document.getElementById( "cry" );
const h = svg.clientHeight;
const w = svg.clientWidth;

const viewBoxW = svg.viewBox.baseVal.width;
const viewBoxH = svg.viewBox.baseVal.height;
let wRatio = w / viewBoxW;
let hRatio = h / svg.viewBoxH;
let viewBoxX = svg.viewBox.baseVal.x;
let viewBoxY = svg.viewBox.baseVal.y;

if (wRatio > hRatio) {
    wRatio = hRatio;
    viewBoxX = w / 2 / wRatio - (viewBoxX + viewBoxW / 2);
} else {
    hRatio = wRatio;
    viewBoxY = h / 2 / hRatio - (viewBoxY + viewBoxH / 2);
}


svg.addEventListener( "mousedown", function(){
    this.addEventListener( "mousemove", function( e ){

        let newX = e.pageX / wRatio - viewBoxX - 22,
            newY = e.pageY / hRatio + viewBoxY - 22;

        cry.setAttribute( "transform", `translate(${ newX },${ newY })`);
    });
});

请注意,您应该将转换添加到cry元素。

另外,当你第一次点击元素时,比如说它的角落,它会跳跃,所以鼠标位于中心。为避免这种情况,您需要计算点击和对象中心之间的原始偏移量,并使用它来代替(-22,-22)。