From 35d76ed23c9b0f8ecf48aca91d8a9e2af7e246a3 Mon Sep 17 00:00:00 2001 From: Sebastian Gatscha Date: Mon, 12 Aug 2024 23:05:09 +0200 Subject: [PATCH] added clustercharts News, pkgdown, refactor (move aggregation/valueFile out of options, cleanup --- NEWS.md | 1 + R/clusterCharts.R | 15 +- _pkgdown.yml | 5 + inst/examples/clusterCharts_app.R | 44 ++-- inst/examples/clustercharts_sum.R | 34 ++- .../lfx-clustercharts-bindings.js | 211 +++++++----------- man/addClusterCharts.Rd | 6 + man/clusterchartOptions.Rd | 6 - 8 files changed, 151 insertions(+), 171 deletions(-) diff --git a/NEWS.md b/NEWS.md index 102bed15..c35a1849 100644 --- a/NEWS.md +++ b/NEWS.md @@ -4,6 +4,7 @@ * The opened sidebar tab is returned as Shiny input using the `sidebar_tabs` ID. * allow `...` in `antpathOptions` to be able to set the pane (e.g.: `renderer= JS('L.svg({pane: "my-pane"})')`) * Added custom `clusterCharts` using `Leaflet.markercluster` and `d3` for piechart and barcharts. +* Added `addClusterCharts` to enable **pie** and **bar** charts in Marker clusters using `Leaflet.markercluster`, `d3` and `L.DivIcon`, with support for customizable category styling and various aggregation methods like **sum, min, max, mean**, and **median**. * Switched from `geojsonsf` to `yyjsonr` (*heightgraph*, *timeslider*, *clustercharts*) diff --git a/R/clusterCharts.R b/R/clusterCharts.R index c3de081a..33b25936 100644 --- a/R/clusterCharts.R +++ b/R/clusterCharts.R @@ -21,6 +21,8 @@ clusterchartsDependencies <- function() { #' @param type The type of chart to use for clusters, either \code{c("pie","bar","horizontal","custom")}. #' @param categoryField The name of the feature property used to categorize the charts. #' @param categoryMap A data frame mapping categories to chart properties (label, color, icons, stroke). +#' @param aggregation If `type = "custom"` in the `addClusterCharts` function, this aggregation method will be used. +#' @param valueField If `type = "custom"` in the `addClusterCharts` function, the aggregation will be used on this column. #' @param icon Include an icon or a set of icons with \code{makeIcon} or \code{iconList} #' @param html The html to include in the markers #' @param popup Use the column name given in popup to collect the feature property with this name. @@ -74,6 +76,7 @@ clusterchartsDependencies <- function() { addClusterCharts <- function( map, lng = NULL, lat = NULL, layerId = NULL, group = NULL, type = c("pie","bar","horizontal","custom"), + aggregation = "sum", valueField = NULL, options = clusterchartOptions(), icon = NULL, html = NULL, popup = NULL, popupOptions = NULL, label = NULL, labelOptions = NULL, @@ -109,6 +112,8 @@ addClusterCharts <- function( clusterOptions$maxClusterRadius = NULL clusterOptions$iconCreateFunction = NULL } + options$aggregation = aggregation + options$valueField = valueField ## CSS string ############# css <- paste(apply(categoryMap, 1, generate_css, icon), collapse = "\n") @@ -169,8 +174,6 @@ addClusterCharts <- function( #' @param labelStroke The label stroke color. Default is `black` #' @param labelColor The label color. Default is `black` #' @param labelOpacity The label color. Default is `0.9` -#' @param aggregation If `type = "custom"` in the `addClusterCharts` function, this aggregation method will be used. -#' @param valueField If `type = "custom"` in the `addClusterCharts` function, the aggregation will be used on this column. #' @param digits The amount of digits. Default is `2` #' @param sortTitlebyCount Should the svg-title be sorted by count or by the categories. #' @@ -184,8 +187,6 @@ clusterchartOptions <- function(rmax = 30, size = c(20, 20), labelStroke = "black", labelColor = "black", labelOpacity = 0.9, - aggregation = "sum", - valueField = NULL, digits = 2, sortTitlebyCount = TRUE) { filterNULL(list( @@ -200,8 +201,6 @@ clusterchartOptions <- function(rmax = 30, size = c(20, 20), , labelStroke = labelStroke , labelColor = labelColor , labelOpacity = labelOpacity - , aggregation = aggregation - , valueField = valueField , digits = digits , sortTitlebyCount = sortTitlebyCount )) @@ -235,7 +234,7 @@ generate_css <- function(row, icon) { css <- paste0(css, ".icon-", label_nospaces, " {\n", " background-image: url('", icon, "');\n", - " background-repeat: round;\n", + " background-repeat: no-repeat;\n", " background-position: 0px 1px;\n", "}" ) @@ -263,7 +262,7 @@ generate_css <- function(row, icon) { css <- paste0(css, ".icon-", label_nospaces, " {\n", " background-image: url('", iconuse$data, "');\n", - " background-repeat: round;\n", + " background-repeat: no-repeat;\n", " background-position: 0px 1px;\n", size, "}" diff --git a/_pkgdown.yml b/_pkgdown.yml index 7a18070c..6a6310f7 100644 --- a/_pkgdown.yml +++ b/_pkgdown.yml @@ -25,6 +25,11 @@ reference: - menuItem - mapmenuItems - markermenuItems + - title: Clustercharts with d3 + contents: + - matches("Contextmenu") + - matches("ClusterCharts") + - matches("clusterchart") - title: Easy Print contents: - matches("Easyprint") diff --git a/inst/examples/clusterCharts_app.R b/inst/examples/clusterCharts_app.R index 8a6acaf6..0826a27a 100644 --- a/inst/examples/clusterCharts_app.R +++ b/inst/examples/clusterCharts_app.R @@ -34,8 +34,12 @@ data$tosum <- sample(1:100, nrow(data), replace = TRUE) ui <- fluidPage( tags$head(tags$style(" - .clusterchartsicon { - background-position: left !important; + .inputs { + display: flex; + } + .inputdiv { + position: relative; + z-index: 100000000; } .markerhtml { height: 100%; @@ -43,6 +47,18 @@ ui <- fluidPage( left: 41px; position: absolute; }")), + div(class="inputdiv", + div(class="inputs", + selectInput("type", "Plot type", choices = c("bar","horizontal", "pie"), selected = "pie"), + numericInput("stroke", "strokeWidth", 1, 1, 10), + numericInput("rmax", "MaxRadius", 50, 1, 150), + numericInput("innerRadius", "InnerRadius", 10, 1, 100), + numericInput("width", "Width", 50, 1, 150), + numericInput("height", "Height", 50, 1, 150), + selectInput("labelBackground", "labelBackground", choices = c(T,F)), + selectInput("sortTitlebyCount", "sortTitlebyCount", choices = c(T,F)), + numericInput("labelOpacity", "labelOpacity", 0.5, 0, 1, step = 0.1), + )), leafletOutput("map", height = 650), splitLayout(cellWidths = paste0(rep(20,4), "%"), div(verbatimTextOutput("click")), @@ -59,20 +75,22 @@ server <- function(input, output, session) { leaflet::addLayersControl(overlayGroups = c("clustermarkers","normalcircles")) %>% # addCircleMarkers(data = data, group = "normalcircles", clusterOptions = markerClusterOptions()) %>% addClusterCharts(data = data - , options = clusterchartOptions(rmax = 50, + , options = clusterchartOptions(rmax = input$rmax, size = c(100,40), # size=40, - width = 100, height = 30, - strokeWidth = 1, - labelBackground = T, + width = input$width, + height = input$height, + strokeWidth = input$stroke, + labelBackground = as.logical(input$labelBackground), # labelFill = "red", # labelStroke = "green", labelColor = "blue", - labelOpacity = 0.5, - innerRadius = 10, - sortTitlebyCount = T) + labelOpacity = input$labelOpacity, + innerRadius = input$innerRadius, + sortTitlebyCount = as.logical(input$sortTitlebyCount)) # , type = "bar" # , type = "horizontal" + , type = input$type , categoryField = "categoryfields" , html = "web" , icon = shipIcon @@ -86,21 +104,19 @@ server <- function(input, output, session) { strokes = "gray" ) , group = "clustermarkers" - # group = "zipcode", , layerId = "id" , clusterId = "id" , popupFields = c("brewery","address","zipcode", "category") , popupLabels = c("Brauerei","Addresse","PLZ", "Art") - , popup = "popup" + # , popup = "popup" , label = "label" ## Options ############# , markerOptions = markerOptions(interactive = TRUE, draggable = TRUE, keyboard = TRUE, - # stroke = 0.1, title = "Some Marker Title", zIndexOffset = 100, - opacity = 1, + opacity = 0.6, riseOnHover = TRUE, riseOffset = 400) , legendOptions = list(position = "bottomright", title = "Unfälle im Jahr 2003") @@ -111,7 +127,7 @@ server <- function(input, output, session) { , spiderLegPolylineOptions = list(weight = 1.5, color = "#222", opacity = 0.5) , freezeAtZoom = TRUE , clusterPane = "clusterpane" - , spiderfyDistanceMultiplier = 1 + , spiderfyDistanceMultiplier = 34 ) , labelOptions = labelOptions(opacity = 0.8, textsize = "14px") , popupOptions = popupOptions(maxWidth = 900, minWidth = 200, keepInView = TRUE) diff --git a/inst/examples/clustercharts_sum.R b/inst/examples/clustercharts_sum.R index 130e93b8..eb8a144e 100644 --- a/inst/examples/clustercharts_sum.R +++ b/inst/examples/clustercharts_sum.R @@ -5,7 +5,7 @@ library(leaflet.extras) library(leaflet.extras2) options("shiny.autoreload" = TRUE) - +## Icons ############## # shipIcon <- leaflet::makeIcon( # iconUrl = "./icons/Icon5.svg" # ,className = "lsaicons" @@ -23,6 +23,7 @@ shipIcon <- iconList( # iconAnchorX = 0, iconAnchorY = 0 # ) +## Data ############## data <- sf::st_as_sf(breweries91) data$category <- sample(c("Schwer", "Mäßig", "Leicht", "kein Schaden"), size = nrow(data), replace = TRUE) data$label <- paste0(data$brewery, "
", data$address) @@ -30,16 +31,13 @@ data$id <- paste0("ID", seq.int(nrow(data))) data$popup <- paste0("
", data$brewery, "
", data$address, "
") data$tosum <- sample(1:100, nrow(data), replace = TRUE) data$tosum2 <- sample(1:10, nrow(data), replace = TRUE) -# data$tosum <- 10 data$tosumlabel <- paste("Sum: ", data$tosum) data$web <- gsub(">(.*?)<", ">",data$tosum,"<", data$web) data$web <- ifelse(is.na(data$web), "", paste0("
", data$web, "
")) +## UI ############## ui <- fluidPage( tags$head(tags$style(" - .clusterchartsicon { - background-position: left !important; - } .markerhtml { height: 100%; margin-top: 8px; @@ -47,10 +45,13 @@ ui <- fluidPage( position: absolute; }")), leafletOutput("map", height = 650), - selectInput("aggr", "Aggregation", choices = c("sum","max", "min", "mean", - # "variance","deviation" ## working but not correct? ?? - # "cumsum", "mode", "least" ## not wokring - new d3 v? - "median"), selected = "mean"), + selectInput("type", "Plot type", choices = c("bar","horizontal", "custom", "pie")), + conditionalPanel("input.type == 'custom'", + selectInput("aggr", "Aggregation", choices = c("sum","max", "min", "mean", + # "variance","deviation" ## working but not correct? ?? + # "cumsum", "mode", "least" ## not wokring - new d3 v? + "median"), selected = "mean") + ), splitLayout(cellWidths = paste0(rep(20,4), "%"), div(h5("Click Event"), verbatimTextOutput("click")), div(h5("Mouseover Event"), verbatimTextOutput("mouseover")), @@ -59,6 +60,7 @@ ui <- fluidPage( ) ) +## Server ############## server <- function(input, output, session) { output$map <- renderLeaflet({ leaflet() %>% addMapPane("clusterpane", 420) %>% @@ -70,17 +72,13 @@ server <- function(input, output, session) { size = 40, # size = c(100,140), labelBackground = TRUE, - labelStroke = "orange", - labelColor = "gray", labelOpacity = 0.5, innerRadius = 20, - aggregation = input$aggr, - valueField = "tosum", digits = 0, sortTitlebyCount = TRUE) - # , type = "bar" - # , type = "horizontal" - , type = "custom" + , aggregation = input$aggr + , valueField = "tosum" + , type = input$type , categoryField = "category" , html = "web" , icon = shipIcon @@ -90,8 +88,8 @@ server <- function(input, output, session) { , group = "clustermarkers" , layerId = "id" , clusterId = "id" - , popupFields = c("id","brewery","address","zipcode", "category","tosum","tosum2") - , popupLabels = c("id","Brauerei","Addresse","PLZ", "Art", "tosum","tosum2") + # , popupFields = c("id","brewery","address","zipcode", "category","tosum","tosum2") + # , popupLabels = c("id","Brauerei","Addresse","PLZ", "Art", "tosum","tosum2") , label = "label" ## Options ############# , markerOptions = markerOptions(interactive = TRUE, diff --git a/inst/htmlwidgets/lfx-clustercharts/lfx-clustercharts-bindings.js b/inst/htmlwidgets/lfx-clustercharts/lfx-clustercharts-bindings.js index 4bcae79a..90f3261a 100644 --- a/inst/htmlwidgets/lfx-clustercharts/lfx-clustercharts-bindings.js +++ b/inst/htmlwidgets/lfx-clustercharts/lfx-clustercharts-bindings.js @@ -22,8 +22,6 @@ LeafletWidget.methods.addClusterCharts = function(geojson, layerId, group, type, var digits = options.digits ? options.digits : null; // Make L.markerClusterGroup, markers, fitBounds and renderLegend - console.log("geojson"); console.log(geojson) - console.log("clusterOptions"); console.log(clusterOptions) var markerclusters = L.markerClusterGroup( Object.assign({ maxClusterRadius: 2 * rmax, @@ -54,7 +52,7 @@ LeafletWidget.methods.addClusterCharts = function(geojson, layerId, group, type, // Functions function defineFeature(feature, latlng) { var categoryVal = feature.properties[categoryField] - var myClass = 'clustermarker category-'+categoryVal+' clusterchartsicon icon-'+categoryVal; + var myClass = 'clustermarker category-'+categoryVal+' icon-'+categoryVal; let extraInfo = { clusterId: clusterId }; //console.log("feature"); console.log(feature) @@ -99,7 +97,6 @@ LeafletWidget.methods.addClusterCharts = function(geojson, layerId, group, type, if (popup && props[popup]) { popupContent = props[popup] + ''; } else if (popupFields !== null ) { - console.log("popupFields"); console.log(popupFields) popupContent += ''; popupFields.map( function(key, idx) { if (props[key]) { @@ -150,7 +147,6 @@ LeafletWidget.methods.addClusterCharts = function(geojson, layerId, group, type, //mode: (leaves, accessor) => d3.mode(leaves, accessor), //cumsum: (leaves, accessor) => d3.cumsum(leaves, accessor), //least: (leaves, accessor) => d3.least(leaves, accessor), - //variance: (leaves, accessor) => d3.variance(leaves, accessor), //deviation: (leaves, accessor) => d3.deviation(leaves, accessor), }; @@ -182,15 +178,11 @@ LeafletWidget.methods.addClusterCharts = function(geojson, layerId, group, type, }); } else { - console.log("data");console.log(data) - console.log("categoryField");console.log(categoryField) var data = d3.nest() //Build a dataset for the pie chart .key(function(d) { return d.feature.properties[categoryField]; }) .entries(children, d3.map) if (type == "pie") { - console.log("Piechart") - html = bakeThePie({ data: data, valueFunc: function(d) { return d.values.length; }, @@ -207,7 +199,6 @@ LeafletWidget.methods.addClusterCharts = function(geojson, layerId, group, type, } }) } else if (type == "horizontal") { - console.log("Barchart horizontal") html = bakeTheBarChartHorizontal({ data: data, width: options.width ? options.width : 70, @@ -215,15 +206,14 @@ LeafletWidget.methods.addClusterCharts = function(geojson, layerId, group, type, barLabel: n, barClass: 'cluster-bar', barLabelClass: 'clustermarker-cluster-bar-label', - pathClassFunc: function(d){ + pathClassFunc: function(d) { return "category-" + d.key; }, - pathTitleFunc: function(d){ + pathTitleFunc: function(d) { return d.key + ' (' + d.values.length + ')'; } }); } else { - console.log("Barchart") html = bakeTheBarChart({ data: data, width: options.width ? options.width : 70, @@ -255,120 +245,85 @@ LeafletWidget.methods.addClusterCharts = function(geojson, layerId, group, type, if (!options.data || !options.valueFunc) { return ''; } - console.log("bakeTheBubbleChart with these options"); console.log(options) - if (false) { - console.log("1") - var data = options.data, - valueFunc = options.valueFunc, - r = options.outerRadius, - rInner = options.innerRadius, - pathClassFunc = options.pathClassFunc, - pathTitleFunc = options.pathTitleFunc, - origo = (r+strokeWidth), // Center coordinate - w = origo * 2, // Width and height of the svg element - h = w, - donut = d3.layout.pie(), - arc = d3.svg.arc().innerRadius(rInner).outerRadius(r); - - console.log("3") - var svg = document.createElementNS(d3.ns.prefix.svg, 'svg'); - var vis = d3.select(svg) - .data([data]) - .attr('class', options.bubbleClass) - .attr('width', w) - .attr('height', h); - - console.log("4 - data"); - console.log(data) - var arcs = vis.selectAll('g.arc') - .data(donut.value(valueFunc)) - .enter().append('svg:g') - .attr('class', 'arc') - .attr('transform', 'translate(' + origo + ',' + origo + ')'); - - arcs.append('svg:path') - .attr('class', pathClassFunc) - .attr('stroke-width', strokeWidth) - .attr('d', arc) - - } else { - var data = options.data, - valueFunc = options.valueFunc, - r = options.outerRadius, - rInner = options.innerRadius, - pathClassFunc = options.pathClassFunc, - pathTitleFunc = options.pathTitleFunc, - totalAggregation = options.totalAggregation, - bubbleLabelClass = options.bubbleLabelClass, - origo = (r+strokeWidth), - w = origo * 2, - h = w, - donut = d3.layout.pie(), - arc = d3.svg.arc().innerRadius(rInner).outerRadius(r); + var data = options.data, + valueFunc = options.valueFunc, + r = options.outerRadius, + rInner = options.innerRadius, + pathClassFunc = options.pathClassFunc, + pathTitleFunc = options.pathTitleFunc, + totalAggregation = options.totalAggregation, + bubbleLabelClass = options.bubbleLabelClass, + origo = (r + strokeWidth), + w = origo * 2, + h = w, + donut = d3.layout.pie(), + arc = d3.svg.arc().innerRadius(rInner).outerRadius(r); - let radius = w; + let radius = w; - let pie = donut - .padAngle(1 / radius) - //.sort(null) - .value(valueFunc); + let pie = donut + .padAngle(1 / radius) + //.sort(null) + .value(valueFunc); - var arc = d3.svg.arc() - .innerRadius(rInner) - .outerRadius(r); + var arc = d3.svg.arc() + .innerRadius(rInner) + .outerRadius(r); - // Create SVG - var svg = document.createElementNS(d3.ns.prefix.svg, 'svg'); - var vis = d3.select(svg) - .attr("width", w) - .attr("height", h) + // Create SVG + var svg = document.createElementNS(d3.ns.prefix.svg, 'svg'); + var vis = d3.select(svg) + .attr("width", w) + .attr("height", h) + + // Create the Arcs + var arcs = vis.selectAll('g.arc') + .data(pie(data)) + .enter().append('svg:g') + .attr('class', 'arc') + .attr('transform', 'translate(' + origo + ',' + origo + ')'); + + arcs.append('svg:path') + .attr('class', pathClassFunc) + .attr('stroke-width', strokeWidth) + .attr('d', arc) + + // Display the text of each Arc + arcs.append('text') + .attr('transform', function(d) { + return 'translate(' + arc.centroid(d) + ')'; + }) + .attr('class', bubbleLabelClass) + .attr('text-anchor', 'middle') + .attr('fill', labelColor) + .attr('dy','.3em') + .text(function(d){ return d.data.values.toFixed(digits); }) + .append('svg:title') + .text(pathTitleFunc); - // Create the Arcs - var arcs = vis.selectAll('g.arc') - .data(pie(data)) - .enter().append('svg:g') - .attr('class', 'arc') - .attr('transform', 'translate(' + origo + ',' + origo + ')'); + // Show Label Background + if (labelBackground && labelBackground == true) { + vis.append('circle') + .attr('r', rInner-5) + .attr('transform', 'translate(' + origo + ',' + origo + ')') + .attr('fill', labelFill) + .attr('stroke', labelStroke) + .attr('stroke-width', strokeWidth) + .attr('opacity', labelOpacity) + } - arcs.append('svg:path') - .attr('class', pathClassFunc) + // Display the total aggregation in the Center + vis.append('text') + .attr('x', origo) + .attr('y', origo) + .attr('class', bubbleLabelClass) + .attr('text-anchor', 'middle') + .attr('fill', labelColor) + .attr('stroke', labelStroke) + .attr('opacity', labelOpacity) .attr('stroke-width', strokeWidth) - .attr('d', arc) - - // Display the text of each Arc - arcs.append('text') - .attr('transform', function(d) { - return 'translate(' + arc.centroid(d) + ')'; - }) - .attr('class', bubbleLabelClass) - .attr('text-anchor', 'middle') - .attr('fill', labelColor) - .attr('dy','.3em') - .text(function(d){ return d.data.values.toFixed(digits); }) - .append('svg:title') - .text(pathTitleFunc); - - // Show Label Background - if (labelBackground && labelBackground == true) { - vis.append('circle') - .attr('r', rInner-5) - .attr('transform', 'translate(' + origo + ',' + origo + ')') - .attr('fill', labelFill) - .attr('stroke', labelStroke) - .attr('stroke-width', strokeWidth) - .attr('opacity', labelOpacity) - } - - // Display the total aggregation in the Center - vis.append('text') - .attr('x', origo) - .attr('y', origo) - .attr('class', bubbleLabelClass) - .attr('text-anchor', 'middle') - .attr('fill', labelColor) - .attr('dy', '.3em') - .text(totalAggregation); - } + .attr('dy', '.3em') + .text(totalAggregation); return serializeXmlNode(svg); } @@ -377,7 +332,6 @@ LeafletWidget.methods.addClusterCharts = function(geojson, layerId, group, type, if (!options.data || !options.valueFunc) { return ''; } - console.log("bakeThePie with these options"); console.log(options) var data = options.data, valueFunc = options.valueFunc, r = options.outerRadius, @@ -416,7 +370,7 @@ LeafletWidget.methods.addClusterCharts = function(geojson, layerId, group, type, .text(pathTitleFunc); // Create Title for Individual Elements and All in Cluster - pathTitleFunc = function(d){ + pathTitleFunc = function(d) { return d.key + ' (' + d.values.length + ')'; } let allTitles = "" @@ -461,6 +415,9 @@ LeafletWidget.methods.addClusterCharts = function(geojson, layerId, group, type, .attr('class', pieLabelClass) .attr('text-anchor', 'middle') .attr('fill', labelColor) + .attr('stroke', labelStroke) + .attr('opacity', labelOpacity) + .attr('stroke-width', strokeWidth) .attr('dy','.3em') .text(pieLabel) .append('svg:title') @@ -474,7 +431,6 @@ LeafletWidget.methods.addClusterCharts = function(geojson, layerId, group, type, if (!options.data) { return ''; } - console.log("bakeTheBarChart with these options"); console.log(options) var data = options.data, barClass = options.barClass, barLabel = options.barLabel ? options.barLabel : d3.sum(data, function(d) { return d.values.length; }), @@ -552,8 +508,11 @@ LeafletWidget.methods.addClusterCharts = function(geojson, layerId, group, type, .attr('y', height + 13) .attr('class', barLabelClass) .attr('text-anchor', 'middle') - .attr('dy', '.3em') .attr('fill', labelColor) + .attr('stroke', labelStroke) + .attr('opacity', labelOpacity) + .attr('stroke-width', strokeWidth) + .attr('dy', '.3em') .text(barLabel) .append('svg:title') .text(allTitles); @@ -565,7 +524,6 @@ LeafletWidget.methods.addClusterCharts = function(geojson, layerId, group, type, if (!options.data) { return ''; } - console.log("bakeTheBarChart with these options"); console.log(options) var data = options.data, barClass = options.barClass, barLabel = options.barLabel ? options.barLabel : d3.sum(data, function(d) { return d.values.length; }), @@ -645,6 +603,9 @@ LeafletWidget.methods.addClusterCharts = function(geojson, layerId, group, type, .attr('text-anchor', 'middle') .attr('dominant-baseline', 'middle') .attr('alignment-baseline', 'middle') + .attr('stroke', labelStroke) + .attr('opacity', labelOpacity) + .attr('stroke-width', strokeWidth) .attr('dy', '.3em') .attr('fill', labelColor) .text(barLabel) diff --git a/man/addClusterCharts.Rd b/man/addClusterCharts.Rd index a4bcb4bc..18c0732f 100644 --- a/man/addClusterCharts.Rd +++ b/man/addClusterCharts.Rd @@ -11,6 +11,8 @@ addClusterCharts( layerId = NULL, group = NULL, type = c("pie", "bar", "horizontal", "custom"), + aggregation = "sum", + valueField = NULL, options = clusterchartOptions(), icon = NULL, html = NULL, @@ -52,6 +54,10 @@ layers (e.g. markers and polygons) can share the same group name.} \item{type}{The type of chart to use for clusters, either \code{c("pie","bar","horizontal","custom")}.} +\item{aggregation}{If `type = "custom"` in the `addClusterCharts` function, this aggregation method will be used.} + +\item{valueField}{If `type = "custom"` in the `addClusterCharts` function, the aggregation will be used on this column.} + \item{options}{Additional options for cluster charts (see \code{\link{clusterchartOptions}}).} \item{icon}{Include an icon or a set of icons with \code{makeIcon} or \code{iconList}} diff --git a/man/clusterchartOptions.Rd b/man/clusterchartOptions.Rd index 446720d5..5a87ac19 100644 --- a/man/clusterchartOptions.Rd +++ b/man/clusterchartOptions.Rd @@ -16,8 +16,6 @@ clusterchartOptions( labelStroke = "black", labelColor = "black", labelOpacity = 0.9, - aggregation = "sum", - valueField = NULL, digits = 2, sortTitlebyCount = TRUE ) @@ -45,10 +43,6 @@ clusterchartOptions( \item{labelOpacity}{The label color. Default is `0.9`} -\item{aggregation}{If `type = "custom"` in the `addClusterCharts` function, this aggregation method will be used.} - -\item{valueField}{If `type = "custom"` in the `addClusterCharts` function, the aggregation will be used on this column.} - \item{digits}{The amount of digits. Default is `2`} \item{sortTitlebyCount}{Should the svg-title be sorted by count or by the categories.}