mr-azazael / lightweightcharts.blazor Goto Github PK
View Code? Open in Web Editor NEWA blazor wrapper for TradingView's Lightweight Charts javascript library.
License: Apache License 2.0
A blazor wrapper for TradingView's Lightweight Charts javascript library.
License: Apache License 2.0
I'm not using NuGet packaging, using this repo as a project reference in my project, I have created a separate page in your example project, and that page works fine with the chart. but then I transferred my main project, this page is not working,
I'm referencing lightweight charts scripts in my project, and it is a .net 8.0 server-side rendering. what is missing here?
other than .net 8.0, do I have to enable anything in a server-side rendering project?
chart is also working fine in a blank new project ,but not in my main project with 8.0 target .
page code.
@using LightweightCharts.Blazor.Charts;
@using LightweightCharts.Blazor.Customization.Chart;
@using LightweightCharts.Blazor.Customization.Enums;
@using LightweightCharts.Blazor.Customization.Series;
@using LightweightCharts.Blazor.DataItems;
@using LightweightCharts.Blazor.Models.Events;
@using LightweightCharts.Blazor.Series;
@using LightweightCharts.Blazor;
@using System.Collections.Generic;
@using System.Drawing;
@using System.Linq;
@using System.Threading.Tasks;
@using Microsoft.AspNetCore.Components.Web
@rendermode Microsoft.AspNetCore.Components.Web.RenderMode.InteractiveServer
@page "/Counter"
<PageTitle>ChartComponent</PageTitle>
@log
<div style="width:1800px;height:600px;">
<ChartComponent @ref="@ChartComponent" />
</div>
@code {
ISeriesApi<CandlestickStyleOptions> _Candlestick;
ISeriesApi<HistogramStyleOptions> _Histogram;
IEnumerable<SeriesPrice> _MouseHoverPrices;
string _LastClickedId;
bool _InitChartComponent;
ChartOptionsBase _Options;
bool _Initialize;
ChartComponent _ChartComponent;
ChartComponent ChartComponent
{
set
{
if( _ChartComponent == value )
return;
log = " ChartComponent ChartComponent _Initialize true , ";
_ChartComponent = value;
_Initialize = true;
StateHasChanged();
}
}
protected override async Task OnAfterRenderAsync(bool firstRender)
{
await base.OnAfterRenderAsync(firstRender);
if( firstRender )
{
StateHasChanged();
}
if( _Initialize )
{
log = " OnAfterRenderAsync , ";
_Initialize = false;
await InitializeChartComponent();
}
}
string _BackgroundType;
string BackgroundType
{
get => _BackgroundType;
set
{
_BackgroundType = value;
_Options.Layout.Background = _BackgroundType switch
{
"Solid" => new SolidColor(),
_ => new VerticalGradientColor()
};
}
}
string log = "Started ";
async Task InitializeChartComponent()
{
log = "InitializeChartComponent 0";
if( _ChartComponent == null )
{
log = "return _ChartComponent == null";
return;
}
await _ChartComponent.InitializationCompleted;
log += "await InitializationCompleted 1";
_ChartComponent.Clicked += OnChartClicked;
_ChartComponent.CrosshairMoved += OnChartCrosshairMoved;
await _ChartComponent.ApplyOptions(new ChartOptionsBase
{
Crosshair = new CrosshairOptions
{
Mode = CrosshairMode.Normal
},
LeftPriceScale = new PriceScaleOptions
{
Visible = false
},
RightPriceScale = new PriceScaleOptions
{
ScaleMargins = new LightweightCharts.Blazor.Customization.PriceScaleMargins
{
Bottom = 0.1d,
Top = 0
}
},
OverlayPriceScale = new BasePriceScaleOptions
{
ScaleMargins = new LightweightCharts.Blazor.Customization.PriceScaleMargins
{
Bottom = 0,
Top = 0.9d
}
}
});
log += " , ApplyOptions end";
_Options = await _ChartComponent.Options();
BackgroundType = "Solid";
StateHasChanged();
await SetupCandlestickSeries();
var timeScale = await _ChartComponent.TimeScaleAsync();
await timeScale.FitContent();
log += "FitContent end";
StateHasChanged();
}
List<CandlestickData> graphCandleData = new();
async Task SetupCandlestickSeries()
{
var random = new Random();
int c = 0;
DateTime StartTime = DateTime.Now.AddDays(-12);
for( int i = 1; i <= 120; i++ )
{
CandlestickData a = new CandlestickData();
a.Open = random.Next(1, 5) * random.Next(5, 15);
a.Close = random.Next(1, 5) * random.Next(5, 15);
a.High = random.Next(1, 5) * random.Next(5, 15);
a.Low = random.Next(1, 5) * random.Next(5, 15);
a.Time = StartTime.AddHours(i);
c++;
if( c > 24 )
{
StartTime = StartTime.AddDays(2);
c = 0;
}
graphCandleData.Add(a);
}
_Candlestick = await _ChartComponent.AddCandlestickSeriesAsync();
await _Candlestick.SetData(graphCandleData);
}
void OnChartCrosshairMoved(object sender, MouseEventParams e)
{
_MouseHoverPrices = e.SeriesPrices;
StateHasChanged();
}
async void OnChartClicked(object sender, MouseEventParams e)
{
}
async Task OnApplyOptions()
{
await _ChartComponent.ApplyOptions(_Options);
}
}
i Created a simple blazor project and try to integrate the chart without any success.
Your example is working but cannot succeed with mine, i tried :
You can find my test project here : BlazorApp1.zip
I integrate TW Chart under the Counter Page
Thanks a lot
Amaury
time scale time string is in local time which is okay,js runtime invoke is working fine,but cross hair label time is in UTC , how to change this to local?
Hello... Thanks for the hard work with this wrapper. It's pretty good.
I am trying to change the background color on the chart.
Other properties like TextColor or FontSize work just fine. But not Background.
Here is my code to initialize the component:
`
async void InitializeChartComponent(ChartComponent chart)
{
await chart.InitializationCompleted;
chart.Clicked += OnChartClicked!;
chart.CrosshairMoved += OnChartCrosshairMoved!;
await chart.ApplyOptions(new LightweightCharts.Blazor.Customization.Chart.ChartOptions
{
LeftPriceScale = new LightweightCharts.Blazor.Customization.Chart.PriceScaleOptions
{
Visible = false
},
RightPriceScale = new LightweightCharts.Blazor.Customization.Chart.PriceScaleOptions
{
ScaleMargins = new LightweightCharts.Blazor.Customization.PriceScaleMargins
{
Bottom = 0.1d,
Top = 0
}
},
OverlayPriceScale = new LightweightCharts.Blazor.Customization.Chart.BasePriceScaleOptions
{
ScaleMargins = new LightweightCharts.Blazor.Customization.PriceScaleMargins
{
Bottom = 0,
Top = 0.9d
}
},
Layout = new LightweightCharts.Blazor.Customization.Chart.LayoutOptions
{
Background = new LightweightCharts.Blazor.Customization.Chart.SolidColor { Color = Color.RoyalBlue },
TextColor = Color.Red,
FontSize = 14
}
});
await SetupCandlestickSeries(chart);
await SetupHistogramSeries(chart);
var timeScale = await chart.TimeScaleAsync();
await timeScale.FitContent();
initialLoad = false;
}
`
This compiles just fine, but the background property is the only one that has no effect when rendered. The TextColor and FontSize do change.
Thanks in advance for the help.
i could not find any documentation of the wrapper, is it planned?
hi,
want to oi chart like the below screenshot, histogram series works on the bottom panel, need to shift to price panel,will the existing histogram series work for it,or need to do a custom series? does this wrapper support custom series?
Give me your idea or a way to achieve to this.
need to bring option data into charts .
Thanks
kiran
I have use this package to my project which is a server side blazor project. but It show nothing.
Does it support server-side blazor? Did you test on it?
Hi,
Im using the .net 8 Blazor Web App template with rendermode InteractiveAuto applied globally.
When running i get the error: Microsoft.JSInterop.JSException: 'There are multiple .NET runtimes present, so a default dispatcher could not be resolved. Use DotNetObject to invoke .NET instance methods.
I tried the same Webapp template, the same rendermode but applied per page/component.
I made a page with a chart in the server project (rendermode = server) and one in the client project(rendermode = WebAssembly).
Both pages are giving the same error if i open the other first. So
open server side, than open client side => error
or
open client side, then open serverside => error
Microsoft.JSInterop.JSException
HResult=0x80131500
Message=There are multiple .NET runtimes present, so a default dispatcher could not be resolved. Use DotNetObject to invoke .NET instance methods.
Error: There are multiple .NET runtimes present, so a default dispatcher could not be resolved. Use DotNetObject to invoke .NET instance methods.
at v (https://localhost:44307/_framework/blazor.web.js:1:2037)
at e.invokeMethodAsync (https://localhost:44307/_framework/blazor.web.js:1:2428)
at Object.lightweightChartsInvoke (https://localhost:44307/_content/LightweightCharts.Blazor/lightweight-charts.scripts.js:19:45)
at https://localhost:44307/_framework/blazor.web.js:1:3244
at new Promise (<anonymous>)
at y.beginInvokeJSFromDotNet (https://localhost:44307/_framework/blazor.web.js:1:3201)
at fn._invokeClientMethod (https://localhost:44307/_framework/blazor.web.js:1:62541)
at fn._processIncomingData (https://localhost:44307/_framework/blazor.web.js:1:60016)
at connection.onreceive (https://localhost:44307/_framework/blazor.web.js:1:53657)
at i.onmessage (https://localhost:44307/_framework/blazor.web.js:1:81802)
Source=System.Private.CoreLib
StackTrace:
at System.Threading.Tasks.ValueTask`1.get_Result()
at System.Runtime.CompilerServices.ValueTaskAwaiter`1.GetResult()
at Microsoft.JSInterop.JSRuntime.<InvokeAsync>d__16`1.MoveNext()
at System.Threading.Tasks.ValueTask`1.get_Result()
at System.Runtime.CompilerServices.ValueTaskAwaiter`1.GetResult()
at LightweightCharts.Blazor.Charts.ChartComponent.<JavascriptInvokeAsync>d__53`1.MoveNext() in C:\Projects\GSL.CryptoHunter\LightweightCharts.Blazor\Charts\ChartComponent.cs:line 436
at LightweightCharts.Blazor.Charts.ChartComponent.<Options>d__38.MoveNext() in C:\Projects\GSL.CryptoHunter\LightweightCharts.Blazor\Charts\ChartComponent.cs:line 287
at BlazorApp1.Components.Pages.CandlestickSeries.<InitializeChartComponent>d__13.MoveNext() in C:\Projects\GSL.CryptoHunter\BlazorApp1\BlazorApp1\Components\Pages\CandlestickSeries.razor.cs:line 96
Regards,
Glenn
Hello! Thank's a lot for this project!
I was trying to add multiple axis on a chart in a cycle like this:
` for (int i = 0; i < _seriesCount; i++)
{
var YAxis = new NumericAxis()
{
Id = $"Y{i}",
MaxAutoTicks = 5,
DrawMajorGridLines = false,
VisibleRange = new SciChartNumberRange(-100.0, 100.0),
VisibleRangeLimit = new SciChartNumberRange(-1000.0, 1000.0),
IsVisible = (i == 0)
};
await _chartBuilder.AddAxis(YAxis, AxisType.Y);
var XAxis = new NumericAxis()
{
Id = $"X{i}",
MaxAutoTicks = 5,
DrawMajorGridLines = false,
GrowBy = new SciChartNumberRange(0, 0.2),
VisibleRange = new SciChartNumberRange(-1000.0, 1000.0),
VisibleRangeLimit = new SciChartNumberRange(-1000.0, 1000.0),
IsVisible = (i == 0)
};
await _chartBuilder.AddAxis(XAxis, AxisType.X);
} `
But it ended with error
Error from chart in div Ced51579e-26cc-4536-96e2-49f46254f9db: TypeError: Cannot read properties of undefined (reading 'min') at ExtremeResamplerHelper.resetAndFillBasicNativeArgs (ExtremeResamplerHelper.js:178:54) at ExtremeResamplerHelper.needsResampling (ExtremeResamplerHelper.js:50:18) at BaseRenderableSeries.needsResampling (BaseRenderableSeries.js:935:37) at SciChartRenderer.resampleSeries (SciChartRenderer.js:65:17) at SciChartRenderer.prepareSeriesRenderData (SciChartRenderer.js:328:57) at SciChartRenderer.render (SciChartRenderer.js:144:35) at SciChartSurface.doDrawingLoop (SciChartSurface.js:707:35) at SciChartSurface.onRenderSurfaceDraw (SciChartSurface.js:1337:18) at RenderSurface.onRenderTimeElapsed (RenderSurface.js:37:14) at Object.Draw (createMaster.js:294:60)
I looked closer to js code and found out that in this function
SciChartRenderer.prototype.prepareAxesRenderData = function () { var xAxesById = new Dictionary_1.Dictionary(); var yAxesById = new Dictionary_1.Dictionary(); // Prepare XAxes this.sciChartSurface.xAxes.asArray().forEach(function (xAxis) { xAxesById.add(xAxis.id, xAxis); xAxis.prepareRenderData(); }); // Prepare YAxes this.sciChartSurface.yAxes.asArray().forEach(function (yAxis) { yAxesById.add(yAxis.id, yAxis); yAxis.prepareRenderData(); }); return { xAxesById: xAxesById, yAxesById: yAxesById }; };
this.sciChartSurface.xAxes
has only last axe with last id.
I tried rewriting the wrapper and pass serialized list of axis. It works, but all Ids have default values, so the error doesn't go away.
Is it possible to add axes in different way or maybe fix something in existing method?
A declarative, efficient, and flexible JavaScript library for building user interfaces.
๐ Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
An Open Source Machine Learning Framework for Everyone
The Web framework for perfectionists with deadlines.
A PHP framework for web artisans
Bring data to life with SVG, Canvas and HTML. ๐๐๐
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
Some thing interesting about web. New door for the world.
A server is a program made to process requests and deliver data to clients.
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
Some thing interesting about visualization, use data art
Some thing interesting about game, make everyone happy.
We are working to build community through open source technology. NB: members must have two-factor auth.
Open source projects and samples from Microsoft.
Google โค๏ธ Open Source for everyone.
Alibaba Open Source for everyone
Data-Driven Documents codes.
China tencent open source team.