Search Results for

    Show / Hide Table of Contents

    PointMarker API

    SciChart features a rich PointMarkers API to annotate the data-points of certain series with markers, e.g. Ellipse, Square, Triangle, Cross or a Custom Shape marker. Some series types, such as XyScatterRenderableSeries or FastImpulseRenderableSeries, require a PointMarker assigned to them unless they won't render at all.

    This article is about how to configure and add PointMarkers to a IRenderableSeries to render markers for every data point.

    PointMarkers API

    Note

    Examples of using PointMarkers API can be found in the SciChart Android Examples Suite as well as on GitHub:

    • Native Example

    PointMarker Types

    SciChart provides several PointMarker shapes out of the box which can be found below:

    • EllipsePointMarker
    • TrianglePointMarker
    • SquarePointMarker
    • CrossPointMarker
    • SpritePointMarker

    It is possible to change how point markers appears by extending any of the above classes. The SpritePointMarker allows to render a point marker from a Bitmap. For more details, refer to the Custom PointMarkers section down the page.

    All the PointMarker types conforms to the IPointMarker protocol, which provides the following properties for styling point markers:

    IPointMarker property Description
    size Allows to specify the size of a PointMarker. PointMarkers will not appear if this value isn't set. The units are in user space coordinate system
    strokeStyle Specifies a stroke pen of the PenStyle type. It contains information about the Color, Stroke Thickness, etc.
    fillStyle Specifies a fill brush of the BrushStyle type. It contains information about the fill Color and the desired type of visual output.
    Note

    To learn more about Pens and Brushes and how to utilize them, please refer to the PenStyle, BrushStyle and FontStyle article.

    Using PointMarkers

    Code for creation and assigning a PointMarker to a IRenderableSeries is essentially the same regardless of a PointMarker type. After an instance of it has been created, it can be configured and then applied to the pointMarker property:

    • Java
    • Java with Builders API
    • Kotlin
    // Create an Ellipse PointMarker instance
    final EllipsePointMarker pointMarker = new EllipsePointMarker();
    pointMarker.setSize(40, 40);
    pointMarker.setStrokeStyle(new SolidPenStyle(Color.GREEN, false, 2.0f, null));
    pointMarker.setFillStyle(new SolidBrushStyle(Color.RED));
    
    // Apply the PointMarker to a LineSeries
    final FastLineRenderableSeries lineSeries = new FastLineRenderableSeries();
    lineSeries.setPointMarker(pointMarker);
    
    // Create an Ellipse PointMarker instance
    final EllipsePointMarker pointMarker = sciChartBuilder.newPointMarker(new EllipsePointMarker())
            .withSize(40)
            .withStroke(Color.GREEN, 2.0f)
            .withFill(Color.RED)
            .build();
    
    // Apply the PointMarker to a LineSeries
    final FastLineRenderableSeries lineSeries = sciChartBuilder.newLineSeries()
            .withPointMarker(pointMarker)
            .build();
    
    // Create an Ellipse PointMarker instance
    val pointMarker = EllipsePointMarker()
    pointMarker.setSize(40, 40)
    pointMarker.strokeStyle = SolidPenStyle(Color.GREEN, false, 2.0f, null)
    pointMarker.fillStyle = SolidBrushStyle(Color.RED)
    
    // Apply the PointMarker to a LineSeries
    val lineSeries = FastLineRenderableSeries()
    lineSeries.pointMarker = pointMarker
    

    The code above will produce the following chart (assuming that the data has been added to the Line Series):

    PointMarker Example

    Custom PointMarkers

    There are two ways of creating custom PointMarkers in SciChart. The first one involves using our RenderContext2D API for drawing, and the second allows to use CoreGraphics drawing capabilities.

    Extend DrawablePointMarker

    This technique requires extending the DrawablePointMarker class and overriding the its internalDraw(IRenderContext2D renderContext, float x, float y, IPen2D strokePen, IBrush2D fillBrush) method which is called for every data point in a series. In the implementation, a PointMarker can be drawn calling methods from IRenderContext2D. The code below demonstrates how custom EllipsePointMarker can be created using this approach:

    • Java
    • Java with Builders API
    • Kotlin
    class EllipsePointMarker extends DrawablePointMarker {
        @Override
        protected void internalDraw(IRenderContext2D renderContext, float x, float y, IPen2D strokePen, IBrush2D fillBrush) {
            renderContext.drawEllipse(x, y, getWidth(), getHeight(), strokePen, fillBrush);
        }
    }
    
    class EllipsePointMarker extends DrawablePointMarker {
        @Override
        protected void internalDraw(IRenderContext2D renderContext, float x, float y, IPen2D strokePen, IBrush2D fillBrush) {
            renderContext.drawEllipse(x, y, getWidth(), getHeight(), strokePen, fillBrush);
        }
    }
    
    class EllipsePointMarker : DrawablePointMarker() {
        override fun internalDraw(renderContext: IRenderContext2D, x: Float, y: Float, strokePen: IPen2D, fillBrush: IBrush2D) {
            renderContext.drawEllipse(x, y, width.toFloat(), height.toFloat(), strokePen, fillBrush)
        }
    }
    

    However, the RenderContext2D API has its own limitations. It isn't suitable for drawing complex custom shapes. Besides, calling drawing methods for every data point is redundant and is an overkill. So the second technique, described in the following paragraph, is better suited for most cases.

    Implement ISpritePointMarkerDrawer

    This approach is rather different. It allows to draw a shape on Android Canvas with Android Paint objects. Then, a sprite is created out of the Canvas, which is rendered for every data point in a series.

    This requires creating an object which conforms to SpritePointMarker.ISpritePointMarkerDrawer protocol and pass it's instance into the SpritePointMarker initializer, like shown below:

    • Java
    • Java with Builders API
    • Kotlin
    class CustomPointMarkerDrawer implements SpritePointMarker.ISpritePointMarkerDrawer {
        private final Drawable drawable;
    
        CustomPointMarkerDrawer(Context context, @DrawableRes int drawableId) {
            this.drawable = ResourcesCompat.getDrawable(context.getResources(), drawableId, null);
        }
    
        @Override
        public void onDraw(Canvas canvas, Paint stroke, Paint fill) {
            drawable.setBounds(0, 0, canvas.getWidth(), canvas.getHeight());
            drawable.draw(canvas);
        }
    }
    
    final IPointMarker pointMarker = new SpritePointMarker(
            new CustomPointMarkerDrawer(requireContext(), R.drawable.example_weather_storm)
    );
    pointMarker.setSize(40, 40);
    
    // Apply the PointMarker to a LineSeries
    final FastLineRenderableSeries lineSeries = new FastLineRenderableSeries();
    lineSeries.setPointMarker(pointMarker);
    
    class CustomPointMarkerDrawer implements SpritePointMarker.ISpritePointMarkerDrawer {
        private final Drawable drawable;
    
        CustomPointMarkerDrawer(Context context, @DrawableRes int drawableId) {
            this.drawable = ResourcesCompat.getDrawable(context.getResources(), drawableId, null);
        }
    
        @Override
        public void onDraw(Canvas canvas, Paint stroke, Paint fill) {
            drawable.setBounds(0, 0, canvas.getWidth(), canvas.getHeight());
            drawable.draw(canvas);
        }
    }
    
    final IPointMarker pointMarker = sciChartBuilder.newPointMarker(
            new SpritePointMarker(new CustomPointMarkerDrawer(requireContext(), R.drawable.example_weather_storm))
    )
            .withSize(40, 40)
            .build();
    
    // Apply the PointMarker to a LineSeries
    final FastLineRenderableSeries lineSeries = sciChartBuilder.newLineSeries()
            .withPointMarker(pointMarker)
            .build();
    
    class CustomPointMarkerDrawer(context: Context, @DrawableRes drawableId: Int) :
        ISpritePointMarkerDrawer {
        private val drawable: Drawable? = ResourcesCompat.getDrawable(context.resources, drawableId, null)
    
        override fun onDraw(canvas: Canvas, stroke: Paint, fill: Paint) {
            drawable!!.setBounds(0, 0, canvas.width, canvas.height)
            drawable.draw(canvas)
        }
    }
    
    val pointMarker: IPointMarker = SpritePointMarker(
        CustomPointMarkerDrawer(requireContext(), R.drawable.example_weather_storm)
    )
    pointMarker.setSize(40, 40)
    
    // Apply the PointMarker to a LineSeries
    val lineSeries = FastLineRenderableSeries()
    lineSeries.pointMarker = pointMarker
    

    This would result in the following chart:

    Custom PointMarker Drawer

    Back to top © 2011-2025 SciChart. All rights reserved. | sitemap.xml