UI Experiment: Clock View for a List of Appointments in Your Day
Midnight -> Noon
Noon -> Night
One day I had come up with an idea to show various times of day that is most appropriate for certain types of tasks. For instance, right in the morning when you’re still a bit groggy and not quite focused on your everyday things just yet is a great time to “be creative” and come up with a bunch of crazy creative ideas and write them down for later–and then later again maybe after your afternoon nap (or maybe the best time for your afternoon nap to help you solve some problems.).
Anyway, this lead to thoughts on how I might represent this–one of which was a pie graph of the times throughout the day. A pie graph, showing sized chunks of times throughout the day for meaningful events, and other chunks of time in between those events (free time), seemed the most appropriate. Plus, this easily translates to a clock face.
And I thought, why hasn’t anyone made a clock view for a day before, or why is it not common?
So I built one that you could use on the web, which I’m calling Chart.Clock.js. You can see how this works in the visuals at the top of this post. It’s based off of both Charts.js (to extend and create a new chart type) and moment.js (to easily handle date/time calculations).
Fuller-featured demo also located here: https://andymudrak.com/demos/Chart.Clock.js/
Thoughts on the UI
When I’m thinking about the UI here, I’m not thinking about just one clock face. But instead, I’m thinking of using such a UI tool to represent appointments for a given day–the full day, not just a portion of it.
This new bit of UI seems natural at first. We are familiar with clock faces and find them natural to read from–well, most of us anyway. At a quick glance of a clock, why not have my appointments upcoming? It does seem pretty cool, and intuitive. But, I think there are some issues to be worked out.
Morning vs. Night
One issue that comes to mind is morning vs. night. In my samples (above, and in the demo page that I have set up), I have two clock faces showing at the same time. One represents 12:00 AM to 12:00 PM of that day, while the second represents 12:00 PM to 12:00 AM the next day. It was hard enough just to come up with titles for these two, which I settled on a simple phrase for now. But this initially makes looking at the times already difficult for the user. I find that it’s easy to get lost and remember which clock face to look at.
Further, remembering how appointments cross these two faces is sometimes confusing (unless you train your brain for this over time). Let’s take working hours, for example, which typically span across the morning (e.g. beginning at 9:00 AM) and night (e.g. ending at 5:00 PM) clock faces. We could, of course, fix this by only working a small amount of hours in the afternoon, and change society accordingly, but that would take decades and not everyone may be on board with it.
In the meantime, we might want an appointment during working hours beginning at 11:30 AM – 12:15 PM. This would have to be rendered as something that appears to start at 11:30 AM and end at 12:00 PM on the morning face, but on the afternoon the second half of that appointment is shown as 12:00 PM – 12:15 PM. I think we need some additional UI cues to handle this. For example, this could be resolved by handling hover effects for a split appointment on one clock face, such that the other side also highlights. I think it would be necessary to produce other visual cues that don’t require explicit interaction to see this, equivalent to an ellipsis. I haven’t found the best solution for this yet, but I believe the 12:00 border on the clock face could be made into a double, or dotted line to help show this.
The eye also doesn’t easily roll from morning clock face to night, especially in these situations where we want to understand continuity of the timeline from something before 12:00 PM to something after. The challenge here is the big visual jump. In a normal day view on a calendar, the appointment is not split, but it is shown in a single list and you can visually understand the ratio/duration of time relative to the full timeline. In the clock view, the appointment is split and we have to search for it on the other side. Again, ellipsis make this a little easier, but it still proves difficult. Part of the issue is the left-to-right reading (for people reading in languages that are left-to-right, of course). The expectation is that the second half is immediately next to the appointment you’re looking at. But the night side can have appointments near 10 or 11 PM, which makes it a little confusing to find the continuation immediately. My sense is that this could be fixed by adding a circular border around the clock, which fades as a gradient all the way around (starting at dark grey at 12:00PM, gradually fading to white as it gets all the way around clock-wise). This could help give a better anchor point for the eye.
Note also that working-hours free time is typically rendered differently than non-working (light gray vs. dark gray, by default). This was an important mental cue to keep track of hours on the two clockfaces.
Time as Wedges
I believe seeing the time as a visual ratio of hours across the clock make great sense. This is especially true since the current time is displayed on one of the clock faces, and makes it clear how far away your appointments might be (except with the morning/night issue, of course). However, overlapping appointments make this a little tricky. I handled overlaps similarly to the way we might see calendars do this in a list–indentation.
However, you can’t just indent a pie wedge in a pie graph, right? I played around with using rings, but the best option seemed to be to keep overlapping wedges. This still fills the time in toward the center of the clock–spaces here just don’t look correct. As such, the pie pieces can be shifted inward to display this overlap, and I think it works fairly well. The sizes are adjustable in the system I produced, and overlaps sizes are based on the percentage of the radius, rather than a fixed size.
I think the tricky issue with the wedge, however, is dealing with minutes. We often have both an hour and minute hand on a clock face. But here, we only have an hour hand. This makes it easy to see where the current time is relative to an appointment. But when we want to visually see how many minutes lie between appointments, it’s not easy to translate. Adding tick marks for minutes could work. But depending on the size of the view, this may be impractical–60 tick marks between a 1/12th size pie piece on a small graph will be difficult to see, if even technically possible. So I believe a responsive view is needed, to produce tick marks that are significant when the view gets small: by 5 minutes, by 15 minutes, etc.. If the view is large enough, we can include 1-minute marks, but these 5- and 15-minute marks could be longer–as you might see on a gauge on a dashboard.
Is it Useful
What does the user gain by using such a clock view? Is it all aesthetic? I would say it definitely has such an appeal, but beside form, what function can you gain by using this?
My only thought on this is actually part-aesthetic and part-function: you can condense a single day’s time more efficiently. I’m sure some might disagree with this, and that’s fine. But I find the outer edges of the clock view to be more efficient for displaying detail within a timeline due to their much longer circumference length than a single vertical line. Theoretically we’re showing 3.14 times more detail (or 6.28, if you count two circles). And this view can typically be condensed further and fit in smaller spaces. I think it’s worth seeing how this might look on a phone, as well!
Here’s some technical stuff, if you’re interested in how I made this happen. The source code is under the MIT license, and available on my GitHub page for Chart.Clock.js.
Extending Chart.js with a New “Clock” Chart Type
Since I built this onto Chart.js, I found it pretty intriguing how you could easily extend it to produce other types of charts and visualizations. I started by literally extending their “Pie” chart, but found quickly that I needed to do a lot of customization. This become most evident is when I attempted to handle overlapping appointments. This throws the traditional Pie chart right out the window. But thankfully, the entire library was open source and I could basically take the working parts of the Pie chart and refactor them as needed.
I found that using moment.js made it easy enough to handle doing date differences for duration calculation. In the process, I decided to force time-only start/end times, which made calculations a little easier. However, I can definitely see changing this in the future so that we can take a multi-day list of appointments, and just truncate the view to a single day easily. But for now, it is quicker to create an extract of a single day’s times and produce the view this way–you know, making a “view model” for the chart.
Making the Pie and Calculating Free Time
So if you give this chart a list of appointments, generally you’re not going to want to figure out all the boundaries in between appointments and add segments for free time yourself. In fact, it was actually pretty complicated to do this. That was the reason I decided to make the chart do this for you and I had it add the segments it needs–including time that is represented outside of “working hours”.
The algorithm had to truncate appointments to the start/end time of the clock face (e.g. 12:00 PM, and 12:00 AM the next day). Plus, it filters appointments that don’t appear on the clock at all. This makes it easy for you to use a single list of appointments for the morning and night clock faces. This was easy enough to do using moment.js.
The requirement for free time calculation is that the iteration over the appointments had to be sorted by start time. Once this was done, we can calculate the gaps between the last appointment we added to the graph, and the one we’re processing. Then at the end, the remainder is added, as is typical for these types of iterations.
Where it got hairy was splitting free time across working hours. The algorithm would figure out the total amount of free time needed. But if this free time crossed the beginning of working hours (meaning it should be split into two as non-working and working), or ending of working hours (vice-versa), then we needed to add segments differently. Remember that working-hours free time is typically rendered differently than non-working (light gray vs. dark gray, by default). So it in-turn broke down the start time across the working hours beginning, and end, and followed up with a final insert of free time. This meant up to two splits, into three components (in case it crossed BOTH the beginning and end of the working hours).
This wasn’t too bad to set up, when it came down to it. The objective was to reduce the radius of the pie pieces added for each appointment, when we were adding it, it overlapped another appointment. What I came up with was a way to track “layers” of overlaps. This essentially just became a “queue” structure, where I tracked X number of overlapping appoints, from earliest to latest–easy to do since the appointments list was first sorted. So the first appointment is always first on the list. If the next appointment overlaps any of the others (start time is after the maximum end time of all appointments processed so far), then it adds itself to the end of the queue.
If I left it here, the queue would get endlessly long and look weird when rendered. So I had items replace other items in the “overlap queue”, if those other items end time was not overlapping the start time of the appointment being added. In other words, the other item being replaced was no longer overlapping this and future appointments. So by replacing the first non-overlapping appointment, we return appointments back to the largest possible radius as quickly as possible. Anything at the end that is no longer overlapping is deleted.
You might wonder, why not just delete the no-longer-overlapping items outright? Well, as we go, we note the index of overlap–this becomes a multiplier for rendering later. But this index is based on the number of the item in the overlap queue, and deleting an item would shift all the indexes of the later queue items less by one. This would result in losing track of the appropriate layer the new appointments should be on. So it’s kept as a positional record throughout the algorithm, until there’s no more items AFTER the item being processed.
Before we render the pieces, the overlap index is recorded with the appointment, and the appointment list is recreated by layer index–those with lower values will be drawn first, and those with higher values second. Then, when rendering, the pieces that overlap will be drawn on top of the appointment that was there first. The rendering will shorten the radius of the pie piece by a ratio based on the total number of overlapping layers, and which layer it is on. This overall ratio I made adjustable with the “overlapRadiusPercent” option. If this is set to 25% it means that 25% of the total radius of the chart will be used to render ALL overlapping margin. It means it gets tight if there’s a ton of overlaps–this seemed unlikely to be a problem in most calendar views.
Dynamically Changing the Clock – Adding/Removing as You Go
In the end, I decided to allow the developer to add/remove appointments on an existing chart, rather than have to make a whole new one if you want to modify it. I think it was worth it. However, the implementation truly requires recalculating the entire pie, potential overlaps, and free time segments. I’m sure there’s some magic bullet algorithm for making delta changes. But not only was it easier to re-initialize the entire graph when a change was made, but there would likely be so little number of appointments on a single clock face that it should not have a high performance impact.
I think this type of UI might be something of a mix of a novelty, but potentially something useful to represent a day-at-a-glance in a more meaningful and efficient way. I’m very open to comments on this, including ways to improve the visuals and general interactivity level of the view!
If you have any comments or questions, feel free to contact me on Twitter (@AndyMudrak)!