Как предотвратить "шатание" цифровых часов? - PullRequest
0 голосов
/ 01 августа 2020

Для моего проекта цифровых вывесок я сделал простые цифровые часы с датой в 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>

Ответы [ 2 ]

2 голосов
/ 01 августа 2020

Вы не можете использовать шрифт переменной ширины, выравнивать по правому краю и не перемещать текст. Одна из этих двух вещей (переменная ширина или выравнивание по правому краю) должна уступить место (ну, возможно, вы можете просто минимизировать одну). : -)

Вы сказали, что должны использовать шрифт переменной ширины, поэтому у меня есть два обходных пути (я думаю, что называть их «решениями» было бы излишним :-)):

  1. Поставьте время в начало. Это минимизирует эффект; это происходит только при смене дня.

  2. Поместите текст с выравниванием по левому краю в контейнер максимального размера, который вам понадобится, с выравниванием контейнера по правому краю. 1012 *

  3. Сделайте только цифры на часах фиксированной ширины и посмотрите, не пожалуется ли кто-нибудь. : -)

Я не думал о третьем допоздна, но №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, с использованием временного и, вероятно, пустого sh значения ширины; вам нужно больше внимания уделять ширине, чтобы использовать:

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 в текущем шрифте ( подробности ):

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 надежно возвращать строку вместо того, чтобы иногда возвращать строку, а иногда возвращать число .)

0 голосов
/ 05 августа 2020

Если разрешено установить фиксированный интервал шрифта с помощью (по крайней мере, для чисел), вы можете заключить каждый di git в диапазон:

Примечание: 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>
...