mirror of
https://github.com/radzenhq/radzen-blazor.git
synced 2026-02-04 05:35:44 +00:00
* 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>
169 lines
5.4 KiB
C#
169 lines
5.4 KiB
C#
using System;
|
|
using Microsoft.AspNetCore.Components;
|
|
using Radzen.Blazor.Rendering;
|
|
|
|
namespace Radzen.Blazor
|
|
{
|
|
/// <summary>
|
|
/// Displays a text label for the specified data item from the series.
|
|
/// </summary>
|
|
/// <example>
|
|
/// <code>
|
|
/// <RadzenChart>
|
|
/// <RadzenLineSeries Data=@revenue CategoryProperty="Quarter" ValueProperty="Revenue">
|
|
/// <RadzenSeriesAnnotation Data="@revenue[1] Text="Q2 Revenue" />
|
|
/// </RadzenLineSeries>
|
|
/// </RadzenChart>
|
|
/// @code {
|
|
/// class DataItem
|
|
/// {
|
|
/// public string Quarter { get; set; }
|
|
/// public double Revenue { get; set; }
|
|
/// }
|
|
/// DataItem[] revenue = new DataItem[]
|
|
/// {
|
|
/// new DataItem { Quarter = "Q1", Revenue = 234000 },
|
|
/// new DataItem { Quarter = "Q2", Revenue = 284000 },
|
|
/// new DataItem { Quarter = "Q3", Revenue = 274000 },
|
|
/// new DataItem { Quarter = "Q4", Revenue = 294000 }
|
|
/// };
|
|
/// }
|
|
/// </code>
|
|
/// </example>
|
|
public partial class RadzenSeriesAnnotation<TItem> : RadzenChartComponentBase, IChartSeriesOverlay, IDisposable
|
|
{
|
|
/// <summary>
|
|
/// The data item from the series this annotation applies to.
|
|
/// </summary>
|
|
[Parameter]
|
|
public TItem Data { get; set; }
|
|
|
|
/// <summary>
|
|
/// The text to display in the annotation.
|
|
/// </summary>
|
|
[Parameter]
|
|
public string Text { get; set; }
|
|
|
|
/// <summary> Horizontal offset from the default position. </summary>
|
|
[Parameter]
|
|
public double OffsetX { get; set; }
|
|
|
|
/// <summary> Vertical offset from the default position. </summary>
|
|
[Parameter]
|
|
public double OffsetY { get; set; }
|
|
|
|
/// <summary> Determines whether the annotation is visible. Set to <c>true</c> by default.</summary>
|
|
[Parameter]
|
|
public bool Visible { get; set; } = true;
|
|
|
|
CartesianSeries<TItem> series;
|
|
|
|
/// <summary> The series this annotation applies to. Set to <c>true</c> by default.</summary>
|
|
[CascadingParameter]
|
|
protected CartesianSeries<TItem> Series
|
|
{
|
|
get
|
|
{
|
|
return series;
|
|
}
|
|
set
|
|
{
|
|
if (!value.Overlays.Contains(this))
|
|
{
|
|
series = value;
|
|
series.Overlays.Add(this);
|
|
}
|
|
}
|
|
}
|
|
|
|
/// <inheritdoc/>
|
|
public RenderFragment Render(ScaleBase categoryScale, ScaleBase valueScale)
|
|
{
|
|
double x = series.TooltipX(Data);
|
|
double y = series.TooltipY(Data);
|
|
|
|
var coordinateSystem = series.CoordinateSystem;
|
|
|
|
var textAnchor = "middle";
|
|
|
|
switch (coordinateSystem)
|
|
{
|
|
case Radzen.CoordinateSystem.Cartesian:
|
|
x += OffsetX;
|
|
y += OffsetY;
|
|
break;
|
|
|
|
case Radzen.CoordinateSystem.Polar:
|
|
double orgX;
|
|
double orgY;
|
|
if (series is RadzenPieSeries<TItem>)
|
|
{
|
|
var pieSeries = series as RadzenPieSeries<TItem>;
|
|
orgX = pieSeries.CenterX;
|
|
orgY = pieSeries.CenterY;
|
|
}
|
|
else
|
|
{
|
|
orgX = x;
|
|
orgY = y;
|
|
}
|
|
|
|
x -= orgX;
|
|
y -= orgY;
|
|
|
|
// find angle and add offset
|
|
var phi = Math.Atan2(y, x);
|
|
phi += Polar.ToRadian(OffsetY % 360);
|
|
|
|
textAnchor = phi >= -1.5 && phi <= 1.5 ? "start" : "end";
|
|
|
|
// find radius
|
|
var hyp = Math.Sqrt(x * x + y * y) + OffsetX + 16;
|
|
|
|
// move along the radius and rotate
|
|
x = orgX + hyp * Math.Cos(phi);
|
|
y = orgY + hyp * Math.Sin(phi);
|
|
break;
|
|
}
|
|
|
|
return builder =>
|
|
{
|
|
builder.OpenElement(0, "g");
|
|
builder.OpenComponent<Text>(1);
|
|
builder.AddAttribute(2, "Value", Text);
|
|
builder.AddAttribute(3, "Position", new Point{ X = x, Y = y });
|
|
builder.AddAttribute(4, "TextAnchor", textAnchor);
|
|
builder.SetKey($"{Text}-{Chart.Series.IndexOf(series)}");
|
|
builder.CloseComponent();
|
|
builder.CloseElement();
|
|
};
|
|
}
|
|
|
|
/// <inheritdoc/>
|
|
protected override bool ShouldRefreshChart(ParameterView parameters)
|
|
{
|
|
return parameters.DidParameterChange(nameof(Visible), Visible);
|
|
}
|
|
|
|
/// <inheritdoc/>
|
|
public bool Contains(double mouseX, double mouseY, int tolerance)
|
|
{
|
|
return false;
|
|
}
|
|
|
|
/// <inheritdoc/>
|
|
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);
|
|
}
|
|
} |