3300.me

canvas timecount

last update: 2020/12/19
<!doctype html>
<html>
<head>
<meta charset="utf-8">
<title>title</title>
<meta name="viewport" content="width=device-width, user-scalable=no, initial-scale=1, maximum-scale=1">
<style>
.circles {
overflow: hidden;
}
.year, .day, .hour, .minute, .second {
float: left;
position: relative;
margin: 0 4px;
}
@keyframes fadeIn {
  from {
    opacity: 0;
  }
  to {
    opacity: 1;
  }
}
@keyframes fadeOut {
  from {
    opacity: 1;
  }
  to {
    opacity: 0;
  }
}
.fadeIn {
animation-name: fadeIn;
animation-duration: .7s;
}
.fadeOut {
animation-name: fadeOut;
animation-duration: .7s;
}
.diff {
opacity: 1;
}
.prev {
opacity: 0;
}
.diff, .prev {
width: 100%;
position: absolute;
top: 38px;
text-align: center;
font-size: 44px;
line-height: 44px;
}
.diff + span {
display: block;
width: 100%;
position: absolute;
top: 86px;
text-align: center;
font-size: 11px;
line-height: 14px;
}
.information {
font-size: 12px;
}
</style>
</head>
<body>

<div class="information" style="margin-bottom: 20px;">
  <div class="target">target: <span></span></div>
  <div class="targetMil">targetMil: <span></span></div>
  <div class="nowMil">nowMil: <span></span></div>
  <div class="diffMil">diffMil: <span></span></div>
  <div class="digits">digits: <span></span></div>
</div>

<div class="countdown">
  <div class="circles">
    <div class="year">
      <canvas class="canvas" width="" height=""></canvas>
      <div class="prev"></div>
      <div class="diff"></div>
      <span>---<br>99<br>year</span>
    </div>
    <div class="day">
      <canvas class="canvas" width="" height=""></canvas>
      <div class="prev"></div>
      <div class="diff"></div>
      <span>---<br>365<br>day</span>
    </div>
    <div class="hour">
      <canvas class="canvas" width="" height=""></canvas>
      <div class="prev"></div>
      <div class="diff"></div>
      <span>---<br>24<br>hour</span>
    </div>
    <div class="minute">
      <canvas class="canvas" width="" height=""></canvas>
      <div class="prev"></div>
      <div class="diff"></div>
      <span>---<br>60<br>min</span>
    </div>
    <div class="second">
      <canvas class="canvas" width="" height=""></canvas>
      <div class="prev"></div>
      <div class="diff"></div>
      <span>---<br>60<br>sec</span>
    </div>
  </div>
</div>


<script>
(function (w, d) {
const targetDate = new Date('January 1, 2110 10:00:00'); // target date and time

let squareX = 320; // width of canvas (retina)
let squareY = 320; // height of canvas (retina)
let centerX = 160; // center of circle X (retina)
let centerY = 160; // center of circle Y (retina)
let radius = 150; // radius of circle (retina)
let lineWeightBack = 4; // line weight of gray circle (retina)
let lineWeightCount = 10; // line weight of count circle (retina)

// get DOM & set param
const data = [
  {
    canvas: d.querySelector('.year .canvas'),
    diff: d.querySelector('.year .diff'),
    prev: d.querySelector('.year .prev'),
    full: 99,
    changeFlag: false,
  },
  {
    canvas: d.querySelector('.day .canvas'),
    diff: d.querySelector('.day .diff'),
    prev: d.querySelector('.day .prev'),
    full: 365,
    changeFlag: false,
  },
  {
    canvas: d.querySelector('.hour .canvas'),
    diff: d.querySelector('.hour .diff'),
    prev: d.querySelector('.hour .prev'),
    full: 24,
    changeFlag: false,
  },
  {
    canvas: d.querySelector('.minute .canvas'),
    diff: d.querySelector('.minute .diff'),
    prev: d.querySelector('.minute .prev'),
    full: 60,
    changeFlag: false,
  },
  {
    canvas: d.querySelector('.second .canvas'),
    diff: d.querySelector('.second .diff'),
    prev: d.querySelector('.second .prev'),
    full: 60,
    changeFlag: false,
  },
];

// set canvas size
data.map((e) => {
  e.canvas.setAttribute('width', squareX);
  e.canvas.setAttribute('height', squareY);
  e.canvas.setAttribute('style', 'width: ' + squareX / 2 + 'px; height: ' + squareY / 2 + 'px;');
});

// make two digits
const shapeValue = (value) => ('0' + Math.floor(value)).slice(-2);

// make three digits
const shapeValueThree = (value) => ('00' + Math.floor(value)).slice(-3);

// make diffSet and prevSet
const pushValue = (set, time) => {
  set.push(shapeValue(time / 1000 / 60 / 60 / 24 / 365));
  set.push(shapeValueThree(time / 1000 / 60 / 60 / 24 % 365));
  set.push(shapeValue(time / 1000 / 60 / 60 % 24));
  set.push(shapeValue(time / 1000 / 60 % 60));
  set.push(shapeValue(time / 1000 % 60));
};

// print digit to DOM
const printDiff = (callback) => {
  const nowDate = new Date();
  const diff = targetDate - nowDate;
  const prev = diff + 1000;
  let diffSet = [];
  let prevSet = [];

  if (diff >= 0) {
    pushValue(diffSet, diff);
    pushValue(prevSet, prev);
  } else {
    diffSet = ['00', '000', '00', '00', '00'];
    prevSet = ['00', '000', '00', '00', '00'];
  }

  for (let i = 0; i < data.length; i++) {
    if (data[i].diff.innerHTML === diffSet[i]) {
      data[i].changeFlag = false;
    } else {
      data[i].changeFlag = true;
      data[i].diff.innerHTML = diffSet[i];
      data[i].prev.innerHTML = prevSet[i];
      data[i].diff.classList.add('fadeIn');
      data[i].prev.classList.add('fadeOut');
      w.setTimeout(function () {
        data[i].diff.classList.remove('fadeIn');
        data[i].prev.classList.remove('fadeOut');
      }, 900);
    }
  }

  callback(data);

  // for test
  const info = {
    target: d.querySelector('.information .target span'),
    targetMil: d.querySelector('.information .targetMil span'),
    nowMil: d.querySelector('.information .nowMil span'),
    diffMil: d.querySelector('.information .diffMil span'),
    digits: d.querySelector('.information .digits span'),
  }
  info.target.innerHTML = targetDate;
  info.targetMil.innerHTML = targetDate.getTime();
  info.nowMil.innerHTML = nowDate.getTime();
  info.diffMil.innerHTML = diff;
  info.digits.innerHTML = diffSet[0] + ' ' + diffSet[1] + ' ' + diffSet[2] + ' ' + diffSet[3] + ' ' + diffSet[4];
};

// drow circle on canvas
const drowCircle = (data) => {
  let endPointPer;
  let endPoint;
  let canvas;
  let context;
  let rotate;
  let posStart;
  let posEnd;
  let contextColor;

  data.forEach((e) => {
    if (e.changeFlag !== true) {
      return;
    }
    startPointPer = (e.full - Number(e.diff.innerHTML)) / e.full * 100;
    startPoint = 360 / 100 * startPointPer;
    canvas = e.canvas;
    if (!canvas || !canvas.getContext) {
      return false;
    }
    context = canvas.getContext('2d');
    rotate = -90;
    posStart = startPoint + rotate;
    posEnd = 0 + rotate;

    context.clearRect(0, 0, squareX, squareY);

    context.beginPath();
    context.arc(centerX, centerY, radius, 0 * Math.PI / 180, 360 * Math.PI / 180, false);
    context.strokeStyle = '#eee';
    context.lineWidth = lineWeightBack;
    context.stroke();

    if (posStart === 270) {
      return;
    }
    context.beginPath();
    context.arc(centerX, centerY, radius, posStart * Math.PI / 180, posEnd * Math.PI / 180, false);
    contextColor = context.createLinearGradient(120, 30, 30, 120);
    contextColor.addColorStop(0.0, '#ccc');
    contextColor.addColorStop(1.0, '#ccc');
    context.strokeStyle = contextColor;
    context.lineWidth = lineWeightCount;
    context.stroke();
    return true;
  });
};

// background control
let id;
d.addEventListener('webkitvisibilitychange', () => {
  if (d.webkitHidden) {
    clearInterval(id);
  } else {
    init(new Date());
  }
}, false);

// init
const init = (backgroundControl) => {
  printDiff(drowCircle);
  id = setInterval(() => {
    printDiff(drowCircle);
    if (targetDate < backgroundControl) {
      clearInterval(id);
    }
  }, 1000);
};
init(new Date());

})(window, document);
</script>


</body>
</html>

code_popup

sample