# Charts ยท Interaction
> Dates with zoom, annotations, events and changing data, custom tooltip and export to image.
Source page: https://doc.astrolui.com/chart/examples/interaction
Each example is a complete component: copy its code (markup and **@code**), including the sample data, and replace it with yours.
## Dates and zoom
Date axis (**XAxisType.Datetime**) with zoom: drag over the chart to zoom in; the toolbar resets it.
```razor
@using AstrolCharts
@* Date axis: X goes as Unix milliseconds. Drag over the chart to zoom; the toolbar resets it. *@
@code {
private readonly AstrolChartOptions options = new()
{
Chart = new Chart
{
Zoom = new Zoom { Enabled = true, Type = AxisType.X, AutoScaleYaxis = true },
Toolbar = new Toolbar { Show = true },
},
Xaxis = new XAxis { Labels = new XAxisLabels { Format = "dd MMM" } },
DataLabels = new DataLabels { Enabled = false },
Stroke = new Stroke { Width = 2 },
};
// Deterministic sample: 90 days
private readonly List values = Enumerable.Range(0, 90)
.Select(i => new DailyValue
{
Date = new DateTimeOffset(2026, 1, 1, 0, 0, 0, TimeSpan.Zero).AddDays(i),
Orders = 40 + (i * 7 % 23) + i / 3,
})
.ToList();
public class DailyValue
{
public DateTimeOffset Date { get; set; }
public decimal Orders { get; set; }
}
}
```
## Annotations
**Options.Annotations**: a horizontal line (goal) and a vertical band (campaign). They can also be added from code.
```razor
@using AstrolCharts
@* Annotations: a horizontal line (goal) and a vertical band (campaign). *@
@code {
private readonly AstrolChartOptions options = new()
{
Stroke = new Stroke { Width = 3 },
Annotations = new Annotations
{
Yaxis = new List
{
new AnnotationsYAxis
{
Y = 500,
BorderColor = "#12ba38",
Label = new Label { Text = "Goal", Style = new Style { Background = "#12ba38", Color = "#fff" } },
},
},
Xaxis = new List
{
new AnnotationsXAxis
{
X = "W4",
X2 = "W6",
FillColor = "#ffd800",
Opacity = 0.2,
Label = new Label { Text = "Campaign", Style = new Style { Background = "#ffd800", Color = "#222" } },
},
},
},
};
private readonly List sales = new()
{
new() { Week = "W1", Amount = 320 },
new() { Week = "W2", Amount = 360 },
new() { Week = "W3", Amount = 340 },
new() { Week = "W4", Amount = 450 },
new() { Week = "W5", Amount = 560 },
new() { Week = "W6", Amount = 610 },
new() { Week = "W7", Amount = 480 },
new() { Week = "W8", Amount = 470 },
};
public class WeeklySale
{
public string Week { get; set; } = string.Empty;
public decimal Amount { get; set; }
}
}
```
## Events and changing data
Click a column (**OnDataPointSelection**), generate new data (**UpdateSeriesAsync**) or hide a series (**ToggleSeriesAsync**).
```razor
@using AstrolCharts
@using Astrol.Component.Basic.Button
@using Astrol.Entities.Basic.UI
@* Click a column (OnDataPointSelection), change the data (UpdateSeriesAsync) or hide a series (ToggleSeriesAsync). *@
@message
@code {
private AstrolChart? chart;
private string message = "Click a column.";
private int round;
private readonly List results = new()
{
new() { Team = "Lions", Won = 12, Lost = 4 },
new() { Team = "Eagles", Won = 9, Lost = 7 },
new() { Team = "Sharks", Won = 14, Lost = 2 },
new() { Team = "Wolves", Won = 6, Lost = 10 },
};
private void OnSelected(SelectedData selected)
{
var team = selected.DataPoint.Items.First();
message = selected.IsSelected
? $"{selected.Series.Name} - {team.Team}: won {team.Won}, lost {team.Lost}"
: "Selection cleared.";
}
private async Task NewData()
{
round++;
foreach (var (team, i) in results.Select((t, i) => (t, i)))
{
team.Won = (round * 5 + i * 3) % 15 + 2;
team.Lost = (round * 3 + i * 7) % 12 + 1;
}
// The list is the same object: tell the chart to read it again
await chart!.UpdateSeriesAsync(animate: true);
}
private Task ToggleLost() => chart!.ToggleSeriesAsync("Lost");
public class TeamResult
{
public string Team { get; set; } = string.Empty;
public decimal Won { get; set; }
public decimal Lost { get; set; }
}
}
```
## Custom tooltip
**AstrolPointTooltip** renders the tooltip with Blazor; **context.DataPoint.Items** holds the objects of the point. The series go in ****.
```razor
@using AstrolCharts
@* AstrolPointTooltip: Blazor content of the tooltip. context.DataPoint.Items are the items of the point.
With a tooltip, the series go inside . *@
@{ var product = context.DataPoint.Items.First(); }
@code {
private readonly List products = new()
{
new() { Name = "Keyboard", Units = 320, Price = 35 },
new() { Name = "Mouse", Units = 540, Price = 18 },
new() { Name = "Monitor", Units = 120, Price = 210 },
new() { Name = "Headset", Units = 260, Price = 49 },
};
public class Product
{
public string Name { get; set; } = string.Empty;
public decimal Units { get; set; }
public decimal Price { get; set; }
}
}
```
## Export to image
**GetDataUriAsync** returns the chart as a PNG (data URI) to show it, save it or include it in a report.
```razor
@using AstrolCharts
@using Astrol.Component.Basic.Button
@using Astrol.Entities.Basic.UI
@* GetDataUriAsync returns the chart as a PNG (data URI) to show it, save it or put it in a report. *@
@if (image != null)
{
}
@code {
private AstrolChart? chart;
private string? image;
private async Task Export()
{
image = await chart!.GetDataUriAsync(new DataUriOptions { Scale = 1 });
}
private readonly List channels = new()
{
new() { Name = "Search", Leads = 420 },
new() { Name = "Social", Leads = 310 },
new() { Name = "Email", Leads = 180 },
new() { Name = "Referral", Leads = 95 },
};
public class Channel
{
public string Name { get; set; } = string.Empty;
public decimal Leads { get; set; }
}
}
```