我想知道我在使用以下代码时遇到了什么问题。
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 })`);
});
});
答案 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)。