This is a migrated thread and some comments may be shown as answers.

Add vertical guideline

1 Answer 261 Views
Charts
This is a migrated thread and some comments may be shown as answers.
Anthony
Top achievements
Rank 1
Anthony asked on 20 Nov 2015, 08:24 PM
Using Kendo Charts, is it possible to add vertical guidelines? For example, on a chart showing all the days of this month vs. amount of remaining budget, I'd like there to be a red vertical line the height of the entire chart to indicate the current date. Thank You. 

1 Answer, 1 is accepted

Sort by
0
Accepted
EZ
Top achievements
Rank 2
answered on 23 Nov 2015, 05:38 PM

You could either use plotbands or draw on the chart surface.

 

For plotBands, have a look at categoryAxis.plotBands

 

$("#chart").kendoChart({
  theme: "Bootstrap",
  dataSource: data,
  series: [{
    type: "line",
    field: "value",
    categoryField: "day"
  }],
  valueAxis: {
    name: "value"
  },
  categoryAxis: {
    name: "category",
    plotBands: [
      { from: 15, to: 16, color: "red" }
    ]
  },
});

DEMO

 

For drawing, on render, you can get the axis objects and use slot and range to get the coordinates of the line to draw:

See Docs for ChartAxis and getAxis

 

$("#chart").kendoChart({
  theme: "Bootstrap",
  dataSource: data,
  series: [{
    type: "line",
    field: "value",
    categoryField: "day"
  }],
  valueAxis: {
    name: "value"
  },
  categoryAxis: {
    name: "category"
  },
  render: function(e){
         
    var chart = e.sender;
    var valueAxis = chart.getAxis("value");
    var categoryAxis = chart.getAxis("category");
     
    var catSlot = categoryAxis.slot(15,16);
    var valRange = valueAxis.range();
    var valSlot = valueAxis.slot(valRange.min, valRange.max);
     
    var path = new kendo.drawing.Path({
     stroke: {
      color: "red",
      width: 3
    }
    }).moveTo(catSlot.origin.x + catSlot.size.width/2, valSlot.origin.y)
      .lineTo(catSlot.origin.x + catSlot.size.width/2, valSlot.bottomRight().y);
 
    chart.surface.draw(path);   
         
  }
});

 

DEMO

Ryan
Top achievements
Rank 1
Iron
Iron
commented on 06 Apr 2023, 09:21 PM

This does not work right with panning and zooming capability enabled as below. How can I draw on the x-axis a vertical guideline based on an x-axis value? For me I have dates on the x-axis and I want to get the slot for that by date value and always have the vertical line drawn over that. Thank you.

pannable: {
      lock: "none"
    },
    zoomable: {
      mousewheel: {
        lock: "none",
      },
      selection: {
        lock: "none"
      }
    },
Erik
Top achievements
Rank 1
Iron
Iron
commented on 07 Apr 2023, 03:37 PM

You can use the chart events for 'drag', 'dragEnd', 'zoom', 'zoomEnd' to catch user pans and zooms and then re-render the line in the correct place.

DEMO

For this, I am deleting the line and re-creating it each time:

  function RenderVerticalLine(chart) {
    //remove old line
    chart.wrapper.find("svg > path").remove();
    
    //calc new position based on pan and zoom
    var valueAxis = chart.getAxis("value");
    var categoryAxis = chart.getAxis("category");
     
    var catSlot = categoryAxis.slot(15,16);     
    var valRange = valueAxis.range();
    var valSlot = valueAxis.slot(valRange.min, valRange.max);
    var yRange = categoryAxis.range();
    var xRangeSlot = categoryAxis.slot(yRange.min, yRange.max);

    //check if line is still in zoomed/panned view
    if (catSlot.origin.x <= xRangeSlot.origin.x) return;
    if (catSlot.origin.x >= xRangeSlot.origin.x + xRangeSlot.size.width) return;
     
    var path = new kendo.drawing.Path({
     stroke: {
      color: "red",
      width: 3
    }
    }).moveTo(catSlot.origin.x + catSlot.size.width/2, valSlot.origin.y)
      .lineTo(catSlot.origin.x + catSlot.size.width/2, valSlot.bottomRight().y);
 
    chart.surface.draw(path);   
  }

 

$("#chart").kendoChart({
  theme: "Bootstrap",
  dataSource: data,
  series: [{
    type: "line",
    field: "value",
    categoryField: "day"
  }],
  valueAxis: {
    name: "value"
  },
  categoryAxis: {
    name: "category",
  },
  
  render: function(e){
    RenderVerticalLine(e.sender);
  },
  zoom: function(e) {
     RenderVerticalLine(e.sender);
  },
  zoomEnd: function(e) {
     RenderVerticalLine(e.sender);
  },
  drag: function(e) {
     RenderVerticalLine(e.sender);
  },
  dragEnd: function(e) {
     RenderVerticalLine(e.sender);
  },
  
  pannable: {
      lock: "none"
    },
    zoomable: {
      mousewheel: {
        lock: "none",
      },
      selection: {
        lock: "none"
      }
    },
  
});



 

Ryan
Top achievements
Rank 1
Iron
Iron
commented on 07 Apr 2023, 04:52 PM

Hi,

This is helpful thank you. My issue is with this line:

categoryAxis.slot(15,16);

I need to get a slot for an axis value that is a date. Imagine the x-axis being Jan-23, Feb-23, Mar-23, Apr-23, May-23 displayed as such. I need to draw the vertical line where x-axis is Apr-23 (today's date). How would I get the slot for that so the line is always just above that?

Erik
Top achievements
Rank 1
Iron
Iron
commented on 07 Apr 2023, 06:31 PM | edited

I updated the DOJO with a date axis:

DEMO

Just use the date in the slot() call:

var catSlot = categoryAxis.slot(new Date("2011/12/26"),new Date("2011/12/27"));  

My demo uses days, you can use months or any other base unit...

Ryan
Top achievements
Rank 1
Iron
Iron
commented on 10 Apr 2023, 06:24 PM

Hi,

 

For the category axis I am using a label template like so:

categoryAxis: {
                color: 'white',
                labels: {
                    font: '4px',
                    rotation: 60,
                    template: "#= kendo.toString(new Date(value), 'MMM-yy') #"
                },
            },

I tried doing categoryAxis.slot(kendo.toString(new Date("2011/12/26"), "MMM-yy")); and categoryAxis.slot(new Date("2011/12/26")); and they did not work. I am still having to provide a number for the slot function to draw it in the right spot, but getting that number is difficult with panning/zooming. Without zoom/panning it is trivial to get the index.

Erik
Top achievements
Rank 1
Iron
Iron
commented on 10 Apr 2023, 06:45 PM

The label formatting has no effect on actual underlying data... See updated DEMO

Is your dataSource/Schema actually using a date object? Can you create an example DOJO?

Ryan
Top achievements
Rank 1
Iron
Iron
commented on 10 Apr 2023, 06:45 PM

data is bound from the DB in this format 2023-04-01T00:00:00
Ryan
Top achievements
Rank 1
Iron
Iron
commented on 10 Apr 2023, 06:47 PM

Despite it coming back as a DateTime from the C# side
Ryan
Top achievements
Rank 1
Iron
Iron
commented on 10 Apr 2023, 06:50 PM

categoryAxis.slot(dateField.toISOString().split('.')[0]); 
this seemed to work
Erik
Top achievements
Rank 1
Iron
Iron
commented on 10 Apr 2023, 06:53 PM | edited

Have you tried setting a Schema on the datasource just for the date column:

                schema: {
                    model: {
                        fields: {
                            Timestamp: {
                                type: "date"
                            }
                        }
                    }
                }

 

Change "Timestamp" to the actual key name for your date field

Erik
Top achievements
Rank 1
Iron
Iron
commented on 10 Apr 2023, 07:11 PM

I also get data back from c# as a string like this: 

"2023-04-10T00:00:00"

I then use the dataSource schema to force the conversion to a date object.

 

Erik
Top achievements
Rank 1
Iron
Iron
commented on 10 Apr 2023, 07:17 PM

Here is a new DOJO Demo with the schema and string date in the data:

http://dojo.telerik.com/@ezanker/oTetotog

Ryan
Top achievements
Rank 1
Iron
Iron
commented on 10 Apr 2023, 08:02 PM

Hi,

I am drawing a line and a label with a kendo.drawing.group, how would I remove those from the chart?

Ryan
Top achievements
Rank 1
Iron
Iron
commented on 10 Apr 2023, 08:04 PM

And I had to do this for some reason:
var catSlot = categoryAxis.slot(thisMonth.toISOString().split('.')[0], nextMonth.toISOString().split('.')[0]);
Ryan
Top achievements
Rank 1
Iron
Iron
commented on 10 Apr 2023, 08:12 PM

Basically need to remove my drawn group instead of this and I should be good to go:

chart.wrapper.find("svg > path").remove();

thank you!

Erik
Top achievements
Rank 1
Iron
Iron
commented on 11 Apr 2023, 03:32 PM

Telerik does not seem to have a way to set an ID for drawing elements (including groups) that would allow for easy selection. With the path, it was the only one at the top level of the svg, so I could just remove all paths found there. With groups, they use groups at the top level for the rest of the chart; so my hack is to create the group with opacity set to 0.99999:

var grp = new kendo.drawing.Group({opacity: 0.99999});

This does not affect display, and the Kendo automatically generated SVG groups are unlikely to have that exact opacity. Then to remove that group:

chart.wrapper.find("svg > g").each(function(idx){
  if ($(this).attr('opacity') && $(this).attr('opacity') == 0.99999){
    $(this).remove();
  }
});

Find all top level groups, and if opacity is 0.99999, remove tham.

Updated DEMO

I imagine someone at Telerik has a better way to do this, but this will get you going.

Ryan
Top achievements
Rank 1
Iron
Iron
commented on 11 Apr 2023, 03:35 PM

I ended up storing the kendo drawing group into a variable, if it is initialized in the draw line/label function then I removed it's elements and set the visibility to false. Not sure if that technically still renders the element with visibility false on it but it worked visually. I may try your method out instead because the element actually gets removed from the stack. thanks again for all your efforts and time!
Tags
Charts
Asked by
Anthony
Top achievements
Rank 1
Answers by
EZ
Top achievements
Rank 2
Share this question
or