diff --git a/CHANGELOG.md b/CHANGELOG.md index 0f64dff2..b64f3c39 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -11,6 +11,7 @@ The format is based on [Keep a Changelog](http://keepachangelog.com/en/1.0.0/) a - [[#410](https://github.com/plotly/plotly.rs/pull/410)] Add `Choropleth` (geo subplot) and `ChoroplethMap` (MapLibre `map` subplot) trace types, with a `LocationMode` enum and a dedicated `choropleth::Marker`; add the MapLibre `map` subplot via `LayoutMap`/`MapStyle`/`MapBounds` - [[#410](https://github.com/plotly/plotly.rs/pull/410)] Add `LayoutGeo` options: `fitbounds` (`GeoFitBounds`), `resolution` (`GeoResolution`, 1:110M/1:50M base-layer detail), and `bgcolor` - [[#412](https://github.com/plotly/plotly.rs/pull/412)] Add `Violin` trace type with box, mean line, KDE span, and split/grouped support +- [[#414](https://github.com/plotly/plotly.rs/issues/414)] Add `DensityMap` (MapLibre `map` subplot) trace type — density heatmaps with full color-scale and hover support ### Changed diff --git a/plotly/src/common/mod.rs b/plotly/src/common/mod.rs index 962ed1e4..d5925399 100644 --- a/plotly/src/common/mod.rs +++ b/plotly/src/common/mod.rs @@ -230,6 +230,7 @@ pub enum PlotType { Sankey, Surface, DensityMapbox, + DensityMap, Table, Pie, Treemap, diff --git a/plotly/src/lib.rs b/plotly/src/lib.rs index 149d22db..057e197e 100644 --- a/plotly/src/lib.rs +++ b/plotly/src/lib.rs @@ -60,14 +60,14 @@ pub use layout::Layout; pub use plot::{Plot, Trace, Traces}; // Also provide easy access to modules which contain additional trace-specific types pub use traces::{ - box_plot, choropleth, choropleth_map, contour, heat_map, histogram, image, mesh3d, sankey, - scatter, scatter3d, scatter_mapbox, sunburst, surface, treemap, violin, + box_plot, choropleth, choropleth_map, contour, density_map, heat_map, histogram, image, mesh3d, + sankey, scatter, scatter3d, scatter_mapbox, sunburst, surface, treemap, violin, }; // Bring the different trace types into the top-level scope pub use traces::{ - Bar, BoxPlot, Candlestick, Choropleth, ChoroplethMap, Contour, DensityMapbox, HeatMap, - Histogram, Image, Mesh3D, Ohlc, Pie, Sankey, Scatter, Scatter3D, ScatterGeo, ScatterMapbox, - ScatterPolar, Sunburst, Surface, Table, Treemap, Violin, + Bar, BoxPlot, Candlestick, Choropleth, ChoroplethMap, Contour, DensityMap, DensityMapbox, + HeatMap, Histogram, Image, Mesh3D, Ohlc, Pie, Sankey, Scatter, Scatter3D, ScatterGeo, + ScatterMapbox, ScatterPolar, Sunburst, Surface, Table, Treemap, Violin, }; pub trait Restyle: serde::Serialize {} diff --git a/plotly/src/traces/density_map.rs b/plotly/src/traces/density_map.rs new file mode 100644 index 00000000..5cc32ae9 --- /dev/null +++ b/plotly/src/traces/density_map.rs @@ -0,0 +1,207 @@ +//! Density heatmap trace for the MapLibre `map` subplot. + +use plotly_derive::FieldSetter; +use serde::Serialize; + +use crate::common::{ + ColorBar, ColorScale, Dim, HoverInfo, Label, LegendGroupTitle, PlotType, Visible, +}; +use crate::private::{NumOrString, NumOrStringCollection}; +use crate::Trace; + +/// Construct a density heatmap trace drawn on the MapLibre `map` subplot +/// (configured via [`LayoutMap`](crate::layout::LayoutMap)). +/// +/// `DensityMap` is the modern MapLibre-based counterpart to +/// [`DensityMapbox`](crate::DensityMapbox): it draws a weighted kernel-density +/// heatmap from `lat`/`lon` points (with an optional per-point weight `z`) onto +/// the `layout.map` subplot. +/// +/// # Examples +/// +/// ``` +/// use plotly::DensityMap; +/// +/// let trace = DensityMap::new(vec![45.5017], vec![-73.5673], vec![1.0]) +/// .radius(20) +/// .name("montreal"); +/// ``` +#[serde_with::skip_serializing_none] +#[derive(Serialize, Clone, Debug, FieldSetter)] +#[field_setter(box_self, kind = "trace")] +pub struct DensityMap +where + Lat: Serialize + Clone, + Lon: Serialize + Clone, + Z: Serialize + Clone, +{ + #[field_setter(default = "PlotType::DensityMap")] + r#type: PlotType, + /// Sets the trace name. The trace name appears as the legend item and on + /// hover. + name: Option, + /// Determines whether or not this trace is visible. + visible: Option, + /// Determines whether or not an item corresponding to this trace is shown + /// in the legend. + #[serde(rename = "showlegend")] + show_legend: Option, + /// Sets the legend rank for this trace. + #[serde(rename = "legendrank")] + legend_rank: Option, + /// Sets the legend group for this trace. + #[serde(rename = "legendgroup")] + legend_group: Option, + /// Set and style the title to appear for the legend group. + #[serde(rename = "legendgrouptitle")] + legend_group_title: Option, + /// Assigns id labels to each datum. + ids: Option>, + + /// Sets the latitude coordinates (in degrees North). + lat: Option>, + /// Sets the longitude coordinates (in degrees East). + lon: Option>, + /// Sets the points' weight. For example, a value of 10 would be equivalent + /// to having 10 points of weight 1 in the same spot. + z: Option>, + /// Sets the radius of influence of one `lat`/`lon` point in pixels. + /// Increasing the value makes the density map smoother, but less detailed. + radius: Option, + /// Sets the opacity of the trace. + opacity: Option, + + /// Sets the text elements associated with each (lat,lon,z) triplet. + text: Option>, + /// Sets the hover text elements associated with each (lat,lon,z) triplet. + #[serde(rename = "hovertext")] + hover_text: Option>, + /// Determines which trace information appears on hover. + #[serde(rename = "hoverinfo")] + hover_info: Option, + /// Template string used for rendering the information that appears on the + /// hover box. + #[serde(rename = "hovertemplate")] + hover_template: Option>, + #[serde(rename = "hovertemplatefallback")] + hover_template_fallback: Option>, + /// Properties of the hover label. + #[serde(rename = "hoverlabel")] + hover_label: Option