Pre loader

1

Welcome to the SciChart Forums!

  • Please read our Question Asking Guidelines for how to format a good question
  • Some reputation is required to post answers. Get up-voted to avoid the spam filter!
  • We welcome community answers and upvotes. Every Q&A improves SciChart for everyone

WPF Forums | JavaScript Forums | Android Forums | iOS Forums

0 votes

In case someone else wants to do this I have achieved what I needed by subclassing CursorModifier as

  public class VerticalCursorModifier : CursorModifier
{
    private Line _verticalLine;
    protected override void ShowCrosshairCursor(Point mousePoint, bool drawHorizontalLine, bool drawVerticalLine)
    {

        var modifierRect = ModifierSurface.GetBoundsRelativeTo(RootGrid);


        if (drawVerticalLine)
        {
            ShowCrosshairLine(ref _verticalLine, mousePoint.X, 0d, mousePoint.X, modifierRect.Height - 1);
        }
    }

    private void ShowCrosshairLine(ref Line line, double x1, double y1, double x2, double y2)
    {
        if (line == null)
        {
            line = new Line { Style = LineOverlayStyle, IsHitTestVisible = false };

            ModifierSurface.Children.Add(line);
        }

        line.X1 = x1;
        line.X2 = x2;
        line.Y1 = y1;
        line.Y2 = y2;
    }

    protected override void UpdateYAxesOverlay(Point mousePoint)
    {
       // base.UpdateYAxesOverlay(mousePoint);
    }
}
0 votes

Can I ask the same question here since no answer was given.

I want to display a CursorModifier so that I can show all the series values in one tooltip popup. I already have this working fine for cross-hair cursor using the CursorModifier.

The customer also wants the same tooltip option shown but with a single vertical line cursor, not the cross-hairs.

I cannot use RolloverModifier as this shows each series value in a separate popup.

CursorModifier with only vertical line would do the job.

Thanks

0 votes

Thank you! This is exactly what I was looking for.

0 votes
In reply to: Discreet colormap

Hi Pramod

There is a way, yes

There is a technique we use in 3D charts in our WPF (windows) version of scichart, where we basically define gradient stops like this:

Given a set of gradient stops

    const heatmapColorMap = new HeatmapColorMap({ 
                    gradientStops: [
                       { offset: 0, color: "Red" },
                       { offset: 0.5, color: "Green" }
                       { offset: 1, color: "Blue" }
                    ]
                });

This will perform a gradient between offset 0 (red) and offset 0.5 (green) and offset 1 (blue).

If you want a hard transition from red to green, and green to blue, then inject extra gradient stops like this

 gradientStops: [
        { offset: 0, color: "Red" },
        { offset: 0.4999, color: "Red" },
        { offset: 0.5, color: "Green" }
        { offset: 0.9999, color: "Green" }
        { offset: 1, color: "Blue" }
 ]

Anything between stop 0 and 0.4999 will now be red and 0.5 to 0.9999 will be hard green

Let me know if this helps!

Best regards,
Andrew

1 vote

Nervemind I manged to find a solution for this. For anyone else who may have a similar issue, the solution is to add extra options to your SVG directly. style="image-rendering: pixelated"

eg.

            svgString =
            `<svg  
                id="bmp"
                x="0"
                y="0"
                width="${heatMapDataSeriesRef.current.xMax}" 
                height="${heatMapDataSeriesRef.current.yMax}" 
                preserveAspectRatio="none"
                viewBox="0 0 ${img.width} ${img.height}">
               <image style="image-rendering: pixelated" id="box_2_rect" href="${imageScanned.data}"/>
        </svg>`

Pramod

0 votes

Hello,

To implement this you would probably need the Series Selection API in combination with a custom Rollover Modifier.

class CustomRolloverModifier extends RolloverModifier {
  getIncludedRenderableSeries() {
    return super.getIncludedRenderableSeries().filter((rs) => rs.isSelected);
  }
}

const rolloverModifier = new CustomRolloverModifier({
  showRolloverLine: true,
  showTooltip: true,
  // ...
});

const seriesSelectionModifier = new SeriesSelectionModifier({
  enableSelection: true,
  onSelectionChanged: (args: SelectionChangedArgs) => {
    args.allSeries.forEach((rs) => {
      rolloverModifier.includeSeries(rs, false);
    });
    rolloverModifier.includeSeries(args.selectedSeries[0], true);
  },
});

sciChartSurface.chartModifiers.add(rolloverModifier, seriesSelectionModifier);

Here is a live CodeSandbox Example:

Also consider checking out the Cursor Modifier.

0 votes

Dear Jim thank you for you response.

I think i made it work for us for time being. For any one else looking for a solution here is what I did:

i have a toggle switch which changes,

  1. the position (z-index) of the svg to 0 or -1 thus sending it behind or in front (default) of the heatmap canvas.
  2. turns off all the gird lines and ticks
  3. make the background default
  4. remove the major bands

    useEffect(() => {
    if (sciChartSurfaceRef.current) {
        if (visibleImageBelowHeatmap) {
            console.log(document.getElementById(sciChartSurfaceRef.current))
            document.getElementById(sciChartSurfaceRef.current.domSvgContainer.id).style.zIndex = '-1'
            document.getElementById(sciChartSurfaceRef.current.domCanvas2D.id).style.zIndex = '0'
            sciChartSurfaceRef.current.background = "#00000000"
            sciChartSurfaceRef.current.xAxes.get(0).drawMinorGridLines = false
            sciChartSurfaceRef.current.xAxes.get(0).drawMajorGridLines = false
            sciChartSurfaceRef.current.xAxes.get(0).drawMinorTickLines = false
            sciChartSurfaceRef.current.xAxes.get(0).drawMajorTickLines = false
    
            sciChartSurfaceRef.current.yAxes.get(0).drawMinorGridLines = false
            sciChartSurfaceRef.current.yAxes.get(0).drawMajorGridLines = false
            sciChartSurfaceRef.current.yAxes.get(0).drawMinorTickLines = false
            sciChartSurfaceRef.current.yAxes.get(0).drawMajorTickLines = false
    
            sciChartSurfaceRef.current.xAxes.get(0).drawMajorBands = false
            sciChartSurfaceRef.current.yAxes.get(0).drawMajorBands = false
    
        } else {
            document.getElementById(sciChartSurfaceRef.current.domSvgContainer.id).style.zIndex = '0'
            document.getElementById(sciChartSurfaceRef.current.domCanvas2D.id).style.zIndex = '0'
            sciChartSurfaceRef.current.background = "radial-gradient(circle, #3C3C3FFF 0%, #1C1C1EFF 100%)"
            sciChartSurfaceRef.current.xAxes.get(0).drawMinorGridLines = true
            sciChartSurfaceRef.current.xAxes.get(0).drawMajorGridLines = true
            sciChartSurfaceRef.current.xAxes.get(0).drawMinorTickLines = true
            sciChartSurfaceRef.current.xAxes.get(0).drawMajorTickLines = true
    
            sciChartSurfaceRef.current.yAxes.get(0).drawMinorGridLines = true
            sciChartSurfaceRef.current.yAxes.get(0).drawMajorGridLines = true
            sciChartSurfaceRef.current.yAxes.get(0).drawMinorTickLines = true
            sciChartSurfaceRef.current.yAxes.get(0).drawMajorTickLines = true
    
            sciChartSurfaceRef.current.xAxes.get(0).drawMajorBands = true
            sciChartSurfaceRef.current.yAxes.get(0).drawMajorBands = true
        }
    }
    

    }, [visibleImageBelowHeatmap])

and the just reverse the changes.

video

0 votes

Hi Suhib,

Thanks for your inquiry.
First of all, we would recommend taking a look at the “Performance Tips & Tricks” section of our documentation. Here is a link:
https://www.scichart.com/documentation/win/current/webframe.html#General%20Performance%20Tips.html

It’s also worth mentioning that the rendering performance depends on the hardware you use. Mainly on the GPU if you are using our hardware-accelerated rendering engine.
More details can be found in the “SciChart WPF System Requirements” article here:
https://www.scichart.com/documentation/win/current/webframe.html#SciChart%20System%20Requirements.html

Please let us know if you need any further assistance.

With best regards,
Lex S., MSEE
SciChart Technical Support Engineer

  • Lex answered 7 days ago
0 votes

Hello Roland,

Thanks for your inquiry.
We have introduced configurable Scene Lighting in SciChart v6.4. Please take a look:
https://www.scichart.com/scichart-wpf-v6-4-released/

You can now manipulate both Scene Lighting and Light Direction. Here you can find more details:
https://www.scichart.com/documentation/win/current/webframe.html#3D%20Scene%20Lighting.html

You can also find our “Customize 3D Scene Lighting” example useful. Here is a link:
https://www.scichart.com/example/wpf-chart/wpf-3d-chart-customize-scene-lighting-example/

Please upgrade to the SciChart v6.4 or newer and let us know if this helps.

With best regards,
Lex S., MSEE
SciChart Technical Support Engineer

  • Lex answered 7 days ago
0 votes

Thank you! the css hack is weird but i think a good temp solution.

unfortunately, we have 15-20 heatmaps open at any time which more than 200,000 points, so doubling them is not practical. It will be good to get a sense on the time on the task. seems a bit behind in the priority list. 🙂

thank you,

Pramod

0 votes

Hello, the reason for the behavior is that Custom Annotations are rendering their SVG content onto the internal SVG layer which is placed above the Canvas where the series are rendered.

The ability to place annotation behind the series looks like a valuable feature.
There is an appropriate task in our backlog that we likely will try to implement.
You can observe its status here – https://abtsoftware.myjetbrains.com/youtrack/issue/SCJS-1507

Meanwhile, I would suggest trying out some workarounds.
You can reorder the canvas and SVG layers with a bit of extra CSS or JS code.
Here is one example of how to do it:

See the Pen
ScalableCustomAnnotation behind Canvas
by SciChart.js Official (@scichart)
on CodePen.

However, notice that this would affect all of the SVG annotations on the chart including some cursor tooltips…

Alternatively, you can stack an extra chart above or below the original one. Synchronize their visible ranges. And then separate annotation rendering with series rendering and gridlines between them.

0 votes

Hi Harut,

Thanks for your inquiry.
You can set the DataPointWidthMode property to Absolute to use the same column width in pixels set to the DataPointWidth property of both Could Series.
More details can be found in the “Specifying Column Width” of the following documentation article:
SciChart WPF 2D Charts: The Column Series Type

Hope this helps.

With best regards,
Lex S., MSEE
SciChart Technical Support Engineer

  • Lex answered 1 week ago
0 votes

Hi Fedor,

We discussed the provided details.
Your implementation looks correct.

There is an IsVisible property both in the RenderableSeries and SeriesInfo. They are synchronized so you can feel free to use any of them.

Regarding the RenderbleSeries order, the order of the Series in the Legend is based on the order in the RenderbleSeries collection. This it would be enough to organize the collection in the way you need.

With best regards,
Lex S., MSEE
SciChart Technical Support Engineer

  • Lex answered 1 week ago
0 votes

Hi Li,

Thanks for your inquiry.
I have noticed the RenderableSeries you refer to doesn’t look like our FastBandRenderableSeries:
https://www.scichart.com/documentation/win/current/webframe.html#The%20Band%20Series%20Type.html

​We can recommend taking a look at our custom SplineLineRenderableSeries instead featured in the following example:
https://www.scichart.com/example/wpf-chart/wpf-chart-example-spline-scatter-line-chart/

Is this what you are looking for?

With best regards,

Lex S., MSEE
SciChart Technical Support Engineer

  • Lex answered 2 weeks ago
0 votes

Hello,
So as far as I understand, you would need to modify the chart size and visible range before doing the export. And to not affect the original chart you want to do it on a separate hidden one.

Since the example of chart export is not a core feature of SciChart,
you should look for the info regarding exporting not visible element within the docs of corresponding library that is used for converting DOM element to an image.

FYI, we are working on an example of server side image export that may be useful for this case as well.

0 votes

Great thanks for Lex. As I expected knowledge database’s example helped me.
Looks like in

<Grid>
    <Grid.ColumnDefinitions>
        <ColumnDefinition Width="Auto" />
    </Grid.ColumnDefinitions>
    <ListView Grid.Column="0" x:Name="ChartsListView" BorderBrush="Transparent" ItemContainerStyle="{StaticResource ListViewItemContainerDefaultStyle}"
              ItemsSource="{Binding SeriesData.SeriesInfo}">
        <ListView.ItemTemplate>
            <DataTemplate>
                <Grid>
                    <Grid.ColumnDefinitions>
                        <ColumnDefinition Width="*" />
                        <ColumnDefinition Width="Auto" />
                    </Grid.ColumnDefinitions>
                    <Label Grid.Column="0" Style="{StaticResource LabelDefaultStyle}"
                           Content="{Binding SeriesName}" Visibility="{Binding IsVisible, Converter={StaticResource BooleanToVisibilityConverter}}" />
                    <Label Grid.Column="1" Style="{StaticResource LabelIndicatorStyle}"
                           Content="{Binding YValue}" />
                </Grid>
            </DataTemplate>
        </ListView.ItemTemplate>
    </ListView>
</Grid>

I nee to use

ItemsSource="{Binding RenderableSeries}"

instead of

ItemsSource="{Binding SeriesData.SeriesInfo}"

As I see RenderableSeries.IsVisible looks like that I need. And values for controls is in RenderableSeries.DataSeries.LatestYValue.

I need to check but if somebody (maybe from SciChart team) knows better way please show it.

0 votes

Hi Lex,

Eventually there was another requirement that “Shift” modifier will produce an X-axis pan, “Ctrl” modifier will produce Y-axis zoom, and “Alt” modifier will produce XY-axes zoom.

Therefore I eventually concluded that it would be easier to inherit “RelativeZoomModifierBase” and override “OnModifierMouseWheel” method.

public class XAxisZoomWithModifiers : RelativeZoomModifierBase
{
public XAxisZoomWithModifiers()
{
GrowFactor = .1;
}

public override void OnModifierMouseWheel(ModifierMouseArgs e)
{
base.OnModifierMouseWheel(e);
e.Handled = true;
if ((ExecuteWhen != MouseModifier.None) && ExecuteWhen != e.Modifier)
{
return;
}

SetZoomState(ZoomStates.UserZooming);
using IUpdateSuspender updateSuspender = ParentSurface.SuspendUpdates();

double arg = -e.Delta / 120.0;
if (e.Modifier == MouseModifier.Shift)
{
foreach (var axis in XAxes)
{
axis.Scroll(arg * GrowFactor * GetAxisSize(axis), ClipMode.None);
}
return;
}

var point = GetPointRelativeTo(e.MousePoint, base.ModifierSurface);

XyDirection = e.Modifier switch
{
MouseModifier.None => XyDirection.XDirection,
MouseModifier.Ctrl => XyDirection.YDirection,
_ => XyDirection.XYDirection,
};
PerformZoom(point, arg, arg);
}

protected virtual double GetAxisSize(IAxis axis)
{
double num = axis.IsHorizontalAxis ? axis.Width : axis.Height;
if (Math.Abs(num) < double.Epsilon && (ParentSurface != null) && (ParentSurface.RenderSurface != null))
{
num = axis.IsHorizontalAxis ? ParentSurface.RenderSurface.ActualWidth : ParentSurface.RenderSurface.ActualHeight;
}

if (axis.IsPolarAxis)
{
num /= 2.0;
}

return num;
}
}

  • Ben Mendel answered 3 weeks ago
  • last active 2 weeks ago
0 votes

Hello Raman,

We discussed your inquiry and would like to provide you with a few recommendations.

  1. Draw all 10000 polygons as a single Renderable Series. Creating each one as a separate Series leads to a huge impact on performance. Additionally, you can get coordinates in one batch calling the GetCoordinates(T[],Double[],Double)) method. Please take a look:
    https://www.scichart.com/documentation/win/current/webframe.html#SciChart.Data~SciChart.Charting.Numerics.CoordinateCalculators.ICoordinateCalculator%601~GetCoordinates.html

  2. Do not allocate a new array on each redraw. You can cache the array instead or use the ArrayPool class. You can find more details in the following Microsoft Learn article:
    https://learn.microsoft.com/en-us/dotnet/api/system.buffers.arraypool-1?view=net-8.0

  3. As Andrew has mentioned, resource creation like Brush or Pen is an expensive
    operation. So you should cache such resources and recreate them only when necessary. E.g. having a collection of such resources:

    var brush = new SolidColorBrush(color);
    using var sBrush = renderContext.CreateBrush(brush, Opacity);

Hope this helps.

With best regards,
Lex S., MSEE
SciChart Technical Support Engineer

  • Lex answered 3 weeks ago
  • last active 3 weeks ago
0 votes

I tried caching IBrush2D into a dictionary, but the problem remained the same. This probably helps by 5-10%, but no more. If I create f.e. 20000 polygons from 80000 points delays are long(1 -1.5s).

is it possible some how to get access CustomPolygonRenderableSeries from CustomPolygonRenderableSeries to manually control the Draw updates. like

protected override void Draw(IRenderContext2D renderContext, IRenderPassData renderPassData)
{
if (skipDrawing) return;
…..

Thanks!

0 votes

The percentage of the available area that the bar should fill is indicated by this number, which ranges from 0 to 1. Though I had assumed the reverse, that appeared to be the only attribute that might work. It is quite helpful to set that to 1.

Showing 1 - 20 of 6k results