这就像互联网上的一个大秘密。
在所有游戏中,我都能发现轮子相对于地面运动而言旋转得慢或快。
给出radius of the circle
和intersection point with the plane at 90 deg
角translate the ground on X axis
,以模拟车轮在地面上的真实滚动。
在下面的示例波纹管鼠标中,旋转圆圈。地面波纹管应该按照您在现实世界中的预期移动。
const plane = $('#plane')
const planeX = plane.offset().left
const wheel = $('#wheel>div')
const radius = wheel.width() / 2
let degrees = 0
const offset = wheel.parent().offset()
$(document).on('mouseenter', '.interactive', event => {
$('.interactive').css('background', 'rgba(172, 255, 47, 0.25)')
const radians = Math.atan2(
event.pageX - (offset.left + radius),
event.pageY - (offset.top + radius)
)
const degreeWheelOffset = radians * (180 / Math.PI) * -1 - degrees // to start from where left off
$(document).on('mousemove', event2 => {
const radians = Math.atan2(
event2.pageX - (offset.left + radius),
event2.pageY - (offset.top + radius)
)
degrees = radians * (180 / Math.PI) * -1 - degreeWheelOffset
wheel.css('transform', 'rotate(' + degrees + 'deg)').data('degree', degrees)
plane.css('left', planeX - (Math.sin(radians) * radius) + 'px')
})
})
$(document).on('mouseleave', '.interactive', () => {
$('.interactive').css('background', '')
$(document).off('mousemove')
})
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div id="wheel" style="position:fixed;bottom:1em;left:50%;transform:translateX(-50%);">
<div style="width:150px;height:150px;border:1px solid;border-radius:50%;background:url('data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAACMAAAAjCAAAAAA7suyFAAAABGdBTUEAALGPC/xhBQAAACBjSFJNAAB6JgAAgIQAAPoAAACA6AAAdTAAAOpgAAA6mAAAF3CculE8AAAAAmJLR0QA/4ePzL8AAAFuSURBVDjLfdRBa8IwGMbxx7cjEklIiVQqjsoCnvb9P8FACBQKngQHXpTJhJx2mRDZoXUmqfW9WX68f5tAR1tEw3jD5/EjUPKT1e/68NRQvil/X1MUGSbXeno9LRMUGmJ1NbsgSxHFIXEBeoiSENBHlITayc4hojTUTbiJbiGrulC36WT+UWuI28U82BIjakNNlccEwPGWIwCUWy16BNm520QAk+tydsWD6f44gUSzmF6AYUSU11oNkO6cRl92cAsA+PLgX+ybfEKQHVacijOejZc/R1qJHXtChLDf5Iza0SDhvK4mBGf0ng0R3RRjEOCWeiCn1Ech27twS7V9kPOM2WqC7k6d0Xvqh1RTjnEzcEZ9JjkvxFpPcDdwRsdv5zmrK4nQwBkV5jxXmzYUGDij7kfghbBdKDRw5v52nNWlRN/cD9MztSkneGTgjNoxwAtV64DE34T27gSzhcSQgTNqz1kUAjBKvmN6h4uQ8bM/WtmCgAk7YV0AAAAASUVORK5CYII=')">
<div class="interactive" style="border-radius:50%;position:absolute;top:0;left:0;bottom:0;right:0"></div>
<div style="position: absolute;top:50%;bottom:0;left:50%;border-left:1px solid;"></div>
</div>
</div>
<div id="plane" style="position:fixed;bottom:0;left:-100vw;width:300vw;height:1em;border:1px solid;display:flex;justify-content:space-around;background:url('data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAACMAAAAjCAAAAAA7suyFAAAABGdBTUEAALGPC/xhBQAAACBjSFJNAAB6JgAAgIQAAPoAAACA6AAAdTAAAOpgAAA6mAAAF3CculE8AAAAAmJLR0QA/4ePzL8AAAFuSURBVDjLfdRBa8IwGMbxx7cjEklIiVQqjsoCnvb9P8FACBQKngQHXpTJhJx2mRDZoXUmqfW9WX68f5tAR1tEw3jD5/EjUPKT1e/68NRQvil/X1MUGSbXeno9LRMUGmJ1NbsgSxHFIXEBeoiSENBHlITayc4hojTUTbiJbiGrulC36WT+UWuI28U82BIjakNNlccEwPGWIwCUWy16BNm520QAk+tydsWD6f44gUSzmF6AYUSU11oNkO6cRl92cAsA+PLgX+ybfEKQHVacijOejZc/R1qJHXtChLDf5Iza0SDhvK4mBGf0ng0R3RRjEOCWeiCn1Ech27twS7V9kPOM2WqC7k6d0Xvqh1RTjnEzcEZ9JjkvxFpPcDdwRsdv5zmrK4nQwBkV5jxXmzYUGDij7kfghbBdKDRw5v52nNWlRN/cD9MztSkneGTgjNoxwAtV64DE34T27gSzhcSQgTNqz1kUAjBKvmN6h4uQ8bM/WtmCgAk7YV0AAAAASUVORK5CYII=')"><b>1</b><b>2</b><b>3</b><b>4</b><b>5</b><b>6</b><b>7</b><b>8</b><b>9</b></div>
答案 0 :(得分:1)
当车辆前进2πm时,车轮会滚动2πm,即2弧度/ r弧度。
当车辆前进d m时,车轮会滚动d m,即d / r弧度角。
答案 1 :(得分:1)
对于mousemove
的每次调用:
有符号的角度变化由下图中的向量之间的叉积给出:
尽管如此,为使90度点附近的数值稳定,最好使用atan2
:
(我敢肯定,这里至少建立了一个几何大师,例如Yves Daoust,上面有一篇帖子解释了上面的工作原理,所以我在这里不做。)
工作代码:
const plane = $('#plane')
const planeX = plane.offset().left
const wheel = $('#wheel>div')
const radius = wheel.width() / 2
const offset = wheel.parent().offset()
let degrees = 0;
$(document).on('mouseenter', '.interactive', event => {
$('.interactive').css('background', 'rgba(172, 255, 47, 0.25)')
let mouseX1 = event.pageX, mouseY1 = event.pageY;
$(document).on('mousemove', event2 => {
const mouseX2 = event2.pageX, mouseY2 = event2.pageY;
// center position
const centerX = offset.left + radius,
centerY = offset.top + radius;
// vectors A - C and B - C
const deltaX1 = mouseX1 - centerX, deltaY1 = mouseY1 - centerY;
const deltaX2 = mouseX2 - centerX, deltaY2 = mouseY2 - centerY;
// change in angle formula
const deltaA = Math.atan2(deltaX1 * deltaY2 - deltaY1 * deltaX2,
deltaX1 * deltaX2 + deltaY1 * deltaY2);
// increment
degrees += deltaA * (180 / Math.PI);
const radians = degrees * (Math.PI / 180);
// set previous coordinates
mouseX1 = mouseX2; mouseY1 = mouseY2;
// apply
wheel.css('transform', 'rotate(' + degrees + 'deg)').data('degree', degrees)
plane.css('left', planeX - radians * radius + 'px') // simpler formula
})
})
$(document).on('mouseleave', '.interactive', () => {
$('.interactive').css('background', '')
$(document).off('mousemove')
})
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div id="wheel" style="position:fixed;bottom:1em;left:50%;transform:translateX(-50%);">
<div style="width:150px;height:150px;border:1px solid;border-radius:50%;background:url('data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAACMAAAAjCAAAAAA7suyFAAAABGdBTUEAALGPC/xhBQAAACBjSFJNAAB6JgAAgIQAAPoAAACA6AAAdTAAAOpgAAA6mAAAF3CculE8AAAAAmJLR0QA/4ePzL8AAAFuSURBVDjLfdRBa8IwGMbxx7cjEklIiVQqjsoCnvb9P8FACBQKngQHXpTJhJx2mRDZoXUmqfW9WX68f5tAR1tEw3jD5/EjUPKT1e/68NRQvil/X1MUGSbXeno9LRMUGmJ1NbsgSxHFIXEBeoiSENBHlITayc4hojTUTbiJbiGrulC36WT+UWuI28U82BIjakNNlccEwPGWIwCUWy16BNm520QAk+tydsWD6f44gUSzmF6AYUSU11oNkO6cRl92cAsA+PLgX+ybfEKQHVacijOejZc/R1qJHXtChLDf5Iza0SDhvK4mBGf0ng0R3RRjEOCWeiCn1Ech27twS7V9kPOM2WqC7k6d0Xvqh1RTjnEzcEZ9JjkvxFpPcDdwRsdv5zmrK4nQwBkV5jxXmzYUGDij7kfghbBdKDRw5v52nNWlRN/cD9MztSkneGTgjNoxwAtV64DE34T27gSzhcSQgTNqz1kUAjBKvmN6h4uQ8bM/WtmCgAk7YV0AAAAASUVORK5CYII=')">
<div class="interactive" style="border-radius:50%;position:absolute;top:0;left:0;bottom:0;right:0"></div>
<div style="position: absolute;top:50%;bottom:0;left:50%;border-left:1px solid;"></div>
</div>
</div>
<div id="plane" style="position:fixed;bottom:0;left:-100vw;width:300vw;height:1em;border:1px solid;display:flex;justify-content:space-around;background:url('data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAACMAAAAjCAAAAAA7suyFAAAABGdBTUEAALGPC/xhBQAAACBjSFJNAAB6JgAAgIQAAPoAAACA6AAAdTAAAOpgAAA6mAAAF3CculE8AAAAAmJLR0QA/4ePzL8AAAFuSURBVDjLfdRBa8IwGMbxx7cjEklIiVQqjsoCnvb9P8FACBQKngQHXpTJhJx2mRDZoXUmqfW9WX68f5tAR1tEw3jD5/EjUPKT1e/68NRQvil/X1MUGSbXeno9LRMUGmJ1NbsgSxHFIXEBeoiSENBHlITayc4hojTUTbiJbiGrulC36WT+UWuI28U82BIjakNNlccEwPGWIwCUWy16BNm520QAk+tydsWD6f44gUSzmF6AYUSU11oNkO6cRl92cAsA+PLgX+ybfEKQHVacijOejZc/R1qJHXtChLDf5Iza0SDhvK4mBGf0ng0R3RRjEOCWeiCn1Ech27twS7V9kPOM2WqC7k6d0Xvqh1RTjnEzcEZ9JjkvxFpPcDdwRsdv5zmrK4nQwBkV5jxXmzYUGDij7kfghbBdKDRw5v52nNWlRN/cD9MztSkneGTgjNoxwAtV64DE34T27gSzhcSQgTNqz1kUAjBKvmN6h4uQ8bM/WtmCgAk7YV0AAAAASUVORK5CYII=')"><b>1</b><b>2</b><b>3</b><b>4</b><b>5</b><b>6</b><b>7</b><b>8</b><b>9</b></div>
稍复杂的答案
以上代码得出的近似值是,在鼠标轮询周期(连续的mousemove
调用之间的间隔)内,滚轮保持静止。对于连续运动,这当然是不正确的-滚轮的中心不断与鼠标一起移动。
由此产生一个一阶非线性微分方程,该方程给出每次鼠标移动的“物理上正确的”增量角(我在这里不再显示其推导):
其中m
是鼠标位置,p
是滚轮位置,theta
是累积角度。通过一些变量替换和重新安排,可以解析地解决该问题。否则它可以很容易地与例如自适应RK4。
...但是,当然,如果轮询频率足够高(通常是这样),即每个轮询周期的增量角很小,那么近似值就足够准确了。