There and Back Again competition entry https://shiny.petras.space/commute/
rstats
rshiny
census
competition
leaflet
javascript
stats-nz

extras.R 6.9KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224
  1. extracss <- "
  2. html, body {
  3. width:100%;
  4. height:100%
  5. }
  6. #map {
  7. height: 100% !important;
  8. position: absolute !important;
  9. top: 0;
  10. left: 0;
  11. }
  12. #loading {
  13. cursor: progress !important;
  14. }
  15. #loading p {
  16. border-radius: 5px;
  17. background-color: rgba(255, 255, 255, 0.8);
  18. padding: 6px 8px;
  19. box-shadow: 0 0 15px rgba(0,0,0,0.2);
  20. font-size: 1.5em;
  21. font-weight: bold;
  22. }
  23. #mapcontrol, #infobuttoncontainer, #infopanel {
  24. background-color: rgba(255, 255, 255, 0.8);
  25. border-radius: 5px;
  26. box-shadow: 0 0 15px rgba(0,0,0,0.2);
  27. padding: 6px 8px;
  28. font: 14px/16px Arial, Helvetica, sans-serif;
  29. }
  30. #mapcontrol, #control2 {
  31. z-index: 1000;
  32. }
  33. #mapcontrol {
  34. width: 22em;
  35. max-height: 90%;
  36. overflow: auto;
  37. -ms-overflow-style: none; /* IE and Edge */
  38. scrollbar-width: none; /* Firefox */
  39. }
  40. #mapcontrol::-webkit-scrollbar {
  41. display: none;
  42. }
  43. #infopanel {
  44. display: none;
  45. background-color: rgba(255, 255, 255, 0.9);
  46. padding: 10px;
  47. z-index: 1001;
  48. }
  49. #lochtml ul {
  50. padding-left: 15px;
  51. }
  52. .radio label span p {
  53. margin-top: 3px;
  54. margin-bottom: 0px;
  55. }
  56. .leaflet-container {
  57. background-color: #84e1e1;
  58. }
  59. #infobuttoncontainer {
  60. margin-bottom: 16px;
  61. z-index: 1002;
  62. }
  63. #infobuttoncontainer .shiny-input-container,
  64. #infobuttoncontainer div div {
  65. margin-right: 0px !important;
  66. margin-bottom: 0px !important;
  67. }
  68. h3 {
  69. margin-top: 5px;
  70. margin-bottom: 5px;
  71. }
  72. .overflowable {
  73. max-height: 100%;
  74. overflow: auto;
  75. -ms-overflow-style: none; /* IE and Edge */
  76. scrollbar-width: none; /* Firefox */
  77. }
  78. .overflowable::-webkit-scrollbar {
  79. display: none;
  80. }
  81. blockquote {
  82. font-size: 1em;
  83. font-style: italic;
  84. border: none;
  85. margin: 0;
  86. }
  87. .scrollbuffer {
  88. height: 50px;
  89. }
  90. .overflowable:before {
  91. content:'';
  92. width:100%;
  93. height:50px;
  94. position:absolute;
  95. left:0;
  96. bottom:0;
  97. right:0;
  98. background:linear-gradient(transparent 0px,
  99. rgba(255, 255, 255, 0.9));
  100. }
  101. #infobuttoncontainer label {
  102. font-weight: bold;
  103. }
  104. .locinfo {
  105. max-width: 100%;
  106. }
  107. .loading p {
  108. margin: 0;
  109. }
  110. hr {
  111. margin-top: 10px;
  112. margin-bottom: 10px;
  113. border-top: 1px solid #000;
  114. }
  115. .leaflet-control-search {
  116. box-shadow: none;
  117. }
  118. "
  119. attribhtml <- '
  120. <a href="http://leafletjs.com"
  121. title="A JS library for interactive maps">Leaflet</a> | <a
  122. href="http://datafinder.stats.govt.nz/data/category/census/2018/commuter-view/"
  123. title="Source data">
  124. StatsNZ</a> | <a href="http://petras.space/page/cv/" title="Hire me!">
  125. Petra Lamborn</a> | Numbers subject to <a
  126. href="http://archive.stats.govt.nz/about_us/legisln-policies-protocols/
  127. confidentiality-of-info-supplied-to-snz/safeguarding-confidentiality.aspx"
  128. title="A method of preserving confidentiality and anonymity">
  129. random rounding</a>
  130. '
  131. infotext <- div(class="overflowable",
  132. h3("How did Kiwis commute in 2018?"),
  133. p("This tool maps the 2018 census",
  134. a(href=
  135. "https://datafinder.stats.govt.nz/data/category/census/2018/commuter-view/",
  136. "commuter data"),
  137. "to help visualise transport ",
  138. "connections. It is ", a(href="http://petras.space", "Petra Lamborn's"),
  139. " entry for the ", em("There and Back Again"),
  140. a(href=
  141. "https://www.stats.govt.nz/2018-census/there-and-back-
  142. again-data-visualisation-competition", "data visualisation competition",
  143. .noWS = "after"), ". The employment data counts employed persons 15 years or ",
  144. "older who gave an employment location in the 2018 census, while the ",
  145. "education data counts people in education 15 years or older who gave an ",
  146. "education location in the 2018 census—including older highschoolers and ",
  147. "university students, but not e.g. primary school students."),
  148. h4("Options"),
  149. p("The top right panel (toggleable via the blue switch) allows ",
  150. "you to choose between visualising the people who commute from ",
  151. "and to each area to both employment and education, and between ",
  152. "showing numbers of people or ",
  153. "their primary mode of transportation."),
  154. p("Select an area by clicking on it; deselect by clicking it again ",
  155. "or clicking in the water. When an area is selected the map is ",
  156. "coloured according to the people who commute to or from that area ",
  157. "(including the people who commute within the area). When no area is ",
  158. "selected, colouring is according to commutes to or from all ",
  159. "localities. Hover over areas for a summary (on a tablet, hold press)."),
  160. h4("FAQ"),
  161. shiny::tags$blockquote("Why are so many areas marked as 'works at ",
  162. "home'?"),
  163. p("Working from home includes working from your kitchen table, ",
  164. "but also farming. Anyone who is employed but does not commute ",
  165. "is included in this category."),
  166. shiny::tags$blockquote("Why is every number divisible by three?"),
  167. p("To ensure anonymity and the confidentiality of your census data, ",
  168. "Statistics New Zealand employs a technique called ",
  169. em(a(href=paste0(
  170. "http://archive.stats.govt.nz/about_us/legisln-policies-protocols/",
  171. "confidentiality-of-info-supplied-to-snz/safeguarding-confidentiality.aspx"),
  172. "random rounding", .noWS = "after"), .noWS = "after"), ". ",
  173. "This method rounds all values to a multiple of three, but one-third of ",
  174. "the time rounds to the second nearest multiple, rather than the closest. ",
  175. "Additionally, rounded values less than six are censored."),
  176. p("Note that this also means totals do not always add up."),
  177. shiny::tags$blockquote("In some views there are areas that are greyed ",
  178. "out when looking at transport type, but not ",
  179. "when looking at numbers of people. How does ",
  180. "that work?"),
  181. p("As mentioned above some low values are censored to avoid providing ",
  182. "potentially identifiable information. However it is possible for the ",
  183. "total number of people to be large enough to escape censoring while ",
  184. "all transport", em("type"), "numbers are too small and so no most ",
  185. "common type can be determined."),
  186. div(class="scrollbuffer")
  187. )
  188. keyboardjs <- tags$head(tags$script(HTML("
  189. $(function(){
  190. $(document).keyup(function(e) {
  191. switch(e.key) {
  192. case 'm':
  193. document.getElementsByName('radioeduemp')[0].checked = true;
  194. Shiny.onInputChange('radioeduemp', 'Employment')
  195. break;
  196. case 'd':
  197. document.getElementsByName('radioeduemp')[1].checked = true;
  198. Shiny.onInputChange('radioeduemp', 'Education')
  199. break;
  200. case 'f':
  201. document.getElementsByName('radioinout')[0].checked = true;
  202. Shiny.onInputChange('radioinout', 'res')
  203. break;
  204. case 't':
  205. document.getElementsByName('radioinout')[1].checked = true;
  206. Shiny.onInputChange('radioinout', 'work')
  207. break;
  208. case 'o':
  209. document.getElementsByName('radiocolour')[0].checked = true;
  210. Shiny.onInputChange('radiocolour', 'type')
  211. break;
  212. case 'u':
  213. document.getElementsByName('radiocolour')[1].checked = true;
  214. Shiny.onInputChange('radiocolour', 'number')
  215. break;
  216. default:
  217. break;
  218. }
  219. });
  220. })
  221. ")))