mirror of
https://github.com/radzenhq/radzen-blazor.git
synced 2026-02-03 21:29:20 +00:00
Render chart tooltips in the same way as standard tooltips (#1745)
* Render chart tooltips in the same way as standard tooltips * Move OpenChartTooltip method to TooltipService to avoid code duplications * Avoid partially hiding of chart tooltip near top of page * Make some of the types internal. --------- Co-authored-by: Atanas Korchev <akorchev@gmail.com>
This commit is contained in:
@@ -3,6 +3,7 @@ using System.Linq;
|
||||
using System.Threading;
|
||||
using System.Threading.Tasks;
|
||||
using Bunit;
|
||||
using Microsoft.Extensions.DependencyInjection;
|
||||
using Radzen.Blazor.Rendering;
|
||||
using Xunit;
|
||||
using Xunit.Abstractions;
|
||||
@@ -23,6 +24,9 @@ public class ChartTests
|
||||
using var ctx = new TestContext();
|
||||
ctx.JSInterop.Mode = JSRuntimeMode.Loose;
|
||||
ctx.JSInterop.Setup<Rect>("Radzen.createChart", _ => true).SetResult(new Rect {Left = 0, Top = 0, Width = 200, Height = 200});
|
||||
ctx.Services.AddScoped<TooltipService>();
|
||||
ctx.JSInterop.SetupVoid("Radzen.openChartTooltip", _ => true);
|
||||
ctx.RenderComponent<RadzenChartTooltip>();
|
||||
|
||||
var seriesData = Enumerable.Range(0, 5000).Select(i => new Point { X = i, Y = i });
|
||||
var chart = ctx.RenderComponent<RadzenChart>(chartParameters =>
|
||||
@@ -42,12 +46,12 @@ public class ChartTests
|
||||
})));
|
||||
|
||||
var stopwatch = Stopwatch.StartNew();
|
||||
foreach (var _ in Enumerable.Range(0, 10))
|
||||
foreach (var invocation in Enumerable.Range(0, 10))
|
||||
{
|
||||
await chart.InvokeAsync(() => chart.Instance.MouseMove(100, 80));
|
||||
Assert.Contains("<div class=\"rz-chart-tooltip", chart.Markup);
|
||||
Assert.Equal((invocation + 1) * 2, ctx.JSInterop.Invocations.Count(x => x.Identifier == "Radzen.openChartTooltip"));
|
||||
await chart.InvokeAsync(() => chart.Instance.MouseMove(0, 0));
|
||||
Assert.DoesNotContain("<div class=\"rz-chart-tooltip", chart.Markup);
|
||||
Assert.Equal(invocation + 1, ctx.JSInterop.Invocations.Count(x => x.Identifier == "Radzen.closeTooltip"));
|
||||
}
|
||||
output.WriteLine($"Time took: {stopwatch.Elapsed}");
|
||||
}
|
||||
|
||||
@@ -478,38 +478,30 @@ namespace Radzen.Blazor
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
public virtual RenderFragment RenderTooltip(object data, double marginLeft, double marginTop, double chartHeight)
|
||||
public virtual RenderFragment RenderTooltip(object data)
|
||||
{
|
||||
var item = (TItem)data;
|
||||
|
||||
var x = TooltipX(item);
|
||||
var y = TooltipY(item);
|
||||
|
||||
|
||||
return builder =>
|
||||
{
|
||||
|
||||
if (Chart.Tooltip.Shared)
|
||||
{
|
||||
var category = PropertyAccess.GetValue(item, CategoryProperty);
|
||||
builder.OpenComponent<ChartSharedTooltip>(0);
|
||||
builder.AddAttribute(1, nameof(ChartSharedTooltip.X), x + marginLeft);
|
||||
builder.AddAttribute(2, nameof(ChartSharedTooltip.Y), y + marginTop);
|
||||
builder.AddAttribute(3, nameof(ChartSharedTooltip.Class), TooltipClass(item));
|
||||
builder.AddAttribute(4, nameof(ChartSharedTooltip.Title), TooltipTitle(item));
|
||||
builder.AddAttribute(4, nameof(ChartSharedTooltip.ChildContent), RenderSharedTooltipItems(category));
|
||||
builder.AddAttribute(1, nameof(ChartSharedTooltip.Class), TooltipClass(item));
|
||||
builder.AddAttribute(2, nameof(ChartSharedTooltip.Title), TooltipTitle(item));
|
||||
builder.AddAttribute(3, nameof(ChartSharedTooltip.ChildContent), RenderSharedTooltipItems(category));
|
||||
builder.CloseComponent();
|
||||
}
|
||||
else
|
||||
{
|
||||
builder.OpenComponent<ChartTooltip>(0);
|
||||
builder.AddAttribute(1, nameof(ChartTooltip.X), x + marginLeft);
|
||||
builder.AddAttribute(2, nameof(ChartTooltip.Y), y + marginTop);
|
||||
builder.AddAttribute(3, nameof(ChartTooltip.ChildContent), TooltipTemplate?.Invoke(item));
|
||||
builder.AddAttribute(4, nameof(ChartTooltip.Title), TooltipTitle(item));
|
||||
builder.AddAttribute(5, nameof(ChartTooltip.Label), TooltipLabel(item));
|
||||
builder.AddAttribute(6, nameof(ChartTooltip.Value), TooltipValue(item));
|
||||
builder.AddAttribute(7, nameof(ChartTooltip.Class), TooltipClass(item));
|
||||
builder.AddAttribute(8, nameof(ChartTooltip.Style), TooltipStyle(item));
|
||||
builder.AddAttribute(1, nameof(ChartTooltip.ChildContent), TooltipTemplate?.Invoke(item));
|
||||
builder.AddAttribute(2, nameof(ChartTooltip.Title), TooltipTitle(item));
|
||||
builder.AddAttribute(3, nameof(ChartTooltip.Label), TooltipLabel(item));
|
||||
builder.AddAttribute(4, nameof(ChartTooltip.Value), TooltipValue(item));
|
||||
builder.AddAttribute(5, nameof(ChartTooltip.Class), TooltipClass(item));
|
||||
builder.AddAttribute(6, nameof(ChartTooltip.Style), TooltipStyle(item));
|
||||
builder.CloseComponent();
|
||||
}
|
||||
};
|
||||
@@ -546,6 +538,16 @@ namespace Radzen.Blazor
|
||||
};
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
public Point GetTooltipPosition(object data)
|
||||
{
|
||||
var item = (TItem)data;
|
||||
var x = TooltipX(item);
|
||||
var y = TooltipY(item);
|
||||
|
||||
return new Point { X = x, Y = y };
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets the tooltip inline style.
|
||||
/// </summary>
|
||||
|
||||
@@ -50,20 +50,24 @@ namespace Radzen.Blazor
|
||||
/// <param name="valueScale">The value scale.</param>
|
||||
/// <returns>RenderFragment.</returns>
|
||||
RenderFragment RenderOverlays(ScaleBase categoryScale, ScaleBase valueScale);
|
||||
|
||||
/// <summary>
|
||||
/// Renders the series tooltip.
|
||||
/// </summary>
|
||||
/// <param name="data">The data.</param>
|
||||
/// <param name="marginLeft">The left margin.</param>
|
||||
/// <param name="marginTop">The right margin.</param>
|
||||
/// <param name="chartHeight">Height of the whole char area.</param>
|
||||
/// <returns>RenderFragment.</returns>
|
||||
RenderFragment RenderTooltip(object data, double marginLeft, double marginTop, double chartHeight);
|
||||
RenderFragment RenderTooltip(object data);
|
||||
/// <summary>
|
||||
/// Renders a tooltip item with the specified data to be displayed in a shared tooltip
|
||||
/// </summary>
|
||||
RenderFragment RenderSharedTooltipItem(object category);
|
||||
/// <summary>
|
||||
/// Get position of the series tooltip.
|
||||
/// </summary>
|
||||
/// <param name="data">The data.</param>
|
||||
/// <returns>Position.</returns>
|
||||
Point GetTooltipPosition(object data);
|
||||
/// <summary>
|
||||
/// Renders the legend item.
|
||||
/// </summary>
|
||||
/// <returns>RenderFragment.</returns>
|
||||
|
||||
@@ -28,6 +28,12 @@ namespace Radzen.Blazor
|
||||
/// <summary>
|
||||
/// Renders tooltip
|
||||
/// </summary>
|
||||
RenderFragment RenderTooltip(double mouseX, double mouseY, double marginLeft, double marginTop);
|
||||
RenderFragment RenderTooltip(double mouseX, double mouseY);
|
||||
|
||||
/// <summary>
|
||||
/// Get position of the overlay tooltip.
|
||||
/// </summary>
|
||||
/// <returns>Position.</returns>
|
||||
Point GetTooltipPosition(double mouseX, double mouseY);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -38,12 +38,6 @@
|
||||
@donut.RenderTitle(MarginLeft, MarginTop)
|
||||
}
|
||||
}
|
||||
<ChartTooltipContainer @ref="@chartTooltipContainer">
|
||||
@if (tooltip != null)
|
||||
{
|
||||
@tooltip
|
||||
}
|
||||
</ChartTooltipContainer>
|
||||
|
||||
</CascadingValue>
|
||||
}
|
||||
|
||||
@@ -52,6 +52,9 @@ namespace Radzen.Blazor
|
||||
/// </summary>
|
||||
[Parameter]
|
||||
public EventCallback<LegendClickEventArgs> LegendClick { get; set; }
|
||||
|
||||
[Inject]
|
||||
TooltipService TooltipService { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets the runtime width of the chart.
|
||||
@@ -276,7 +279,6 @@ namespace Radzen.Blazor
|
||||
}
|
||||
}
|
||||
|
||||
ChartTooltipContainer chartTooltipContainer;
|
||||
RenderFragment tooltip;
|
||||
object tooltipData;
|
||||
double mouseX;
|
||||
@@ -367,11 +369,15 @@ namespace Radzen.Blazor
|
||||
{
|
||||
foreach (var overlay in series.Overlays.Reverse())
|
||||
{
|
||||
if (overlay.Visible && overlay.Contains(mouseX - MarginLeft, mouseY - MarginTop, TooltipTolerance))
|
||||
if (overlay.Visible && overlay.Contains(queryX, queryY, TooltipTolerance))
|
||||
{
|
||||
tooltipData = null;
|
||||
tooltip = overlay.RenderTooltip(mouseX, mouseY, MarginLeft, MarginTop);
|
||||
chartTooltipContainer.Refresh();
|
||||
tooltip = overlay.RenderTooltip(queryX, queryY);
|
||||
var tooltipPosition = overlay.GetTooltipPosition(queryX, queryY);
|
||||
TooltipService.OpenChartTooltip(Element, tooltipPosition.X + MarginLeft, tooltipPosition.Y + MarginTop, _ => tooltip, new ChartTooltipOptions
|
||||
{
|
||||
ColorScheme = ColorScheme
|
||||
});
|
||||
await Task.Yield();
|
||||
|
||||
return;
|
||||
@@ -399,21 +405,25 @@ namespace Radzen.Blazor
|
||||
if (closestSeriesData != tooltipData)
|
||||
{
|
||||
tooltipData = closestSeriesData;
|
||||
tooltip = closestSeries.RenderTooltip(closestSeriesData, MarginLeft, MarginTop, Height ?? 0);
|
||||
chartTooltipContainer.Refresh();
|
||||
tooltip = closestSeries.RenderTooltip(closestSeriesData);
|
||||
var tooltipPosition = closestSeries.GetTooltipPosition(closestSeriesData);
|
||||
TooltipService.OpenChartTooltip(Element, tooltipPosition.X + MarginLeft, tooltipPosition.Y + MarginTop, _ => tooltip, new ChartTooltipOptions
|
||||
{
|
||||
ColorScheme = ColorScheme
|
||||
});
|
||||
await Task.Yield();
|
||||
}
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
if (tooltip != null)
|
||||
{
|
||||
tooltipData = null;
|
||||
tooltip = null;
|
||||
if (tooltip != null)
|
||||
{
|
||||
tooltipData = null;
|
||||
tooltip = null;
|
||||
|
||||
chartTooltipContainer.Refresh();
|
||||
await Task.Yield();
|
||||
}
|
||||
TooltipService.Close();
|
||||
await Task.Yield();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
184
Radzen.Blazor/RadzenChartTooltip.razor
Normal file
184
Radzen.Blazor/RadzenChartTooltip.razor
Normal file
@@ -0,0 +1,184 @@
|
||||
@implements IAsyncDisposable
|
||||
@using Microsoft.JSInterop
|
||||
@inject IJSRuntime JSRuntime
|
||||
|
||||
@foreach (var tooltip in tooltips)
|
||||
{
|
||||
<div id="@UniqueID"
|
||||
style="display: none; top: 0; left: 0; z-index: 1001; position: absolute;"
|
||||
class="@($"rz-scheme-{tooltip.Options.ColorScheme.ToString().ToLowerInvariant()}")">
|
||||
@tooltip.Options.ChildContent(Service)
|
||||
</div>
|
||||
}
|
||||
|
||||
@code {
|
||||
public string UniqueID { get; set; }
|
||||
|
||||
[Inject] private TooltipService Service { get; set; }
|
||||
|
||||
List<ChartTooltip> tooltips = new List<ChartTooltip>();
|
||||
|
||||
async Task Open(ElementReference chart, double x, double y, ChartTooltipOptions options)
|
||||
{
|
||||
tooltips.Clear();
|
||||
tooltips.Add(new ChartTooltip { Options = options, Chart = chart, X = x, Y = y });
|
||||
|
||||
await InvokeAsync(StateHasChanged);
|
||||
|
||||
var tooltip = tooltips.LastOrDefault();
|
||||
|
||||
if (tooltip != null)
|
||||
{
|
||||
await JSRuntime.InvokeVoidAsync("Radzen.openChartTooltip",
|
||||
tooltip.Chart,
|
||||
x,
|
||||
y,
|
||||
UniqueID);
|
||||
}
|
||||
}
|
||||
|
||||
bool IsJSRuntimeAvailable { get; set; }
|
||||
|
||||
protected override async Task OnAfterRenderAsync(bool firstRender)
|
||||
{
|
||||
IsJSRuntimeAvailable = true;
|
||||
|
||||
var tooltip = tooltips.LastOrDefault();
|
||||
|
||||
if (tooltip != null)
|
||||
{
|
||||
await JSRuntime.InvokeVoidAsync("Radzen.openChartTooltip",
|
||||
tooltip.Chart,
|
||||
tooltip.X,
|
||||
tooltip.Y,
|
||||
UniqueID,
|
||||
Reference,
|
||||
"RadzenChartTooltip.CloseTooltip");
|
||||
}
|
||||
}
|
||||
|
||||
private DotNetObjectReference<RadzenChartTooltip> reference;
|
||||
|
||||
/// <summary>
|
||||
/// Gets the reference for the current component.
|
||||
/// </summary>
|
||||
/// <value>The reference.</value>
|
||||
protected DotNetObjectReference<RadzenChartTooltip> Reference
|
||||
{
|
||||
get
|
||||
{
|
||||
if (reference == null)
|
||||
{
|
||||
reference = DotNetObjectReference.Create(this);
|
||||
}
|
||||
|
||||
return reference;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Closes this instance.
|
||||
/// </summary>
|
||||
[JSInvokable("RadzenChartTooltip.CloseTooltip")]
|
||||
public void CloseTooltip()
|
||||
{
|
||||
Service.Close();
|
||||
}
|
||||
|
||||
public async Task Close()
|
||||
{
|
||||
var lastTooltip = tooltips.LastOrDefault();
|
||||
if (lastTooltip != null)
|
||||
{
|
||||
if (IsJSRuntimeAvailable)
|
||||
{
|
||||
try
|
||||
{
|
||||
tooltips.Remove(lastTooltip);
|
||||
await JSRuntime.InvokeVoidAsync("Radzen.closeTooltip", UniqueID);
|
||||
}
|
||||
catch
|
||||
{
|
||||
// ignored
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
await InvokeAsync(StateHasChanged);
|
||||
}
|
||||
|
||||
public async ValueTask DisposeAsync()
|
||||
{
|
||||
while (tooltips.Count != 0)
|
||||
{
|
||||
await Close();
|
||||
}
|
||||
reference?.Dispose();
|
||||
reference = null;
|
||||
|
||||
if (IsJSRuntimeAvailable)
|
||||
{
|
||||
try
|
||||
{
|
||||
await JSRuntime.InvokeVoidAsync("Radzen.destroyPopup", UniqueID);
|
||||
}
|
||||
catch
|
||||
{
|
||||
// ignored
|
||||
}
|
||||
}
|
||||
|
||||
Service.OnOpenChartTooltip -= OnOpen;
|
||||
Service.OnClose -= OnClose;
|
||||
Service.OnNavigate -= OnNavigate;
|
||||
}
|
||||
|
||||
protected override void OnInitialized()
|
||||
{
|
||||
UniqueID = Convert.ToBase64String(Guid.NewGuid().ToByteArray()).Replace("/", "-").Replace("+", "-").Substring(0, 10);
|
||||
|
||||
Service.OnOpenChartTooltip += OnOpen;
|
||||
Service.OnClose += OnClose;
|
||||
Service.OnNavigate += OnNavigate;
|
||||
}
|
||||
|
||||
void OnOpen(ElementReference element, double x, double y, ChartTooltipOptions options)
|
||||
{
|
||||
Open(element, x, y, options).ConfigureAwait(false);
|
||||
}
|
||||
|
||||
void OnClose()
|
||||
{
|
||||
Close().ConfigureAwait(false);
|
||||
}
|
||||
|
||||
void OnNavigate()
|
||||
{
|
||||
JSRuntime.InvokeVoidAsync("Radzen.closePopup", UniqueID);
|
||||
}
|
||||
|
||||
private sealed class ChartTooltip
|
||||
{
|
||||
/// <summary>
|
||||
/// Gets or sets the owning chart.
|
||||
/// </summary>
|
||||
/// <value>The chart.</value>
|
||||
public ElementReference Chart { get; set; }
|
||||
/// <summary>
|
||||
/// Gets or sets the horizontal position of the tooltip.
|
||||
/// </summary>
|
||||
/// <value>The position.</value>
|
||||
public double X { get; set; }
|
||||
/// <summary>
|
||||
/// Gets or sets the vertical position of the tooltip.
|
||||
/// </summary>
|
||||
/// <value>The position.</value>
|
||||
public double Y { get; set; }
|
||||
/// <summary>
|
||||
/// Gets or sets the options.
|
||||
/// </summary>
|
||||
/// <value>The options.</value>
|
||||
public ChartTooltipOptions Options { get; set; }
|
||||
}
|
||||
}
|
||||
@@ -2,6 +2,7 @@
|
||||
<RadzenNotification @attributes="Attributes" />
|
||||
<RadzenContextMenu @attributes="Attributes" />
|
||||
<RadzenTooltip @attributes="Attributes" />
|
||||
<RadzenChartTooltip @attributes="Attributes" />
|
||||
|
||||
@code {
|
||||
/// <summary>
|
||||
|
||||
@@ -152,11 +152,17 @@ namespace Radzen.Blazor
|
||||
}
|
||||
|
||||
/// <inheritdoc/>
|
||||
public RenderFragment RenderTooltip(double mouseX, double mouseY, double marginLeft, double marginTop)
|
||||
public RenderFragment RenderTooltip(double mouseX, double mouseY)
|
||||
{
|
||||
return null;
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
public Point GetTooltipPosition(double mouseX, double mouseY)
|
||||
{
|
||||
return new Point { X = mouseX, Y = mouseY };
|
||||
}
|
||||
|
||||
/// <inheritdoc/>
|
||||
public void Dispose() => series?.Overlays.Remove(this);
|
||||
}
|
||||
|
||||
@@ -54,10 +54,16 @@
|
||||
return false;
|
||||
}
|
||||
|
||||
public RenderFragment RenderTooltip(double mouseX, double mouseY, double marginLeft, double marginTop)
|
||||
public RenderFragment RenderTooltip(double mouseX, double mouseY)
|
||||
{
|
||||
return null;
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
public Point GetTooltipPosition(double mouseX, double mouseY)
|
||||
{
|
||||
return new Point { X = mouseX, Y = mouseY };
|
||||
}
|
||||
|
||||
public void Dispose() => series?.Overlays.Remove(this);
|
||||
}
|
||||
@@ -73,10 +73,16 @@
|
||||
return false;
|
||||
}
|
||||
|
||||
public RenderFragment RenderTooltip(double mouseX, double mouseY, double marginLeft, double marginTop)
|
||||
public RenderFragment RenderTooltip(double mouseX, double mouseY)
|
||||
{
|
||||
return null;
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
public Point GetTooltipPosition(double mouseX, double mouseY)
|
||||
{
|
||||
return new Point { X = mouseX, Y = mouseY };
|
||||
}
|
||||
|
||||
public void Dispose() => series?.Overlays.Remove(this);
|
||||
}
|
||||
|
||||
@@ -88,19 +88,15 @@
|
||||
}
|
||||
}
|
||||
|
||||
public RenderFragment RenderTooltip(double mouseX, double mouseY, double marginLeft, double marginTop)
|
||||
public RenderFragment RenderTooltip(double mouseX, double mouseY)
|
||||
{
|
||||
string text;
|
||||
if (Chart.ShouldInvertAxes())
|
||||
{
|
||||
mouseX = Chart.CategoryScale.Scale(Value) + marginLeft;
|
||||
mouseY = Math.Max(marginTop, Math.Min(Chart.ValueScale.OutputSize + marginTop, mouseY));
|
||||
text = Chart.ValueAxis.Format(Chart.CategoryScale, Value);
|
||||
}
|
||||
else
|
||||
{
|
||||
mouseY = Chart.ValueScale.Scale(Value) + marginTop;
|
||||
mouseX = Math.Max(marginLeft, Math.Min(Chart.CategoryScale.OutputSize + marginLeft, mouseX));
|
||||
text = Chart.ValueAxis.Format(Chart.ValueScale, Value);
|
||||
}
|
||||
|
||||
@@ -108,20 +104,35 @@
|
||||
{
|
||||
builder.OpenComponent<ChartTooltip>(0);
|
||||
|
||||
builder.AddAttribute(1, nameof(ChartTooltip.X), mouseX);
|
||||
builder.AddAttribute(2, nameof(ChartTooltip.Y), mouseY);
|
||||
builder.AddAttribute(1, nameof(ChartTooltip.ChildContent), TooltipTemplate?.Invoke(Value));
|
||||
|
||||
builder.AddAttribute(3, nameof(ChartTooltip.ChildContent), TooltipTemplate == null ? null : TooltipTemplate(Value));
|
||||
builder.AddAttribute(6, nameof(ChartTooltip.Title), series.GetTitle());
|
||||
builder.AddAttribute(2, nameof(ChartTooltip.Label), Name);
|
||||
builder.AddAttribute(3, nameof(ChartTooltip.Value), text);
|
||||
|
||||
builder.AddAttribute(8, nameof(ChartTooltip.Title), series.GetTitle());
|
||||
builder.AddAttribute(4, nameof(ChartTooltip.Label), Name);
|
||||
builder.AddAttribute(5, nameof(ChartTooltip.Value), text);
|
||||
|
||||
builder.AddAttribute(6, nameof(ChartTooltip.Style), $"border: 1px solid {Stroke};");
|
||||
builder.AddAttribute(7, nameof(ChartTooltip.Class), "");
|
||||
builder.AddAttribute(4, nameof(ChartTooltip.Style), $"border: 1px solid {Stroke};");
|
||||
builder.AddAttribute(5, nameof(ChartTooltip.Class), "");
|
||||
|
||||
builder.CloseComponent();
|
||||
};
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
public Point GetTooltipPosition(double mouseX, double mouseY)
|
||||
{
|
||||
if (Chart.ShouldInvertAxes())
|
||||
{
|
||||
mouseX = Chart.CategoryScale.Scale(Value);
|
||||
mouseY = Math.Max(0, Math.Min(Chart.ValueScale.OutputSize, mouseY));
|
||||
}
|
||||
else
|
||||
{
|
||||
mouseY = Chart.ValueScale.Scale(Value);
|
||||
mouseX = Math.Max(0, Math.Min(Chart.CategoryScale.OutputSize, mouseX));
|
||||
}
|
||||
|
||||
return new Point { X = mouseX, Y = mouseY };
|
||||
}
|
||||
|
||||
public void Dispose() => series?.Overlays.Remove(this);
|
||||
}
|
||||
@@ -1,4 +1,4 @@
|
||||
<div class="rz-chart-tooltip rz-chart-shared-tooltip @Class" style="left: @(X.ToInvariantString())px; top: @(Y.ToInvariantString())px">
|
||||
<div class="rz-chart-tooltip rz-chart-shared-tooltip @Class">
|
||||
<div class="rz-chart-tooltip-content">
|
||||
<div class="rz-chart-tooltip-title">@Title</div>
|
||||
@ChildContent
|
||||
@@ -9,12 +9,6 @@
|
||||
[Parameter]
|
||||
public RenderFragment ChildContent { get; set; }
|
||||
|
||||
[Parameter]
|
||||
public double X { get; set; }
|
||||
|
||||
[Parameter]
|
||||
public double Y { get; set; }
|
||||
|
||||
[Parameter]
|
||||
public string Class { get; set; }
|
||||
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
<div class="rz-chart-tooltip @Class" style="left: @(X.ToInvariantString())px; top: @(Y.ToInvariantString())px">
|
||||
<div class="rz-chart-tooltip @Class">
|
||||
<div class="rz-chart-tooltip-content" style="@Style">
|
||||
@if (ChildContent != null)
|
||||
{
|
||||
@@ -21,12 +21,6 @@
|
||||
[Parameter]
|
||||
public RenderFragment ChildContent { get; set; }
|
||||
|
||||
[Parameter]
|
||||
public double X { get; set; }
|
||||
|
||||
[Parameter]
|
||||
public double Y { get; set; }
|
||||
|
||||
[Parameter]
|
||||
public string Title { get; set; }
|
||||
|
||||
|
||||
@@ -1,12 +0,0 @@
|
||||
@ChildContent
|
||||
|
||||
@code {
|
||||
[Parameter]
|
||||
public RenderFragment ChildContent { get; set; }
|
||||
|
||||
internal void Refresh()
|
||||
{
|
||||
StateHasChanged();
|
||||
}
|
||||
|
||||
}
|
||||
@@ -3,11 +3,12 @@ using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Threading.Tasks;
|
||||
using Radzen.Blazor;
|
||||
|
||||
namespace Radzen
|
||||
{
|
||||
/// <summary>
|
||||
/// Class TooltipService. Contains various methods with options to open and close tooltips.
|
||||
/// Class TooltipService. Contains various methods with options to open and close tooltips.
|
||||
/// Should be added as scoped service in the application services and RadzenTooltip should be added in application main layout.
|
||||
/// Implements the <see cref="IDisposable" />
|
||||
/// </summary>
|
||||
@@ -75,6 +76,11 @@ namespace Radzen
|
||||
/// </summary>
|
||||
public event Action<ElementReference, Type, TooltipOptions> OnOpen;
|
||||
|
||||
/// <summary>
|
||||
/// Occurs when [on open chart tooltip].
|
||||
/// </summary>
|
||||
internal event Action<ElementReference, double, double, ChartTooltipOptions> OnOpenChartTooltip;
|
||||
|
||||
/// <summary>
|
||||
/// Opens the specified element.
|
||||
/// </summary>
|
||||
@@ -169,6 +175,23 @@ namespace Radzen
|
||||
OpenTooltip<object>(element, options);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Opens the specified chart tooltip.
|
||||
/// </summary>
|
||||
/// <param name="element">The chart element.</param>
|
||||
/// <param name="x"></param>
|
||||
/// <param name="y"></param>
|
||||
/// <param name="childContent">Content of the chart tooltip.</param>
|
||||
/// <param name="o">The options of the chart tooltip.</param>
|
||||
internal void OpenChartTooltip(ElementReference element, double x, double y, RenderFragment<TooltipService> childContent, ChartTooltipOptions o = null)
|
||||
{
|
||||
var options = o ?? new ChartTooltipOptions();
|
||||
|
||||
options.ChildContent = childContent;
|
||||
|
||||
OnOpenChartTooltip?.Invoke(element, x, y, options);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Opens the tooltip.
|
||||
/// </summary>
|
||||
@@ -288,4 +311,18 @@ namespace Radzen
|
||||
/// <value>The element.</value>
|
||||
public ElementReference Element { get; set; }
|
||||
}
|
||||
|
||||
internal class ChartTooltipOptions
|
||||
{
|
||||
/// <summary>
|
||||
/// Gets or sets the color scheme used to render the tooltip.
|
||||
/// </summary>
|
||||
/// <value>The color scheme.</value>
|
||||
public ColorScheme ColorScheme { get; set; }
|
||||
/// <summary>
|
||||
/// Gets or sets the child content.
|
||||
/// </summary>
|
||||
/// <value>The child content.</value>
|
||||
public RenderFragment<TooltipService> ChildContent { get; set; }
|
||||
}
|
||||
}
|
||||
|
||||
@@ -234,12 +234,18 @@ $chart-color-schemes: (
|
||||
|
||||
.rz-chart-tooltip {
|
||||
position: absolute;
|
||||
transform: translate(-50%, -100%);
|
||||
transition: top 0.2s, left 0.2s;
|
||||
top: 0;
|
||||
left: 0;
|
||||
}
|
||||
|
||||
.rz-top-chart-tooltip {
|
||||
transform: translate(-50%, -100%);
|
||||
}
|
||||
|
||||
.rz-bottom-chart-tooltip {
|
||||
transform: translate(-50%, 0);
|
||||
}
|
||||
|
||||
.rz-chart-tooltip-content {
|
||||
background: var(--rz-chart-tooltip-background);
|
||||
color: var(--rz-chart-tooltip-color);
|
||||
@@ -253,16 +259,25 @@ $chart-color-schemes: (
|
||||
.rz-chart-tooltip {
|
||||
&:not(.rz-pie-tooltip) {
|
||||
.rz-chart-tooltip-content {
|
||||
margin-bottom: 15px;
|
||||
&:after {
|
||||
content: ' ';
|
||||
position: absolute;
|
||||
width: 8px;
|
||||
height: 8px;
|
||||
left: 50%;
|
||||
bottom: 0;
|
||||
background-color: inherit;
|
||||
transform-origin: center;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.rz-top-chart-tooltip {
|
||||
&:not(.rz-pie-tooltip) {
|
||||
.rz-chart-tooltip-content {
|
||||
margin-bottom: 15px;
|
||||
&:after {
|
||||
left: 50%;
|
||||
bottom: 0;
|
||||
transform: translate(-50%, -11px) rotate(45deg);
|
||||
border-bottom: inherit;
|
||||
border-right: inherit;
|
||||
@@ -271,6 +286,21 @@ $chart-color-schemes: (
|
||||
}
|
||||
}
|
||||
|
||||
.rz-bottom-chart-tooltip {
|
||||
&:not(.rz-pie-tooltip) {
|
||||
.rz-chart-tooltip-content {
|
||||
margin-top: 15px;
|
||||
&:after {
|
||||
left: 50%;
|
||||
top: 0;
|
||||
transform: translate(-50%, 11px) rotate(45deg);
|
||||
border-top: inherit;
|
||||
border-left: inherit;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.rz-chart-tooltip-title {
|
||||
font-weight: 700;
|
||||
}
|
||||
@@ -299,7 +329,7 @@ $chart-color-schemes: (
|
||||
justify-content: space-between;
|
||||
gap: 1rem;
|
||||
padding: 0.125rem 0.5rem;
|
||||
border-radius: var( --rz-chart-tooltip-item-border-radius);
|
||||
border-radius: var(--rz-chart-tooltip-item-border-radius);
|
||||
|
||||
&:hover {
|
||||
background-color: var(--rz-chart-tooltip-item-hover-background-color);
|
||||
|
||||
@@ -1746,9 +1746,6 @@ window.Radzen = {
|
||||
var inside = false;
|
||||
ref.mouseMoveHandler = this.throttle(function (e) {
|
||||
if (inside) {
|
||||
if (e.target.matches('.rz-chart-tooltip-content') || e.target.closest('.rz-chart-tooltip-content')) {
|
||||
return
|
||||
}
|
||||
var rect = ref.getBoundingClientRect();
|
||||
var x = e.clientX - rect.left;
|
||||
var y = e.clientY - rect.top;
|
||||
@@ -1758,7 +1755,10 @@ window.Radzen = {
|
||||
ref.mouseEnterHandler = function () {
|
||||
inside = true;
|
||||
};
|
||||
ref.mouseLeaveHandler = function () {
|
||||
ref.mouseLeaveHandler = function (e) {
|
||||
if (e.relatedTarget && (e.relatedTarget.matches('.rz-chart-tooltip') || e.relatedTarget.closest('.rz-chart-tooltip'))) {
|
||||
return;
|
||||
}
|
||||
inside = false;
|
||||
instance.invokeMethodAsync('MouseMove', -1, -1);
|
||||
};
|
||||
@@ -2440,5 +2440,27 @@ window.Radzen = {
|
||||
} else {
|
||||
start();
|
||||
}
|
||||
},
|
||||
openChartTooltip: function (chart, x, y, id, instance, callback) {
|
||||
Radzen.closeTooltip(id);
|
||||
|
||||
var chartRect = chart.getBoundingClientRect();
|
||||
x = Math.max(2, chartRect.left + x);
|
||||
y = Math.max(2, chartRect.top + y);
|
||||
Radzen.openPopup(chart, id, false, null, x, y, instance, callback, true, false, false);
|
||||
|
||||
var popup = document.getElementById(id);
|
||||
if (!popup) {
|
||||
return;
|
||||
}
|
||||
var tooltipContent = popup.children[0];
|
||||
var tooltipContentRect = tooltipContent.getBoundingClientRect();
|
||||
var tooltipContentClassName = 'rz-top-chart-tooltip';
|
||||
if (y - tooltipContentRect.height < 0) {
|
||||
tooltipContentClassName = 'rz-bottom-chart-tooltip';
|
||||
}
|
||||
tooltipContent.classList.remove('rz-top-chart-tooltip');
|
||||
tooltipContent.classList.remove('rz-bottom-chart-tooltip');
|
||||
tooltipContent.classList.add(tooltipContentClassName);
|
||||
}
|
||||
};
|
||||
|
||||
@@ -176,9 +176,9 @@ The Radzen Blazor components are distributed via the <a href="">Radzen.Blazor</a
|
||||
}
|
||||
</code>
|
||||
</pre>
|
||||
<h3 id="outlets"><a href="#outlets">Dialog, context menu, tooltip and notification</a></h3>
|
||||
<h3 id="outlets"><a href="#outlets">Dialog, context menu, tooltip, chart tooltip and notification</a></h3>
|
||||
<p>
|
||||
To use RadzenDialog, RadzenContextMenu, RadzenTooltip and RadzenNotification you need to perform a few additional steps.
|
||||
To use RadzenDialog, RadzenContextMenu, RadzenTooltip, RadzenChartTooltip and RadzenNotification you need to perform a few additional steps.
|
||||
</p>
|
||||
<ol>
|
||||
<li>Open <code>MainLayout.razor</code> and add this code
|
||||
|
||||
Reference in New Issue
Block a user