从中心抓取并移动一个元素
Grab & Move An Element From The Centre
我想知道我在使用以下代码时做错了什么。
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 })`);
});
});
问题是 viewBox 与实际使用的视口不同。例如,您的 viewBox 从 191 个单位开始,但您可以看到 x 坐标为 0 的 cry 元素。如果您添加一个矩形来查看视口,它会有所帮助:
<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)。
我想知道我在使用以下代码时做错了什么。
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 })`);
});
});
问题是 viewBox 与实际使用的视口不同。例如,您的 viewBox 从 191 个单位开始,但您可以看到 x 坐标为 0 的 cry 元素。如果您添加一个矩形来查看视口,它会有所帮助:
<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)。