- html - 出于某种原因,IE8 对我的 Sass 文件中继承的 html5 CSS 不友好?
- JMeter 在响应断言中使用 span 标签的问题
- html - 在 :hover and :active? 上具有不同效果的 CSS 动画
- html - 相对于居中的 html 内容固定的 CSS 重复背景?
我创建了这个动画仪表,其中绿色填充和白色数字过渡到数字字段中新输入的值。有时它工作正常,但大多数时候仪表数字只会接近字段值或根本没有变化。例如,如果您输入 400,000,数字将匹配,但如果您输入 450,000,则数字将停止在 442,500。
updateGauge()
中存在问题,因为它会在过渡的任何部分获取填充宽度。我搞砸了一段时间但没有运气。帮助将不胜感激!
window.requestAnimFrame = (function(callback) {
return window.requestAnimationFrame ||
window.webkitRequestAnimationFrame ||
window.mozRequestAnimationFrame ||
window.oRequestAnimationFrame ||
window.msRequestAnimationFrame ||
function(callback) {
window.setTimeout(callback, 1000 / 60);
};
})();
document.addEventListener("DOMContentLoaded", app);
function app() {
let inputVal = document.getElementById("val"),
gaugeVal = document.querySelector(".gauge-value"),
gauge = document.querySelector(".gauge-inner"),
gaugeFill = document.querySelector(".gauge-fill"),
updateGauge = function() {
let rawDigits = (gaugeFill.offsetWidth / gauge.offsetWidth) * inputVal.max,
roundedDigits = Math.round(rawDigits),
digits = String(roundedDigits).split("").reverse(),
displayValueArr = [],
displayValue = "";
// use reversed digits to make comma insertion easier
for (let d in digits) {
displayValueArr.unshift(digits[d]);
if (d % 3 == 2 && d < digits.length - 1) {
displayValueArr.unshift(",");
}
}
for (let a in displayValueArr) {
displayValue += displayValueArr[a];
}
gaugeVal.innerHTML = displayValue;
// update until value reached
if (rawDigits != inputVal.value) {
requestAnimFrame(updateGauge);
}
},
updateVal = function() {
// keep input in range
if (+inputVal.value > inputVal.max) {
inputVal.value = inputVal.max;
} else if (+inputVal.value < inputVal.min) {
inputVal.value = inputVal.min;
}
gaugeFill.style.width = (inputVal.value/inputVal.max * 100) + "%";
updateGauge();
},
userEvent = "oninput" in document.documentElement ? "input": "change";
inputVal.addEventListener(userEvent,updateVal);
}
@import "https://fonts.googleapis.com/css?family=Hind:400,700";
*, *:before, *:after {
box-sizing: border-box;
margin: 0;
padding: 0;
}
:root {
font-size: 20px;
}
body, input {
background: #aca;
font: 1em "Hind", Helvetica, sans-serif;
line-height: 1.5;
}
input {
background: #fff;
border: 0;
box-shadow: 0 0 0 1px #aaa inset;
-webkit-appearance: none;
-moz-appearance: none;
appearance: none;
padding: 0.375em;
}
label {
display: block;
}
main {
padding: 3em 1.5em;
}
form, .gauge {
margin: auto;
}
form {
text-align: center;
}
.gauge {
font-size: 2em;
margin-bottom: 0.75em;
outline: 0;
position: relative;
width: 10em;
height: 1.5em;
transition: all 0.1s linear;
}
.gauge:hover {
filter: brightness(1.1);
-webkit-filter: brightness(1.1);
}
.gauge:active {
filter: brightness(1.25);
-webkit-filter: brightness(1.25);
transform: scale(0.95,0.95);
}
.gauge:not(:active):focus > .gauge-details {
visibility: visible;
}
.gauge > *, .gauge-inner:before, .gauge-details:before {
position: absolute;
}
/* Statistical */
.gauge-stats {
top: 0;
transform: translateY(-25%);
padding: 0 0.375em;
z-index: 1;
}
.gauge-symbol, .gauge-value {
font-weight: bold;
-webkit-text-stroke: 2px #000;
vertical-align: middle;
text-shadow: 0 0.1em 0 #000;
}
.gauge-symbol {
color: #4c4;
font-size: 2em;
line-height: 1.5;
}
.gauge-value {
color: #fff;
}
/* Fill */
.gauge-inner, .gauge-fill {
height: 100%;
}
.gauge-inner {
border: 0.075em solid black;
border-radius: 0.375em;
overflow: hidden;
width: 100%;
}
.gauge-inner:before {
background: #fff;
border-radius: 0.375em;
content: "";
display: block;
opacity: 0.5;
top: 0.125em;
left: 0.125em;
width: calc(100% - 0.25em);
height: 0.5em;
}
.gauge-fill {
background: linear-gradient(-90deg,rgba(255,255,255,0.7),rgba(255,255,255,0) 0.2em) #080;
transition: width 1s linear;
width: 50%;
}
/* Popover */
.gauge-details {
background: rgba(0,0,0,0.7);
border-radius: 0.25em;
color: #fff;
visibility: hidden;
font-size: 0.5em;
padding: 0.375em 0.75em;
text-align: right;
text-shadow: 0 0.1em 0 #000;
top: calc(100% + 0.75em);
left: 50%;
transform: translateX(-50%);
}
.gauge-details:before {
border-left: 0.5em solid transparent;
border-right: 0.5em solid transparent;
border-bottom: 0.5em solid rgba(0,0,0,0.7);
content: "";
width: 0;
height: 0;
bottom: 100%;
left: calc(50% - 0.5em);
}
<main>
<div class="gauge" tabindex="0">
<div class="gauge-stats">
<span class="gauge-symbol">$</span>
<span class="gauge-value">500,000</span>
</div>
<div class="gauge-inner">
<div class="gauge-fill"></div>
</div>
<div class="gauge-details">Max: <strong>1,000,000</strong></div>
</div>
<form>
<label for="val">Change value to:</label>
<input id="val" type="number" min="0" step="1" max="1000000" value="500000">
</form>
</main>
最佳答案
问题与这个比率有关:
(gaugeFill.offsetWidth / gauge.offsetWidth)
offsetWidth 返回元素的宽度包括其边框。所以你可以通过删除类 gauge-inner 的边界来解决你的问题。如果你不太喜欢你的圆形边框,你可以用一个简单的直线轮廓来代替它。否则,您可以使用 box-shadow 创建看起来像边框的东西。
此外,由于在您的情况下 gaugeFill.offsetWidth 是一个只能小于或等于 400 的整数,roundedDigits 只有 400 个可能的值,因此它不是很准确。 这就是为什么你应该用 inputVal.value 替换显示的数字。(我没有自己做,因为你可以看到仪表已修复。)
window.requestAnimFrame = (function(callback) {
return window.requestAnimationFrame ||
window.webkitRequestAnimationFrame ||
window.mozRequestAnimationFrame ||
window.oRequestAnimationFrame ||
window.msRequestAnimationFrame ||
function(callback) {
window.setTimeout(callback, 1000 / 60);
};
})();
document.addEventListener("DOMContentLoaded", app);
function app() {
let inputVal = document.getElementById("val"),
gaugeVal = document.querySelector(".gauge-value"),
gauge = document.querySelector(".gauge-inner"),
gaugeFill = document.querySelector(".gauge-fill"),
// Added variables
oldInputValue = 500000,
timeDifference = 0,
valueDifference = 0,
timeBetweenUpdating = 100; // (in milliseconds) The digits will be updated every 0.1s
updateGauge = function() {
/*let rawDigits = ((gaugeFill.offsetWidth) / (gauge.offsetWidth)) * inputVal.max,
roundedDigits = Math.round(rawDigits),*/
// the value of the digits when they change rapidly
var changingDigits = oldInputValue;
// the time left to animate digits
var timeLeft = Math.abs(timeDifference);
oldInputValue = Number(inputVal.value);
// Every 0.1s the digits a recalculated and displayed.
var digitsUpdating = setInterval(function () {
changingDigits += (timeBetweenUpdating/timeDifference)*valueDifference;
timeLeft -=timeBetweenUpdating;
// If there is no time left (the animation is over)
// the updating stops and the last value to be displayed is inputVal.value
if (timeLeft < 0)
{
changingDigits = inputVal.value;
clearInterval(digitsUpdating);
}
digits = String(Math.trunc(changingDigits)).split("").reverse(),
displayValueArr = [],
displayValue = "";
// use reversed digits to make comma insertion easier
for (let d in digits) {
displayValueArr.unshift(digits[d]);
if (d % 3 == 2 && d < digits.length - 1) {
displayValueArr.unshift(",");
}
}
for (let a in displayValueArr) {
displayValue += displayValueArr[a];
}
gaugeVal.innerHTML = displayValue;
}, timeBetweenUpdating);
// update until value reached
/*if (rawDigits != inputVal.value) {
requestAnimFrame(updateGauge);
}*/
},
updateVal = function() {
// keep input in range
if (+inputVal.value > inputVal.max) {
inputVal.value = inputVal.max;
} else if (+inputVal.value < inputVal.min) {
inputVal.value = inputVal.min;
}
// Added code; animate the gauge fill.
valueDifference = inputVal.value - oldInputValue;
var width = String((inputVal.value/ inputVal.max) * 100) + "%";
timeDifference = (Math.abs(valueDifference) / inputVal.max) * 1500; // Fill the gauge entirely would take 1500ms.
jQuery(gaugeFill).animate({width: width}, timeDifference);
/*gaugeFill.style.width = (inputVal.value/inputVal.max * 100) + "%";*/
updateGauge();
},
userEvent = "oninput" in document.documentElement ? "input": "change";
inputVal.addEventListener(userEvent,updateVal);
}
@import "https://fonts.googleapis.com/css?family=Hind:400,700";
*, *:before, *:after {
box-sizing: border-box;
margin: 0;
padding: 0;
}
:root {
font-size: 20px;
}
body, input {
background: #aca;
font: 1em "Hind", Helvetica, sans-serif;
line-height: 1.5;
}
input {
background: #fff;
border: 0;
box-shadow: 0 0 0 1px #aaa inset;
-webkit-appearance: none;
-moz-appearance: none;
appearance: none;
padding: 0.375em;
}
label {
display: block;
}
main {
padding: 3em 1.5em;
}
form, .gauge {
margin: auto;
}
form {
text-align: center;
}
.gauge {
font-size: 2em;
margin-bottom: 0.75em;
outline: 0;
position: relative;
width: 10em;
height: 1.5em;
/*transition: all 0.1s linear;*/
}
.gauge:hover {
filter: brightness(1.1);
-webkit-filter: brightness(1.1);
}
.gauge:active {
filter: brightness(1.25);
-webkit-filter: brightness(1.25);
transform: scale(0.95,0.95);
}
.gauge:not(:active):focus > .gauge-details {
visibility: visible;
}
.gauge > *, .gauge-inner:before, .gauge-details:before {
position: absolute;
}
/* Statistical */
.gauge-stats {
top: 0;
transform: translateY(-25%);
padding: 0 0.375em;
z-index: 1;
}
.gauge-symbol, .gauge-value {
font-weight: bold;
-webkit-text-stroke: 2px #000;
vertical-align: middle;
text-shadow: 0 0.1em 0 #000;
}
.gauge-symbol {
color: #4c4;
font-size: 2em;
line-height: 1.5;
}
.gauge-value {
color: #fff;
}
/* Fill */
.gauge-inner, .gauge-fill {
height: 100%;
}
.gauge-inner {
border: 0.075em solid black;
border-radius: 0.375em;
overflow: hidden;
width: 100%;
}
.gauge-inner:before {
background: #fff;
border-radius: 0.375em;
content: "";
display: block;
opacity: 0.5;
top: 0.125em;
left: 0.125em;
width: calc(100% - 0.25em);
height: 0.5em;
}
.gauge-fill {
background: linear-gradient(-90deg,rgba(255,255,255,0.7),rgba(255,255,255,0) 0.2em) #080;
/*transition: width 1s linear;*/
width: 50%;
}
/* Popover */
.gauge-details {
background: rgba(0,0,0,0.7);
border-radius: 0.25em;
color: #fff;
visibility: hidden;
font-size: 0.5em;
padding: 0.375em 0.75em;
text-align: right;
text-shadow: 0 0.1em 0 #000;
top: calc(100% + 0.75em);
left: 50%;
transform: translateX(-50%);
}
.gauge-details:before {
border-left: 0.5em solid transparent;
border-right: 0.5em solid transparent;
border-bottom: 0.5em solid rgba(0,0,0,0.7);
content: "";
width: 0;
height: 0;
bottom: 100%;
left: calc(50% - 0.5em);
}
<main>
<div class="gauge" tabindex="0">
<div class="gauge-stats">
<span class="gauge-symbol">$</span>
<span class="gauge-value">500,000</span>
</div>
<div class="gauge-inner">
<div class="gauge-fill"></div>
</div>
<div class="gauge-details">Max: <strong>1,000,000</strong></div>
</div>
<form>
<label for="val">Change value to:</label>
<input id="val" type="number" min="0" step="1" max="1000000" value="500000">
</form>
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
</main>
第二次编辑:
正如我之前所说,我将 jquery 用于其 animate()
函数。所以我在 HTML 中添加了 jQuery 文件(最后)。我还删除了 CSS 中的 transition
属性。因为我不再使用 gaugeFill.offsetWidth
,所以我重新建立了边界。
我直接在 javascript 文件中评论我所做的更改。
动画似乎终于可以完美运行了。仪表填充和数字是动画的,边界重新建立。
我必须说这比我最初想象的要难得多......
关于javascript - 动画仪表未正确更新,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/49417424/
我是 ASM(字节码操作工具包)的新手,正在使用它来检测 Java 字节码。我想访问类的方法并使用 ASM 更改它们的访问修饰符。有人知道如何实现这一目标吗?我知道调用 visitMethod 会有所
如何使用 Instrumentation 从 TestCase 中控制 Android Activity 的生命周期? 关于 official documentation ,声明为“生命周期控制:使用
我正在尝试构建类似于以下内容的 SVG: 笔画是完全动态的,因为它们来自 API。我想将笔画放在收到的点上(作为百分比值数组)。不必有序且两笔之间的距离不必相等 我正在尝试类似下面的方法,但无法提出笔
我正在使用基于 (Chartjs-tsgauge) 的仪表图表。 我想为图表设置与仪表限制分开的背景颜色。如何的问题图表.JS 渲染背景,因为我使用的插件没有关于背景的代码。 例如,我有一个有限制的仪
我有一个来自 logstash 的数据,它显示了数据库中的表使用了多少空间以及表的最大分配容量。我想在 Kibana 中为每个表创建显示当前占用多少空间的仪表。 问题是最大可用空间有时会发生变化,因此
我正在使用 HighChart 的 Angular Gauge,想知道是否可以有不等的间隔。目前,Y 轴上的不等间隔会影响仪表中每个绘图带的大小。如何才能在 Y 轴上具有相等的绘图带大小和不等间隔。
我是 HighCharts 的新手。 我有一个问题,当页面上有多个仪表时,第一个仪表会消失。 这个例子工作正常: HighChart test
我正在尝试使用一些现成的 javascript 来制作仪表。我快到了,但我不知道如何管理值(value)标题。 现在我的代码是这样工作的: 这就是我喜欢它的工作方式: 不知道如何解决问题。使用 Mat
我需要创建一个如下图所示的仪表。 我尝试使用JustGage为了做到这一点,但我找不到渲染仪表下部的方法(图像中的红色半圆)。 我想使用 JustGage。有人知道如何使用 JustGage 绘制“镜
我正在尝试在页面上插入多个 Google 仪表(或 Highchart 仪表)实例。 我想使用不同的选项集并将它们分开。所以我不能使用这里介绍的解决方案,我认为:Google Charts multi
我正在创建一个单页仪表板,它将在我想显示一些图表的监视器上全屏运行。我已经制作了图表,现在我只需要一个合适的页面模板。我在想这样的事情 我真的很喜欢它的外观,但我对如何使用大概的 css/js 制作这
我正在尝试编写一个应用程序,它从加速度计中获取值并通过条形仪表(或者可能是针规)显示它们,但我不确定如何让仪表工作。我正在考虑这些选择: 将仪表分成多个部分,因此仪表“填满”的多个图像,并根据加速度计
我正在尝试使用 Modbus 协议(protocol)对 Socomec 仪表执行 ping 操作,经过研究,我发现了 NModbus,这是一个 C# 库。我之前从未使用过库或 C#(通常是 Java
是否可以将 flexdashboard(下图)中的仪表嵌入 Shiny 应用程序(shinydashboard 或 shiny) >)? 来自 flexdashboard 的 Shiny flexda
已关闭。此问题不符合Stack Overflow guidelines 。目前不接受答案。 要求我们推荐或查找工具、库或最喜欢的场外资源的问题对于 Stack Overflow 来说是偏离主题的,因为
我尝试向我的网站添加仪表,我将 js 和 css 添加到我的信息文件 比在页面中我有这段代码 $(document).ready(function(){ s1 = [1]; plo
我正在尝试在数据标签中添加图标,我成功地添加了一些像这样的 HTML return 'Partially rejected: ' + partial + '' +'Rejected: ' + reje
我发现了一些像 VU 表一样移动指针的 CSS。这模仿了我想做的事情。然而,它从头到尾做一个完整的动画。而我想通过一系列的点击来实现改变。我试图弄清楚如何做到这一点,但我没有成功。我想知道如何让针只通
我在 D3 或 C3js 中寻找这样的东西: C3 中的默认 Gauge Chart 将多个列作为数据,但随后将它们显示在同一行上,因此它们相互覆盖。 最佳答案 如果您使用的是 Angular 4,则
关闭。这个问题不符合Stack Overflow guidelines .它目前不接受答案。 要求我们推荐或查找工具、库或最喜欢的场外资源的问题对于 Stack Overflow 来说是偏离主题的,
我是一名优秀的程序员,十分优秀!