DEV Community

Dominic Myers
Dominic Myers

Posted on • Originally published at drmsite.blogspot.com on

p5 Clock (HUMANS SINCE 1982)

I saw this a little while back so this week I coded it using p5:

A nice bit of modular JS too, so it was:

Clock.js

export class Clock {
  constructor(p5, x, y, width, multiplier) {
    this.degrees = 8 * multiplier
    this.ticker = false
    this.p5 = p5
    this.x = x
    this.y = y
    this.width = width
    this.arm = 0.85
    this.minute = 0
    this.hour = 0
    this.pg = p5.createGraphics(width, width)
  }
  update(minute, hour) {
    if(this.minute !== minute) {
      if(this.minute + 1 === this.degrees){
        this.minute = 0
      } else {
        this.minute++
      }
    }
    if(this.hour !== hour) {
      if(this.hour - 1 < 0){
        this.hour = this.degrees
      } else {
        this.hour--
      }
    }
    return this.draw()
  }
  draw() {
    this.pg.noStroke()
    this.pg.fill(255)
    this.pg.rect(0, 0, this.width, this.width)
    this.pg.stroke(0)
    this.pg.strokeWeight(this.width * 0.1)
    let m = this.p5.map(
      this.minute, 
      0, 
      this.degrees, 
      0, 
      this.p5.TWO_PI
    ) - this.p5.HALF_PI
    let h = this.p5.map(
      this.hour,
      0,
      this.degrees,
      0,
      this.p5.TWO_PI
    ) - this.p5.HALF_PI
    this.pg.line(
      this.width / 2, 
      this.width / 2, 
      (this.width / 2) + this.p5.cos(m) * ((this.width / 2) * this.arm), 
      (this.width / 2) + this.p5.sin(m) * ((this.width / 2) * this.arm)
    )
    this.pg.line(
      this.width / 2, 
      this.width / 2, 
      (this.width / 2) + this.p5.cos(h) * ((this.width / 2) * this.arm), 
      (this.width / 2) + this.p5.sin(h) * ((this.width / 2) * this.arm)
    )
    return this.pg
  }
}
Enter fullscreen mode Exit fullscreen mode

Numeral.js

import { Clock } from "./Clock.js"
export class Numeral {
  constructor(p5, x, y, unitWidth = 30, degreeMuliplier = 5) {
    this.num = 0
    this.p5 = p5
    this.x = x
    this.y = y
    this.unitWidth = unitWidth
    this.degreeMuliplier = degreeMuliplier
    this.Clocks = [
      new Clock(p5, x, y, unitWidth, degreeMuliplier),
      new Clock(p5, x + unitWidth, y, unitWidth, degreeMuliplier),
      new Clock(p5, x, y + unitWidth, unitWidth, degreeMuliplier),
      new Clock(p5, x + unitWidth, y + unitWidth, unitWidth, degreeMuliplier),
      new Clock(p5, x, y + (unitWidth \* 2), unitWidth, degreeMuliplier),
      new Clock(p5, x + unitWidth, y + (unitWidth \* 2), unitWidth, degreeMuliplier)
    ]
    this.Numbers = [
      [[2,4],[4,6],[0,4],[0,4],[0,2],[0,6]],
      [[5,5],[4,4],[5,5],[0,4],[5,5],[0,0]],
      [[2,2],[4,6],[2,4],[0,6],[0,2],[6,6]],
      [[2,2],[4,6],[2,2],[0,6],[2,2],[0,6]],
      [[4,4],[4,4],[0,2],[0,4],[5,5],[0,0]],
      [[2,4],[6,6],[0,2],[4,6],[2,2],[0,6]],
      [[2,4],[6,6],[0,4],[4,6],[0,2],[0,6]],
      [[2,2],[4,6],[5,5],[0,4],[5,5],[0,0]],
      [[2,4],[4,6],[0,2],[0,6],[0,2],[0,6]],
      [[2,4],[4,6],[0,2],[0,4],[2,2],[0,6]]
    ]
  }
  draw(){
    this.Clocks.forEach((c, i) => this.p5.image(c.update(...this.Numbers[this.num][i].map(e => e \* this.degreeMuliplier)), c.x, c.y))
  }
}
Enter fullscreen mode Exit fullscreen mode

script.js

import { Numeral } from "./Numeral.js"
new p5(p5 => {
  const style = window.getComputedStyle(document.querySelector("body"), null)
  const bodyWidth = parseInt(style.getPropertyValue("width"), 10)
  const Numerals = []
  p5.setup = () => {
    p5.createCanvas(bodyWidth, bodyWidth)
    Numerals.push(new Numeral(p5, 0, 0, 50))
    Numerals.push(new Numeral(p5, 100, 0, 50))
    Numerals.push(new Numeral(p5, 200, 0, 50))
    Numerals.push(new Numeral(p5, 300, 0, 50))
    Numerals.push(new Numeral(p5, 400, 0, 50))
    Numerals.push(new Numeral(p5, 500, 0, 50))
  }
  p5.draw = () => {
    const date = new Date
    const hour = date.getHours().toString().split('')
    const minutes = date.getMinutes().toString().split('')
    const seconds = date.getSeconds().toString().split('')
    Numerals[0].num = hour.length === 1 ? 0 : hour[0]
    Numerals[1].num = hour.length === 1 ? hour[0] : hour[1]
    Numerals[2].num = minutes.length === 1 ? 0 :minutes[0]
    Numerals[3].num = minutes.length === 1 ? minutes[0] : minutes[1]
    Numerals[4].num = seconds.length === 1 ? 0 :seconds[0]
    Numerals[5].num = seconds.length === 1 ? seconds[0] : seconds[1]
    Numerals.forEach(numeral => numeral.draw())
  }
})
Enter fullscreen mode Exit fullscreen mode

Image of Timescale

🚀 pgai Vectorizer: SQLAlchemy and LiteLLM Make Vector Search Simple

We built pgai Vectorizer to simplify embedding management for AI applications—without needing a separate database or complex infrastructure. Since launch, developers have created over 3,000 vectorizers on Timescale Cloud, with many more self-hosted.

Read full post →

Top comments (0)

Sentry image

See why 4M developers consider Sentry, “not bad.”

Fixing code doesn’t have to be the worst part of your day. Learn how Sentry can help.

Learn more

👋 Kindness is contagious

Engage with a sea of insights in this enlightening article, highly esteemed within the encouraging DEV Community. Programmers of every skill level are invited to participate and enrich our shared knowledge.

A simple "thank you" can uplift someone's spirits. Express your appreciation in the comments section!

On DEV, sharing knowledge smooths our journey and strengthens our community bonds. Found this useful? A brief thank you to the author can mean a lot.

Okay