timelyportfolio / leaftime

Leaflet.timeline for R leaflet
Other
58 stars 7 forks source link

Syling based on data does not work? #2

Closed JimShady closed 4 years ago

JimShady commented 4 years ago

I don't think that styling the markers, based on data, is working properly. Using the example from the docs creates the below image (which I don't think it is meant to?)

library(leaflet)
library(leaftime)
library(htmltools)

#Build data.frame with 10 obs + 3 cols
power <- data.frame(
  "Latitude" = c(
    33.515556, 38.060556, 47.903056, 49.71, 49.041667, 31.934167,
    54.140586, 54.140586, 48.494444, 48.494444
  ),
  "Longitude" = c(
    129.837222, -77.789444, 7.563056, 8.415278, 9.175, -82.343889,
    13.664422, 13.664422, 17.681944, 17.681944
  ),
  "start" = seq.Date(as.Date("2015-01-01"), by = "day", length.out = 10),
  "end" = seq.Date(as.Date("2015-01-01"), by = "day", length.out = 10) + 1
)

# use geojsonio to convert our data.frame
#  to GeoJSON which timeline expects
power_geo <- geojsonio::geojson_json(power,lat="Latitude",lon="Longitude")

power_styled <- power
# IE does not like alpha so strip colors of alpha hex
power_styled$color <- substr(topo.colors(6)[ceiling(runif(nrow(power),0,6))],1,7)
power_styled$radius <- ceiling(runif(nrow(power),3,10))
leaflet(geojsonio::geojson_json(power_styled)) %>%
  addTiles() %>%
  setView(44.0665,23.74667,2) %>%
  addCircleMarkers(
    data = power_styled, lat = ~Latitude, lng = ~Longitude, radius = 11
  ) %>%
  addTimeline(
    timelineOpts = timelineOptions(
      styleOptions = styleOptions(
        radius = htmlwidgets::JS("function getRadius(d) {return +d.properties.radius}"),
        color = htmlwidgets::JS("function getColor(d) {return d.properties.color}"),
        fillOpacity = 1,
        stroke = FALSE
      )
    )
  )

image

Trying this with my own data .... n.b the variable color is set to '#FF0000'

data_geo                  <- select(data, x, y, start,end, color) %>%
                              geojsonio::geojson_json(data,lat="y",lon="x")

leaflet(data_geo) %>%
  addTiles() %>%
  addTimeline(
    timelineOpts = timelineOptions(
      styleOptions = styleOptions(
        color = htmlwidgets::JS("function getColor(d) {return d.properties.color}"),
        fillOpacity = 0.5,
        stroke = FALSE,
        fill = TRUE,
        radius= 20
      )
    )
  )

image

Grateful for any thoughts. Thanks.

timelyportfolio commented 4 years ago

Thanks for the report and trying leaftime out. I changed last night in develop branch so not sure if you are using develop or master. I will look at this tonight and provide a solution.

timelyportfolio commented 4 years ago

@JimShady with the develop branch, this is how we can get it to work, and unfortunately I have not thought of an easier way for this. I am not sure why master example is no longer working.

leaflet(geojsonio::geojson_json(power_styled)) %>%
  addTiles() %>%
  setView(44.0665,23.74667,2) %>%
  addCircleMarkers(
    data = power_styled, lat = ~Latitude, lng = ~Longitude, radius = 11
  ) %>%
  addTimeline(
    timelineOpts = timelineOptions(
      styleOptions = NULL, # make sure default style does not override
      pointToLayer = htmlwidgets::JS(
"
function(data, latlng) {
  return L.circleMarker(
    latlng,
    {
      radius: data.properties.radius,
      color: data.properties.color,
      fillColor: data.properties.color,
      fillOpacity: 1
    }
  );
}
"
      )
    )
  )
NadyaMamoozadeh commented 4 years ago

@timelyportfolio I've found your code super helpful for my own needs, thanks for sharing!

I have run into the same issue as described here, I am unable to customize the radius for each point. With the original code the addTimeline points do not appear at all, and with the suggestion proposed above the addTimeline points are all the same width (rather than the customized width; static image below). Do you have a fix for this?

Screen Shot 2020-01-09 at 5 01 38 PM
timelyportfolio commented 4 years ago

@nrcombs I really appreciate the report. Do you mind trying

# remotes::install_github("timelyportfolio/leaftime@develop")

library(leaflet)
library(leaftime)
library(htmltools)

#Build data.frame with 10 obs + 3 cols
power <- data.frame(
  "Latitude" = c(
    33.515556, 38.060556, 47.903056, 49.71, 49.041667, 31.934167,
    54.140586, 54.140586, 48.494444, 48.494444
  ),
  "Longitude" = c(
    129.837222, -77.789444, 7.563056, 8.415278, 9.175, -82.343889,
    13.664422, 13.664422, 17.681944, 17.681944
  ),
  "start" = seq.Date(as.Date("2015-01-01"), by = "day", length.out = 10),
  "end" = seq.Date(as.Date("2015-01-01"), by = "day", length.out = 10) + 1
)

# to style each point differently based on the data
power_styled <- power
# IE does not like alpha so strip colors of alpha hex
power_styled$color <- substr(topo.colors(6)[ceiling(runif(nrow(power),0,6))],1,7)
power_styled$radius <- seq_len(nrow(power_styled)) # ceiling(runif(nrow(power),3,10))

leaflet(geojsonio::geojson_json(power_styled)) %>%
  addTiles() %>%
  setView(44.0665,23.74667,2) %>%
  # addCircleMarkers(
  #   data = power_styled, lat = ~Latitude, lng = ~Longitude, radius = 11
  # ) %>%
  addTimeline(
    timelineOpts = timelineOptions(
      styleOptions = NULL, # make sure default style does not override
      pointToLayer = htmlwidgets::JS(
"
function(data, latlng) {
  return L.circleMarker(
    latlng,
    {
      radius: +data.properties.radius,
      color: data.properties.color,
      fillColor: data.properties.color,
      fillOpacity: 1
    }
  );
}
"
      )
    )
  )

I noticed that radius is converted into a string, so +data.properties.radius or parseInt(data.properties.radius) is necessary.

NadyaMamoozadeh commented 4 years ago

@timelyportfolio thanks so much for the fix, and so quickly, works perfectly! This is exactly what I needed.

timelyportfolio commented 4 years ago

I pushed new release to CRAN with these changes. Please reopen if this does not solve the problem or you have other ideas for improvement.