Pre loader

Tag: BoxAnnotation

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

1 vote
2k views

I have a chart with a box annotation. When I try to resize the box annotation by dragging the left or right border, I got the “Uncaught TypeError: Cannot read properties of undefined (reading ‘x’)”. It’s not always reproducible and cannot be reproduced by dragging the whole box. Also, it only occurs with SciChart version 3 but not SciChart version 2. Please check the screenshots for more details.

  • Quyen Sy asked 1 year ago
  • last active 12 months ago
1 vote
13k views

Hi,

I’m creating a CustomChartModifier which I am able to hook to a SciStockChart (a template item in a SciChartGroup MVVM) and now I’m having difficulties in adding the BoxAnnotation to the Chart.

This is the code I’m using in my ChartModifier and placing a breakpoint shows me that indeed the code runs through this method, however, I do not see any BoxAnnotation on my chart? I’ve even tried adding the Height and Width properties without any further success. Other CustomModifiers to draw Lines and Ellipses works without problems. Do BoxAnnotations work differently?

I’m looking to have the the user be able to draw a BoxAnnotation on the chart, free hand / dynamically.

SimpleBoxAnnotationModifier.cs

public override void OnModifierMouseDown(ModifierMouseArgs e)
{
        base.OnModifierMouseDown(e);

        var resources = new AnnotationStyles();
        // x:Key="BoxAnnotationStyle" TargetType="s:BoxAnnotation"
        var style = (Style)resources["BoxAnnotationStyle"];

        _annotationCreation = new AnnotationCreationModifier () { AnnotationType = typeof(BoxAnnotation), AnnotationStyle = style };

        this.ModifierSurface.Children.Add(_annotationCreation);
}

AnnotationStyles.xaml

<ResourceDictionary xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
                xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
                xmlns:s="http://schemas.abtsoftware.co.uk/scichart"
                x:Class="ChartModifierBinding.AnnotationStyles">

<Style x:Key="BoxAnnotationStyle" TargetType="s:BoxAnnotation">
    <Setter Property="BorderBrush" Value="#279B27"/>
    <Setter Property="Background" Value="#551964FF"/>
    <Setter Property="BorderThickness" Value="1"/>
    <Setter Property="IsEditable" Value="True"/>
</Style>

Thanks for any pointers or tips!

  • David T asked 9 years ago
  • last active 7 years ago
0 votes
7k views

I’m using boxAnnotation Object with some properties

I use
.withDragDirections(Direction2D.XDirection)
.withResizeDirections(Direction2D.XDirection)
for resize and drag only x direction

It looks like drag and resize only x direction but the box resize y direction a little bit

I do not use any special properties using boxAnnotation

use of course .withIsEditable for editing
.withPosition, .withBackgroundDrawableId
that’ it

and I also wonder when i declare new CustomIResizingGrip object with new Canvas

why withDragDirections, withResizeDirections dont work?

  • cy bang asked 4 years ago
  • last active 4 years ago
0 votes
5k views

EDIT 3:

I figured out the problem. The reason why I did not see them was two-fold. The annotation view for some reason cannot infere the height of the parent (the chart) so setting match_parent as height doesn’t work and the view doesn’t have height. Second problem was that I have set .withPosition() with Y value as 0, and that would draw the view under the visible area of the chart.

So let me now ask new questions

1 Is there a possibility to move the annotation just by grabbing it, without first selecting it?
2 How can I change the red border when selecting the annotation?
3 How to set the annotation to return X value of it’s position from the center of its view and not from the start of its view
4 How do I restrict movement of the annotation to only X axis?

/// original question
Hello.

I have a problem with annotations. What I need to achieve, is to draw custom view (it’s fairly simple) on my chart, and this view should have always the height of the chart.

I can’t make it work, I am adding the annotation in exact same way as in example android project, and I even copied annotation code from your example project to mine, but for some reason it doesn’t work in my project.

this is the drawable:

<?xml version="1.0" encoding="utf-8"?>
<layer-list xmlns:android="http://schemas.android.com/apk/res/android">
<item android:width="40dp">
<color android:color="@color/secondary_18"/>
</item>
<item android:gravity="center_horizontal" android:width="4dp">
<color android:color="@color/secondary"/>
</item>
</layer-list>

EDIT: There is no < br > in this code ^

what I already tried:
1. Wrapping the drawable into layout consisting of <ImageView> with src= set to drawable
2. Creating a class extending View() class and then setting the imageResource there
3. inflating my layout first and then putting it inside .withContent()
4. using .withContent() directly with R.layout.some_layout_view
5. using it with .withBackgroundDrawableId()
6. various combinations with setting different widths and heights and .withPosition() and whatever you can think of

I managed to display the CustomAnnotation once (don’t remember with which combination of settings) but it wouldn’t move anyway despite the .withIsEditable(true) and despite it was “selected” (red border around it appeared on click)

my axes:

        val xAxis = sciChartBuilder.newNumericAxis()
        .withAxisId(X_AXIS_ID)
        .withDrawMajorBands(false)
        .withDrawMajorGridLines(false)
        .withDrawLabels(false)
        .withIsCenterAxis(true)
        .withDrawMinorTicks(false)
        .withDrawMinorGridLines(false)
        .withDrawMajorTicks(false)
        .build()

    val yAxis = sciChartBuilder.newNumericAxis()
        .withAutoRangeMode(AutoRange.Always)
        .withAxisId(Y_AXIS_ID)
        .withDrawMajorBands(false)
        .withDrawMajorGridLines(false)
        .withDrawMinorGridLines(false)
        .withDrawLabels(false)
        .withIsCenterAxis(true)
        .withDrawMajorTicks(false)
        .withDrawMinorTicks(false)
        .build()

    chartSurface.xAxes.add(xAxis)
    chartSurface.yAxes.add(yAxis)

my series:

 chartSurface.renderableSeriesAreaFillStyle = SolidBrushStyle(chartBackgroundColor)
    chartSurface.renderableSeriesAreaBorderStyle = SolidPenStyle(0x0, false, 0f, null)

    val mountainSeries = sciChartBuilder.newMountainSeries()
        .withDataSeries(dataSeries)
        .withStrokeStyle(SolidPenStyle(-0x1, true, 0f, null))
        .withAreaFillLinearGradientColors(-0x1, -0xed7422)
        .withXAxisId(X_AXIS_ID)
        .withYAxisId(Y_AXIS_ID)
        .build()

    chartSurface.renderableSeries.add(mountainSeries)

my control modifiers:

   val chartModifiers = sciChartBuilder.newModifierGroup()
        .withPinchZoomModifier()
        .withXyDirection(Direction2D.XDirection)
        .withReceiveHandledEvents(true)
        .withScaleFactor(0.8f)
        .build()
        .withZoomPanModifier()
        .withXyDirection(Direction2D.XDirection)
        .withClipModeX(ClipMode.ClipAtExtents)
        .withZoomExtentsY(true)
        .withReceiveHandledEvents(true)
        .build()
        .withZoomExtentsModifier()
        .withReceiveHandledEvents(true)
        .withXyDirection(Direction2D.XyDirection)
        .build()
        .build()

    chartSurface.chartModifiers.add(chartModifiers)

one example of many of how I tried to add the annotations:

        chartSurface.annotations.add(
        sciChartBuilder.newBoxAnnotation()
            .withContent(CustomView(context))
            .withXAxisId(X_AXIS_ID)
            .withYAxisId(Y_AXIS_ID)
            .withIsEditable(true)
            .build()
    )

ofc I also tried the same with CustomAnnotation and like I said with various other settings I could think of like .withPosition() and withResizingGrip. Curious thing is that VerticalLineAnnotation works with no problems really.

EDIT2:

Alternatively I could go with two VerticalLineAnnotations on top of each other moving together but I would have to be able to move them instantly, without selecting them first, because those circular handles look really bad and I have to disable them.

But later on I need to have box annotation working anyway, there will be X values selecting feature

1 vote
17k views

Hi, I am displaying no of BoxAnnotation , I want to link some of the BoxAnnotation randomly .I want to perform the operaton on annotation with relation.When it move BoxAnnotation,related link should also move accordingly.I am also performing Y axis with yaxisID so Annotation also move to Y direction with Y axis.
Please help me out.
Thanks

0 votes
11k views

Dear support,

What is the best way to anchor a GroupBox to the top right corner of a SciChartSurface (as shown in the attached screenshot)? At the moment, I am using an absolute positioning that often fails at initialization or when the surface is resized. I am looking into the annotation API, but have not yet found a clean solution.

Thank you,
Lucas

0 votes
12k views

How to change IsEditable behaviour for a annotation ?

Requirement is to allow Editing (Allow resizing box annotation only on X1 or X2 or Y1 or Y2 side).

It must be possible to specify which sides we can resize. (IsEditable on X1 or X2 or (X1 and X2) all combinations ). Because I’m programmatically creating box annotations.

1 vote
2k views

I am using the solution you provided on, https://www.scichart.com/questions/js/is-it-possible-to-create-info-box-that-will-sync-with-the-xaxis-of-the-chart.

The solution work great but there is one issue, the issue is that the text annotation should always be visible.

The issue with this solution is that the text annotation disappear if I zoom in somewhere not the text area.

Also another issue is that, in this example, the first info box x1 is beyond the current range, and so the text annotation is not visible, since the x1 of the text annotation is the same as info box and x1 is not within the current range.

First image show the first red info box x1 is not within current range, therefore not showing text annotation and the second info box working as expected with text annotation.

The second image show what happen once I zoom in on the right side away from the text annotation, then the ‘#21H’ is not visible anymore, which is wrong. Just like in my previous question example, the text annotation should always be visible, other than that, everything work great.

Thank you and let me know if there is any question.

  • Nung Khual asked 6 months ago
  • last active 6 months ago
0 votes
7k views

Hi,

I have made the chart vertical by changing X axis alignment to left and Y axis alignment to bottom. After changing like this, im not able to resize the box annotation using all four resize adorners. Only two working, other two resetting Y1 value. below is the code snippet.

<s:SciChartSurface.Annotations>
     <s:BoxAnnotation
         x:Name="rangeBox"
         AnnotationCanvas="AboveChart"
         Background="Red"
         ClipToBounds="False"
         CoordinateMode="RelativeX"
         DragDirections="YDirection"
         IsEditable="True"
         Opacity="0.3"
         ResizeDirections="YDirection"
         X1="{Binding TopDepth, Mode=OneWay, UpdateSourceTrigger=PropertyChanged}"
         X2="{Binding BottomDepth, Mode=OneWay, UpdateSourceTrigger=PropertyChanged}"
         Y1="0"
         Y2="1"
         YAxisId="Top" />
 </s:SciChartSurface.Annotations>
 <s:SciChartSurface.XAxis>
     <s:NumericAxis
         AutoRange="Once"
         AxisAlignment="Left"
         AxisTitle="Depth [ft]"
         DrawMajorBands="False"
         FlipCoordinates="{Binding FlipYAxis}"
         TitleStyle="{StaticResource AxisTitleStyle}" />
 </s:SciChartSurface.XAxis>
 <s:SciChartSurface.YAxis>
     <s:NumericAxis
         AxisAlignment="Bottom"
         BorderBrush="DarkGray"
         BorderThickness="0,0,0,1"
         DrawMajorBands="False"
         DrawMajorGridLines="True"
         Id="Top"
         TickTextBrush="DarkGray"
         TitleStyle="{StaticResource AxisTitleStyle}" />
 </s:SciChartSurface.YAxis>

Can you please let me know what i’ve missed?

Thanks
-MK

  • Sync Kumar asked 4 years ago
  • last active 4 years ago
0 votes
19k views

Hi,
I’ve created a custom annotation and have set it’s .IsEditable property in code so the user can reposition it. I have two issues:
1.I want the user to be able to resize the “PPZLine” in the X direction, but I can’t figure out how to get the anchor points to appear.

  1. I want to be able to see the chart data that the annotation is covering. I tried setting AnnotationCanvas = BelowChart, but then I couldn’t move the annotation or get any annotation mouse handlers to trigger.

Here’s the annoation’s xaml:

<s:CustomAnnotation x:Class="CinchV2DemoWPF.Views.SciChart.PPZView"
             xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
             xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
             xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
             xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
             xmlns:CinchV2="clr-namespace:Cinch;assembly=Cinch.WPF"
             xmlns:meffed="clr-namespace:MEFedMVVM.ViewModelLocator;assembly=MEFedMVVM.WPF"
             xmlns:Interactivity="clr-namespace:System.Windows.Interactivity;assembly=System.Windows.Interactivity"
             xmlns:s="clr-namespace:Abt.Controls.SciChart;assembly=Abt.Controls.SciChart.Wpf" 
             meffed:ViewModelLocator.ViewModel="PPZViewModel"

             X1="{Binding X1}"
             Y1="{Binding Y1}"
             mc:Ignorable="d" 
             d:DesignHeight="300" d:DesignWidth="300">
<Grid>
        <Grid.RowDefinitions>
            <RowDefinition Height="Auto"/>
            <RowDefinition Height="Auto"/>
            <RowDefinition Height="*"/>
        </Grid.RowDefinitions>

    <!-- price line must use margin 0,0 or obj will not be visible-->
        <s:BoxAnnotation Name="LongEntryMarker" Grid.Row="0"
                       Width="20"    Height="10"  Background="DarkViolet" Margin="0,0"  VerticalAlignment="Top" 
                         HorizontalAlignment="Right"
                         >
        </s:BoxAnnotation>

        <!-- long marker line MouseRightButtonDown="LongEntryMarker_OnMouseRightButtonDown"-->
        <s:BoxAnnotation Name="PPZLine" Grid.Row="1"
                       Width="150"    Height="5"  Background="red" Margin="0,0"  VerticalAlignment="Top" 
                         >
        </s:BoxAnnotation>
</Grid>
</s:CustomAnnotation>
  • tecman234 asked 11 years ago
  • last active 9 years ago
1 vote
15k views

Hi
I want to plot line chart on BoxAnnotation, so that BoxAnnotion become as a container.
i.e dataSeries.Append(100, 100);
dataSeries.Append(200, 150;
on BoxAnnotation
Please have a lool into the picture.

0 votes
2k views

Hello,
I am trying to add a BoxAnnotation with MVVM pattern where the X-Axis is a DateTime axis. The annotation can be dragged into the X-direction. I need to know the DateTime of each position while dragging and also the final position(DateTime) of the BoxAnnotation when the drag Ended. I am listening to the DragDelta and DragEnded events in ViewModel. But here I couldn’t able to get the DateTime from X1 and X2 of that annotation model. I am sharing some snippets of my code. Can you please let me know how I can achieve this?

In xaml:

<Style x:Key="_boxAnnotationStyle" BasedOn="{StaticResource AnnotationBaseStyle}" TargetType="scichart:BoxAnnotation">
        <Setter Property="Template">
            <Setter.Value>
                <ControlTemplate TargetType="scichart:BoxAnnotation">
                    <Border x:Name="PART_BoxAnnotationRoot"
              Margin="{TemplateBinding Margin}"
              Background="{TemplateBinding Background}"
              BorderBrush="{TemplateBinding BorderBrush}"
              BorderThickness="{TemplateBinding BorderThickness}"
              CornerRadius="{TemplateBinding CornerRadius}" />
                </ControlTemplate>
            </Setter.Value>
        </Setter>
</Style>
<scichart:SciChartSurface x:Name="GraphSurface"
                 Annotations="{scichart:AnnotationsBinding ItsAnnotations}">

                <scichart:SciChartSurface.XAxis>
                    <scichart:DateTimeAxis x:Name="GraphXAxis"
                                           VisibleRange="{Binding ItsTimeVisibleRange, Mode=TwoWay}" />
                </scichart:SciChartSurface.XAxis>

                <scichart:SciChartSurface.YAxes>
                    <scichart:NumericAxis x:Name="GraphYAxis"
                                          VisibleRange="0, 10" />

                </scichart:SciChartSurface.YAxes>
 </scichart:SciChartSurface>

In ViewModel.cs

{
    private DateRange _timeVisibleRange;
    private ObservableCollection<IAnnotationViewModel> _annotations;
    private IAnnotationViewModel _boxAnnotation;
    public ObservableCollection<IAnnotationViewModel> ItsAnnotations
    {
        get
        {
            return _annotations;
        }
    }
    public DateRange ItsTimeVisibleRange
    {
        get { return _timeVisibleRange; }
        set
        {
            if (_timeVisibleRange == value) return;
            _timeVisibleRange = value;
            RaisePropertyChanged(() => ItsTimeVisibleRange);
        }
    }
    .
    .
    .
    _boxAnnotation = new BoxAnnotationViewModel()
        {
            IsEditable = true,
            DragDirections = SciChart.Charting.XyDirection.XDirection,
            X1 = DateTime.UtcNow.AddSeconds(300),
            X2 = DateTime.UtcNow,
            Y1 = 0,
            Y2 = 8,
            StyleKey = "_boxAnnotationStyle"
        };

     _annotations = new ObservableCollection<IAnnotationViewModel>() { };
     _annotations.Add(_boxAnnotation );

     _captureTimeRangeSelectorAnnotation.DragDelta += OnDrag;
     _captureTimeRangeSelectorAnnotation.DragEnded += DragEnded;
       .
       .
       .
    private void DragEnded(object sender, EventArgs e)
    {
         var boxAnnotationModel = sender as BoxAnnotationViewModel;
          // Need to know the DateTime value of X1 and X2
    }
    private void OnDrag(object sender, AnnotationDragDeltaEventArgs e)
    {
         var boxAnnotationModel = sender as BoxAnnotationViewModel;
         // Need to know the DateTime value of X1 and X2
    }
    .....
    .....
}
0 votes
8k views

To whom this may concern:

I am following up to an issue that I posted a few years ago: https://www.scichart.com/questions/wpf/resizing-custom-annotations

I’ve attached a sample project that outlines what I am trying to accomplish. It is a simple scatter chart with randomized points in which I am trying to draw a rotatable ellipse annotation around the points.

The annotation inherits the “BoxAnnotation” class and replaces it’s template with an ellipse that is shaped to within the bounds of the annotation. This ellipse can be rotated by dragging the ellipse with the right-click button of the mouse. Upon doing so, in order to ensure the ellipse still maintains its shape when zooming in, the ellipse is converted to a geometric path. (Shown when the color of the ellipse changes from red to green.) Like this, when re-sizing the ellipse, it maintains its shape. After re-sizing, if the user wants to rotate the ellipse again, the original Ellipse UIElement re-surfaces and the Path UIElement is hidden. The user can then rotate the ellipse, which is in turn rendered back to a Path UIElement once again. The bounds of the annotation are modified to ensure the ellipse and its geometric path maintains its shape when switching between the Ellipse and the Path UIElements.

The issue is when re-sizing the annotation, and then attempting to rotate the ellipse again, the ellipse is clipped by the bounds of the annotation, even though “ClipToBounds” is set to false (in the code-behind). Unfortunately, I can’t find a pattern for which this occurs, and I have no solution to this issue. Examples of the clipped and non-clipped ellipses are shown in the attached images.

Hopefully the attached project is easy to understand. Can you please advise?

Thank you kindly!

— Ari

EDIT: Code attached as .ZIP file

  • Ari Sagiv asked 4 years ago
  • last active 4 years ago
1 vote
2k views

Hi, I want to create info boxes between xAxis and chart, info box will contain text, but the width/position of the box will be base on the xAxis and should sync with the chart (zoom etc). For example, if xAxis is from 1-100, and the first info box start from 1 to 10, then the width/position of the box should cover from 1-10, and if I zoom between 1-10, then info box should also sync and expand.

So far, I have created it using horizontal stacked xAxes and custom axis layout strategy provided by you. But the issue is that the stacked xAxes are not sync with the chart, for now, to make it seem sync, I am recalculating stacked axis length when zoom. But the issue comes when there should be gap between the info boxes, for example, if xAxis is 1-100 and the first box is 1-10 and the second box is 20-40, then there is a gap of 10 between the first and second. Right now, those gap are filled using empty xAxes, but they are not correct. When there is gap, the position of the boxes are wrong.

  • First image is my current implementation of it using custom axis layout and stacked xAxes.
  • Second image is how it look when zoomed
  • Third image is the gap issue with the current implementation
  • Fourth image is how the correct implementation should look like.

Codesanbox example:
https://codesandbox.io/s/scichart-stacked-xaxis-stacked-length-issue-3knt23?file=/src/App.tsx

  • Nung Khual asked 7 months ago
  • last active 7 months ago
1 vote
12k views

How to create custom annotation which has BoxAnnotation with a VerticalLine Annotation at one end.

At present I’m achieving this by creating both annotations and synchronizing them in ChartModifier.
Look at the attached image where you can see two BoxAnnotations both having a VerticalLineAnnotation at one end. I’m disabling editing for BoxAnnotation and enabling editing only for VerticalLineAnnotation.

When VerticalLineAnnotation is dragged in X-Direction, I get the X1 value from it and manually set it to BoxAnnotations X2.

This is not good implementation. I can see lag between sync events. Is it possible to create a custom annotation which incorporates both Box and Vertical line annotations ? Or is it possible to set IsEditing for BoxAnnotations One End only ?

0 votes
7k views

i wanna use vertical line annotation in box annotation that only one edge moves to drag like using ‘chart drag area to zoom’

I checked about custom annotation and there’s features said ‘common features of annotations’ but they don’t have any features l’m looking for

i put pictures for understanding.

there are box annotation on a graph and I want to move line to drag and box is going to smaller or larger

and i also want the other edge is fixed, it can not be dragged

do you guys have any tips for me?

  • cy bang asked 4 years ago
  • last active 4 years ago
2 votes
13k views

I want to have a BoxAnnotation where Y1 (- double.Infinity) and Y2 (+ double.Infinity). Basically I wanna specify only X1 and X2. And the behaviour must ensure always the box annotations Y1 & Y2 stretch to visible area even when I resize (zoomout) the chart.

In the screen shot its not stretched.

1 vote
6k views

Hi, so I need to get the data of an annotation when clicked, I have tried with addEventListener ‘mousedown’ event and it work for most case, but the issue comes when some annotations are overlapping.

codesandbox example: https://codesandbox.io/s/vertically-stacked-axes-forked-smkd8v?file=/src/App.tsx

In the codesandbox example, you will see that M1 and M2 are overlapping, if I were to click on M2, the click event will return both M1 and M2, but I only want M2 to be return since I only click on M2.

I couldn’t make the clicking to work on codesandbox but I’m sure you get the idea. I have tested it on my local and I got that issue.

Please let me know if you got any other question, thank you.

  • Nung Khual asked 5 months ago
  • last active 5 months ago
1 vote
1k views

When I’m using a BoxAnnotation, and it is selected, I can see that the borders are shown expanding past the chart area, on top of the axes.
Ideally they would have the same behaviour as the normal stroke, and keep constrained to the chart area.

Codepen showing the issue: https://codepen.io/jrfv/full/bGzqvoE

Am I missing some configuration to make this work?

Thanks!

0 votes
11k views

Hi,
I have the necessity to allow the user to draw one or several polygons upon a heatmap chart to let him select the region he is interested in. See attached image.

I don’t want to selected the markers inside the drawn polygon, only to know the coordinates (in data coordinates, not screen) of the various point that define the polygon.
I saw that the way to do this is to use Annotations however it’s not clear to me if is it possible to have the same behaviour of the BoxAnnotation but with a polygon (without any side number limit)?

Thank you,

Raphael

0 votes
7k views

I used box annotation like pic
in a boxAnnotation I used

.withIsEditable(true)
.withPosition(1,-2, 0, 2)
.withBackgroundDrawableId(R.drawable.example_box_annotation_background_4)
.withResizingGrip(customIResizingGrip)
.withAnnotationDragListener(customIAnnotationSelectionDrawable)
.withResizeDirections(Direction2D.XDirection)
.withDragDirections(Direction2D.XDirection)
.build();

and i made a 2 box like pic

i use box for drag one side to make a box big or small

the first box which is left doesn’t move anywhere.
it just can only drag that i want
but the second box, the box moves when i drag after first touch
the left box never moves on but right box moves first drags
just move first time not sometimes

am i wrong something?

  • Justin Lee asked 4 years ago
  • last active 4 years ago
1 vote
9k views

Hi everyone,

What would be the easiest way of shading all vertical bands for weekend days? I’ve got two ideas:

  1. Setting major band brush won’t work because there’s no way of setting only weekend bands to be major bands (as far as I know).
  2. Using box annotations.

Problem with 2nd option is that annotations are rendered over the chart (screenshot attached). Is there a way of sending them behind columns?

Thanks,
Igor

  • Igor Peric asked 7 years ago
  • last active 7 years ago
1 vote
13k views

I’m trying to put together a chart that adds a bar at the bottom, to visualise Y values going over specific thresholds (in this example, below 20 is Green, 20 to 30 range is Yellow, and over 30 is Orange), as shown here:
BoxAnnotations

The bar scales along with the line when zooming the chart
BoxAnnotationsZoomed

The version pictured builds the bar using box annotations, each defined as below:

new BoxAnnotationViewModel()
{
    X1 = currentXValue,
    X2 = currentXValue, + xValuesStepSize,
    Y1 = 0.96,
    Y2 = 1,
    Background = backgroundColor, //Colour calculated based on Y value
    AnnotationCanvas = AnnotationCanvas.AboveChart,
    CoordinateMode = AnnotationCoordinateMode.RelativeY
};

This implementation works, but the issue is that the bar is drawn inside the main chart area, and so covers some of the chart itself; if this could just be moved onto the X axis, rather than the chart canvas, then this would be exactly what I need.

I tried to just switch the canvas on the BoxAnnotations to use AnnotationCanvas.XAxis, but when doing this the annotations don’t seem to be getting the right X / Y coordinates for positioning – the width and height of each block looks correct, and the width scales when the chart is zoomed in, but every block appears to be positioned at 0,0 on the XAxis canvas (it looks like X1/Y1 values are ignored, so all blocks are stacked on top of each other in the same position rather than appearing alongside each other as a bar)
BoxAnnotationsOnAxis BoxAnnotationsOnAxisZoomed

With a bit of searching I found an old post (https://www.scichart.com/questions/wpf/annotation-on-axis) stating that ‘AxisMarkerAnnotation’ is the only supported annotation for display on an axis canvas, so I tried using this instead, which does seem to respect the X1 position. Here though, the X2 value seems be be interpreted as just a static pixel width, and the width of the annotations does not scale when the chart is zoomed, so the blocks stay as whatever width is initially drawn and get moved further apart the more the chart is zoomed in.
AxisMarkerAnnotations AxisMarkerAnnotationsZoomed

I’m new to SciChart so hopefully I’m missing something obvious; is there any way of either getting the BoxAnnotation to work on an axis canvas, or of setting an AxisMarkerAnnotation’s width to be the width between two points on the X axis, scaling along with the chart when zooming?

I hope the above makes sense, thanks in advance for your help.

0 votes
6k views

I am trying to use a BoxAnnotation to put an image on my graph. I am using BelowChart AnnotationCanvas so I can have the graph on top of the image. However, doing so also puts the grid lines on top of the annotation as well. Is there a way to keep the annotation below the chart but still keep it above the grid lines?

1 vote
5k views

Hi, Support team.

I’m using MVVM pattern and trying to implement multi-chart which can insert Box Annotations at the same time into each chart .
So I’m testing in SciChart Example [“DigitalAnalyzerPerformanceDemo”] to know how to implement this.

But what i only got is just looping through and create annotation for each ChannelViewModels.

In the Demo, the VisibleRange ‘XRange’ is shared to all the ChannelViewModels by binding TwoWay-mode in ParentViewModel without looping for each ChildViewModels.
Like this, I wonder is there ways to apply BoxAnnotation all the ChannelViewModel at the same time by binding in ParentViewModel.

    <!-- BottomAxis -->
        <s:SciChartSurface Grid.Column="1">
            <s:SciChartSurface.XAxis>
                <s:NumericAxis Height="30"
                               AxisAlignment="Bottom"
                               VisibleRange="{Binding XRange, Mode=TwoWay}"                 
                               LabelProvider="{StaticResource TimeLabelProvider}"
                               MajorTickLineStyle="{StaticResource TimeAxisMajorTickLineStyle}"
                               MinorTickLineStyle="{StaticResource TimeAxisMinorTickLineStyle}"/>
            </s:SciChartSurface.XAxis>
            <s:SciChartSurface.YAxis>
                <s:NumericAxis Visibility="Collapsed"/>
            </s:SciChartSurface.YAxis>
        </s:SciChartSurface>
    </Grid>

    <!--  Create an X Axis with GrowBy  -->
     <s:SciChartSurface.XAxis>
           <s:NumericAxis Style="{StaticResource HiddenAxisStyle}"
                    VisibleRangeLimitMode="Min"
                    VisibleRangeLimit="0,0"
                    VisibleRange="{Binding DataContext.XRange, Mode=TwoWay, RelativeSource={RelativeSource AncestorType=ItemsControl, AncestorLevel=2}}"/>
     </s:SciChartSurface.XAxis>

I tried to bind annotation in ParentViewModel like XRange Binding method, But it doesn’t work.


This is View.xaml.

<Grid Grid.IsSharedSizeScope="True" IsEnabled="{Binding IsLoading, Converter={StaticResource InvertBooleanConverter}}">


    <!-- BottomAxis -->
        <s:SciChartSurface Grid.Column="1">
            <s:SciChartSurface.XAxis>
                <s:NumericAxis Height="30"
                               AxisAlignment="Bottom"
                               VisibleRange="{Binding XRange, Mode=TwoWay}"                 
                               LabelProvider="{StaticResource TimeLabelProvider}"
                               MajorTickLineStyle="{StaticResource TimeAxisMajorTickLineStyle}"
                               MinorTickLineStyle="{StaticResource TimeAxisMinorTickLineStyle}"/>
            </s:SciChartSurface.XAxis>
            <s:SciChartSurface.YAxis>
                <s:NumericAxis Visibility="Collapsed"/>
            </s:SciChartSurface.YAxis>
        </s:SciChartSurface>
    </Grid>

    <!-- Channels -->
        <ScrollViewer Background="#1C1C1E"
                      VerticalScrollBarVisibility="Auto"
                      HorizontalScrollBarVisibility="Disabled">

            <b:Interaction.Behaviors>
                <common:DigitalAnalyzerScrollBehavior ChannelHeightDelta="10" ChangeChannelHeightCommand="{Binding ChangeChannelHeightCommand}"/>
            </b:Interaction.Behaviors>

            <ItemsControl x:Name="chartItemsControl" ItemsSource="{Binding ChannelViewModels}">

                <b:Interaction.Behaviors>
                    <common:FocusedChannelScrollBehavior ScrollToFocusedChannel="False"/>
                </b:Interaction.Behaviors>

                <ItemsControl.ItemTemplate>
                    <DataTemplate DataType="{x:Type local:ChannelViewModel}">
                        <Grid Background="#2D2C32" Height="{Binding ChannelHeight, Mode=OneWay}" Focusable="False" UseLayoutRounding="False" >
                            <Grid.ColumnDefinitions>
                                <ColumnDefinition SharedSizeGroup="ChannelNames" />
                                <ColumnDefinition />
                            </Grid.ColumnDefinitions>

                            <Border BorderThickness="0,0,0,1" BorderBrush="#1C1C1E">
                                <DockPanel>
                                    <Border DockPanel.Dock="Left"     
                                            Background="{Binding ChannelColor, Mode=OneWay}" 
                                            Width="5"/>

                                    <TextBlock DockPanel.Dock="Left"
                                               Margin="10,5"
                                               VerticalAlignment="Center"
                                               Foreground="White"
                                               Text="{Binding ChannelName}"/>
                                </DockPanel>
                            </Border>

                            <s:SciChartSurface x:Name="channelSurface" Grid.Column="1"
                                               RenderableSeries="{Binding RenderableSeries}"
                                               Annotations="{s:AnnotationsBinding  DataContext.Annotations, Mode=TwoWay, RelativeSource={RelativeSource AncestorType=ItemsControl, AncestorLevel=2} }">

                                <!--  Create an X Axis with GrowBy  -->
                                <s:SciChartSurface.XAxis>
                                    <s:NumericAxis Style="{StaticResource HiddenAxisStyle}"
                                                   VisibleRangeLimitMode="Min"
                                                   VisibleRangeLimit="0,0"
                                                   VisibleRange="{Binding DataContext.XRange, Mode=TwoWay, RelativeSource={RelativeSource AncestorType=ItemsControl, AncestorLevel=2}}"/>
                                </s:SciChartSurface.XAxis>

                                <!--  Create a Y Axis with GrowBy. Optional bands give a cool look and feel for minimal performance impact  -->
                                <s:SciChartSurface.YAxis>
                                    <s:NumericAxis Style="{StaticResource HiddenAxisStyle}"
                                                   VisibleRange="{Binding YRange, Mode=OneWay}"/>
                                </s:SciChartSurface.YAxis>

                                <s:SciChartSurface.ChartModifier>
                                    <s:ModifierGroup s:MouseManager.MouseEventGroup="ChannelModifierGroup">
                                        <s:RubberBandXyZoomModifier IsAnimated="False" IsXAxisOnly="True" ZoomExtentsY="False" ReceiveHandledEvents="True" IsEnabled="{Binding IsChecked, Mode=OneWay, ElementName=IsZoomEnabled}"/>
                                        <s:ZoomPanModifier ZoomExtentsY="False" XyDirection="XDirection" IsEnabled="{Binding IsChecked, Mode=OneWay, ElementName=IsPanEnabled}"/>
                                        <s:ZoomExtentsModifier XyDirection="XDirection" IsAnimated="False" />
                                        <s:MouseWheelZoomModifier XyDirection="XDirection" />
                                    </s:ModifierGroup>
                                </s:SciChartSurface.ChartModifier>
                            </s:SciChartSurface>

                            <Border Grid.Column="1"
                                    BorderThickness="0,0,0,1"
                                    BorderBrush="#2D2C32"
                                    VerticalAlignment="Bottom"/>
                        </Grid>
                    </DataTemplate>
                </ItemsControl.ItemTemplate>
            </ItemsControl>
        </ScrollViewer>
    </Border>


</Grid>

This is ViewModel.cs

public class DigitalAnalyzerExampleViewModel : BaseViewModel
{
    private bool _isLoading;
    private DoubleRange _xRange;

    public DigitalAnalyzerExampleViewModel()
    {
        ChannelViewModels = new ObservableCollection<ChannelViewModel>();
        Annotations = new ObservableCollection<IAnnotationViewModel>();
        Annotations.Add(new BoxAnnotationViewModel() { X1 = 0, X2 = 1000, Y1 = 0, Y2 = 1 }); //I want to implement sharing annotation like this.

        SelectedChannelType = "Digital";
        SelectedChannelCount = 32;
        SelectedPointCount = 1000000;
        SelectedResamplingPrecision =ResamplingPrecision.Default;
        SelectedStrokeThickness = 1;

        ChangeChannelHeightCommand = new ActionCommand<object>((d) =>
        {
            var delta = (double)d;
            foreach (var channelViewModel in ChannelViewModels)
            {
                channelViewModel.SetChannelHeightDelta(delta);
            }
        });

        AddChannelCommand = new ActionCommand(async () =>
        {
            IsLoading = true;

            var isDigital = SelectedChannelType == "Digital";
            await AddChannels(isDigital ? 1 : 0, isDigital ? 0 : 1);

            IsLoading = false;
        });

        LoadChannelsCommand = new ActionCommand(async () =>
        {
            IsLoading = true;

            // Clear ViewModels
            foreach (var channelVm in ChannelViewModels)
            {
                channelVm.Clear();
            }
            ChannelViewModels.Clear();
            XRange = null;

            // Create a bunch of Digital channels
            await AddChannels(SelectedChannelCount, 0);

            XRange = new DoubleRange(0, SelectedPointCount);
            IsLoading = false;
        });

        LoadChannelsCommand.Execute(null);
    }


    public ObservableCollection<ChannelViewModel> ChannelViewModels { get; private set; }
    public ObservableCollection<IAnnotationViewModel> Annotations { get; private set; }

    public string SelectedChannelType { get; set; }


    public ResamplingPrecision SelectedResamplingPrecision { get; set; }

    public int SelectedChannelCount { get; set; }

    public ActionCommand<object> ChangeChannelHeightCommand { get; }

    public ActionCommand AddChannelCommand { get; }

    public ActionCommand LoadChannelsCommand { get; }

    public long TotalPoints => ChannelViewModels.Sum(c => (long)c.DataCount);

    public bool IsLoading
    {
        get => _isLoading;
        set
        {
            _isLoading = value;
            OnPropertyChanged(nameof(IsLoading));
        }
    }

    public bool IsEmpty => ChannelViewModels.Count <= 0;

    public DoubleRange XRange
    {
        get => _xRange;
        set
        {
            _xRange = value;
            OnPropertyChanged(nameof(XRange));
        }
    }
}

+Attached image below is what i want to implement.
++I also attached tried code in .zip .

0 votes
9k views

Hi,
I am creating iOS aplication which displays charts based on stocks data.
I want to create box annotations to show when market is open or closed.
I am using CategoryDateTimeAxis to display data but when i add AnnotationCollection with BoxAnnotations to Surface i can not see the annotations.

This is my code for creating box Annotation:

    let pre = SCIBoxAnnotation()
    pre.coordinateMode = .relative
    pre.x1 = SCIGeneric(setDate(date, 4, 0, 0)!)
    pre.x2 = SCIGeneric(setDate(date, 9, 30, 0)!)
    pre.y1 = SCIGeneric(max )
    pre.y2 = SCIGeneric(0)
    pre.isEditable = false
    pre.style.fillBrush = SCISolidBrushStyle(color: #colorLiteral(red: 0.01680417731, green: 0.1983509958, blue: 1, alpha: 0.13))
    pre.style.borderPen = SCISolidPenStyle(color: .clear, withThickness: 0)
  • Marcin C asked 6 years ago
  • last active 6 years ago
1 vote
2k views

Hi,

I have added a data series and also a custom box annotation which is overlapping the data series.
But the question is I am trying to move the box annotation which drag and drop but have to clip on the data series as well.
May I know if is scichart js able to do so? Or best if I just convert it into svg and make it drag and drop will do?

  • eva yeoh asked 1 year ago
  • last active 1 year ago
0 votes
9k views

In WPF, I am trying to allow user to resize a box annotation by holding the mouse on its side edges and dragging the mouse to left or right. By default, the box annotation allows to resize only by its round shaped holders appearing on top corners. Is there any way to allow such functionality?

So far, I have thought of placing two vertical annotations inside the box annotation template exactly on its edges and then sync their X coordinates with that of the box by two way binding. However, it is not an easy way to do it and also it does not work when used together as a single custom annotation or composite annotation.

Please suggest if any property can be tweaked for box annotation to achieve this?

  • Anil Soman asked 5 years ago
  • last active 5 years ago
1 vote
8k views

I have a chart that allow users to add one BoxAnnotation and multiple CustomAnnotation (a marker). I got error and failed to drag the BoxAnnotation with the following steps:

Step 1: Call the addMarkerAnnotation() to add a CustomAnnotation

const markerSvgString = '<svg height="26" width="18" xmlns="http://www.w3.org/2000/svg">' +
    '<polygon id="SVG_ID" fill="#000" fill-opacity="0.5" stroke="#00fc00" stroke-width="1.5" points="0,12 8,0 16,12 8,24" clip-path="url(#clip_normal)" />' +
    '<clipPath id="clip_normal"><use xlink:href="#SVG_ID"/></clipPath>' +
    '<text x="5" y="16" fill="#00fc00" font-weight="bold" font-size = "12">MARKER_ID</text>' +
'</svg>';

const deltaSvgString = '<svg height="28" width="28" xmlns="http://www.w3.org/2000/svg">' +
    '<polygon id="SVG_ID" fill="#000" fill-opacity="0.5" stroke="#00fc00" stroke-width="1.5" points="0,0 12,24 22,0" clip-path="url(#clip_delta)" />' +
    '<clipPath id="clip_delta"><use xlink:href="#SVG_ID"/></clipPath>' +
    '<text x="5" y="10" fill="#00fc00" font-weight="bold" font-size="10">MARKER_ID</text>' +
'</svg>';

const addMarkerAnnotation = useCallback((markerId, mode, x1, y1) => {   
    x1 = parseFloat(x1);
    y1 = parseFloat(y1);

    if (x1 != null && y1 != null) {
        let svgString;
        const svgId = "markerSvg_" + markerId;

        if (mode.includes("Delta")) {
            const compareMarkerKey = mode.replace("Delta ", "");
            svgString = deltaSvgString.replace(/MARKER_ID/g, (parseInt(markerId)+1) + "-" + compareMarkerKey);
        } else {
            svgString = markerSvgString.replace(/MARKER_ID/g, parseInt(markerId)+1);
        }
        svgString = svgString.replace(/SVG_ID/g, svgId);

        markerAnnotations.current[markerId] = new CustomAnnotation({
            x1,
            y1,
            id: markerId,
            isEditable: true,
            isSelected: true,
            verticalAnchorPoint: EVerticalAnchorPoint.Center,
            horizontalAnchorPoint: EHorizontalAnchorPoint.Center,
            svgString: svgString
        });
        sciChartSurfaceRef.current.annotations.add(markerAnnotations.current[markerId]);
        reorderMarkers(markerId);

        markerAnnotations.current[markerId].dragEnded.handlers.push(() => {
            let annotation = markerAnnotations.current[markerId];
            let freq = annotation.x1 * FREQ_UNITS.KHZ;

            markersInfoSetter.current[markerId](origMarkerInfo => ({...origMarkerInfo, ...{freq: freq.toFixed(numDP.FREQ), power: annotation.y1.toFixed(numDP.POWER)}}));

            if (markersInfoObj.current[markerId].mode !== "Fixed") {
                getMarkerPeak(markerId, markersInfoObj.current[markerId].trace, annotation.x1 * FREQ_UNITS.GHZ);
            }
            reorderMarkers(markerId);
        });
    }
}, [deltaSvgString, markerSvgString, getMarkerPeak, reorderMarkers, numDP]);

Step 2: Call the removeMarkerAnnotation() to remove the CustomAnnotation

const removeMarkerAnnotation = useCallback((markerId) => {
    if (markerAnnotations.current[markerId]) {
        sciChartSurfaceRef.current.annotations.remove(markerAnnotations.current[markerId]);
        markerAnnotations.current[markerId].delete();
        markerAnnotations.current[markerId] = null;
    }
}, []);

Step 3: Call addTriggerAnnotation() to add a BoxAnnotation

const addTriggerAnnotation = useCallback((x1, x2, y2) => {
    x1 = parseFloat(x1);
    x2 = parseFloat(x2);    
    y2 = parseFloat(y2);

    if (x1 != null && x2 != null) {
        console.log("addTriggerAnnotation: ", x1, x2, triggerAnnotation.current, sciChartSurfaceRef.current.annotations);
        if (!triggerAnnotation.current) {
            triggerAnnotation.current = new BoxAnnotation({
                id: "triggerBox",
                fill: "transparent",
                stroke: "#93A3B1",  //#93A3B1   //#6B818C
                strokeThickness: 2,
                xCoordinateMode: ECoordinateMode.DataValue,
                x1: x1,
                x2: x2,
                yCoordinateMode: ECoordinateMode.DataValue,
                y1: minY,
                y2: y2,
                isEditable: true,
                resizeDirections: EXyDirection.XyDirection,     
            });
            sciChartSurfaceRef.current.annotations.add(triggerAnnotation.current);

            triggerAnnotation.current.dragDelta.handlers.push(() => {
                triggerAnnotation.current.y1 = minY;

                const minX =  specSettingsRef.current.start/freqUnits.KHZ;
                const maxX = specSettingsRef.current.stop/freqUnits.KHZ;
                const maxY = specSettingsRef.current.refLevel;

                if (minX != null && maxX != null) {
                    if (triggerAnnotation.current.x1 < minX) {
                        triggerAnnotation.current.x1 = minX;
                    } else if (triggerAnnotation.current.x1 > maxX) {
                        triggerAnnotation.current.x1 = maxX;
                    } else if (triggerAnnotation.current.x2 > maxX) {
                        triggerAnnotation.current.x2 = maxX;
                    } else if (triggerAnnotation.current.x2 < minX) {
                        triggerAnnotation.current.x2 = minX;
                    }
                }

                if (maxY != null) {
                    if (triggerAnnotation.current.y2 < minY) {
                        triggerAnnotation.current.y2 = minY;
                    } else if (triggerAnnotation.current.y2 > maxY) {
                        triggerAnnotation.current.y2 = maxY;
                    }
                }
            });

            triggerAnnotation.current.dragEnded.handlers.push(() => {
                const maxX = specSettingsRef.current.stop/freqUnits.KHZ;
                const x1 = triggerAnnotation.current.x1;
                const x2 = triggerAnnotation.current.x2;
                const y2 = triggerAnnotation.current.y2;

                if (x1 != null && x2 != null && maxX != null) {
                    if (x1 > x2) {
                        triggerAnnotation.current.x1 = x2;
                        triggerAnnotation.current.x2 = x1;
                    } else if (x2 < x1) {
                        triggerAnnotation.current.x1 = x2;
                        triggerAnnotation.current.x2 = x1;
                    } else if (x1 === x2) {
                        if (x2 + xInterval.current <= maxX) {
                            triggerAnnotation.current.x2 = x2 + xInterval.current;
                        } else {
                            triggerAnnotation.current.x1  = x1 - xInterval.current;
                        }
                    }

                    const origStartFreq = parseFloat(triggersRef.current.startFreq);
                    const origStopFreq = parseFloat(triggersRef.current.stopFreq);
                    const newStartFreq = parseFloat((triggerAnnotation.current.x1 * freqUnits.KHZ).toFixed(numDP.FREQ));
                    const newStopFreq = parseFloat((triggerAnnotation.current.x2 * freqUnits.KHZ).toFixed(numDP.FREQ));

                    if (origStartFreq !== newStartFreq || origStopFreq !== newStopFreq) {
                        setTriggers(origObj => ({...origObj, ...{
                            startFreq: newStartFreq, 
                            stopFreq: newStopFreq,
                            level: parseFloat(y2.toFixed(numDP.POWER)),
                        }}));
                    }
                }
            });
        } else {
            updateTriggerAnnotation(x1, x2, y2);
        }
    }
}, [setTriggers, freqUnits.KHZ, numDP.FREQ, numDP.POWER, minY, updateTriggerAnnotation]);

Step 4: Drag the BoxAnnotation. It’s failed to drag the box and got the error “Uncaught TypeError: Cannot read properties of undefined (reading ‘seriesViewRect’)”.

It’s a strange bug as it can only be reproduced with the steps above. With the following steps, I can drag the BoxAnnoation without problem:

Step 1 -> Step 3 -> Step 4
Step 3 -> Step 4
Step 3 -> Step 1 -> Step 2 -> Step 4

  • Quyen Sy asked 1 year ago
  • last active 1 year ago
Showing 29 results

Try SciChart Today

Start a trial and discover why we are the choice
of demanding developers worldwide

Start TrialCase Studies