[CLOSED] RectangleSprite height is cut off in cartesian chart

  1. #1

    [CLOSED] RectangleSprite height is cut off in cartesian chart

    Dear EXT.NET Team,

    I have a question regarding my custom chart and the renderer. I am adding a rectangle Sprite to the chart based on my store data. The rectSprites have a dynamic height, proportional to the ChartColumn's height. You can see the implementation in ErrorChart.cshtml: 87-88; 110. The result right now is not wished, because the rectSprite height is cut off, if the ChartColumn's height value is too big. You can see it in the Screenshot below. The height is not being scaled and it gets cut off (the column where teh pointer is in the screenshot):
    Click image for larger version. 

Name:	2017-02-03 12_12_06-Error Chart - My ASP.png 
Views:	75 
Size:	31.2 KB 
ID:	24835

    The Question is, how can I make the rectSprite height and ChartColumn's height scale to eachother without being cut off?

    ErrorChart.cshtml:
    @using Ext.Net
    @using Ext.Net.MVC
    @{
        ViewBag.Title = "Error Chart";
        var X = Html.X();
    }
    
    @(Html.X().ResourceManager())
    
    <!DOCTYPE html>
    <html>
        <head>
            <meta charset="utf-8" />
            <meta name="viewport" content="width=device-width, initial-scale=1.0">
            <title>@ViewBag.Title</title>
    
            <script>
                var axesScaleFactor = 0.9;
                var onSwipe = function(e) {
                    var offset = parseInt(App.Offset.value);
                    switch (e.direction) {
                    case "left":
                        App.Offset.setValue(offset + 1);
                        break;
                    case "right":
                        App.Offset.setValue(offset - 1);
                        break;
                    case "down":
                    case "up":
                        handleUpDown(e.direction);
                        console.log(App.AggregationId.value + ' swiped ' + e.direction);
                        break;
                    default:
                    }
                    //console.log(App.Offset.value +' swiped ' + e.direction);
                    App.ChartStore.reload();
    
                }
                Number.prototype.mod = function(n) {
                    return ((this % n) + n) % n;
                }
                var handleUpDown = function(direction) {
                    var aggs = ['Hour', 'Day', 'Week'];
                    var index = aggs.indexOf(App.AggregationId.value);
                    if (direction == 'down') index++;
                    else index--;
    
                    App.AggregationId.setValue(aggs[index.mod(3)]);
                    var aggrName = aggs[index.mod(3)];
    
                    var rndNumber = Math.floor((Math.random() * 1000) + 100);
                    App.Comparison.setText("Vergleich Vorjahr: " + Math.floor((Math.random() * 1200) + -300));
    
                    switch (aggrName) {
                    case "Day":
                        App.Frequency.setText("Wochenfrequenz: " + rndNumber);
                        break;
                    case "Week":
                        App.Frequency.setText("Jahresfrequenz: " + rndNumber);
                        break;
                    case "Hour":
                        App.Frequency.setText("Tagesfrequenz: " + rndNumber);
                        break;
                    default:
                    }
    
                }
    
                function renderData(sprite, config, rendererData, index) {
                    var store = rendererData.store,
                        storeItems = store.getData().items,
                        record = storeItems[index],
                        surface = sprite.getParent(),
                        sprites,
                        rectSprite,
                        changes = {};
    
                    if (!record) {
                        return;
                    }
                    var past = record.get("Past");
                    var present = record.get("Present");
    
                    if (!past || !present)
                        return; //no need to further handle rendering
    
                    var dataDiff = present - past;
                    var spriteHeight = (dataDiff / present) * config.y;
    
                    var spriteColor = dataDiff > 0 ? 'green' : 'red';
                    sprites = surface.mysprites;
    
                    if (!sprites) {
                        sprites = surface.mysprites = [];
                    }
    
                    rectSprite = sprites[index];
    
                    if (!rectSprite) {
                        rectSprite = sprites[index] = surface.add({ type: 'rect' });
                    } else {
                        rectSprite.show();
                    }
    
                    config.y = config.y * axesScaleFactor;
                    rectSprite.setAttributes({
                        x: config.x,
                        y: config.y + 2,
                        width: config.width,
                        height: Math.abs(spriteHeight), // --> spriteHeight is the dynamical height for the rectSprite (See line:88-89),
                        fillStyle: spriteColor,
    
                    }, true); //todo avoidcopy=true as well?
    
                    return changes;
                }
    
                function renderTooltipS1(toolTip, record, ctx) {
    
                    var past = record.get("Past");
                    var present = record.get("Present");
                    var forecast = record.get("Forecast");
    
                    if (forecast != null) {
                        toolTip.setHtml('Forecast: ' + forecast);
                    } else {
                        var dataDiff = present - past;
                        toolTip.setHtml("<content>" +
                            "<div>" +
                            "<ul>" +
                            "<li>Present: " + present + "</li>" +
                            "<li>Past: " + past + "</li>" +
                            "<li>Diff: " + dataDiff + "</li>" +
                            "</ul>" +
                            "</div>" +
                            "</content>");
                    }
    
                }
            </script>
        </head>
        <body>
            @(Html.X().Container()
                  .ID("ChartContainer")
                  .Height(800)
                  .Layout(LayoutType.VBox)
                  .LayoutConfig(new VBoxLayoutConfig()
                  {
                      Align = VBoxAlign.Stretch,
                      Pack = BoxPack.Start
                  })
                  .Items(
                      X.Container().Layout(LayoutType.Card)
                          .ID("passerbyCardLayout")
                          .Flex(7)
                          .Items(
                              X.CartesianChart()
                                  .ID("passersbyChart")
                                  .Flex(3)
                                  .SetActiveItem(0)
                                  .Plugins(p => p.Add(X.ChartItemEvents()))
                                  .Listeners(l => { l.Swipe.Fn = "onSwipe"; })
                                  .Bin(
                                      X.Hidden().ID("Offset").Value(0))
                                  .InsetPadding(40).Flex(1)
                                  .Store(Html.X().Store().ID("ChartStore")
                                      .Model(Html.X().Model().Fields(f =>
                                      {
                                          f.Add(Html.X().ModelField().Name("Intervall"));
                                          f.Add(Html.X().ModelField().Name("Present"));
                                          f.Add(Html.X().ModelField().Name("Past"));
                                      })).Proxy(Html.X().RestProxy().AppendAction(false).Reader(
                                          Html.X().JsonReader().RootProperty("data")).API(urls => { urls.Read = Url.Action("GenerateDummyData", "Chart", new {locationId = Guid.NewGuid()}); })
                                      ).Parameters(pm => { pm.Add(new StoreParameter("offset", "App.Offset.value", ParameterMode.Raw)); })
                                  )
                                  .Axes(
                                      Html.X().CategoryAxis()
                                          .Position(Position.Bottom)
                                          .Fields("Intervall")
                                          .Label(Html.X().ChartLabel().RotationDegrees(-45))
                                  )
                                  .Series(
                                      Html.X().BarSeries()
                                          .XField("Intervall")
                                          .StyleSpec(Html.X().Sprite()
                                              .FillStyle("#0000CD"))
                                          .YField(new[] {"Present"})
                                          .Titles(new[] {"Present"})
                                          .Renderer(r => r.Fn = "renderData")
                                          .Tooltip(Html.X().ChartTip().TrackMouse(true)
                                              .Renderer(x => x.Fn = "renderTooltipS1"))
                                  ))                  
                  ))
        </body>
    </html>
    Controller:
      public StoreResult GenerateDummyData()
            {
                //get the location
                //get the counts for location with granularity and offset
                var data = new List<object>();
                var rnd = new Random();
             
                    //Hour aggregation
                    for (var i = 8; i < 14; i++)
                    {
                        data.Add(new { Intervall = i + ":00", Present = rnd.Next(5, 12), Past = rnd.Next(5, 12) });
                    }
          
                return new StoreResult(data);
            }
    Last edited by fabricio.murta; Feb 27, 2017 at 11:33 AM.
  2. #2
    Hello @nikolai!

    I believe you would have this done by charts itself if you just used the stacked chart approach but something tells me you don't really want to use the stacked charts, right?

    If stock stacked charts as shown above is not an option I can't see you adjusting the maximum on the y-axis if you don't actually bind an y-axis to the chart. With simply fixing a maximum value enough to show all charts I could see the charts' space but still feels like more work on the renderer will be necessary in order to show the complementary bars right.

    At first, by adding this axis:
    Html.X().NumericAxis()
        .AxisID("y")
        .Fields("Present")
        .Position(Position.Left)
    to the .Axes() will allow you for example to

    var ordinateAxis = App.passerbyChart.getAxis('y');
    ordinateAxis.setMaximum(20);
    Without sending the chart a refresh command, you'll see no difference. But then just hover the mouse over the chart blue bars, and it will refresh, reflecting the change you made.

    So maybe one way to solve this would be to track a variable in the series or axis object holding the value of the highest rendered column (with value being present+previous -- or is it present+diff?) and then when loading data send an axis.setMaximum() as shown above to the axis. I believe a good place to set this is on the chart store's load event, when it will have all data and will be able to calculate the value height you need. Pretty much I believe this is ways of "re-implementing" the stacked charts approach and checking how the example linked first in this thread works will probably show better ways to develop this behavior yourself.

    Hope this helps and that I could understand your actual question!
    Last edited by fabricio.murta; Feb 27, 2017 at 11:32 AM.
  3. #3
    Hello again @nikolai!

    Been some time since we replied you here but still no feedback from you. Do you still need help here?

    Notice we may mark this thread as closed if you don't post a follow-up in 7+ days from now, but you will still be able to post here when you are able to respond.
    Fabrício Murta
    Developer & Support Expert
  4. #4
    Hey Fabricio,

    Sorry for not answering back, I have totally forgotten. Your answer was very good and I could fix my problem. You can mark this thread as closed. Wish you a nice day.

    Nikolay
  5. #5
    Hello Nikolay!

    Glad it helped, and thanks for the feedback! And I just noticed a typo in the post (code block) from my side which I should have fixed before. :)
    Fabrício Murta
    Developer & Support Expert

Similar Threads

  1. [CLOSED] Increase the height of legend, Change line color of chart
    By praveencat123 in forum 2.x Legacy Premium Help
    Replies: 1
    Last Post: Aug 26, 2015, 2:26 PM
  2. [CLOSED] Cartesian Chart Menu Popup on data point
    By Sobhia in forum 3.x Legacy Premium Help
    Replies: 4
    Last Post: May 27, 2015, 1:52 PM
  3. [CLOSED] Cartesian Chart's Highlight
    By RCN in forum 3.x Legacy Premium Help
    Replies: 2
    Last Post: Mar 03, 2015, 10:45 AM
  4. Replies: 1
    Last Post: May 13, 2014, 4:09 PM
  5. [CLOSED] Line chart getting shrink, due to legend box Height
    By PriceRightHTML5team in forum 2.x Legacy Premium Help
    Replies: 4
    Last Post: May 08, 2014, 9:12 AM

Tags for this Thread

Posting Permissions