{"id":2157,"date":"2015-06-09T09:00:15","date_gmt":"2015-06-09T13:00:15","guid":{"rendered":"http:\/\/www.danielpradilla.info\/blog\/?p=2157"},"modified":"2017-08-15T02:53:01","modified_gmt":"2017-08-15T06:53:01","slug":"a-swiss-railway-clock-in-d3","status":"publish","type":"post","link":"https:\/\/www.danielpradilla.info\/blog\/a-swiss-railway-clock-in-d3\/","title":{"rendered":"A swiss railway clock in D3.js"},"content":{"rendered":"<p><a href=\"https:\/\/github.com\/danielpradilla\/d3clock\"><img loading=\"lazy\" decoding=\"async\" data-attachment-id=\"2158\" data-permalink=\"https:\/\/www.danielpradilla.info\/blog\/a-swiss-railway-clock-in-d3\/screen-shot-2015-06-05-at-5-26-54-pm\/\" data-orig-file=\"https:\/\/www.danielpradilla.info\/blog\/wp-content\/uploads\/2015\/06\/Screen-Shot-2015-06-05-at-5.26.54-PM.png\" data-orig-size=\"460,435\" data-comments-opened=\"1\" data-image-meta=\"{&quot;aperture&quot;:&quot;0&quot;,&quot;credit&quot;:&quot;&quot;,&quot;camera&quot;:&quot;&quot;,&quot;caption&quot;:&quot;&quot;,&quot;created_timestamp&quot;:&quot;0&quot;,&quot;copyright&quot;:&quot;&quot;,&quot;focal_length&quot;:&quot;0&quot;,&quot;iso&quot;:&quot;0&quot;,&quot;shutter_speed&quot;:&quot;0&quot;,&quot;title&quot;:&quot;&quot;,&quot;orientation&quot;:&quot;0&quot;}\" data-image-title=\"Screen Shot 2015-06-05 at 5.26.54 PM\" data-image-description=\"\" data-image-caption=\"\" data-large-file=\"https:\/\/www.danielpradilla.info\/blog\/wp-content\/uploads\/2015\/06\/Screen-Shot-2015-06-05-at-5.26.54-PM.png\" class=\"aligncenter size-full wp-image-2158\" src=\"http:\/\/www.danielpradilla.info\/blog\/wp-content\/uploads\/2015\/06\/Screen-Shot-2015-06-05-at-5.26.54-PM.png\" alt=\"Screen Shot 2015-06-05 at 5.26.54 PM\" width=\"460\" height=\"435\" srcset=\"https:\/\/www.danielpradilla.info\/blog\/wp-content\/uploads\/2015\/06\/Screen-Shot-2015-06-05-at-5.26.54-PM.png 460w, https:\/\/www.danielpradilla.info\/blog\/wp-content\/uploads\/2015\/06\/Screen-Shot-2015-06-05-at-5.26.54-PM-300x284.png 300w\" sizes=\"auto, (max-width: 460px) 100vw, 460px\" \/><\/a><\/p>\n<p>&nbsp;<\/p>\n<p>The other day I saw <a href=\"http:\/\/joncom.be\/code\/css-clocks\/\" target=\"_blank\">this cool JavaScript+CSS clock<\/a> and I immediately thought that I wanted to create an analog clock in D3.js. First of all as an exercise, but also with the aim \u2013perhaps\u2013 of smuggling it in to a future dashboard \ud83d\ude09<\/p>\n<p>It seemed straightforward: just paint the clock and re-paint it each second. Right? Well, yes if you&#8217;re lazy. The better way is to paint the clock and periodically rotate the hands.<\/p>\n<p>As with most things on the internet, turns out I was late to the party. Some much more clever people have built <a href=\"https:\/\/ericbullington.com\/blog\/2012\/10\/27\/d3-oclock\/\" target=\"_blank\">D3 clocks<\/a> and even a <a href=\"http:\/\/www.infocaptor.com\/dashboard\/d3-javascript-visualization-to-build-world-analog-clocks\" target=\"_blank\">multi-clock D3 visualization<\/a>\u00a0for displaying multiple time zones.<\/p>\n<p>Good. I had some ideas and a starting point.<\/p>\n<p>I&#8217;m in love with the <a href=\"https:\/\/en.wikipedia.org\/wiki\/Swiss_railway_clock\" target=\"_blank\">Swiss Federal Railways (SBB) clock<\/a>, designed by <a href=\"https:\/\/en.wikipedia.org\/wiki\/Hans_Hilfiker\" target=\"_blank\">Hans Hilfiker<\/a>. It&#8217;s an emblem of the most effective train system in the world, and a testimony of exquisite swiss modernism. I wanted to make <em>that<\/em>.<\/p>\n<p>There&#8217;s already an <a href=\"http:\/\/svgjs.com\/clock\/\" target=\"_blank\">SVG visualization of the SBB clock<\/a> (<a href=\"https:\/\/github.com\/wout\/svg.clock.js\" target=\"_blank\">here&#8217;s the code<\/a>). As I was checking it out, it made me realize for the first time that the axis of rotation is not at the end of the hands, but like at 10% of its length. And that extra length is different for the seconds hand.\u00a0Also, that ball at the end of the seconds hand was going to be tricky.<\/p>\n<p>As with all great designs of that era, everything is proportional in that clock. I noticed that I would be able to derive all the measurements from the width of the minute ticks. So I defined a starting measurement unit and multiplied away!<\/p>\n<p>The key for doing the hands rotation in D3 is to enclose each hand in its own g element and rotate those g elements using <a href=\"https:\/\/developer.mozilla.org\/en-US\/docs\/Web\/API\/WindowTimers\/setInterval\" target=\"_blank\">setInterval<\/a>. The rotation of the hands in the SBB clock is smooth, and thankfully <a href=\"https:\/\/github.com\/mbostock\/d3\/wiki\/Transitions\" target=\"_blank\">D3 offers transitions<\/a> for seamless interpolations.<\/p>\n<p>The seconds and minutes hands have to rotate 6\u00cb\u0161 each time (360\u00cb\u0161\u00c3\u00b760) and the hours hand has to rotate 30\u00cb\u0161. Since the clock shows only 12 hours, you have to multiply 30\u00cb\u0161 by the modulo 12 of the hours.<\/p>\n<pre class=\"brush: jscript; title: ; notranslate\" title=\"\">   \r\nclockHand.transition().duration(1000).ease('linear').attr('transform', function(d,i) {\r\n\tif (d.unit==='hours'){\r\n\t\treturn 'rotate('+d.numeric%12 * 30+')';\r\n\t} else {\r\n\t\treturn 'rotate('+d.numeric * 6+')';\r\n\t}\r\n});\r\n<\/pre>\n<p>I was able to quickly put together a very rudimentary version\u00a0and tweak the design little by little. Then I decided not to waste my first tests, got a little bit carried away and externalized all the functions that defined the characteristics of the clock. I\u00a0ended up with a module\u00a0that enables you to create multiple instances of the clock, each with its own configuration, defined in the &#8216;face&#8217; variable of the configuration object.<\/p>\n<pre class=\"brush: jscript; title: ; notranslate\" title=\"\">\r\nd3clock({\r\n\ttarget:'#sbb',\r\n\tface:'sbb',\r\n\twidth:500,\r\n\t\/\/date:'Mon May 25 2015 10:09:37',\r\n\tTZOffset:{\r\n\t\thours:0\r\n\t}\r\n});\r\n<\/pre>\n<div class=\"col-md-4\" id=\"modern\"><\/div>\n<div class=\"col-md-4\" id=\"sbb\"><\/div>\n<div class=\"col-md-4\" id=\"braun\"><\/div>\n<p><script src=\"\/resources\/d3\/bower_components\/d3\/d3.min.js\"><\/script><br \/>\n<script src=\"\/resources\/d3\/d3clock.js\"><\/script><br \/>\n\t<script>\n\t\td3clock({\n\t\t\ttarget:'#sbb',\n\t\t\tface:'sbb',\n\t\t\twidth:500,\n\t\t\t\/\/date:'Mon May 25 2015 10:09:37',\n\t\t\tTZOffset:{\n\t\t\t\thours:0\n\t\t\t}\n\t\t});\nd3clock({\n\t\t\ttarget:'#modern',\n\t\t\tface:'modern',\n\t\t\twidth:500,\n\t\t\t\/\/date:'Mon May 25 2015 10:09:37',\n\t\t\tTZOffset:{\n\t\t\t\thours:0\n\t\t\t}\n\t\t});\nd3clock({\n\t\t\ttarget:'#braun',\n\t\t\tface:'braun',\n\t\t\twidth:500,\n\t\t\t\/\/date:'Mon May 25 2015 10:09:37',\n\t\t\tTZOffset:{\n\t\t\t\thours:0\n\t\t\t}\n\t\t});\n\t<\/script><\/p>\n<p><a href=\"https:\/\/github.com\/danielpradilla\/d3clock\" target=\"_blank\">You can get the code for the library here<\/a>.<\/p>\n<p>Mind you, this implementation has its differences with the SBB clock (perhaps that will spare me from a takedown notice?):<\/p>\n<ul>\n<li>The SBB clock makes a 2 second pause at the end of each rotation. Yes, crazy, <a href=\"https:\/\/www.youtube.com\/watch?v=fGRJWl48b7w.\" target=\"_blank\">look<\/a>.<\/li>\n<li>The hands in the original clock are not rectangles, but very tall truncated triangles.<\/li>\n<\/ul>\n","protected":false},"excerpt":{"rendered":"<p>&nbsp; The other day I saw this cool JavaScript+CSS clock and I immediately thought that I wanted to create an analog clock in D3.js. First of all as an exercise, but also with the aim \u2013perhaps\u2013 of smuggling it in to a future dashboard \ud83d\ude09 It seemed straightforward: just paint the clock and re-paint it&hellip; <a class=\"more-link\" href=\"https:\/\/www.danielpradilla.info\/blog\/a-swiss-railway-clock-in-d3\/\">Continue reading <span class=\"screen-reader-text\">A swiss railway clock in D3.js<\/span><\/a><\/p>\n","protected":false},"author":2,"featured_media":0,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"_jetpack_newsletter_access":"","_jetpack_dont_email_post_to_subs":false,"_jetpack_newsletter_tier_id":0,"_jetpack_memberships_contains_paywalled_content":false,"_jetpack_memberships_contains_paid_content":false,"footnotes":"","jetpack_post_was_ever_published":false},"categories":[174,331],"tags":[197],"class_list":["post-2157","post","type-post","status-publish","format-standard","hentry","category-bestof","category-software-development-en-en","tag-visualization","entry"],"aioseo_notices":[],"jetpack_featured_media_url":"","jetpack_shortlink":"https:\/\/wp.me\/p1tlzy-yN","jetpack_sharing_enabled":true,"jetpack-related-posts":[{"id":2139,"url":"https:\/\/www.danielpradilla.info\/blog\/interactive-visualizations-javascript\/","url_meta":{"origin":2157,"position":0},"title":"Creating interactive visualizations of large datasets using JavaScript","author":"Daniel Pradilla","date":"09\/04\/2015","format":false,"excerpt":"Crossfilter is a JavaScript library initially designed by Square to explore large multivariate datasets in a web browser. It basically allows you to create sorted indexes and feed them to a charting library like D3, and enable the user to filter by clicking and dragging, even when sifting through 200.000\u2026","rel":"","context":"In &quot;Project Mgmt.&quot;","block_context":{"text":"Project Mgmt.","link":"https:\/\/www.danielpradilla.info\/blog\/category\/projectmanagement-en\/"},"img":{"alt_text":"","src":"","width":0,"height":0},"classes":[]},{"id":2082,"url":"https:\/\/www.danielpradilla.info\/blog\/amcharts-a-charting-library-for-creating-interactive-web-charts\/","url_meta":{"origin":2157,"position":1},"title":"amCharts, a charting library for creating interactive web charts","author":"Daniel Pradilla","date":"19\/05\/2014","format":false,"excerpt":"amCharts is a new JavaScript library for creating charts on the web. It handles many types of charts and it's somewhat reminiscent of D3.js. Its most exciting feature is a live editor, which removes the grunt work related to your typical JavaScript charting library and enables you to design, change\u2026","rel":"","context":"In &quot;Project Mgmt.&quot;","block_context":{"text":"Project Mgmt.","link":"https:\/\/www.danielpradilla.info\/blog\/category\/projectmanagement-en\/"},"img":{"alt_text":"amcharts","src":"https:\/\/i0.wp.com\/www.danielpradilla.info\/blog\/wp-content\/uploads\/2014\/05\/amcharts.jpg?resize=350%2C200","width":350,"height":200,"srcset":"https:\/\/i0.wp.com\/www.danielpradilla.info\/blog\/wp-content\/uploads\/2014\/05\/amcharts.jpg?resize=350%2C200 1x, https:\/\/i0.wp.com\/www.danielpradilla.info\/blog\/wp-content\/uploads\/2014\/05\/amcharts.jpg?resize=525%2C300 1.5x, https:\/\/i0.wp.com\/www.danielpradilla.info\/blog\/wp-content\/uploads\/2014\/05\/amcharts.jpg?resize=700%2C400 2x"},"classes":[]},{"id":1884,"url":"https:\/\/www.danielpradilla.info\/blog\/how-to-create-better-charts\/","url_meta":{"origin":2157,"position":2},"title":"How to create better charts","author":"Daniel Pradilla","date":"10\/11\/2012","format":false,"excerpt":"We're often tempted to include some kind of accessorizing effect in our charts without knowing that deep down we're making them impossible to interpret and thus ruining their purpose. A typical case is the 3D pie chart. Many people, including executives, have a certain likeness for 3D charts. Somehow they\u2026","rel":"","context":"In &quot;Best of&quot;","block_context":{"text":"Best of","link":"https:\/\/www.danielpradilla.info\/blog\/category\/bestof\/"},"img":{"alt_text":"","src":"https:\/\/i0.wp.com\/www.danielpradilla.info\/blog\/wp-content\/uploads\/2012\/11\/Tufte-Chartjunk.png?resize=350%2C200","width":350,"height":200,"srcset":"https:\/\/i0.wp.com\/www.danielpradilla.info\/blog\/wp-content\/uploads\/2012\/11\/Tufte-Chartjunk.png?resize=350%2C200 1x, https:\/\/i0.wp.com\/www.danielpradilla.info\/blog\/wp-content\/uploads\/2012\/11\/Tufte-Chartjunk.png?resize=525%2C300 1.5x, https:\/\/i0.wp.com\/www.danielpradilla.info\/blog\/wp-content\/uploads\/2012\/11\/Tufte-Chartjunk.png?resize=700%2C400 2x"},"classes":[]},{"id":1787,"url":"https:\/\/www.danielpradilla.info\/blog\/como-hacer-mejores-graficos\/","url_meta":{"origin":2157,"position":3},"title":"C\u00c3\u00b3mo hacer mejores gr\u00c3\u00a1ficos","author":"Daniel Pradilla","date":"12\/11\/2012","format":false,"excerpt":"Muchas veces estamos tentados a incluir alg\u00c3\u00ban efecto embellecedor en nuestros gr\u00c3\u00a1ficos sin saber que en el fondo estamos haci\u00c3\u00a9ndolos imposibles de interpretar y arruinando su prop\u00c3\u00b3sito. El caso t\u00c3\u00adpico es el del gr\u00c3\u00a1fico circular en 3D. Mucha gente, incluyendo los directivos, tienen cierta afici\u00c3\u00b3n por las gr\u00c3\u00a1ficas en 3D.\u2026","rel":"","context":"In &quot;Control de Proyectos&quot;","block_context":{"text":"Control de Proyectos","link":"https:\/\/www.danielpradilla.info\/blog\/category\/controldeproyectos\/"},"img":{"alt_text":"","src":"https:\/\/i0.wp.com\/www.danielpradilla.info\/blog\/wp-content\/uploads\/2012\/11\/Tufte-Chartjunk.png?resize=350%2C200","width":350,"height":200,"srcset":"https:\/\/i0.wp.com\/www.danielpradilla.info\/blog\/wp-content\/uploads\/2012\/11\/Tufte-Chartjunk.png?resize=350%2C200 1x, https:\/\/i0.wp.com\/www.danielpradilla.info\/blog\/wp-content\/uploads\/2012\/11\/Tufte-Chartjunk.png?resize=525%2C300 1.5x, https:\/\/i0.wp.com\/www.danielpradilla.info\/blog\/wp-content\/uploads\/2012\/11\/Tufte-Chartjunk.png?resize=700%2C400 2x"},"classes":[]},{"id":2152,"url":"https:\/\/www.danielpradilla.info\/blog\/hello-p5js\/","url_meta":{"origin":2157,"position":4},"title":"Having fun coding with p5.js","author":"Daniel Pradilla","date":"01\/06\/2015","format":false,"excerpt":"p5.js is an effort to port the ideas and concepts of the Processing programming language to JavaScript. Even though there's already processing.js \u2013which transcodes Processing code into JavaScript\u2013, p5.js is built with extensibility in mind, trough plugins, and instead of writing Processing code to be transcoded, you write pure JavaScript.\u2026","rel":"","context":"In &quot;Software Dev.&quot;","block_context":{"text":"Software Dev.","link":"https:\/\/www.danielpradilla.info\/blog\/category\/software-development-en-en\/"},"img":{"alt_text":"p5js","src":"https:\/\/i0.wp.com\/www.danielpradilla.info\/blog\/wp-content\/uploads\/2015\/06\/p5js.jpg?resize=350%2C200","width":350,"height":200,"srcset":"https:\/\/i0.wp.com\/www.danielpradilla.info\/blog\/wp-content\/uploads\/2015\/06\/p5js.jpg?resize=350%2C200 1x, https:\/\/i0.wp.com\/www.danielpradilla.info\/blog\/wp-content\/uploads\/2015\/06\/p5js.jpg?resize=525%2C300 1.5x, https:\/\/i0.wp.com\/www.danielpradilla.info\/blog\/wp-content\/uploads\/2015\/06\/p5js.jpg?resize=700%2C400 2x"},"classes":[]},{"id":2245,"url":"https:\/\/www.danielpradilla.info\/blog\/recommender-system-for-finding-subject-matter-experts-using-the-enron-email-corpus\/","url_meta":{"origin":2157,"position":5},"title":"Recommender system for finding subject matter experts using the Enron email corpus","author":"Daniel Pradilla","date":"20\/11\/2018","format":false,"excerpt":"This is a little project to create a recommender system to find mentors inside an organization, using Natural Language Processing. It started as an excuse to build a data visualization I had in mind: an interactive word cloud that did something. When I started, I didn't know anything about Topic\u2026","rel":"","context":"In &quot;Best of&quot;","block_context":{"text":"Best of","link":"https:\/\/www.danielpradilla.info\/blog\/category\/bestof\/"},"img":{"alt_text":"","src":"https:\/\/i0.wp.com\/www.danielpradilla.info\/blog\/wp-content\/uploads\/2018\/11\/bubbles2.jpg?resize=350%2C200&ssl=1","width":350,"height":200,"srcset":"https:\/\/i0.wp.com\/www.danielpradilla.info\/blog\/wp-content\/uploads\/2018\/11\/bubbles2.jpg?resize=350%2C200&ssl=1 1x, https:\/\/i0.wp.com\/www.danielpradilla.info\/blog\/wp-content\/uploads\/2018\/11\/bubbles2.jpg?resize=525%2C300&ssl=1 1.5x"},"classes":[]}],"_links":{"self":[{"href":"https:\/\/www.danielpradilla.info\/blog\/wp-json\/wp\/v2\/posts\/2157","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/www.danielpradilla.info\/blog\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/www.danielpradilla.info\/blog\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/www.danielpradilla.info\/blog\/wp-json\/wp\/v2\/users\/2"}],"replies":[{"embeddable":true,"href":"https:\/\/www.danielpradilla.info\/blog\/wp-json\/wp\/v2\/comments?post=2157"}],"version-history":[{"count":0,"href":"https:\/\/www.danielpradilla.info\/blog\/wp-json\/wp\/v2\/posts\/2157\/revisions"}],"wp:attachment":[{"href":"https:\/\/www.danielpradilla.info\/blog\/wp-json\/wp\/v2\/media?parent=2157"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/www.danielpradilla.info\/blog\/wp-json\/wp\/v2\/categories?post=2157"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/www.danielpradilla.info\/blog\/wp-json\/wp\/v2\/tags?post=2157"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}