4

I decided to try and create an analog 12 hour clock with some basic CSS properties. I start off by creating a square div of 500px. I then set the border-radius to 250px and get a nice looking circle. After this, I add in the twelve tick marks, position them absolute-ly, and get their corresponding positions.

The angle for each tick mark is based on this (apologies for spelling out the simple math):

  • 12 tick marks
  • 360° in our circle
  • 360 / 12 = 30° angles

The position for each tick mark can be calculated using some basic trigonometry. I know θ (0°, 30°, 60°, etc.) and radius (250), and by using cos and sin, I can figure out the associated top, bottom, left, and right values. To get the left or right value (x), I can simply use: r * sin θ. To get the top or bottom value (y), I can use: r - (r * cos θ). Hopefully the image below (excuse the MS Paint lack of skill) can help clear up what I'm trying to do.

Image below

Once I have these equations, it becomes much easier to get the respective x and y values:

    θ (angle)   |  250 * sin θ [x]  | 250 - (250 * cos θ) [y]
--------------------------------------------------------------
   30° (1:00)   |   right: 125px    |      top: 33.5px
   60° (2:00)   |   right: 33.5px   |      top: 125px
   90° (3:00)   |   right: 0px      |      top: 250px
  120° (4:00)   |   right: 33.5px   |      bottom: 125px
  150° (5:00)   |   right: 125px    |      bottom: 33.5px
  180° (6:00)   |   right: 250px    |      bottom: 0px
  210° (7:00)   |   left: 125px     |      bottom: 33.5px
  240° (8:00)   |   left: 33.5px    |      bottom: 125px
  270° (9:00)   |   left: 0px       |      bottom: 250px
  300° (10:00)  |   left: 33.5px    |      top: 125px
  330° (11:00)  |   left: 125px     |      top: 33.5px
  360° (12:00)  |   left: 250px     |      top: 0px

Now that I've dragged the question on for far too long... my question is, why would my tick marks for 2, 3, 4, 8, 9, and 10 all be a bit off? Based on my calculations (I've always wanted to say that), I shouldn't be having these issues. Sure, I did some rounding and left off some sig figs, but they are not that significant to make the positioning look wonky. Here is my code:

The HTML

<body>
    <div id="clock">
        <div id="one" class="oneEleven tick"></div>
        <div id="two" class="twoTen tick"></div>
        <div id="three" class="threeNine tick"></div>
        <div id="four" class="fourEight tick"></div>
        <div id="five" class="fiveSeven tick"></div>
        <div id="six" class="sixTwelve tick"></div>
        <div id="seven" class="fiveSeven tick"></div>
        <div id="eight" class="fourEight tick"></div>
        <div id="nine" class="threeNine tick"></div>
        <div id="ten" class="twoTen tick"></div>
        <div id="eleven" class="oneEleven tick"></div>
        <div id="twelve" class="sixTwelve tick"></div>
    </div>
</body>

The CSS

#clock {
  height: 500px;
  width: 500px;
  border-radius: 50%;
  border: 1px solid black;
  position: relative;
}

.tick {
  background-color: black;
  height: 20px;
  width: 5px;
  position: absolute;
}

.oneEleven {
  /* ~6.7% */
  top: 33.5px;
}

.twoTen {
  /* 25% */
  top: 125px;
}

.threeNine {
  /* 50% */
  top: 250px;
}

.fourEight {
  /* 25% */
  bottom: 125px;
}

.fiveSeven {
  /* ~6.7% */
  bottom: 33.5px;
}

#one {
  right: 125px;
  transform: rotate(30deg);
}

#two {
  /* ~93.3% */
  right: 33.5px;
  transform: rotate(60deg);
}

#three {
  right: 0px;
  transform: rotate(90deg);
}

#four {
  right: 33.5px;
  transform: rotate(120deg);
}

#five {
  right: 125px;
  transform: rotate(150deg);
}

#six {
  left: 250px;
  bottom: 0px;
}

#seven {
  left: 125px;
  transform: rotate(-150deg);
}

#eight {
  left: 33.5px;
  transform: rotate(-120deg);
}

#nine {
  left: 0px;
  transform: rotate(-90deg);
}

#ten {
  left: 33.5px;
  transform: rotate(-60deg);
}

#eleven {
  left: 125px;
  transform: rotate(-30deg);
}

#twelve {
  left: 250px;
  top: 0px;
}

The jsFiddle. It's not entirely obvious on first glance, but if you look at the tick marks I've referenced, you'll see they're not lined up on the circle. I'm eventually going to move to percentages, but I would like to know why they're off, and is this the best approach for creating a circle that you'd like to add styling too? I realize there's the HTML5 canvas tag, but I feel like that would be too difficult to work with and would be doing more processing than I need to perform...

Any help would be appreciated!

incutonez
  • 3,241
  • 9
  • 43
  • 92
  • You could also try doing something like this http://stackoverflow.com/questions/12813573/position-icons-into-circle/12817454#12817454 You don't even need to compute the sin & cos for each angle this way. Also, you could generate the tick marks via JS, like this http://codepen.io/thebabydino/pen/qgoBL – Ana Apr 29 '13 at 17:19

1 Answers1

3

It looks like you've positioned each tick to get one corner in the right position on the circle. But then the tick gets rotated about the origin, which pushes part of it outside the circle. You should be able to fix it by setting transform-origin appropriately for each tick. You need to rotate about the same corner you've positioned. So if you positioned with top and right, set the transform-origin to "top right". For example:

#two {
  /* ~93.3% */
  right: 33.5px;
  transform: rotate(60deg);
  transform-origin: top right;
}
  • Wow, I didn't realize the transform-origin property existed... all that explanation for such an easy fix! Thanks. Any insight as to which approach (CSS or HTML/JS) for building a circle? – incutonez Apr 29 '13 at 15:48