raw Software
Kinematic clock The minute hand is attached to the hour hand, and the second hand is attached to the minute hand.

Kinematic Clock with Nested SVG Transforms

Robert Eisele

This SVG demonstration treats a clock as a serial kinematic chain: the minute hand pivots at the hour hand's tip, and the second hand pivots at the minute hand's tip. The article derives the relative joint angles that preserve each hand's correct absolute orientation.

Read the story

A conventional clock places all three hands at the center. This kinematic clock uses a serial chain instead: the minute hand starts at the tip of the hour hand, and the second hand starts at the tip of the minute hand. The SVG demonstration above shows the current local time with exactly that linkage.

A Clock as a Kinematic Chain

Let \(H\), \(M\), and \(S\) be the absolute clockwise angles of the hour, minute, and second hands. Measured in degrees from twelve o'clock, their continuously changing values are

\[ H=30\left(h+\frac{m}{60}+\frac{s}{3600}\right),\qquad M=6\left(m+\frac{s}{60}\right),\qquad S=6\left(s+\frac{u}{1000}\right), \]

where \(h\) is the hour modulo 12, \(m\) the minute, \(s\) the second, and \(u\) the milliseconds. Those angles would be sufficient if every hand rotated independently around the same origin.

Converting Absolute Angles to Joint Angles

SVG transformations on nested groups accumulate. Rotating the hour group also rotates everything inside it. The minute joint must therefore cancel the inherited hour rotation before contributing its own absolute orientation:

\[ \theta_h=H,\qquad \theta_m=M-H,\qquad \theta_s=S-M. \]

The resulting global orientations telescope:

\[ \theta_h+\theta_m=M, \qquad \theta_h+\theta_m+\theta_s=S. \]

This is the same local-versus-world-coordinate distinction used in robot arms and skeletal animation. Each SVG group first translates to the previous joint and then applies only the relative rotation needed at that joint.

SVG Structure

The dial, tick marks, links, and joints are vector elements, so the clock remains crisp at any viewport size. Only three transform attributes change while the clock runs; the SVG geometry is created once and is not rebuilt on every frame.

<g transform="translate(320 320)">
  <g id="hour-joint">
    <line y2="-125" />
    <g transform="translate(0 -125)">
      <g id="minute-joint">
        <line y2="-95" />
        <g transform="translate(0 -95)">
          <g id="second-joint">...</g>
        </g>
      </g>
    </g>
  </g>
</g>

Using a viewBox instead of assigning canvas pixels also removes viewport-specific size branches. CSS controls the displayed size, while the complete linkage continues to use one stable 640 by 640 coordinate system.