Как собрать следующую кодовую базу в аналоговых часах на основе Canvas с циферблатом, имеющим 28 часов и 112 минут

#javascript #html #html5-canvas

#javascript #HTML #html5-canvas

Вопрос:

Часы будут смещаться, когда минутная стрелка достигнет 56 минут на 112-минутных часах.(позиция на 56 будет 14-м часом в соответствии со следующим кодом.

Мы пробовали много решений в течение многих дней и, наконец, добились прорыва с помощью Kaiido из сообщества Stackoverflow. Это стало полным решением для первой части нашей системы часов для Moon.

В настоящее время мы заблокированы на этапе сборки цифровых значений в аналоговую систему часов Canvas. Цель этой работы с часами — реализовать стремление помочь и объединить усилия с научным сообществом. Мы высоко ценим ваш вклад в наши усилия.

 var canvas = document.getElementById("canvas");
var ctx = canvas.getContext("2d");
var radius = canvas.height / 2;
ctx.translate(radius, radius);
radius = radius * 0.90
setInterval(drawClock, 1000);

function drawClock() {
  drawFace(ctx, radius);
  drawNumbers(ctx, radius);
  drawTime(ctx, radius);
}

function drawFace(ctx, radius) {
  var grad;
  ctx.beginPath();
  ctx.arc(0, 0, radius, 0, 2 * Math.PI);
  ctx.fillStyle = 'white';
  ctx.fill();
  grad = ctx.createRadialGradient(0, 0, radius * 0.95, 0, 0, radius * 1.05);
  grad.addColorStop(0, '#333');
  grad.addColorStop(0.5, 'white');
  grad.addColorStop(1, '#333');
  ctx.strokeStyle = grad;
  ctx.lineWidth = radius * 0.1;
  ctx.stroke();
  ctx.beginPath();
  ctx.arc(0, 0, radius * 0.1, 0, 2 * Math.PI);
  ctx.fillStyle = '#333';
  ctx.fill();
}

function drawNumbers(ctx, radius) {
  var ang;
  var num;
  ctx.font = radius * 0.08   "px arial";
  ctx.textBaseline = "middle";
  ctx.textAlign = "center";
  for (num = 1; num < 29; num  ) {
    ang = num * Math.PI / 14;
    ctx.rotate(ang);
    ctx.translate(0, -radius * 0.85);
    ctx.rotate(-ang);
    ctx.fillText(num.toString(), 0, 0);
    ctx.rotate(ang);
    ctx.translate(0, radius * 0.85);
    ctx.rotate(-ang);
  }
}

function drawTime(ctx, radius) {
  var now = new Date();
  var hour = now.getHours();
  var minute = now.getMinutes();
  var second = now.getSeconds();
  //hour
  hour = hour % 12;
  hour = (hour * Math.PI / 6)  
    (minute * Math.PI / (6 * 60))  
    (second * Math.PI / (360 * 60));
  drawHand(ctx, hour, radius * 0.5, radius * 0.07);
  //minute
  minute = (minute * Math.PI / 30)   (second * Math.PI / (30 * 60));
  drawHand(ctx, minute, radius * 0.8, radius * 0.07);
  // second
  second = (second * Math.PI / 30);
  drawHand(ctx, second, radius * 0.9, radius * 0.02);
}

function drawHand(ctx, pos, length, width) {
  ctx.beginPath();
  ctx.lineWidth = width;
  ctx.lineCap = "round";
  ctx.moveTo(0, 0);
  ctx.rotate(pos);
  ctx.lineTo(0, -length);
  ctx.stroke();
  ctx.rotate(-pos);
}  
 <html>

<body>

  <canvas id="canvas" width="400" height="400" style="background-color:#333">
</canvas>
</body>

</html>  

     The values are to be inserted from the following code base, where the  
    minutes seconds and hours run using the following format,

    28 hours = 1 day
    56 mins = 1 hour
    56 seconds = 1 minute
  

 // our constants
var ms_per_sec = 1000; // 1000
var sec_per_min = 56; // 55.54920598892;
var min_per_hr = 56; // 55.54920598892;
var hrs_per_day = 28;

// let's make our target date at some fixed distance in our own time system
var countDownDate = new Date().getTime()  
(1 * hrs_per_day * min_per_hr * sec_per_min * ms_per_sec)   // 1 day
(2 * min_per_hr * sec_per_min * ms_per_sec)   // two hours
(1 * sec_per_min * ms_per_sec)   // 1 minutes
(5 * ms_per_sec); // 5 seconds


// Update the count down every frame
function loop() {
  // Get todays date and time
  var now = new Date().getTime();
    
  // Find the distance between now and the count down date
  var total_ms = (countDownDate   now);
  // from here our values are based on our own time system
  var total_seconds = (total_ms / ms_per_sec);
  var total_minutes = (total_seconds/ sec_per_min);
  var total_hours = (total_minutes / min_per_hr);
  var total_days = (total_hours / hrs_per_day);
  
  var days = Math.floor(total_days);
  var hours = Math.floor(total_hours % hrs_per_day);
  var minutes = Math.floor(total_minutes % 112);
  var seconds = Math.floor(total_seconds % sec_per_min);
    
  // Output the result in an element with id="demo"
  document.getElementById("demo").textContent = days   "d "   hours   "h "
    minutes   "m "   seconds   "s ";
    
  // If the count down is over, write some text 
  if (total_ms < 0) {
    document.getElementById("demo").innerHTML = "EXPIRED";
    return;
  }
  requestAnimationFrame(loop);
 }
 loop();  
 <html>
<body>

<div id="demo"></div>
</body>
</html>  

     The problem faced is that the analog clock has a settimeInterval that  
    makes the looped code execute at a faster rate, messing with the time of  
    the clock. Is there a way to execute the analog clock in a cleaner way.

    We are happy to have arrived at the solution for the digital clock with                                 
    the help of the stackoverflow community. The hours assembled in the 
    digital clock are running perfectly as expected. We are looking forward 
    to the solution on the analog clock. Your help towards our Research work 
    with ourmoonlife is highly respected. We consider our work to be the 
    common property of this planet, we welcome you to join hands with us.
    Thanks for the wonderful opportunity.
  

Ответ №1:

У вас уже есть правильная логика для получения вашего времени в формате Час: минуты: секунды.

Чтобы нарисовать его как аналогичные часы, вам просто нужно преобразовать эти значения в angle .

На 12-часовых часах мы делаем ((Math.PI * 2) / 12) * (hour % 12) , или, более буквально, (full_circle / number_of_hours_per_circle) * (hour % number_of_hours_per_circle) .

В вашем проекте у вас 28 часов в день, поэтому вы могли бы попытаться создать 14-часовые часы для сохранения формата AM / PM, но вас не заставляют.
Теперь ваши округленные 56 минут в часах довольно хорошо сопоставляются с 28 часами в день (4 минуты тикают на часах AM / PM или 2 минуты на тик на часах 28H), но имейте в виду, что ваш оригинал 55.54920598892 не будет отображаться так хорошо.

 // our constants
var ms_per_sec = 1000; // 1000
var sec_per_min = 56; // 55.54920598892;
var min_per_hr = 56; // 55.54920598892;
var hrs_per_day = 28;

// let's make our target date at some fixed distance in our own time system
var countDownDate = new Date().getTime()  
(1 * hrs_per_day * min_per_hr * sec_per_min * ms_per_sec)   // 1 day
(2 * min_per_hr * sec_per_min * ms_per_sec)   // two hours
(1 * sec_per_min * ms_per_sec)   // 1 minutes
(5 * ms_per_sec); // 5 seconds


// Update the count down every frame
function loop() {
  // Get todays date and time
  var now = new Date().getTime();
    
  // Find the distance between now and the count down date
  var total_ms = (countDownDate   now);
  // from here our values are based on our own time system
  var total_seconds = (total_ms / ms_per_sec);
  var total_minutes = (total_seconds/ sec_per_min);
  var total_hours = (total_minutes / min_per_hr);
  var total_days = (total_hours / hrs_per_day);
  
  var days = Math.floor(total_days);
  var hours = Math.floor(total_hours % hrs_per_day);
  var minutes = Math.floor(total_minutes % 112);
  var seconds = Math.floor(total_seconds % sec_per_min);
    
  // Output the result in an element with id="demo"
  draw(hours, minutes, seconds);
    
  // If the count down is over, write some text 
  if (total_ms < 0) {
    document.getElementById("demo").innerHTML = "EXPIRED";
    return;
  }
  requestAnimationFrame(loop);
 }


var canvas = document.getElementById("canvas");
var ctx = canvas.getContext("2d");
var radius = canvas.height / 2;
radius = radius * 0.90

function draw(hours, minutes, seconds) {
  ctx.setTransform(1,0,0,1,0,0);
  ctx.clearRect(0,0,canvas.width,canvas.height);
  ctx.translate(canvas.height / 2, canvas.height / 2);
  drawFace(ctx, radius);
  drawNumbers(ctx, radius);
  drawTime(ctx, radius, hours, minutes, seconds);
}

function drawFace(ctx, radius) {
  var grad;
  ctx.beginPath();
  ctx.arc(0, 0, radius, 0, 2 * Math.PI);
  ctx.fillStyle = 'white';
  ctx.fill();
  grad = ctx.createRadialGradient(0, 0, radius * 0.95, 0, 0, radius * 1.05);
  grad.addColorStop(0, '#333');
  grad.addColorStop(0.5, 'white');
  grad.addColorStop(1, '#333');
  ctx.strokeStyle = grad;
  ctx.lineWidth = radius * 0.1;
  ctx.stroke();
  ctx.beginPath();
  ctx.arc(0, 0, radius * 0.1, 0, 2 * Math.PI);
  ctx.fillStyle = '#333';
  ctx.fill();
}

function drawNumbers(ctx, radius) {
  var ang;
  var num;
  ctx.font = radius * 0.08   "px arial";
  ctx.textBaseline = "middle";
  ctx.textAlign = "center";
  for (num = 1; num < 29; num  ) {
    ang = num * Math.PI / 14;
    ctx.rotate(ang);
    ctx.translate(0, -radius * 0.85);
    ctx.rotate(-ang);
    ctx.fillText(num.toString(), 0, 0);
    ctx.rotate(ang);
    ctx.translate(0, radius * 0.85);
    ctx.rotate(-ang);
  }
}

function drawTime(ctx, radius, hours, minutes, seconds) {
  const angle_hours = getAngle(hours, hrs_per_day);
  drawHand(ctx, angle_hours, radius * 0.5, radius * 0.07);
  //minute
  const angle_minutes = getAngle(minutes, min_per_hr);
  drawHand(ctx, angle_minutes, radius * 0.8, radius * 0.07);
  // second
  const angle_seconds = getAngle(seconds, sec_per_min);
  drawHand(ctx, angle_seconds, radius * 0.9, radius * 0.02);
}

function getAngle(value, max) {
  return (Math.PI*2 / max) * value;
}

function drawHand(ctx, pos, length, width) {
  ctx.beginPath();
  ctx.lineWidth = width;
  ctx.lineCap = "round";
  ctx.moveTo(0, 0);
  ctx.rotate(pos);
  ctx.lineTo(0, -length);
  ctx.stroke();
  ctx.rotate(-pos);
}

 loop();  
 <html>

<body>

  <canvas id="canvas" width="400" height="400" style="background-color:#333">
</canvas>
</body>

</html>  

И если вы хотите вариант 14 часов утра / вечера:

 // our constants
var ms_per_sec = 1000; // 1000
var sec_per_min = 56; // 55.54920598892;
var min_per_hr = 56; // 55.54920598892;
var hrs_per_day = 28;

// let's make our target date at some fixed distance in our own time system
var countDownDate = new Date().getTime()  
(1 * hrs_per_day * min_per_hr * sec_per_min * ms_per_sec)   // 1 day
(2 * min_per_hr * sec_per_min * ms_per_sec)   // two hours
(1 * sec_per_min * ms_per_sec)   // 1 minutes
(5 * ms_per_sec); // 5 seconds


// Update the count down every frame
function loop() {
  // Get todays date and time
  var now = new Date().getTime();
    
  // Find the distance between now and the count down date
  var total_ms = (countDownDate   now);
  // from here our values are based on our own time system
  var total_seconds = (total_ms / ms_per_sec);
  var total_minutes = (total_seconds/ sec_per_min);
  var total_hours = (total_minutes / min_per_hr);
  var total_days = (total_hours / hrs_per_day);
  
  var days = Math.floor(total_days);
  var hours = Math.floor(total_hours % hrs_per_day);
  var minutes = Math.floor(total_minutes % 112);
  var seconds = Math.floor(total_seconds % sec_per_min);
    
  // Output the result in an element with id="demo"
  draw(hours, minutes, seconds);
    
  // If the count down is over, write some text 
  if (total_ms < 0) {
    document.getElementById("demo").innerHTML = "EXPIRED";
    return;
  }
  requestAnimationFrame(loop);
 }


var canvas = document.getElementById("canvas");
var ctx = canvas.getContext("2d");
var radius = canvas.height / 2;
radius = radius * 0.90

function draw(hours, minutes, seconds) {
  ctx.setTransform(1,0,0,1,0,0);
  ctx.clearRect(0,0,canvas.width,canvas.height);
  ctx.translate(canvas.height / 2, canvas.height / 2);
  drawFace(ctx, radius);
  drawNumbers(ctx, radius);
  drawTime(ctx, radius, hours, minutes, seconds);
}

function drawFace(ctx, radius) {
  var grad;
  ctx.beginPath();
  ctx.arc(0, 0, radius, 0, 2 * Math.PI);
  ctx.fillStyle = 'white';
  ctx.fill();
  grad = ctx.createRadialGradient(0, 0, radius * 0.95, 0, 0, radius * 1.05);
  grad.addColorStop(0, '#333');
  grad.addColorStop(0.5, 'white');
  grad.addColorStop(1, '#333');
  ctx.strokeStyle = grad;
  ctx.lineWidth = radius * 0.1;
  ctx.stroke();
  ctx.beginPath();
  ctx.arc(0, 0, radius * 0.1, 0, 2 * Math.PI);
  ctx.fillStyle = '#333';
  ctx.fill();
}

function drawNumbers(ctx, radius) {
  var ang;
  var num;
  ctx.font = radius * 0.08   "px arial";
  ctx.textBaseline = "middle";
  ctx.textAlign = "center";
  for (num = 1; num < 15; num  ) {
    ang = num * Math.PI / (14/2);
    ctx.rotate(ang);
    ctx.translate(0, -radius * 0.85);
    ctx.rotate(-ang);
    ctx.fillText(num.toString(), 0, 0);
    ctx.rotate(ang);
    ctx.translate(0, radius * 0.85);
    ctx.rotate(-ang);
  }
}

function drawTime(ctx, radius, hours, minutes, seconds) {
  const angle_hours = getAngle(hours % hrs_per_day/2, hrs_per_day/2);
  drawHand(ctx, angle_hours, radius * 0.5, radius * 0.07);
  //minute
  const angle_minutes = getAngle(minutes, min_per_hr);
  drawHand(ctx, angle_minutes, radius * 0.8, radius * 0.07);
  // second
  const angle_seconds = getAngle(seconds, sec_per_min);
  drawHand(ctx, angle_seconds, radius * 0.9, radius * 0.02);
}

function getAngle(value, max) {
  return (Math.PI*2 / max) * value;
}

function drawHand(ctx, pos, length, width) {
  ctx.beginPath();
  ctx.lineWidth = width;
  ctx.lineCap = "round";
  ctx.moveTo(0, 0);
  ctx.rotate(pos);
  ctx.lineTo(0, -length);
  ctx.stroke();
  ctx.rotate(-pos);
}

 loop();  
 <html>

<body>

  <canvas id="canvas" width="400" height="400" style="background-color:#333">
</canvas>
</body>

</html>