Browse Source

Faster loading!!

Courtesy timelyportforlio on github
Petra Lamborn 3 years ago
parent
commit
858d227c69
3 changed files with 158 additions and 17 deletions
  1. 11
    4
      scratch.R
  2. 22
    13
      viz/app.R
  3. 125
    0
      viz/leafletfunctions.R

+ 11
- 4
scratch.R View File

@@ -96,10 +96,17 @@ tencols[which.max(work_from[1, 5:14])]
96 96
 
97 97
 
98 98
 work_from$MAX <- work_from %>% select(home:other) %>% as.matrix() %>% 
99
-  apply(1, which.max)
99
+  apply(1, function(x) {
100
+    ifelse(max(x) <= 0, NA, which.max(x))
101
+    })
100 102
 work_to$MAX <- work_to %>% select(home:other) %>% as.matrix() %>% 
101
-  apply(1, which.max)
103
+  apply(1, function(x) {
104
+    ifelse(max(x) <= 0, NA, which.max(x))
105
+    })
102 106
 work_simp$MAX <- work_simp %>% select(home:other) %>% as.matrix() %>% 
103
-  apply(1, which.max)
107
+  apply(1, function(x) {
108
+    ifelse(max(x) <= 0, NA, which.max(x))
109
+    })
110
+
111
+save(work_simp, work_to, work_from, tencols, file="viz/datasets.RData")
104 112
 
105
-save(work_simp, work_to, work_from, tencols, file="datasets.RData")

+ 22
- 13
viz/app.R View File

@@ -5,6 +5,8 @@ library(rgdal)
5 5
 library(dplyr)
6 6
 library(leaflet.extras)
7 7
 
8
+source("leafletfunctions.R")
9
+
8 10
 # work_travel <- read_csv("../travel-work.csv")
9 11
 load(file="datasets.RData")
10 12
 shpf <- readOGR(dsn="../shapefiles/sa20025WGSfilcth")
@@ -27,6 +29,7 @@ startcols <- ifelse(is.na(startcols), "#808080", startcols)
27 29
 # Define UI
28 30
 ui <- fluidPage(
29 31
   useShinyjs(),
32
+  leafletjs,
30 33
   tags$style(type = "text/css", 
31 34
   "html, body {
32 35
     width:100%;
@@ -42,10 +45,10 @@ ui <- fluidPage(
42 45
     cursor: progress !important;
43 46
   }
44 47
   #loading p {
45
-    border-radius: 25px;
46
-    background: #FFFFFF;
47
-    padding: 10px;
48
-    border: 2px solid #000000;
48
+    border-radius: 5px;
49
+    background-color: rgba(255, 255, 255, 0.8);
50
+    padding: 6px 8px;
51
+    box-shadow: 0 0 15px rgba(0,0,0,0.2);
49 52
     font-size: 1.5em;
50 53
     font-weight: bold;
51 54
   }
@@ -79,8 +82,9 @@ server <- function(input, output) {
79 82
   p.layers <- c("polya", "polyb")
80 83
   output$map <- renderLeaflet({
81 84
     leaf <- leaflet(shpf, options = leafletOptions(minZoom = 3, maxZoom = 13)) %>% 
82
-      addPolygons(group = p.layers[1] ,color="#000", opacity = 1, weight=1,
85
+      addPolygons(color="#000", opacity = 1, weight=1,
83 86
                                 fillColor = startcols, 
87
+                  layerId = ~SA22018_V1,
84 88
                   label = shpf@data$SA22018__1,
85 89
                   fillOpacity = 1) %>%
86 90
       setView(174, -41, 5) %>%
@@ -93,24 +97,27 @@ server <- function(input, output) {
93 97
     leaf
94 98
   })
95 99
   updateMap <- function() {
100
+    selcode <- sel.SA2.code()
101
+    selcode <- ifelse(is.na(selcode), 0, selcode)
96 102
     shinyjs::showElement(selector="#loading p", asis = TRUE, 
97 103
                          anim=TRUE, animType = "slide")
98 104
     fcols <- startcols
99
-    if (sel.SA2.code() != 0) {
100
-      codvs <- work_simp %>% filter(work_code == sel.SA2.code())
105
+    
106
+    if (selcode != 0) {
107
+      codvs <- work_simp %>% filter(work_code == selcode)
101 108
       codvs <- codelist %>% left_join(codvs, by=c("sa2_code" = "res_code"))
102 109
       codvs <- tencols[codvs$MAX]
103 110
       fcols <- ifelse(is.na(codvs), "#808080", codvs)
104 111
     }
105 112
     leafletProxy("map", data = shpf) %>%
106
-      addPolygons(group = p.layers[2] ,color="#000", opacity = 1, weight=1,
107
-                                fillColor = fcols,
108
-                  label = shpf@data$SA22018__1,
109
-                  fillOpacity = 1) %>%
110
-      clearGroup(p.layers[1])
113
+      setShapeStyle(layerId = ~SA22018_V1, fillColor = fcols) %>%
114
+      clearControls() %>%
115
+      addLegend(position = "topleft",
116
+                colors = c(tencols, "#808080"),
117
+                labels = transport.t, opacity = 1)
111 118
     p.layers <<- rev(p.layers)
112 119
     shinyjs::hideElement(selector="#loading p", asis=TRUE, 
113
-                         anim=TRUE, animType = "slide", time = 7)
120
+                         anim=TRUE, animType = "slide")
114 121
   }
115 122
   observeEvent(input$map_shape_click, {
116 123
     p <- input$map_shape_click
@@ -120,11 +127,13 @@ server <- function(input, output) {
120 127
     proj4string(pdat) <- proj4string(shpf)
121 128
     ppoly <- over(pdat, shpf)
122 129
     codetmp <- as.numeric(as.character(ppoly[1,"SA22018_V1"]))
130
+    codetmp <- ifelse(is.na(codetmp), 0, codetmp)
123 131
     sel.SA2.code(ifelse(sel.SA2.code() == codetmp, 0, codetmp))
124 132
     updateMap()
125 133
   })
126 134
   output$lochtml <- renderUI({
127 135
     seled <- sel.SA2.code()
136
+    seled <- ifelse(is.na(seled), 0, seled)
128 137
     if (seled == 0) {
129 138
       HTML("")
130 139
     } else {

+ 125
- 0
viz/leafletfunctions.R View File

@@ -0,0 +1,125 @@
1
+# Courtesy timelyportfolio on github: 
2
+# https://github.com/rstudio/leaflet/issues/496#issuecomment-650122985
3
+### R functions
4
+# add in methods from https://github.com/rstudio/leaflet/pull/598
5
+setCircleMarkerRadius <- function(map, layerId, radius, data=getMapData(map)){
6
+  options <- list(layerId = layerId, radius = radius)
7
+  # evaluate all options
8
+  options <- evalFormula(options, data = data)
9
+  # make them the same length (by building a data.frame)
10
+  options <- do.call(data.frame, c(options, list(stringsAsFactors=FALSE)))
11
+  leaflet::invokeMethod(map, data, "setRadius", options$layerId, options$radius)
12
+}
13
+
14
+setCircleMarkerStyle <- function(map, layerId
15
+                                 , radius = NULL
16
+                                 , stroke = NULL
17
+                                 , color = NULL
18
+                                 , weight = NULL
19
+                                 , opacity = NULL
20
+                                 , fill = NULL
21
+                                 , fillColor = NULL
22
+                                 , fillOpacity = NULL
23
+                                 , dashArray = NULL
24
+                                 , options = NULL
25
+                                 , data = getMapData(map)
26
+){
27
+  if (!is.null(radius)){
28
+    setCircleMarkerRadius(map, layerId = layerId, radius = radius, data = data)
29
+  }
30
+  
31
+  options <- c(list(layerId = layerId),
32
+               options,
33
+               filterNULL(list(stroke = stroke, color = color,
34
+                               weight = weight, opacity = opacity,
35
+                               fill = fill, fillColor = fillColor,
36
+                               fillOpacity = fillOpacity, dashArray = dashArray
37
+               )))
38
+  
39
+  if (length(options) < 2) { # no style options set
40
+    return()
41
+  }
42
+  # evaluate all options
43
+  options <- evalFormula(options, data = data)
44
+  
45
+  # make them the same length (by building a data.frame)
46
+  options <- do.call(data.frame, c(options, list(stringsAsFactors=FALSE)))
47
+  layerId <- options[[1]]
48
+  style <- options[-1] # drop layer column
49
+  
50
+  #print(list(style=style))
51
+  leaflet::invokeMethod(map, data, "setStyle", "marker", layerId, style);
52
+}
53
+
54
+setShapeStyle <- function( map, data = getMapData(map), layerId,
55
+                           stroke = NULL, color = NULL,
56
+                           weight = NULL, opacity = NULL,
57
+                           fill = NULL, fillColor = NULL,
58
+                           fillOpacity = NULL, dashArray = NULL,
59
+                           smoothFactor = NULL, noClip = NULL,
60
+                           options = NULL
61
+){
62
+  options <- c(list(layerId = layerId),
63
+               options,
64
+               filterNULL(list(stroke = stroke, color = color,
65
+                               weight = weight, opacity = opacity,
66
+                               fill = fill, fillColor = fillColor,
67
+                               fillOpacity = fillOpacity, dashArray = dashArray,
68
+                               smoothFactor = smoothFactor, noClip = noClip
69
+               )))
70
+  # evaluate all options
71
+  options <- evalFormula(options, data = data)
72
+  # make them the same length (by building a data.frame)
73
+  options <- do.call(data.frame, c(options, list(stringsAsFactors=FALSE)))
74
+  
75
+  layerId <- options[[1]]
76
+  style <- options[-1] # drop layer column
77
+  
78
+  #print(list(style=style))
79
+  leaflet::invokeMethod(map, data, "setStyle", "shape", layerId, style);
80
+}
81
+
82
+### JS methods
83
+leafletjs <-  tags$head(
84
+  # add in methods from https://github.com/rstudio/leaflet/pull/598
85
+  tags$script(HTML(
86
+    '
87
+window.LeafletWidget.methods.setStyle = function(category, layerId, style){
88
+  var map = this;
89
+  if (!layerId){
90
+    return;
91
+  } else if (!(typeof(layerId) === "object" && layerId.length)){ // in case a single layerid is given
92
+    layerId = [layerId];
93
+  }
94
+
95
+  //convert columnstore to row store
96
+  style = HTMLWidgets.dataframeToD3(style);
97
+  //console.log(style);
98
+
99
+  layerId.forEach(function(d,i){
100
+    var layer = map.layerManager.getLayer(category, d);
101
+    if (layer){ // or should this raise an error?
102
+      layer.setStyle(style[i]);
103
+    }
104
+  });
105
+};
106
+
107
+window.LeafletWidget.methods.setRadius = function(layerId, radius){
108
+  var map = this;
109
+  if (!layerId){
110
+    return;
111
+  } else if (!(typeof(layerId) === "object" && layerId.length)){ // in case a single layerid is given
112
+    layerId = [layerId];
113
+    radius = [radius];
114
+  }
115
+
116
+  layerId.forEach(function(d,i){
117
+    var layer = map.layerManager.getLayer("marker", d);
118
+    if (layer){ // or should this raise an error?
119
+      layer.setRadius(radius[i]);
120
+    }
121
+  });
122
+};
123
+'
124
+  ))
125
+)