Jump to content
  • Making Spotfire® Custom Visuals Render Nicely When Exporting


    Introduction

    This article describes what is needed to migrate an existing custom visual to work with the new Export to PDF that was introduced in version 7.10.

    See also

    Rendering custom visuals

    There are two ways for a visual to be rendered during export and preview generation. They can be rendered via the document model object, or via a web view. 

    Rendering via the model object

    This is the way custom visuals have been exported ever since they were introduced. In your model class, derived from CustomVisual, you override the CustomVisual.RenderCore method. In that override you render your custom visual using a .Net Graphics object.

    This works fine provided that your custom visual can be rendered this way. The framework will scale the graphics object so that it will get the expected resolution, and all rendering is done in a single synchronous call. 

    Rendering via a web view

    The second way is to render the visual through html, using a view based on CustomVisualView. In this case, you create a single view class that handles both rendering in the UI and rendering for export.  

    To make export operations go via the view, you need to override the CustomVisual.RenderUsingViewCore method and return true. This will make the framework create a new instance of your custom view class, and use it for rendering. When your view is rendered during export, there are a few things that are different, as described below.

    Static web views

    The view is a so called static view. Its model object is a readonly version of your custom visual. This means that any attempts to modify it will throw exceptions. You are only allowed to read information from it. You may still set up event handlers on it, but the events will never fire.

    There is a property, CustomVisualView.IsStatic, that can be used to detect if a view is static or not. This property is also available on the JavaScript side of the view, via the property Spotfire.viewProperties.isStatic

    Busy management

    Static views are expected to be rendered as fast as possible, for instance by turning off animations. However, given the asynchronous nature of html and JavaScript, it may be hard to determine when a visual has finished rendering itself.

    By default, the framework will assume your view has finished its rendering when it has no more outstanding read operations (initiated by calling Spotfire.read).

    If your view has more advanced requirements, for instance if it is loading images using other mechanisms, then you need to signal to the framework that the view is busy until all your resources are loaded.

    This is done by calling Spotfire.setBusy(true) as soon as your view has loaded (the SpotfireLoaded event triggers on the views frame), and then Spotfire.setBusy(false) when done.

    If you implement your own busy handling you need to make sure that Spotfire.setBusy(false) is always called, or export or preview rendering operations will hang.

    Raster Quality

    When rendering for export, the desired resolution of raster images is in general higher that when rendering for screen. The desired pixel ratio (the ratio between pixels in html/css and the pixels in the output) is typically a factor larger than 1.

    If your view renders itself using raster technology, for instance using html canvas or img elements, you need to take this into account. Otherwise your visual might appear pixelated and of poor quality. The ratio between the pixel coordinates in the view and the desired output can be retrieved from the property Spotfire.viewProperties.imagePixelRatio.

    The following example (taken from the TrafficLightChart SDK example) shows how to make a canvas based view render at a suitable resolution. It assumes width and height are given in css/html pixels, and that canvas is a canvas DOM element.

    var imagePixelRatio = Spotfire.viewProperties.imagePixelRatio;
    canvas.width = width * imagePixelRatio;
    canvas.height = height * imagePixelRatio;
    canvas.style.width = width + 'px';
    canvas.style.height = height + 'px';
    var ctx = canvas.getContext('2d');
    ctx.scale(imagePixelRatio, imagePixelRatio);
     

    Custom value renderers

    If you have implemented a CustomValueRenderer extension in order to render values in tables and axis labels, there is a new PixelRatio property on the ValueRendererArgs class that can be used to render images at the expected resolution.


    User Feedback

    Recommended Comments

    There are no comments to display.


×
×
  • Create New...