Resizing custom markers in Leaflet for R - r

I am interested in making custom icons while using Leaflet in R.
The documentation has a nice example, but when experimenting with it, I realized that there is no way to allow the custom marker to resize when the map changes size.
Since size is one of the parameters and is fixed (iconWidth = 38, iconHeight = 95,), obviously the marker will stay consistently sized as zoom changes for map beneath it.
greenLeafIcon <- makeIcon(
iconUrl = "http://leafletjs.com/docs/images/leaf-green.png",
iconWidth = 38, iconHeight = 95,
iconAnchorX = 22, iconAnchorY = 94,
shadowUrl = "http://leafletjs.com/docs/images/leaf-shadow.png",
shadowWidth = 50, shadowHeight = 64,
shadowAnchorX = 4, shadowAnchorY = 62
)
Are there any hacks / ideas / protocols for having custom icons resize along with zoom?

Related

RangeSlider does not work with scatter plot

Is it possible to make the range slider work with a scatter plot? The slider works if I change the scatter to a line plot but that does not work for me as I can not use the box select tool with line plots. The snippet below is simplified to demonstrate the issue. I suspect the embedded JavaScript is the issue but I may be wrong as it works just fine with a line plot. Thanks.
from bokeh.io import show
from bokeh.models import CustomJS, RangeSlider, Column, Row
from bokeh.plotting import figure
x = [0, 10, 20, 30, 40, 50, 60, 70, 80, 90, 100]
y = [0, 10, 20, 30, 40, 50, 60, 70, 80, 90, 100]
scatter_plot = figure(width=250, plot_height=600)
scatter_plot.scatter(x, y)
callback = CustomJS(args=dict(y_range=scatter_plot.y_range), code="""
var start = cb_obj.value
y_range.start = start[0]
y_range.end = start[1]
""")
depth_slider = RangeSlider(width=250, show_value=False, start=-20, end=120, value=(20, 80), step=20,
title="Y Scale")
depth_slider.js_on_change('value', callback)
layout = Column(Row(depth_slider), scatter_plot, )
show(layout)
There seems to be some race condition going on or a discrepancy between how Python and JS version of Bokeh work.
By default, all ranges are instances of DataRange1d class which recompute start and end when needed. In this case, it for some reason recomputes the values after you set them manually.
To fix it, specify the range manually from the get go:
scatter_plot = figure(..., y_range=(20, 80))

Using canvas rectangles as buttons to create menus and actions

I am programing a GUI for a device that contains numerous sensors... I need to display their information accordingly... Some of them will require manual input which I want to input via using multiple rectangles used as menu items and adding a tag_bind to them to take action upon being clicked.
If you read carefully... I have attempted to erase the menu that has been pressed so it is not displayed after it is pressed. ( or at least at the last click, go back to only showing the main menu
I am running into an issue with the arguments... I little bit of help would be appreciated.
error: in onSecondClick
canvas.delete(square)
NameError: global name 'square' is not defined
I am able to delete the main menu rectangle but doesn't delete any other... I am a bit stomped
from Tkinter import *
#global square
def onObjectClick(event):
#. print(event.x, event.y)
square = canvas.create_rectangle(40, 50, 150, 100, width=1, fill="#BBB", tags="secondtag")
squaretxt = canvas.create_text(90,70, text="Sub-Menu")
canvas.delete(mainbutton)
canvas.delete(mainbuttontxt)
def onSecondClick(square, *args):
# print(event.x, event.y)
secondsquare = canvas.create_rectangle(60,70,160,110, width=1, fill="#AAA", tags="thirdtag")
secondText = canvas.create_text(110, 90, text="Final Choice")
canvas.delete(square)
def onThirdClick(secondsquare, secondText):
canvas.delete(secondsquare)
canvas.delete(secondText)
root = Tk()
canvas = Canvas(root, width=300, height=200)
mainbutton = canvas.create_rectangle(10, 30, 100, 60, width=5, fill="#666", tags="mainbuttontag")
manibuttontxt = canvas.create_text(55, 45, text="Main Menu", tags="mainbuttontag")
canvas.tag_bind("mainbuttontag", "<ButtonPress-1>", onObjectClick)
canvas.tag_bind('secondtag', "<ButtonPress-1>", onSecondClick)
canvas.tag_bind('thirdtag', "<ButtonPress-1>", onThirdClick)
canvas.pack()
root.mainloop()
I figured out how to do what I needed to do... I have dropped trying to use the canvas variable and used the "tags" option to choose what to delete upon a click action.
Here is the sample code I came up with. Feel free to butcher it if you think I am wrong or if there is a better way to approach this,
from Tkinter import *
txt2 = "Second Square"
txt3 = "Third Square"
global square
global mainbuttontxt
def onObjectClick(event):
square = canvas.create_rectangle(40, 50, 150, 100, width=1, fill="#BBB", tags="secondtag")
squaretxt = canvas.create_text(90,70, text=txt2, tags="secondtag")
canvas.delete("mainbuttontag")
def onSecondClick(event):
secondsquare = canvas.create_rectangle(60,70,160,110, width=1, fill="#AAA", tags="thirdtag")
secondText = canvas.create_text(110, 90, text=txt3, tags="thirdtag")
canvas.delete("secondtag")
def onThirdClick(event):
canvas.delete("thirdtag")
mainbutton = canvas.create_rectangle(10, 30, 100, 60, width=5, fill="#666", tags="mainbuttontag")
manibuttontxt = canvas.create_text(55, 45, text="Main Menu", tags="mainbuttontag")
root = Tk()
canvas = Canvas(root, width=300, height=200)
mainbutton = canvas.create_rectangle(10, 30, 100, 60, width=5, fill="#666", tags="mainbuttontag")
manibuttontxt = canvas.create_text(55, 45, text="Main Menu", tags="mainbuttontag")
canvas.tag_bind("mainbuttontag", '<ButtonPress-1>', onObjectClick)
canvas.tag_bind('secondtag', '<ButtonPress-1>', onSecondClick)
canvas.tag_bind('thirdtag', '<ButtonPress-1>', onThirdClick)
canvas.pack()
root.mainloop()

Shiny R - Custom markers depending on condition

I would like to know if it is possible to add condition in the makeIcon() function
I have a table :
id ; lat ; long ; class1 ; class2 ; class3
And I want the icon to be different depending on these conditions :
if class1 == A, I want image1
else, if class2 == B, I want image2
else, if class3 == C, I want image 3
else, I want image4
Within makeIcon(), probably not. From the API documentation:
For the simple case of applying a single icon to a set of markers, use
makeIcon(). (link)
You probably want to use icon() which is a vector of icons that you can use to draw different icons for different data:
If you have several icons to apply that vary only by a couple of
parameters (i.e. they share the same size and anchor points but have
different URLs), use the icons() function.
Icons contains a vector with each icon image url (or any other icon property that differs among the data).
To do the logic, it might be easiest to nest an extra two ifelse statements into the icon function, something like:
iconUrl = ifelse(df$class1 == "a", "image1",
ifelse(df$class2 == "c", "image2",
ifelse(df$class3 =="x", "image3",
"some other url" #the else condition
)
)
),
Here's a minimal example that's just a slight addition to the example in the linked to api documentation:
library(leaflet)
lat<- c(57,65,60,61)
long<-c(-130,-125,-140,-135)
class1<-c("a","b","c","d")
class2<-c("b","c","d","e")
class3<-c("b","c","d","f")
df <- data.frame(lat,long,class1,class2,class3,stringsAsFactors=FALSE)
leafIcons <- icons(
iconUrl = ifelse(df$class1 == "a", "http://leafletjs.com/examples/custom-icons/leaf-green.png",
ifelse(df$class2 == "c", "http://leafletjs.com/examples/custom-icons/leaf-red.png",
ifelse(df$class3 == "d", "http://leafletjs.com/examples/custom-icons/leaf-orange.png",
"http://leafletjs.com/docs/images/logo.png"
)
)
),
iconWidth = 38, iconHeight = 95,
iconAnchorX = 22, iconAnchorY = 94,
shadowUrl = "http://leafletjs.com/examples/custom-icons/leaf-shadow.png",
shadowWidth = 50, shadowHeight = 64,
shadowAnchorX = 4, shadowAnchorY = 62
)
leaflet(data = df) %>% addTiles() %>%
addMarkers(~long, ~lat, icon = leafIcons)
Sorry the image selection in this isn't fantastic. If you want to some other property vary depending on the data for each icon, icon size for example, you use the same process on iconWidth and/or iconHeight:
iconHeight = ifelse(df$class1 == "a", 100,
ifelse(df$class2 == "c", 200,
ifelse(df$class3 == "d", 300,
400
)
)
),

How to resize an image in R

Let say I have image of dimensions (1, 50, 141, 1). How can resize it to dimensions (None, 40, 110, 1) using R?
I know for imager package, but it only allows to resize width and height using:
resize(image, width, height)
Example:
library(imager)
img <- load.image('.../extdata/parrots.png')
dim(img)
img <- resize(img, 110, 40)
# want dim(img) <- c(110, 40, 1, None)

R Shiny: publishing leaflet maps with custom icons

I have created a leaflet map with custom icons and have the icons in the www folder for publishing. However after I publish I am not able to see the icons. My code is as follows and it works fine in Rstudio.
oceanIcons <- iconList(
Rank1 = makeIcon("23-1.png", "ferry-18#2x.png", 36, 36),
Rank2= makeIcon("23-2.png", "danger-24#2x.png", 36, 36),
Rank3= makeIcon("23-3.png", "danger-24#2x.png", 36, 36),
Rank4= makeIcon("23-4.png", "danger-24#2x.png", 36, 36),
Rank5= makeIcon("23-5.png", "danger-24#2x.png", 36, 36),
Rank0= makeIcon("circle2.png", "danger-24#2x.png", 48, 48)
)
map = leaflet(map_df) %>% addTiles() %>% addMarkers(icon = ~oceanIcons[map_df$rank],
popup=sprintf("<strong> %s <br>Expected Volume of Bike Departures: %s </br> Distance in Miles: %s <br>
%s</br></strong>"
,map_df$st_name,map_df$outbound,map_df$distance, map_df$rank))%>% addProviderTiles(providers$CartoDB.Positron)
Is there a particular reason why this method will not work with leaflets or publishing.
You need to ensure that when you publish to shinyapps.io, that you send those files with, for example:

Resources