旋转元素到点击位置
Rotate element to click position
我有一个带有圆圈的项目,单击该圆圈后会旋转到预定义的位置。它几乎就在那里,但最后的要求是它始终顺时针旋转到标记。我似乎无法弄清楚如何获得正确的值,以便当我设置 css transform:rotate(Xdeg) 时,它总是顺时针方向。将角度保持在 0 到 360 度之间也可以为另一部分加分,但不是必需的。
请参阅下面的 fiddle、javascript Rotation
$(function () {
$('body').on('click', '#graph1', function (e) {
console.log('********************');
//get mouse position relative to div and center of div for polar origin
var pos = getMousePosAndCenter(e, 'graph1');
//get the current degrees of rotation from the css
var currentRotationDegrees = getCSSRotation('#graph1');
console.log('CSS Rotation Value: ' + currentRotationDegrees);
//current rotation in radians
var currentRotationRadians = radians(currentRotationDegrees);
//radians where clicked
var clickRadiansFromZero = Math.atan2(pos.y - pos.originY, pos.x - pos.originX);
//degrees the click is offset from 0 origin
var offsetDegrees = degrees(clickRadiansFromZero);
//how many degrees to rotate in css to put the mouse click at 0
var degreesToZero;
if (offsetDegrees >= 0)
degreesToZero = currentRotationDegrees - Math.abs(offsetDegrees);
else
degreesToZero = currentRotationDegrees + Math.abs(offsetDegrees);
console.log("Degrees to Zero: " + degreesToZero);
//distance in pixels from origin
var distance = calculateDistance(pos.originX, pos.originY, pos.x, pos.y);
console.log("Distance From Origin(px): " + distance);
$('#graph1').css('transform','rotate(' + degreesToZero + 'deg)')
});
});
function getMousePosAndCenter(e, id) {
var rect = document.getElementById(id).getBoundingClientRect();
return {
x: (((e.clientX - rect.left) / rect.width) * rect.width) + 0.5 << 0,
y: (((e.clientY - rect.top) / rect.height) * rect.height) + 0.5 << 0,
originY: (rect.height / 2),
originX: (rect.width / 2)
};
}
function radians(degrees) {
return degrees * Math.PI / 180;
};
function degrees(radians) {
return radians * 180 / Math.PI;
};
function calculateDistance(originX, originY, mouseX, mouseY) {
return Math.floor(Math.sqrt(Math.pow(mouseX - originX, 2) + Math.pow(mouseY - originY, 2)));
}
function getCSSRotation(id) {
var matrix = $(id).css('transform');
var values = matrix.split('(')[1],
values = values.split(')')[0],
values = values.split(',');
var a = values[0];
var b = values[1];
var c = values[2];
var d = values[3];
var cssRotation = degrees(Math.atan2(b, a));
return cssRotation;
}
更新:
认为这很容易做到,但我发现它比我想象的要难一些。 jQuery.animate 的另一个答案有效,但动画没有 css 动画所具有的流畅帧率(它在 GPU 上运行)。
这里是修改后的 fiddle 和 CSS 解决方案:http://jsfiddle.net/2g17cjuL/2/
Keeping the angle between 0 and 360 would also be a plus
你不能继续前进(即旋转正数)并保持旋转正数,但是,在我的fiddle offsetDegrees
(额外旋转的度数)中,或余数totalDegrees
的 totalDegrees
除以 360 应该可以提供您需要在其他地方使用的内容。
要求:总是顺时针旋转
有一件事:如果您使用 CSS 转换,它会为您计算最短路线。你想要更多地控制旋转方向,所以我在你的 CSS 中注释掉了 transition:transform 1s ease;
因为我们将手动控制它。
JAVASCRIPT
我借用了 this JQuery function 并对其进行了修改,因此我们可以为它提供起始角度和结束角度,它会为我们设置动画 #graph1
。 (阅读 link 以更改持续时间、缓动和使用 complete
回调)
$.fn.animateRotate = function(angle, start, duration, easing, complete) {
var args = $.speed(duration, easing, complete);
var step = args.step;
return this.each(function(i, e) {
args.complete = $.proxy(args.complete, e);
args.step = function(now) {
$.style(e, 'transform', 'rotate(' + now + 'deg)');
if (step) return step.apply(e, arguments);
};
$({deg: start}).animate({deg: angle}, args);
});
};
我也修改了你的JQuery所以它不会逆时针旋转:当currentRotationDegrees
大于degreesToZero
时,它会减去360,然后使用这个新的值作为 `animateRotate() 的起始位置。
if(currentRotationDegrees > degreesToZero){
currentRotationDegrees -= 360;
}
$('#graph1').animateRotate(degreesToZero, currentRotationDegrees);
它正在运行。
跳出框框思考:
我们可以 CSS3 rotate
具有 transform
的元素,即:720° ...
它将转 2 顺时针 圈。 (好的,在我们的 UI 中它最多只能转 359 圈,但让我们按照数学计算)
如果我们将其设置为 810°... 则意味着 它将顺时针移动 90°!
所以我们需要做的就是总是增加一个度数变量到疯狂!
嘿!如果在某个时候您想跟踪当前的 标准化 0-360 度...
您始终可以通过 ourCurrentInsanelyHighDegree % 360 = UIdegrees
检索该值
这就是您需要的全部 JS。
function getCSSRotation( $el ) {
var matrix = $el.css('transform'),
v = matrix.split('(')[1].split(')')[0].split(','),
rds = Math.atan2(v[1], v[0]);
return rds*180/Math.PI <<0; // Degrees
}
var $EL = $("#graph1"),
w = $EL.width(),
r = w/2, // Radius
x = parseInt($EL.css("left"), 10),
y = parseInt($EL.css("top"), 10),
d = getCSSRotation( $EL ); // Initial degree (ONLY ONCE!)
$EL.on("click", function(e){
var mx = e.clientX-x-r, // Click coord X
my = e.clientY-y-r, // Click coord Y
rds = Math.atan2(-my, -mx), // Radians
md = (rds*180/Math.PI<<0) + 180; // Mouse Degrees
d += (360-md); // always increment to insanity!!
$(this).css({transform:"rotate("+ d +"deg)"});
});
#graph1 {
position:absolute;
top:10px; left:30px;
width:200px; height:200px;
background:url(//placehold.it/200x200&text=IMAGE);
transition:transform 2s ease;
transform:rotate(30deg);
transform-origin:50% 50%;
border-radius:50%;
}
#marker {
position: absolute;
top:110px;
left:230px;
border-top:1px solid black;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div id="graph1"></div>
<div id="marker">Wherever you click, it rotates to here</div>
我有一个带有圆圈的项目,单击该圆圈后会旋转到预定义的位置。它几乎就在那里,但最后的要求是它始终顺时针旋转到标记。我似乎无法弄清楚如何获得正确的值,以便当我设置 css transform:rotate(Xdeg) 时,它总是顺时针方向。将角度保持在 0 到 360 度之间也可以为另一部分加分,但不是必需的。
请参阅下面的 fiddle、javascript Rotation
$(function () {
$('body').on('click', '#graph1', function (e) {
console.log('********************');
//get mouse position relative to div and center of div for polar origin
var pos = getMousePosAndCenter(e, 'graph1');
//get the current degrees of rotation from the css
var currentRotationDegrees = getCSSRotation('#graph1');
console.log('CSS Rotation Value: ' + currentRotationDegrees);
//current rotation in radians
var currentRotationRadians = radians(currentRotationDegrees);
//radians where clicked
var clickRadiansFromZero = Math.atan2(pos.y - pos.originY, pos.x - pos.originX);
//degrees the click is offset from 0 origin
var offsetDegrees = degrees(clickRadiansFromZero);
//how many degrees to rotate in css to put the mouse click at 0
var degreesToZero;
if (offsetDegrees >= 0)
degreesToZero = currentRotationDegrees - Math.abs(offsetDegrees);
else
degreesToZero = currentRotationDegrees + Math.abs(offsetDegrees);
console.log("Degrees to Zero: " + degreesToZero);
//distance in pixels from origin
var distance = calculateDistance(pos.originX, pos.originY, pos.x, pos.y);
console.log("Distance From Origin(px): " + distance);
$('#graph1').css('transform','rotate(' + degreesToZero + 'deg)')
});
});
function getMousePosAndCenter(e, id) {
var rect = document.getElementById(id).getBoundingClientRect();
return {
x: (((e.clientX - rect.left) / rect.width) * rect.width) + 0.5 << 0,
y: (((e.clientY - rect.top) / rect.height) * rect.height) + 0.5 << 0,
originY: (rect.height / 2),
originX: (rect.width / 2)
};
}
function radians(degrees) {
return degrees * Math.PI / 180;
};
function degrees(radians) {
return radians * 180 / Math.PI;
};
function calculateDistance(originX, originY, mouseX, mouseY) {
return Math.floor(Math.sqrt(Math.pow(mouseX - originX, 2) + Math.pow(mouseY - originY, 2)));
}
function getCSSRotation(id) {
var matrix = $(id).css('transform');
var values = matrix.split('(')[1],
values = values.split(')')[0],
values = values.split(',');
var a = values[0];
var b = values[1];
var c = values[2];
var d = values[3];
var cssRotation = degrees(Math.atan2(b, a));
return cssRotation;
}
更新: 认为这很容易做到,但我发现它比我想象的要难一些。 jQuery.animate 的另一个答案有效,但动画没有 css 动画所具有的流畅帧率(它在 GPU 上运行)。
这里是修改后的 fiddle 和 CSS 解决方案:http://jsfiddle.net/2g17cjuL/2/
Keeping the angle between 0 and 360 would also be a plus
你不能继续前进(即旋转正数)并保持旋转正数,但是,在我的fiddle offsetDegrees
(额外旋转的度数)中,或余数totalDegrees
的 totalDegrees
除以 360 应该可以提供您需要在其他地方使用的内容。
要求:总是顺时针旋转
有一件事:如果您使用 CSS 转换,它会为您计算最短路线。你想要更多地控制旋转方向,所以我在你的 CSS 中注释掉了 transition:transform 1s ease;
因为我们将手动控制它。
JAVASCRIPT
我借用了 this JQuery function 并对其进行了修改,因此我们可以为它提供起始角度和结束角度,它会为我们设置动画 #graph1
。 (阅读 link 以更改持续时间、缓动和使用 complete
回调)
$.fn.animateRotate = function(angle, start, duration, easing, complete) {
var args = $.speed(duration, easing, complete);
var step = args.step;
return this.each(function(i, e) {
args.complete = $.proxy(args.complete, e);
args.step = function(now) {
$.style(e, 'transform', 'rotate(' + now + 'deg)');
if (step) return step.apply(e, arguments);
};
$({deg: start}).animate({deg: angle}, args);
});
};
我也修改了你的JQuery所以它不会逆时针旋转:当currentRotationDegrees
大于degreesToZero
时,它会减去360,然后使用这个新的值作为 `animateRotate() 的起始位置。
if(currentRotationDegrees > degreesToZero){
currentRotationDegrees -= 360;
}
$('#graph1').animateRotate(degreesToZero, currentRotationDegrees);
它正在运行。
跳出框框思考:
我们可以 CSS3 rotate
具有 transform
的元素,即:720° ...
它将转 2 顺时针 圈。 (好的,在我们的 UI 中它最多只能转 359 圈,但让我们按照数学计算)
如果我们将其设置为 810°... 则意味着 它将顺时针移动 90°!
所以我们需要做的就是总是增加一个度数变量到疯狂!
嘿!如果在某个时候您想跟踪当前的 标准化 0-360 度...
您始终可以通过 ourCurrentInsanelyHighDegree % 360 = UIdegrees
这就是您需要的全部 JS。
function getCSSRotation( $el ) {
var matrix = $el.css('transform'),
v = matrix.split('(')[1].split(')')[0].split(','),
rds = Math.atan2(v[1], v[0]);
return rds*180/Math.PI <<0; // Degrees
}
var $EL = $("#graph1"),
w = $EL.width(),
r = w/2, // Radius
x = parseInt($EL.css("left"), 10),
y = parseInt($EL.css("top"), 10),
d = getCSSRotation( $EL ); // Initial degree (ONLY ONCE!)
$EL.on("click", function(e){
var mx = e.clientX-x-r, // Click coord X
my = e.clientY-y-r, // Click coord Y
rds = Math.atan2(-my, -mx), // Radians
md = (rds*180/Math.PI<<0) + 180; // Mouse Degrees
d += (360-md); // always increment to insanity!!
$(this).css({transform:"rotate("+ d +"deg)"});
});
#graph1 {
position:absolute;
top:10px; left:30px;
width:200px; height:200px;
background:url(//placehold.it/200x200&text=IMAGE);
transition:transform 2s ease;
transform:rotate(30deg);
transform-origin:50% 50%;
border-radius:50%;
}
#marker {
position: absolute;
top:110px;
left:230px;
border-top:1px solid black;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div id="graph1"></div>
<div id="marker">Wherever you click, it rotates to here</div>