SciChart® the market leader in Fast WPF Charts, WPF 3D Charts, and iOS Chart & Android Chart Components

0
0

See the Attached image — On the right side in addition to the labels 0.01% – 20.0%; Their is a color coded chart of AAA through C/D.

I need this to also be part of the chart; or maybe a separate control that can be transformed and zoomed based on where the chart is at.

If I’m zoomed in on the 0.15% – 0.50% then the B/BB/BBB should also be zoomed in to match the current scale of the chart.

Ideas on how to handle this. I’ve tagged this question as Android, but I will also need a solution for iOS.

Version
3
Images
  • You must to post comments
0
0

Hi Nathanael,

Unfortunately we don’t support anything like this out of the box.

I would suggest to create a custom View, because that behavior which you describe looks complex. Then you can setVisibleRangeChangeListener() for right yAxis to get notifications when VisibleRange changes and based on newRange value update your custom View to match scale of axis. As for adding it into the chart – it can be difficult to do, because this would require customization of chart’s layout ( e.g. you can add it directly into the chart or you can add it into axis ) and it would be more difficult to do than place chart and your custom view into some common parent like LinearLayout. Are you sure that you need this?

Best regards,
Yura

  • You must to post comments
0
0

Hi Nathanael,

I created some example based on our Line Chart example to show how you can place custom View inside chart which uses custom LayoutManager for chart and VisibleRangeChangeListener. I didn’t write any logic for custom View except some horizontal lines, because I don’t know about your requirements:

public class LineChartFragment extends ExampleBaseFragment {

@BindView(R.id.chart)
SciChartSurface surface;

@Override
protected int getLayoutId() {
    return R.layout.example_single_chart_fragment;
}

@Override
protected void initExample() {
    final IAxis xAxis = sciChartBuilder.newNumericAxis().withGrowBy(0.1d, 0.1d).withVisibleRange(1.1, 2.7).build();
    final IAxis yAxis = sciChartBuilder.newNumericAxis().withGrowBy(0.1d, 0.1d).build();

    final DoubleSeries fourierSeries = DataManager.getInstance().getFourierSeries(1.0, 0.1, 5000);
    final IXyDataSeries<Double, Double> dataSeries = sciChartBuilder.newXyDataSeries(Double.class, Double.class).build();
    dataSeries.append(fourierSeries.xValues, fourierSeries.yValues);

    final FastLineRenderableSeries rSeries = sciChartBuilder.newLineSeries().withDataSeries(dataSeries).withStrokeStyle(0xFF279B27, 1f, true).build();

    UpdateSuspender.using(surface, new Runnable() {
        @Override
        public void run() {
            Collections.addAll(surface.getXAxes(), xAxis);
            Collections.addAll(surface.getYAxes(), yAxis);
            Collections.addAll(surface.getRenderableSeries(), rSeries);
            Collections.addAll(surface.getChartModifiers(), sciChartBuilder.newModifierGroupWithDefaultModifiers().build());

            // create custom view and define how much space to reserve for it drawing
            final Context context = getActivity();
            final CustomView customView = new CustomView(context);
            final int size = (int) TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, 20, context.getResources().getDisplayMetrics());

            // subscribe to changes of VisibleRange
            yAxis.setVisibleRangeChangeListener(customView);

            // add custom view into chart and use custom layout with new logic to correctly perform layout
            surface.setLayoutManager(new CustomLayoutManager(customView, size));
            surface.addView(customView);
        }
    });
}

class CustomLayoutManager extends DefaultLayoutManager {
    private final CustomView customView;
    private final int customViewWidth;

    public CustomLayoutManager(CustomView customView, int customViewWidth) {
        super(new LeftAlignmentOuterAxisLayoutStrategy(), new RightAlignmentOuterAxisLayoutStrategy(), new TopAlignmentOuterAxisLayoutStrategy(), new BottomAlignmentOuterAxisLayoutStrategy(),
                new LeftAlignmentInnerAxisLayoutStrategy(), new RightAlignmentInnerAxisLayoutStrategy(), new TopAlignmentInnerAxisLayoutStrategy(), new BottomAlignmentInnerAxisLayoutStrategy());

        this.customView = customView;
        this.customViewWidth = customViewWidth;
    }

    @Override
    public Size onLayoutChart(int width, int height) {
        // reserve some space for custom view on right side
        final int newWidth = width - customViewWidth;
        final Size size = super.onLayoutChart(newWidth, height);

        // set layout rect for custom view
        customView.layoutArea(newWidth , 0, width, size.height);

        return size;
    }
}

class CustomView extends View implements ILayoutable, VisibleRangeChangeListener {
    private final Rect layoutRect = new Rect();

    private final Paint paint = new Paint();

    private final FloatValues coordsToDraw = new FloatValues();

    private final Runnable requestLayoutRunnable = new Dispatcher.RequestLayoutRunnable(this);
    public CustomView(Context context) {
        super(context);

        paint.setColor(Color.RED);
        paint.setStrokeWidth(4f);
    }

    @Override
    protected void onDraw(Canvas canvas) {
        super.onDraw(canvas);

        // draw stub data as horizontal lines
        final float width = getWidth();
        synchronized (coordsToDraw) {
            for (int i = 0; i < coordsToDraw.size(); i++) {
                final float yCoord = coordsToDraw.get(i);
                canvas.drawLine(0f, yCoord, width, yCoord, paint);
            }
        }
    }

    @Override
    public void layoutArea(int left, int top, int right, int bottom) {
        if(layoutRect.left != left || layoutRect.top != top || layoutRect.right != right || layoutRect.bottom != bottom) {
            layoutRect.set(left, top, right, bottom);
            post(requestLayoutRunnable);
        }
    }

    @Override
    public final Rect getLayoutRect() {
        return layoutRect;
    }

    @Override
    public final int getLayoutWidth() {
        return layoutRect.width();
    }

    @Override
    public final int getLayoutHeight() {
        return layoutRect.height();
    }

    @Override
    public void onVisibleRangeChanged(IAxisCore axis, IRange oldRange, IRange newRange, boolean isAnimating) {
        final ICoordinateCalculator coordCalc = axis.getCurrentCoordinateCalculator();

        final double min = coordCalc.getMinAsDouble();
        final double max = coordCalc.getMaxAsDouble();
        final double step = (max - min) / 6;

        // generate some stub data to draw at
        synchronized (coordsToDraw) {
            coordsToDraw.clear();

            double current = DoubleUtil.roundDown(min, 1);
            while (current <= max) {
                coordsToDraw.add(coordCalc.getCoordinate(current));
                current += step;
            }
        }
        postInvalidate();
    }
}
}

Hope this will help you!

Best regards,
Yura

Images
  • You must to post comments
0
0

I’m not sure that will work properly with Logrithmic data; the onVisibleRange changes will give me .03 to 10.00 and if I scroll the view port it may give me 3 to 7. Using a straight minus will give me a completely different range, despite being at the same zoom factor.

Looks like using log10 on the new range numbers will get me a valid range that doesn’t change depending on the viewport; but having a hell of a time trying to use those numbers to know how much I need to scale my control. So maybe I approach it a different way; say the initial chart is at scale of 1.0; then I pinched zoom in, the AxisY is now 1.8 scale and AxisX is at 1.2 scale. Is their some way I can get the AxisY scaled value; so I know the scale up should be 1.8?


Also related to the example above, and another site example trying to combine into this:
https://www.scichart.com/documentation/android/current/webframe.html#Axis%20Ranging%20-%20Restricting%20VisibleRange.html
(Advanced VisibleRange Clipping) seems to cause a stack overflow if used on Logrithmic numbers. 🙁 My if statement is:

                let r = newRange.getMinAsDouble();
                console.log("R", r, resetingRange);
                if (r < 0.018 && !resetingRange) {
                    resetingRange = true;
                    console.log("Reseting Range", oldRange.getMinAsDouble());
                    yAxis.setVisibleRange(oldRange);
                    resetingRange = false;
                    return
                }

It appears that dropping the zoom below 0.018; actually fires the setVisibleRange; but the very next value pushed into this callback the same number under 0.018 and a stack overflow occurs internally inside the engine (not from my code, as I safe guard going back into the range resetting code until the first one is done — this event appears to be not thread safe; as we have entered it a second time before my call to setVisibleRange has returned, so the resetingRange is still true…

I see the following information printed exactly as so (w/o the <— Comments ):

JS: …. -< Many good ‘R’ values truncated as I was zooming in and then back out….
JS: ‘R’ 0.018785923122271588 false 0.018
JS: ‘R’ 0.01695036880907571 false <– First Bad Value < 0.018
JS: ‘Reseting Range’ 0.018785923122271588 <– Inside the If statement, attempting to reset the range back to the oldRange
JS: ‘R’ 0.01695036880907571 true
System.err: StackTrace:
System.err: java.lang.StackOverflowError: stack size 8MB
System.err: at com.scichart.core.utility.ComparableUtil.a(SourceFile:177)
System.err: at com.scichart.core.utility.ComparableUtil.isDefined(SourceFile:263)
System.err: at com.scichart.data.model.RangeBase.getIsDefined(SourceFile:187)
System.err: at com.scichart.charting.visuals.axes.AxisCore.isValidRange(SourceFile:1101)
System.err: at com.scichart.charting.visuals.axes.LogarithmicNumericAxis.isValidRange(SourceFile:115)
System.err: at com.scichart.charting.visuals.axes.AxisCore.isValidVisibleRange(SourceFile:1092)
—– These four lines below are repeated for ever….
System.err: at com.scichart.charting.visuals.axes.AxisCore$2.onRangeChanged(SourceFile:270)
System.err: at com.scichart.data.model.RangeBase.a(SourceFile:322)
System.err: at com.scichart.data.model.RangeBase.setMinMaxForced(SourceFile:144)
System.err: at com.scichart.data.model.RangeBase.setMinMax(SourceFile:131)

  • Yura Khariton
    The example which I provided isn’t fully functional ( it’s just a stub, because I don’t know all your requirements ). It just demonstrates how to place custom View into chart like on your screenshot and listen to VisibleRange changes. Regarding your question about scale – I don’t understand what this means. Can you provide more information about this?
  • Yura Khariton
    Regarding stack overflow – you should never change VisibleRange from inside VisibleRangeChangeListener because this will lead to another call of listener which will lead to recursive calls. If you want to discard some VisibleRange values before applying then you need to create custom axis and override isValidVisibleRange() and return false when value isn’t valid and should be discarded. Also you can override coerceVisibleRange() and adjust VisibleRange if it’s invalid
  • Nathanael Anderson
    On the first issue; Scale — I mean if I have the image all the way zoomed out so the range of numbers is 1-10. Lets pretend this is scale 1.0. If I zoom in and only the numbers 5-10 are visible The “scale” of the chart is “2” times normal. Is their a way to get that “scale” value; i.e. what everything is being scaled by when it is drawing it? Or is the only thing available is the number range visible?
  • Nathanael Anderson
    On the second issue (Stack Overflow) the code I use that crashes is from the documentation that I linked too. This is the demo your doc’s give on how to adjust the size dynamically. So then the docs will be needed to be updated, because as it stands right now; it gives a stack overflow if I follow the example… https://www.scichart.com/documentation/android/current/webframe.html#Axis%20Ranging%20-%20Restricting%20VisibleRange.html (Advanced VisibleRange Clipping)
  • You must to post comments
Showing 3 results
Your Answer

Please first to submit.