Skip to content

Commit

Permalink
Merge pull request #437 from LayTec-AG/feature/selected-event
Browse files Browse the repository at this point in the history
Add raw data to relayout event and implement restyle event
  • Loading branch information
sean-mcl committed Jun 17, 2024
2 parents d604c58 + aed0ea8 commit afd099b
Show file tree
Hide file tree
Showing 13 changed files with 342 additions and 46 deletions.
112 changes: 86 additions & 26 deletions Plotly.Blazor.Examples/Components/Relayout.razor
Original file line number Diff line number Diff line change
@@ -1,18 +1,34 @@
@using Plotly.Blazor.Interop
@using Plotly.Blazor.LayoutLib
@using Plotly.Blazor.LayoutLib.YAxisLib
@using Plotly.Blazor.Traces.ScatterLib
@using TypeEnum = Plotly.Blazor.LayoutLib.ShapeLib.TypeEnum
@using System.Text.Json
<PlotlyChart style="height: 60vh; min-height: 350px"
@bind-Config="config" @bind-Layout="layout" @bind-Data="data" @ref="chart"
RelayoutAction="RelayoutAction" AfterRender="Init" />
@bind-Config="config" @bind-Layout="layout" @bind-Data="data" @ref="chart"
RelayoutAction="RelayoutAction" RestyleAction="RestyleAction" AfterRender="Init" />

@if (relayoutData?.XRange?.Count() == 2)
<br />
<MudText Typo="Typo.h4">Latest updated relayout properties: </MudText>

@if (relayoutData?.RawData != null)
{
<MudText>X: @relayoutData.XRange[0], @relayoutData.XRange[1]</MudText>
@foreach (var item in relayoutData.RawData)
{
<MudText>(Key: @(item.Key), Value: @(item.Value.ToString()))</MudText>
}
}

@if (relayoutData?.YRange?.Count() == 2)
<br />
<MudText Typo="Typo.h4">Latest updated restyle properties: </MudText>

@if (restyleData?.Changes != null)
{
<MudText>Y: @relayoutData.YRange[0], @relayoutData.YRange[1]</MudText>
<MudText>Updated Traces: [@(string.Join(", ", restyleData.Indices))]</MudText>
@foreach (var item in restyleData.Changes)
{
<MudText>(Key: @(item.Key), Value: @(item.Value.ToString()))</MudText>
}
}

@code
Expand All @@ -25,46 +41,83 @@
private Layout layout;
private IList<ITrace> data;
private RelayoutEventData relayoutData;
private RestyleEventData restyleData;

/// <inheritdoc />
protected override void OnInitialized()
{
var startDate = DateTime.Now;

config = new Config
{
Responsive = true
};
{
Responsive = true,
Editable = true
};

layout = new Layout
{
Title = new Title
{
Text = "Scatter with Relayout Event"
},
PaperBgColor = Theme.PaletteDark.Surface.ToString(),
PlotBgColor = Theme.PaletteDark.Surface.ToString(),
Font = new Font
{
Color = Theme.PaletteDark.TextPrimary.ToString()
},
YAxis = new List<YAxis>
Title = new Title
{
Text = "Scatter with Relayout Event"
},
PaperBgColor = Theme.PaletteDark.Surface.ToString(),
PlotBgColor = Theme.PaletteDark.Surface.ToString(),
Font = new Font
{
Color = Theme.PaletteDark.TextPrimary.ToString()
},
Shapes = new List<Shape>()
{
new()
{
Title = new LayoutLib.YAxisLib.Title { Text = "Scatter Unit" }
Type = TypeEnum.Rect,
X0 = 20,
X1 = 40,
Y0 = 0,
Y1 = 1,
XRef = "x",
YRef = "paper",
Line = new()
{
Width = 0
},
FillColor = "rgba(84,166,143,1)",
Opacity = 0.3m
},
new()
{
Type = TypeEnum.Rect,
X0 = 60,
X1 = 80,
Y0 = 0,
Y1 = 1,
XRef = "x",
YRef = "paper",
Line = new()
{
Width = 0
},
FillColor = "rgba(84,166,143,1)",
Opacity = 0.3m
}
}
};
};

data = new List<ITrace>
{
new Scatter
{
Name = "ScatterTrace",
Name = "Sin",
Mode = ModeFlag.Lines | ModeFlag.Markers,
X = Enumerable.Range(0, 100).Select(i => startDate + TimeSpan.FromHours(i)).Cast<object>().ToList(),
X = Enumerable.Range(0, 100).Cast<object>().ToList(),
Y = Helper.GenerateData(0, 100).Y
},
new Scatter
{
Name = "Cos",
Mode = ModeFlag.Lines | ModeFlag.Markers,
X = Enumerable.Range(0, 100).Cast<object>().ToList(),
Y = Helper.GenerateData(0, 100, GenerateMethod.Cos).Y,
}
};

Expand All @@ -74,11 +127,18 @@
private async void Init()
{
await chart.SubscribeRelayoutEvent();
await chart.SubscribeRestyleEvent();
}

public void RelayoutAction(RelayoutEventData eventData)
{
relayoutData = eventData;
StateHasChanged();
}

public void RelayoutAction(RelayoutEventData data)
public void RestyleAction(RestyleEventData eventData)
{
relayoutData = data;
restyleData = eventData;
StateHasChanged();
}
}
2 changes: 1 addition & 1 deletion Plotly.Blazor.Examples/Shared/NavMenu.razor.cs
Original file line number Diff line number Diff line change
Expand Up @@ -56,7 +56,7 @@ private class PageInfo
new() { Page = "hover", Title = "Hover Event" },
new() { Page = "click", Title = "Click Event" },
new() { Page = "legendclick", Title = "Legend Click Event" },
new() { Page = "relayout", Title = "Relayout Event" },
new() { Page = "relayout", Title = "Relayout & Restyle Event" },
new() { Page = "selected", Title = "Selected Event" }
};

Expand Down
13 changes: 10 additions & 3 deletions Plotly.Blazor.Generator/src/Interop/RelayoutEventData.cs
Original file line number Diff line number Diff line change
@@ -1,6 +1,8 @@
namespace Plotly.Blazor.Interop
{
using System.Collections.Generic;
using System.Text.Json;

namespace Plotly.Blazor.Interop
{
/// <summary>
/// This class is used to parse the event data from the relayout jsinterop action.
/// </summary>
Expand Down Expand Up @@ -29,5 +31,10 @@ public class RelayoutEventData
/// In some cases this may be not be set.
/// </remarks>
public object[] ZRange { get; set; }

/// <summary>
/// Returns a dictionary of all updated properties including their new value.
/// </summary>
public IDictionary<string, JsonElement> RawData { get; set; }
}
}
}
21 changes: 21 additions & 0 deletions Plotly.Blazor.Generator/src/Interop/RestyleEventData.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
using System.Collections.Generic;
using System.Text.Json;

namespace Plotly.Blazor.Interop
{
/// <summary>
/// This class is used to parse the event data from the restyle action.
/// </summary>
public class RestyleEventData
{
/// <summary>
/// Returns a dictionary of all updated properties including their new value.
/// </summary>
public IDictionary<string, JsonElement> Changes { get; set; }

/// <summary>
/// The updated trace indices with the given <see cref="Changes"/>.
/// </summary>
public int[] Indices { get; set; }
}
}
53 changes: 53 additions & 0 deletions Plotly.Blazor.Generator/src/PlotlyChart.razor.cs
Original file line number Diff line number Diff line change
Expand Up @@ -947,12 +947,25 @@ public async Task PrependTraces3D(IEnumerable<IEnumerable<object>> x, IEnumerabl
[Parameter]
public Action<IEnumerable<EventDataPoint>> HoverAction { get; set; }

/// <summary>
/// Defines the action that should happen when the SelectedEvent is triggered.
/// Objects are currently required for accommodating different plot value types
/// </summary>
[Parameter]
public Action<IEnumerable<EventDataPoint>> SelectedAction { get; set; }

/// <summary>
/// Defines the action that should happen when the RelayoutEvent is triggered.
/// </summary>
[Parameter]
public Action<RelayoutEventData> RelayoutAction { get; set; }

/// <summary>
/// Defines the action that should happen when the RestyleEvent is triggered.
/// </summary>
[Parameter]
public Action<RestyleEventData> RestyleAction { get; set; }

/// <summary>
/// Method which is called by JSRuntime once a plot has been clicked, to invoke the passed in ClickAction.
/// Objects are currently required for accommodating different plot value types.
Expand Down Expand Up @@ -986,6 +999,17 @@ public void HoverEvent(IEnumerable<EventDataPoint> eventData)
HoverAction?.Invoke(eventData);
}

/// <summary>
/// Method which is called by JSRuntime once a you selected plot points, to invoke the passed in SelectedAction.
/// Objects are currently required for accommodating different plot value types.
/// </summary>
/// <param name = "eventData"></param>
[JSInvokable("SelectedEvent")]
public void SelectedEvent(IEnumerable<EventDataPoint> eventData)
{
SelectedAction?.Invoke(eventData);
}

/// <summary>
/// Method which is called by JSRuntime when the chart's layout has changed.
/// </summary>
Expand All @@ -995,6 +1019,15 @@ public void RelayoutEvent(RelayoutEventData obj)
RelayoutAction?.Invoke(obj);
}

/// <summary>
/// Method which is called by JSRuntime when the chart's layout has changed.
/// </summary>
[JSInvokable("RestyleEvent")]
public void RestyleEvent(RestyleEventData obj)
{
RestyleAction?.Invoke(obj);
}

/// <summary>
/// Subscribes to the legend click event of the chart.
/// </summary>
Expand Down Expand Up @@ -1025,6 +1058,16 @@ public async Task SubscribeHoverEvent(CancellationToken cancellationToken = defa
await Interop.SubscribeHoverEvent(cancellationToken);
}

/// <summary>
/// Subscribes to the selected event of the chart.
/// </summary>
/// <param name = "cancellationToken">CancellationToken</param>
/// <returns>Task</returns>
public async Task SubscribeSelectedEvent(CancellationToken cancellationToken = default)
{
await Interop.SubscribeSelectedEvent(cancellationToken);
}

/// <summary>
/// Subscribes to the relayout event of the chart.
/// </summary>
Expand All @@ -1035,6 +1078,16 @@ public async Task SubscribeRelayoutEvent(CancellationToken cancellationToken = d
await Interop.SubscribeRelayoutEvent(cancellationToken);
}

/// <summary>
/// Subscribes to the restyle event of the chart.
/// </summary>
/// <param name = "cancellationToken">CancellationToken</param>
/// <returns>Task</returns>
public async Task SubscribeRestyleEvent(CancellationToken cancellationToken = default)
{
await Interop.SubscribeRestyleEvent(cancellationToken);
}

/// <summary>
/// Clears the traces from the current chart.
/// </summary>
Expand Down
22 changes: 22 additions & 0 deletions Plotly.Blazor.Generator/src/PlotlyJsInterop.cs
Original file line number Diff line number Diff line change
Expand Up @@ -298,6 +298,17 @@ public async Task SubscribeHoverEvent(CancellationToken cancellationToken)
await jsRuntime.InvokeVoidAsync("subscribeHoverEvent", cancellationToken, dotNetObj, dotNetObj.Value.Id);
}

/// <summary>
/// Can be used to subscribe selected events for points.
/// </summary>
/// <param name="cancellationToken">CancellationToken</param>
public async Task SubscribeSelectedEvent(CancellationToken cancellationToken)
{
var jsRuntime = await moduleTask.Value;

await jsRuntime.InvokeVoidAsync("subscribeSelectedEvent", cancellationToken, dotNetObj, dotNetObj.Value.Id);
}

/// <summary>
/// Can be used to subscribe to relayout events.
/// </summary>
Expand All @@ -309,6 +320,17 @@ public async Task SubscribeRelayoutEvent(CancellationToken cancellationToken)
await jsRuntime.InvokeVoidAsync("subscribeRelayoutEvent", cancellationToken, dotNetObj, dotNetObj.Value.Id);
}

/// <summary>
/// Can be used to subscribe to restyle events.
/// </summary>
/// <param name="cancellationToken"></param>
public async Task SubscribeRestyleEvent(CancellationToken cancellationToken)
{
var jsRuntime = await moduleTask.Value;

await jsRuntime.InvokeVoidAsync("subscribeRestyleEvent", cancellationToken, dotNetObj, dotNetObj.Value.Id);
}

/// <summary>
/// Can be used to export the chart as a static image and returns a binary string of the exported image.
/// </summary>
Expand Down
27 changes: 20 additions & 7 deletions Plotly.Blazor.Generator/src/wwwroot/plotly-interop-5.1.0.js
Original file line number Diff line number Diff line change
Expand Up @@ -249,16 +249,16 @@ export function subscribeHoverEvent(dotNetObj, id) {
}
export function subscribeRelayoutEvent(dotNetObj, id) {
var plot = document.getElementById(id);
plot.on('plotly_relayout', function (data) {
plot.on('plotly_relayout', function (eventdata) {

var x1 = data["xaxis.range[0]"];
var x2 = data["xaxis.range[1]"];
var x1 = eventdata["xaxis.range[0]"];
var x2 = eventdata["xaxis.range[1]"];

var y1 = data["yaxis.range[0]"]
var y2 = data["yaxis.range[1]"]
var y1 = eventdata["yaxis.range[0]"];
var y2 = eventdata["yaxis.range[1]"];

var z1 = data["zaxis.range[0]"]
var z2 = data["zaxis.range[1]"]
var z1 = eventdata["zaxis.range[0]"];
var z2 = eventdata["zaxis.range[1]"];

var result = {};

Expand All @@ -274,6 +274,19 @@ export function subscribeRelayoutEvent(dotNetObj, id) {
result.ZRange = [z1, z2];
}

result.RawData = eventdata;

dotNetObj.invokeMethodAsync('RelayoutEvent', result);
});
}

export function subscribeRestyleEvent(dotNetObj, id) {
var plot = document.getElementById(id);
plot.on('plotly_restyle', function (eventdata) {
var result = {};
result.Changes = eventdata[0];
result.Indices = eventdata[1];

dotNetObj.invokeMethodAsync('RestyleEvent', result);
});
}
Loading

0 comments on commit afd099b

Please sign in to comment.