如何防止 "wobbling" 数字时钟?
How do I prevent "wobbling" of digital clock?
对于我的数字标牌项目,我用 JS 制作了一个带有日期的简单数字时钟。但是当我在顶部栏的右侧对齐时钟(我需要这样做)时,文本会在秒数更新时来回移动。这是由于我使用的压缩字体(我必须使用它)。有什么想法可以防止这种情况发生吗?
这是我的代码:
function startTime() {
var today = new Date();
var h = today.getHours();
var m = today.getMinutes();
var s = today.getSeconds();
var y = today.getFullYear();
var o = today.getMonth();
var a = today.getDate();
var d = today.getDay();
var monthnames = new Array();
monthnames[0] = "January";
monthnames[1] = "February";
monthnames[2] = "March";
monthnames[3] = "April";
monthnames[4] = "May";
monthnames[5] = "June";
monthnames[6] = "July";
monthnames[7] = "August";
monthnames[8] = "September";
monthnames[9] = "Oktober";
monthnames[10] = "November";
monthnames[11] = "December";
var weekdays = new Array();
weekdays[0] = "Sunday";
weekdays[1] = "Monday";
weekdays[2] = "Tuesday";
weekdays[3] = "Wednesday";
weekdays[4] = "Thursday";
weekdays[5] = "Friday";
weekdays[6] = "Saturday";
m = checkTime(m);
s = checkTime(s);
a = checkTime(a);
document.getElementById('clock').innerHTML =
`<h1>${weekdays[d]}, ${a} ${monthnames[o]}, ${y}, <span id="clocktime">${h}:${m}:${s}</h1>`;
var t = setTimeout(startTime, 500);
}
function checkTime(i) {
if (i < 10) { i = "0" + i }; // Fügt vor einstelligen Zahlen (i > 10) eine Null hinzu
return i;
}
startTime()
@import url('https://fonts.googleapis.com/css?family=Ropa+Sans');
* {
font-family: Ropa Sans;
margin: 0;
}
.top-bar {
width: 100%;
height: 50px;
background-color: #ccc;
display: flex;
justify-content: flex-end;
}
.time {
margin-top: auto;
margin-bottom: auto;
margin-right: 1em;
}
<div class="top-bar">
<div class="time" id="clock"></div>
</div>
您不能使用可变宽度字体和右对齐而不让文本四处移动。这两件事之一(可变宽度或右对齐)必须让位(好吧,可能;你可能只是最小化一个)。 :-)
你说过你必须使用可变宽度字体,所以我有两个解决方法(我认为称它们为“解决方案”会有点过分:-)):
把时间放在开头。这样可以最大限度地减少影响;它只发生在日期改变的时候。
将文本左对齐放置在您需要的最大尺寸的容器中,容器右对齐。
只将时钟数字设置为固定宽度,看看是否有人抱怨。 :-)
我很晚才想到第三个,但#3 可能是你最好的选择。
这是#1 的示例:
function startTime() {
var today = new Date();
var h = today.getHours();
var m = today.getMinutes();
var s = today.getSeconds();
var y = today.getFullYear();
var o = today.getMonth();
var a = today.getDate();
var d = today.getDay();
var monthnames = new Array();
monthnames[0] = "January";
monthnames[1] = "February";
monthnames[2] = "March";
monthnames[3] = "April";
monthnames[4] = "May";
monthnames[5] = "June";
monthnames[6] = "July";
monthnames[7] = "August";
monthnames[8] = "September";
monthnames[9] = "Oktober";
monthnames[10] = "November";
monthnames[11] = "December";
var weekdays = new Array();
weekdays[0] = "Sunday";
weekdays[1] = "Monday";
weekdays[2] = "Tuesday";
weekdays[3] = "Wednesday";
weekdays[4] = "Thursday";
weekdays[5] = "Friday";
weekdays[6] = "Saturday";
m = checkTime(m);
s = checkTime(s);
a = checkTime(a);
document.getElementById('clock').innerHTML =
`<h1><span id="clocktime">${h}:${m}:${s}</span> - ${weekdays[d]}, ${a} ${monthnames[o]}, ${y}</h1>`;
var t = setTimeout(startTime, 500);
}
function checkTime(i) {
if (i < 10) { i = "0" + i }; // Fügt vor einstelligen Zahlen (i > 10) eine Null hinzu
return i;
}
startTime()
@import url('https://fonts.googleapis.com/css?family=Ropa+Sans');
* {
font-family: Ropa Sans;
margin: 0;
}
.top-bar {
width: 100%;
height: 50px;
background-color: #ccc;
display: flex;
justify-content: flex-end;
}
.time {
margin-top: auto;
margin-bottom: auto;
margin-right: 1em;
}
<div class="top-bar">
<div class="time" id="clock"></div>
</div>
这里是#2,使用了临时且可能是垃圾的宽度值;你需要对要使用的宽度做更多的努力:
function startTime() {
var today = new Date();
var h = today.getHours();
var m = today.getMinutes();
var s = today.getSeconds();
var y = today.getFullYear();
var o = today.getMonth();
var a = today.getDate();
var d = today.getDay();
var monthnames = new Array();
monthnames[0] = "January";
monthnames[1] = "February";
monthnames[2] = "March";
monthnames[3] = "April";
monthnames[4] = "May";
monthnames[5] = "June";
monthnames[6] = "July";
monthnames[7] = "August";
monthnames[8] = "September";
monthnames[9] = "Oktober";
monthnames[10] = "November";
monthnames[11] = "December";
var weekdays = new Array();
weekdays[0] = "Sunday";
weekdays[1] = "Monday";
weekdays[2] = "Tuesday";
weekdays[3] = "Wednesday";
weekdays[4] = "Thursday";
weekdays[5] = "Friday";
weekdays[6] = "Saturday";
m = checkTime(m);
s = checkTime(s);
a = checkTime(a);
document.getElementById('clock').innerHTML =
`<h1>${weekdays[d]}, ${a} ${monthnames[o]}, ${y}, <span id="clocktime">${h}:${m}:${s}</span></h1>`;
var t = setTimeout(startTime, 500);
}
function checkTime(i) {
if (i < 10) { i = "0" + i }; // Fügt vor einstelligen Zahlen (i > 10) eine Null hinzu
return i;
}
startTime()
@import url('https://fonts.googleapis.com/css?family=Ropa+Sans');
* {
font-family: Ropa Sans;
margin: 0;
}
.top-bar {
width: 100%;
height: 50px;
background-color: #ccc;
display: flex;
justify-content: flex-end;
}
.time {
width: 450px;
margin-top: auto;
margin-bottom: auto;
margin-right: 1em;
}
<div class="top-bar">
<div class="time" id="clock"></div>
</div>
这是#3。这次的宽度不是完全任意的,是1ch
,也就是当前字体中0
的宽度(details):
function startTime() {
var today = new Date();
var h = today.getHours();
var m = today.getMinutes();
var s = today.getSeconds();
var y = today.getFullYear();
var o = today.getMonth();
var a = today.getDate();
var d = today.getDay();
var monthnames = new Array();
monthnames[0] = "January";
monthnames[1] = "February";
monthnames[2] = "March";
monthnames[3] = "April";
monthnames[4] = "May";
monthnames[5] = "June";
monthnames[6] = "July";
monthnames[7] = "August";
monthnames[8] = "September";
monthnames[9] = "Oktober";
monthnames[10] = "November";
monthnames[11] = "December";
var weekdays = new Array();
weekdays[0] = "Sunday";
weekdays[1] = "Monday";
weekdays[2] = "Tuesday";
weekdays[3] = "Wednesday";
weekdays[4] = "Thursday";
weekdays[5] = "Friday";
weekdays[6] = "Saturday";
m = checkTime(m);
s = checkTime(s);
a = checkTime(a);
document.getElementById('clock').innerHTML =
`<h1>${weekdays[d]}, ${a} ${monthnames[o]}, ${y}, <span id="clocktime">${clockDigits(h)}${clockDigits(":")}${clockDigits(m)}${clockDigits(":")}${clockDigits(s)}</span></h1>`;
var t = setTimeout(startTime, 500);
}
function checkTime(i) {
if (i < 10) {
return "0" + i; // Fügt vor einstelligen Zahlen (i > 10) eine Null hinzu
}
return String(i);
}
function clockDigits(s) {
return String(s).split("").map(ch => `<span class="digit">${ch}</span>`).join("");
}
startTime()
@import url('https://fonts.googleapis.com/css?family=Ropa+Sans');
* {
font-family: Ropa Sans;
margin: 0;
}
.top-bar {
width: 100%;
height: 50px;
background-color: #ccc;
display: flex;
justify-content: flex-end;
}
.time {
margin-top: auto;
margin-bottom: auto;
margin-right: 1em;
}
#clocktime .digit {
display: inline-block;
width: 1ch;
text-align: center;
}
<div>x</div>
<div>x</div>
<div>x</div>
<div class="top-bar">
<div class="time" id="clock"></div>
</div>
(请注意,在第三个中,我还可靠地 checkTime
制作了一个字符串 return,而不是有时 return 一个字符串,有时 return 一个数字。 )
如果允许将字体间距本身设置为固定值(至少对于数字),您可以将每个数字包装在一个范围内:
注:jQuery只是举个小例子:
setInterval(function(){
$('span').each(function(){
const newDigit = parseInt(this.innerHTML) +1
this.innerHTML = newDigit > 9 ? 0 : newDigit;
})
},1000);
span{
display: inline-block;
text-align: center;
width: 8.5px;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<span>1</span><span>2</span>:<span>3</span><span>4</span>
对于我的数字标牌项目,我用 JS 制作了一个带有日期的简单数字时钟。但是当我在顶部栏的右侧对齐时钟(我需要这样做)时,文本会在秒数更新时来回移动。这是由于我使用的压缩字体(我必须使用它)。有什么想法可以防止这种情况发生吗?
这是我的代码:
function startTime() {
var today = new Date();
var h = today.getHours();
var m = today.getMinutes();
var s = today.getSeconds();
var y = today.getFullYear();
var o = today.getMonth();
var a = today.getDate();
var d = today.getDay();
var monthnames = new Array();
monthnames[0] = "January";
monthnames[1] = "February";
monthnames[2] = "March";
monthnames[3] = "April";
monthnames[4] = "May";
monthnames[5] = "June";
monthnames[6] = "July";
monthnames[7] = "August";
monthnames[8] = "September";
monthnames[9] = "Oktober";
monthnames[10] = "November";
monthnames[11] = "December";
var weekdays = new Array();
weekdays[0] = "Sunday";
weekdays[1] = "Monday";
weekdays[2] = "Tuesday";
weekdays[3] = "Wednesday";
weekdays[4] = "Thursday";
weekdays[5] = "Friday";
weekdays[6] = "Saturday";
m = checkTime(m);
s = checkTime(s);
a = checkTime(a);
document.getElementById('clock').innerHTML =
`<h1>${weekdays[d]}, ${a} ${monthnames[o]}, ${y}, <span id="clocktime">${h}:${m}:${s}</h1>`;
var t = setTimeout(startTime, 500);
}
function checkTime(i) {
if (i < 10) { i = "0" + i }; // Fügt vor einstelligen Zahlen (i > 10) eine Null hinzu
return i;
}
startTime()
@import url('https://fonts.googleapis.com/css?family=Ropa+Sans');
* {
font-family: Ropa Sans;
margin: 0;
}
.top-bar {
width: 100%;
height: 50px;
background-color: #ccc;
display: flex;
justify-content: flex-end;
}
.time {
margin-top: auto;
margin-bottom: auto;
margin-right: 1em;
}
<div class="top-bar">
<div class="time" id="clock"></div>
</div>
您不能使用可变宽度字体和右对齐而不让文本四处移动。这两件事之一(可变宽度或右对齐)必须让位(好吧,可能;你可能只是最小化一个)。 :-)
你说过你必须使用可变宽度字体,所以我有两个解决方法(我认为称它们为“解决方案”会有点过分:-)):
把时间放在开头。这样可以最大限度地减少影响;它只发生在日期改变的时候。
将文本左对齐放置在您需要的最大尺寸的容器中,容器右对齐。
只将时钟数字设置为固定宽度,看看是否有人抱怨。 :-)
我很晚才想到第三个,但#3 可能是你最好的选择。
这是#1 的示例:
function startTime() {
var today = new Date();
var h = today.getHours();
var m = today.getMinutes();
var s = today.getSeconds();
var y = today.getFullYear();
var o = today.getMonth();
var a = today.getDate();
var d = today.getDay();
var monthnames = new Array();
monthnames[0] = "January";
monthnames[1] = "February";
monthnames[2] = "March";
monthnames[3] = "April";
monthnames[4] = "May";
monthnames[5] = "June";
monthnames[6] = "July";
monthnames[7] = "August";
monthnames[8] = "September";
monthnames[9] = "Oktober";
monthnames[10] = "November";
monthnames[11] = "December";
var weekdays = new Array();
weekdays[0] = "Sunday";
weekdays[1] = "Monday";
weekdays[2] = "Tuesday";
weekdays[3] = "Wednesday";
weekdays[4] = "Thursday";
weekdays[5] = "Friday";
weekdays[6] = "Saturday";
m = checkTime(m);
s = checkTime(s);
a = checkTime(a);
document.getElementById('clock').innerHTML =
`<h1><span id="clocktime">${h}:${m}:${s}</span> - ${weekdays[d]}, ${a} ${monthnames[o]}, ${y}</h1>`;
var t = setTimeout(startTime, 500);
}
function checkTime(i) {
if (i < 10) { i = "0" + i }; // Fügt vor einstelligen Zahlen (i > 10) eine Null hinzu
return i;
}
startTime()
@import url('https://fonts.googleapis.com/css?family=Ropa+Sans');
* {
font-family: Ropa Sans;
margin: 0;
}
.top-bar {
width: 100%;
height: 50px;
background-color: #ccc;
display: flex;
justify-content: flex-end;
}
.time {
margin-top: auto;
margin-bottom: auto;
margin-right: 1em;
}
<div class="top-bar">
<div class="time" id="clock"></div>
</div>
这里是#2,使用了临时且可能是垃圾的宽度值;你需要对要使用的宽度做更多的努力:
function startTime() {
var today = new Date();
var h = today.getHours();
var m = today.getMinutes();
var s = today.getSeconds();
var y = today.getFullYear();
var o = today.getMonth();
var a = today.getDate();
var d = today.getDay();
var monthnames = new Array();
monthnames[0] = "January";
monthnames[1] = "February";
monthnames[2] = "March";
monthnames[3] = "April";
monthnames[4] = "May";
monthnames[5] = "June";
monthnames[6] = "July";
monthnames[7] = "August";
monthnames[8] = "September";
monthnames[9] = "Oktober";
monthnames[10] = "November";
monthnames[11] = "December";
var weekdays = new Array();
weekdays[0] = "Sunday";
weekdays[1] = "Monday";
weekdays[2] = "Tuesday";
weekdays[3] = "Wednesday";
weekdays[4] = "Thursday";
weekdays[5] = "Friday";
weekdays[6] = "Saturday";
m = checkTime(m);
s = checkTime(s);
a = checkTime(a);
document.getElementById('clock').innerHTML =
`<h1>${weekdays[d]}, ${a} ${monthnames[o]}, ${y}, <span id="clocktime">${h}:${m}:${s}</span></h1>`;
var t = setTimeout(startTime, 500);
}
function checkTime(i) {
if (i < 10) { i = "0" + i }; // Fügt vor einstelligen Zahlen (i > 10) eine Null hinzu
return i;
}
startTime()
@import url('https://fonts.googleapis.com/css?family=Ropa+Sans');
* {
font-family: Ropa Sans;
margin: 0;
}
.top-bar {
width: 100%;
height: 50px;
background-color: #ccc;
display: flex;
justify-content: flex-end;
}
.time {
width: 450px;
margin-top: auto;
margin-bottom: auto;
margin-right: 1em;
}
<div class="top-bar">
<div class="time" id="clock"></div>
</div>
这是#3。这次的宽度不是完全任意的,是1ch
,也就是当前字体中0
的宽度(details):
function startTime() {
var today = new Date();
var h = today.getHours();
var m = today.getMinutes();
var s = today.getSeconds();
var y = today.getFullYear();
var o = today.getMonth();
var a = today.getDate();
var d = today.getDay();
var monthnames = new Array();
monthnames[0] = "January";
monthnames[1] = "February";
monthnames[2] = "March";
monthnames[3] = "April";
monthnames[4] = "May";
monthnames[5] = "June";
monthnames[6] = "July";
monthnames[7] = "August";
monthnames[8] = "September";
monthnames[9] = "Oktober";
monthnames[10] = "November";
monthnames[11] = "December";
var weekdays = new Array();
weekdays[0] = "Sunday";
weekdays[1] = "Monday";
weekdays[2] = "Tuesday";
weekdays[3] = "Wednesday";
weekdays[4] = "Thursday";
weekdays[5] = "Friday";
weekdays[6] = "Saturday";
m = checkTime(m);
s = checkTime(s);
a = checkTime(a);
document.getElementById('clock').innerHTML =
`<h1>${weekdays[d]}, ${a} ${monthnames[o]}, ${y}, <span id="clocktime">${clockDigits(h)}${clockDigits(":")}${clockDigits(m)}${clockDigits(":")}${clockDigits(s)}</span></h1>`;
var t = setTimeout(startTime, 500);
}
function checkTime(i) {
if (i < 10) {
return "0" + i; // Fügt vor einstelligen Zahlen (i > 10) eine Null hinzu
}
return String(i);
}
function clockDigits(s) {
return String(s).split("").map(ch => `<span class="digit">${ch}</span>`).join("");
}
startTime()
@import url('https://fonts.googleapis.com/css?family=Ropa+Sans');
* {
font-family: Ropa Sans;
margin: 0;
}
.top-bar {
width: 100%;
height: 50px;
background-color: #ccc;
display: flex;
justify-content: flex-end;
}
.time {
margin-top: auto;
margin-bottom: auto;
margin-right: 1em;
}
#clocktime .digit {
display: inline-block;
width: 1ch;
text-align: center;
}
<div>x</div>
<div>x</div>
<div>x</div>
<div class="top-bar">
<div class="time" id="clock"></div>
</div>
(请注意,在第三个中,我还可靠地 checkTime
制作了一个字符串 return,而不是有时 return 一个字符串,有时 return 一个数字。 )
如果允许将字体间距本身设置为固定值(至少对于数字),您可以将每个数字包装在一个范围内:
注:jQuery只是举个小例子:
setInterval(function(){
$('span').each(function(){
const newDigit = parseInt(this.innerHTML) +1
this.innerHTML = newDigit > 9 ? 0 : newDigit;
})
},1000);
span{
display: inline-block;
text-align: center;
width: 8.5px;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<span>1</span><span>2</span>:<span>3</span><span>4</span>