- html - 出于某种原因,IE8 对我的 Sass 文件中继承的 html5 CSS 不友好?
- JMeter 在响应断言中使用 span 标签的问题
- html - 在 :hover and :active? 上具有不同效果的 CSS 动画
- html - 相对于居中的 html 内容固定的 CSS 重复背景?
引用和这个问题的延续:Making an image spin with css and jQuery
我有兴趣进一步采用这种方法。一个由七部分组成的轮子开始旋转,当轮子停止旋转时,会显示来自相关 block 的正确值。我有一个不同的需要,我想实现。单击时,我的七部分轮停在随机区域,但应始终停在该部分的中心。我将如何实现此功能?现在,我的轮子随机停止,有时停在边缘或轮子的一部分没有任何内容。在我看来,要从零点开始第一站,我需要做一些数学运算,例如 ((360/7)/2),它得出第一个 block 的中心。我应该如何将数学结合到脚本中以始终停在其目标 block 的中心?
这是我到目前为止能够构建的...
<html>
<style>
.roulette_center {
position: absolute;
top: 255px;
left: 258px;
cursor: pointer;
}
.roulette_center:hover {
transform: scale(1.01);
}
.roulette_wheel{
touch-action:auto;pointer-events:painted
}
</style>
<body>
<div style="z-index: 0; position: relative">
<span style="position: absolute; top: 0px; left: 360px; font-weight:700;font-size:24px;" id="score"> </span>
<img class="roulette_wheel" src="https://www.dropbox.com/s/6kp3fmtp72aj3vy/wellness-wheel.png?raw=1" />
<img class="roulette_center" src="https://www.dropbox.com/s/52x8iyb1nvkjm0w/wheelCenter.png?raw=1" onclick="roulette_spin(this)" onfocus="transform()">
<div style="position: absolute; top: 30px; left: 350px; background-color: red; width: 1px; height: 60px;"></div>
</div>
<script>
var force = 0;
var angle = 0;
var rota = 1;
var inertia = 0.985;
var minForce = 15;
var randForce = 15;
var rouletteElem = document.getElementsByClassName('roulette_wheel')[0];
var scoreElem = document.getElementById('score');
var values = [
"Spititual", "Emotional", "Intellectual", "Physical", "Social", "Environmental", "Financial"
].reverse();
function roulette_spin(btn) {
// set initial force randomly
force = Math.floor(Math.random() * randForce) + minForce;
requestAnimationFrame(doAnimation);
}
function doAnimation() {
// new angle is previous angle + force modulo 360 (so that it stays between 0 and 360)
angle = (angle + force) % 360;
// decay force according to inertia parameter
force *= inertia;
rouletteElem.style.transform = 'rotate(' + angle + 'deg)';
// stop animation if force is too low
if (force < 0.05) {
// score roughly estimated
scoreElem.innerHTML = values[Math.floor(((angle / 360) * values.length) - 0.5)];
return;
}
requestAnimationFrame(doAnimation);
}
</script>
</body>
</html>
最佳答案
这是一个解决方案,用于处理类似 flex 的捕捉到停止切片的中心。
它利用我称之为吸引子的东西,根据目标(最近切片的中心)改变旋转速度。不涉及 CSS 转换,仅涉及 vanilla javascript。
你离吸引子越近,将你拉向它的力就越强。它被计算为到吸引子的距离的保护倒数。当距离接近 0 时(当然当它刚好为 0 时),保护意义防止非常大的值
我喜欢这个解决方案,因为它使用简单的人工物理学(车轮惯性和车轮片下的一种磁铁)模拟我们需要的东西,并让物理学只在初始随机插入后解决问题。
您可以尝试使用物理参数和停止条件,但要小心,因为数值不稳定很容易出现。
编辑:
onclick="roulette_spin(this)"
,添加了 document. getElementsByClassName('roulette_center')[0].addEventListener('click', roulette_spin);
在 js 中将现在私有(private)的(范围内的)处理程序(roulette_spin)绑定(bind)到轮子中心)编辑 2:
添加了对点击切片的检测
如果轮子旋转并且没有点击切片,它将根据初始速度和惯性停止,将末端捕捉到(随机)切片的中心。
如果轮子旋转并点击一个切片,速度将改变,以便轮子应该停在非常靠近目标切片的地方,迫使吸引器到点击的切片将确保轮子实际上停在这个片。 @mathspeople 在这里:提议的公式远非准确,我很高兴听到修改后的停止距离公式来计算适当的速度修正。但是,嘿......它只是有效......
如果滚轮没有旋转,单击一个切片将使滚轮动画到单击的切片。这是一个很好的特性,具有高摩擦力(低惯性),因为轮子会快速转动直到正确定位并很好地减速。它充当旋转菜单,这是 OP 可能首先想要的。
(我建议在全页模式下查看代码片段。注意:就目前而言,旋转期间不支持多次单击切片并且会失败,单击切片后,您需要等待轮子停止. 修复很简单,但即使它很有趣,我也花了很多时间在这个答案上,禁闭/宵禁有它的好处 :D)
(function() {
var values = [
"Financial", "Environmental", "Social", "Physical", "Intellectual", "Emotional", "Spititual"
];
var speed = 0;
// should init angle so that the cursor is at the center of the desired value,
// this is just to test the offset is right
var angle = getAngleFor("Intellectual");
// how much of the speed is kept at each update step (0 < i < 1, the bigger the longer the wheel spins)
var inertia = 0.988;
var minSpeed = 15;
// how much randomness in initial push speed
var randRange = 15;
// strongest absolute force that an attractor can exerce (is squashed to before scaling is applied)
var maxAttractionForce = 0.5;
// scale attraction force
var attractionForceFactor = 0.02;
var rouletteElem = document.getElementsByClassName('roulette_wheel')[0];
var scoreElem = document.getElementById('score');
// offset the display angle so that angle 0 is at the edge of the first slice
var offset = 26.42;
var currentAnimationFrame = null;
var clickedSliceIndex = -1;
var estimatedSliceIndex = -1;
var totalAngle = 0;
function addParamInput(name, value, min, max, step, handler) {
var id = name + '-input-id';
var wrapper = document.createElement('div');
wrapper.classList.add('single-input-wrapper');
var label = document.createElement('label');
label.setAttribute('for', id);
label.innerHTML = name;
var input = document.createElement('input');
input.setAttribute('type', 'range');
input.setAttribute('min', ''+min);
input.setAttribute('max', ''+max);
input.setAttribute('step', ''+step);
input.setAttribute('value', ''+value);
input.addEventListener('change', handler);
var meter = document.createElement('span');
meter.classList.add('input-meter');
meter.innerHTML = value;
wrapper.appendChild(label);
wrapper.appendChild(input);
wrapper.appendChild(meter);
document.getElementById('all-input-wrappers').appendChild(wrapper);
}
function updateInputMeter(input) {
input.parentElement.getElementsByClassName('input-meter')[0].innerHTML = input.value;
}
function roulette_spin(evt) {
evt.stopPropagation();
clickedSliceIndex = -1;
totalAngle = 0;
// erase score
scoreElem.innerHTML = '';
// set initial speed randomly
speed = Math.floor(Math.random() * randRange) + minSpeed;
// console.log('initial speed', speed);
// probably far from accurate but it kind of works, attractor
// completely ignored because when spinning fast it cost speed as much
// as it adds, and after it won't matter
// since we will be forcing the attractor to where we want to stop
var estimatedSpin = speed / (1 - inertia);
// console.log('estimated total spin approximation', estimatedSpin);
estimatedSliceIndex = getSliceIndex((angle + estimatedSpin) % 360);
// console.log('estimated stopping slice', values[estimatedSliceIndex]);
if (currentAnimationFrame) {
cancelAnimationFrame(currentAnimationFrame);
}
currentAnimationFrame = requestAnimationFrame(doAnimation);
}
function getSliceIndex(angle) {
return Math.floor(((angle / 360) * values.length));
}
function getCircularDist(a, b) {
// assuming both a and b are positive angles 0 <= angle <= 360
// find shortest oriented distance
// example: if a is 350 degrees and b is 10 degrees what's the actuals angular dist from a to b
// naive implementation would be b - a which gives - 340 => wrong, it only takes
// 20 degrees to rotate from 350 to 10 => b - (a - 360)
// conversely if a is 300 and b is 250 the shortest distance is
// the other way around => b - a = -50 degrees
var d1 = b - a;
var d2 = b - (a - 360);
return Math.abs(d1) >= Math.abs(d2) ? d2 : d1;
}
function setRouletteAngle(angle) {
rouletteElem.style.transform = 'rotate(' + (offset + angle) + 'deg)';
}
function getAngleFor(value) {
return getAngleForIndex(values.indexOf(value));
}
function getAngleForIndex(sliceIndex) {
return (sliceIndex + 0.5) * (360 / values.length);
}
function handleRouletteClick(evt) {
// coordinate of the center of the wheel
var centerX = rouletteElem.offsetWidth / 2;
var centerY = rouletteElem.offsetHeight / 2;
// console.log('centerX', centerX, 'centerY',centerY);
// roulette's parent bounding rect
var rect = evt.target.parentElement.getBoundingClientRect();
// coordinates of the click in roulette's parent coordinates
var clickX = evt.clientX - rect.x;
var clickY = evt.clientY - rect.y;
// resulting coordinates relative to the center of the wheel
var x = clickX - centerX;
var y = clickY - centerY;
// console.log('x', x, 'y', y);
var norm = Math.sqrt(x*x+y*y);
// -pi < rad < pi
var rad = Math.atan2(x, y);
var deg = (rad * 180) / Math.PI;
// 0 <= clickedAngle < 360 starting from the first slice
var clickedAngle = ((deg < 0 ? deg + 360 : deg) + angle + 180) % 360;
clickedSliceIndex = Math.floor((clickedAngle / 360) * values.length);
scoreElem.style.color = 'lightgrey';
scoreElem.innerHTML = 'clicked ' + values[clickedSliceIndex];
// outside of an animation started with the center button it will make the wheel spin to target
if (!currentAnimationFrame) {
// assume wheel is not mmoving so the estimated slice is the slice at the current angle
estimatedSliceIndex = getSliceIndex(angle);
currentAnimationFrame = requestAnimationFrame(doAnimation);
}
var estimatedAngle = getAngleForIndex(estimatedSliceIndex);
var targetFinalAngle = getAngleForIndex(clickedSliceIndex);
var spinError = getCircularDist(estimatedAngle, targetFinalAngle);
var speedCorrection = spinError * (1 - inertia);
speed += speedCorrection;
}
function doAnimation() {
// new angle is previous angle + speed modulo 360 (so that it stays between 0 and 360)
totalAngle += speed;
angle = (angle + speed) % 360;
// decay speed according to inertia parameter
speed = speed - (1 - inertia) * speed;
// add attractor force: inverse of circular oriented dist to the closest slice center * some factor
var sliceIndex = clickedSliceIndex !== -1 ? clickedSliceIndex : getSliceIndex(angle);
var target = getAngleForIndex(sliceIndex);
var orientedDist = getCircularDist(angle, target);
// protect against infinity (division by 0 or close to 0)
var inverseOrientedDistAmplitude = orientedDist === 0
? maxAttractionForce
: Math.min(1/Math.abs(orientedDist), maxAttractionForce);
var finalAttractionForce = Math.sign(orientedDist) * inverseOrientedDistAmplitude * attractionForceFactor;
speed = speed + finalAttractionForce;
setRouletteAngle(angle);
// stop animation if speed is low and close to attraction point
if (speed < 0.01 && Math.abs(orientedDist) < 0.05 ) {
// console.log('total spin', totalAngle);
scoreElem.style.color = 'black';
scoreElem.innerHTML = values[getSliceIndex(angle)];
currentAnimationFrame = null;
return;
}
currentAnimationFrame = requestAnimationFrame(doAnimation);
}
setRouletteAngle(angle);
document.getElementsByClassName('roulette_center')[0].addEventListener('click', roulette_spin);
rouletteElem.parentElement.addEventListener('click', handleRouletteClick);
addParamInput('minSpeed', 15, 0, 60, 0.5, function(evt) {
var rangeInput = evt.target;
minSpeed = parseFloat(rangeInput.value);
updateInputMeter(rangeInput)
});
addParamInput('inertia', 0.988, 0.900, 0.999, 0.001, function(evt) {
var rangeInput = evt.target;
inertia = parseFloat(rangeInput.value);
updateInputMeter(rangeInput)
});
addParamInput('attractionForceFactor', 0.02, 0, 0.1, 0.001, function(evt) {
var rangeInput = evt.target;
attractionForceFactor = parseFloat(rangeInput.value);
updateInputMeter(rangeInput)
});
addParamInput('maxAttractionForce', 0.5, 0, 1.5, 0.01, function(evt) {
var rangeInput = evt.target;
maxAttractionForce = parseFloat(rangeInput.value);
updateInputMeter(rangeInput)
});
})();
.roulette_center {
position: absolute;
top: 255px;
left: 258px;
cursor: pointer;
}
.roulette_center:hover {
transform: scale(1.01);
}
.roulette_wheel{
touch-action: auto;
pointer-events:painted
}
.single-input-wrapper {
display: flex;
align-items: center;
}
.single-input-wrapper > label {
width: 150px;
}
.single-input-wrapper > input {
width: 150px;
}
#score {
position: absolute;
top: 0px;
left: 360px;
font-weight: 700;
font-size: 24px;
}
#indicator {
position: absolute;
top: 30px;
left: 350px;
background-color: red;
width: 1px;
height: 60px;
}
#all-input-wrappers {
z-index: 10;
position: absolute;
top: 0px;
left: 0px;
opacity: 0.2;
background-color: white;
display: flex;
flex-direction: column;
transition: opacity 0.2s;
}
#all-input-wrappers:hover {
opacity: 0.8;
}
<html>
<head>
</head>
<body>
<div style="z-index: 0; position: relative">
<div id="all-input-wrappers"></div>
<span id="score"> </span>
<img
class="roulette_wheel"
src="https://www.dropbox.com/s/6kp3fmtp72aj3vy/wellness-wheel.png?raw=1"
/>
<img
class="roulette_center"
src="https://www.dropbox.com/s/52x8iyb1nvkjm0w/wheelCenter.png?raw=1"
onfocus="transform()"
>
<div id="indicator"></div>
</div>
</body>
</html>
关于jquery - JS中的纺车,如何在随机选择的切片的中心自动停止旋转,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/65959865/
...沮丧。我希望我的游戏仅在横向模式下运行。我已将适当的键/值添加到 Info.plist 文件中,以强制设备方向在启动时正确。 我现在正在尝试旋转 OpenGL 坐标空间以匹配设备的坐标空间。我正
我如何创建一个旋转矩阵,将 X 旋转 a,Y 旋转 b,Z 旋转 c? 我需要公式,除非您使用的是 ardor3d api 的函数/方法。 矩阵是这样设置的 xx, xy, xz, yx, yy, y
假设我有一个包含 3 个 vector 的类(一个用于位置,一个用于缩放,一个用于旋转)我可以使用它们生成一个变换矩阵,该矩阵表示对象在 3D 空间中的位置、旋转和大小。然后我添加对象之间的父/子关系
所以我只是在玩一个小的 javascript 游戏,构建一个 pacman 游戏。你可以在这里看到它:http://codepen.io/acha5066/pen/rOyaPW 不过我对旋转有疑问。你
在我的应用程序中,我有一个 MKMapView,其中显示了多个注释。 map 根据设备的航向旋转。要旋转 map ,请执行以下语句(由方法 locationManager 调用:didUpdateHe
使用此 jquery 插件时:http://code.google.com/p/jqueryrotate/wiki/Documentation我将图像旋转 90 度,无论哪个方向,它们最终都会变得模糊
我有以下代码:CSS: .wrapper { margin:80px auto; width:300px; border:none; } .square { widt
本篇介绍Manim中的两个旋转类的动画,名称差不多,分别是Rotate和Rotating。 Rotate类主要用于对图形对象进行指定角度、围绕特定点的精确旋转,适用于几何图形演示、物理模拟和机械运动
我只想通过小部件的轴移动图像并围绕小部件的中心旋转(就像任何数字绘画软件中的 Canvas ),但它围绕其左顶点旋转...... QPainter p(this); QTransform trans;
我需要先旋转图像,然后再将其加载到 Canvas 中。据我所知,我无法使用 canvas.rotate() 旋转它,因为它会旋转整个场景。 有没有好的JS方法来旋转图片? [不依赖于浏览器的方式] 最
我需要知道我的 Android 设备屏幕何时从一个横向旋转到另一个横向(rotation_90 到 rotation_270)。在我的 Android 服务中,我重新实现了 onConfigurati
**摘要:**本篇文章主要讲解Python调用OpenCV实现图像位移操作、旋转和翻转效果,包括四部分知识:图像缩放、图像旋转、图像翻转、图像平移。 本文分享自华为云社区《[Python图像处理] 六
我只是在玩MTKView中的模板设置;并且,我一直在尝试了解以下内容: 相机的默认位置。 使用MDLMesh和MTKMesh创建基元时的默认位置。 为什么轮换还涉及翻译。 相关代码: matrix_f
我正在尝试使用包 dendexend 创建一个树状图。它创建了非常好的 gg 树状图,但不幸的是,当你把它变成一个“圆圈”时,标签跟不上。我将在下面提供一个示例。 我的距离对象在这里:http://s
我想将一个完整的 ggplot 对象旋转 90°。 我不想使用 coord_flip因为这似乎会干扰 scale="free"和 space="free"使用刻面时。 例如: qplot(as.fac
我目前可以通过首先平移到轴心点然后执行旋转最后平移回原点来围绕轴心点旋转。在我的例子中,我很容易为肩膀做到这一点。但是,我不知道如何为前臂添加绕肘部的旋转。 我已经尝试了以下围绕肘部旋转的前臂: 平移
我想使用此功能旋转然后停止在特定点或角度。现在该元素只是旋转而不停止。代码如下: $(function() { var $elie = $("#bkgimg");
关闭。这个问题需要多问focused 。目前不接受答案。 想要改进此问题吗?更新问题,使其仅关注一个问题 editing this post . 已关闭 4 年前。 Improve this ques
我正在尝试创建一个非常简单的关键帧动画,其中图形通过给定的中点从一个角度旋转到另一个角度。 (目的是能够通过大于 180 度的 OBTUSE 弧角来制作旋转动画,而不是让动画“作弊”并走最短路线,即通
我需要旋转 NSView 实例的框架,使其宽度变为其高度,其高度变为其宽度。该 View 包含一个字符串,并且该字符串也被旋转,这一点很重要。 我查看了 NSView 的 setFrameRotati
我是一名优秀的程序员,十分优秀!