Okay so i have the following highChart tag:
<highchart id="chart1" config="chartConfig" ></highchart>
Now in my system i have several tabs. it happens to be that the high chart is not under the first tab.
Now when i press the tab that contains the chart, the chart looks abit odd:
(You can't tell from this picture but it is only using like 30% of the total width)
But change the browser size and then changing it back to normal the chart places it self correctly inside the element (this also happens if i just open the console while i am inside the tab):
I am guessing that it has something to do with the width of the element once it has been created (maybe because it is within another tab) but i am unsure how to fix this.
I attempted to put a style on the element containg the highchart so that it would look something like this: <highchart id="chart1" config="chartConfig style="width: 100%"></highchart>
However this resulted in the chart running out of the frame.
My chart config
$scope.chartConfig = {
};
$scope.$watchGroup(['login_data'], function(newValues, oldValues) {
// newValues[0] --> $scope.line
// newValues[1] --> $scope.bar
if(newValues !== oldValues) {
$scope.chartConfig = {
options: {
chart: {
type: 'areaspline'
}
},
series: [{
data: $scope.login_data,
type: 'line',
name: 'Aktivitet'
}],
xAxis: {
categories: $scope.login_ticks
},
title: {
text: ''
},
loading: false
}
}
});
Can you try one of the following in your controller? (or perhaps both!)
$timeout(function() {
$scope.chartConfig.redraw();
});
$timeout(function() {
$scope.chartConfig.setSize();
});
Calling the reflow method solved my similar issue on showing chart in a modal. Hope this will help others :D
Add this to your controller after $scope.chartConfig:
$scope.reflow = function () {
$scope.$broadcast('highchartsng.reflow');
};
Related
On my chart using Chart.js I have an annotation created with the chartjs-plugin-annotation. I would like the annotation label to be visible on hover over the line. But I can't get it to work. I have the following code:
//define ChartOneData
var ctx = document.getElementById("chart").getContext("2d");
var chartOne = new Chart(ctx, {
type: 'line',
data: chartOneData,
options: {
annotation: {
events: ["mouseenter", "mouseleave"],
annotations: [{
type: 'line',
mode: 'vertical',
scaleID: 'x-axis-0',
value: 1,
label: {
enabled: false,
content: "Text Label",
},
onMouseenter: function(e) {
var element = this;
element.options.label.enabled = true;
element.chartInstance.update();
},
onMouseleave: function(e) {
var element = this;
element.options.label.enabled = false;
element.chartInstance.update();
}]
}
}
}
}
The events fire and change the attribute 'enabled' (visible in console testing) but the chart, and visuals, do not update.
In fact I receive the error in the console:
Unable to preventDefault inside passive event listener invocation.
dispatcher # chartjs-plugin-annotation.js:261
I don't understand this, can anyone help?
So it turned out that this was an issue with the underlying pluging. The code was correct and worked with chart.js versions 2.5 and 2.6 but not with 2.7. An issue was added to the chart-annotations github repository.
The solution was to downgrade to 2.6 and await a fix in the next version of charts.js
I'm trying to use C3.js(c3js.org) to make charts, but I want to specify everything but the data(and any other minor deviations unique to that chart) once then reuse that for all charts of that variation(a specific configuration of a chart).
All the documentation and all examples I've found for C3.js only deal with how you make a single chart. Applying that to multiple charts means a lot of repeated code and doesn't ensure consistency when making changes.
The only thing related to this that I've found is a concept on making reusable charts in D3.js(d3js.org), the underlying library used by C3.js, and an implementation inspired by that concept. That doesn't really help me because I want the higher-level abstraction that C3.js provides but these may give you an idea what I'm looking for.
I have found no info on this but one idea is to make a chart type that is based on an existing type but that also include the extra configuration(for example make a new chart type called 'horizontalbar' based on the existing 'bar' chart type).
Here is a chart I've made, bindto and columns are the unique parts of this chart, the rest should be part of a template, but I don't know how.
var chart = c3.generate({
bindto: '#chart',
data: {
columns: [
['data1', 125.2],
['data2', 282.7],
['data3', 3211.1],
['data4', 212.2],
['data5', 131.1],
['data6', 329.7]
],
type: 'pie',
order: null
},
pie: {
label: {
format: function (value, ratio, id) {
return d3.format('.1f')(ratio*100)+'%'; //percent with one decimal
}
}
},
tooltip: {
format: {
value: function (value, ratio, id, index) {
return value+'mkr ('+d3.format('.1f')(ratio*100)+'%)'; //example: 155.2mkr (3.3%)
}
}
},
legend: {
item: {
onclick: function () {} //disable clicking to hide/show parts of the chart
}
}
});
<link href="https://cdnjs.cloudflare.com/ajax/libs/c3/0.4.9/c3.min.css" rel="stylesheet" />
<script src="https://cdnjs.cloudflare.com/ajax/libs/d3/3.5.3/d3.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/c3/0.4.9/c3.min.js"></script>
<div id="chart"></div>
I have this in my html:
<script src="../static/js/test.js"></script> <!-- this is the js file contains the drawChart function -->
<div class='chart'>
<div id='chart1'></div>
</div>
<script>drawChart('chart1','pathToCsvData',ture, 200);</script>
in my js code:
function drawChart(toChart,dataURL,showLegend,chartHeight)
{
var chart1 = c3.generate({
bindto: toChart,
data: {
url: dataURL,
labels: false
},
color: {pattern: ['green','black']},
zoom: {enabled: false},
size: {height: chartHeight},
transition: {duration: 0},
legend: {show: showLegend}
});
}
the js code serve as a template, and I can as many different template I want, put them in functions, with customized chart parameters, and the call the js function in html code.
I have enabled my pie chart to have multiple sections selected. (Not yet got it working as I want it though). Open SO questions here
But once I get this done, I would like to return the list of selected sections everytime a change in made in any selection.
Can someone please suggest. !!
My COde:
series: [{
name: 'Departments',
// allowPointSelect : true,
slicedOffset: 0,
states: {
select: {
color: 'red'
}
},
point: {
events: {
click: function(event){
//this.slice(null);
this.select(null, true);
filterCharts(cloneDonutData.Departments, dChart.series[0].name,this.name);
//console.log(this.series[0].chart.getSelectedPoints());
}
}
} ,
data: ....
]
USe: http://api.highcharts.com/highcharts#Chart.getSelectedPoints
getSelectedPoints () Since 1.2.0
Returns an array of all currently selected points in the chart. Points can be selected either programmatically by the point.select() method or by clicking.
I am using a jquery plugin called Hight charts that needs to specify in my html a div with #container and then this put in script tags generate some chart :
$(function() {
Highcharts.setOptions({
options: {...},
}
});
var chart = new Highcharts.Chart({
chart: {
renderTo: 'container',
type: 'bar'
},
other_options:{...}
});
});
Since I need to call this plugin for each element of a dynamic list of my web page, I want to create a plugin that wraps this one. Before caring of DOM's nodes traversal, I put to test
(function($) {
$.fn.ChartPlugin = function() {
Highcharts.setOptions({
options: {...},
}
});
var chart = new Highcharts.Chart({
chart: {
renderTo: 'container',
type: 'bar'
},
other_options:{...}
});
};
})(jQuery);
But now when I call to test $.ChartPlugin(); nothing happens, could someone tell me where I am going wrong ?
Edit : I removed '.fn' and it worked but I don't understand why
I'm am replacing my dot net charting with KendoUI. I'm showing a Score Distribution chart. I want all of the bars to be the same color except the bar with the median score and the Legend. How do I color a single bar a unique color? How would I color the Legend this new color?
Below is my old dotnet charting bar chart and below that is the new KendoUI chart I'm trying to replace it with. I just need to get that coloring right and we'll be in business. Any help is appreciated.
Update: I'm leaving the answer below this line intact in case there are those out there who are using an older version, but per a later comment, KendoUI now allows you to override styles for individual points in a series.
I don't believe you can, in the current version. That said, you can hack your way around the limitation.
You'll need to create two data series - one for your highlighted data, and one for everything else. Add both to you chart, and set them to stacked.
Here's a jsFiddle I put together to illustrate: http://jsfiddle.net/LyndsySimon/9VZdS/. It depends on KendoUI's CDN, so if it breaks in the future I apologize.
Here is the Javascript for reference:
$(function() {
var dataset = new Array(1,2,3,null,5,6);
var highlighted = new Array(null,null,null,4,null,null);
$('#chart').kendoChart({
theme: 'metro',
seriesDefaults: {
type: 'column',
stack: true
},
series: [
{
name: 'Not Highlighted',
data: dataset,
color: '#609'
},
{
name: 'Highlighted',
data: highlighted,
color: '#f03'
}
]
})
});
Starting with the 2012 Q2 release, bar series support binding the point color to a data item field.
This is done through the colorField option. The Binding to local data online example demonstrates it.
Both the Kendo UI and the legacy wrappers for ASP.NET MVC expose it as an option:
.Series(series =>
{
series.Bar(model => model.Value, model => model.Color)
.Name("United States");
})
All series overloads can be seen here.
You could hack the SVG generated by the system. I have supplied the chart with a model which contains the colour for each bar. eg:
public class Model
{
public int Id { get; set; }
public string Name { get; set; }
public string Code { get; set; }
public string Colour { get; set; }
public decimal Score { get; set; }
}
Which is used as a series on the chart. The view then looks like:
#(Html.Telerik().Chart(Model)
.Name("AverageScores")
.Theme("Simple")
.HtmlAttributes(new {style = "height: 500px"})
.Series(series => series.Column(s => s.Score).Name("Name").Color("Blue"))
.SeriesDefaults(sd => sd.Column().Labels(l =>
{
l.Visible(true);
l.Format("{0}%");
}))
.Title("Mean Percentage Scores")
.Legend(builder =>
{
builder.Position(ChartLegendPosition.Bottom);
builder.Visible(false);
})
.CategoryAxis(ca => ca.Categories(x => x.Code))
.Tooltip(builder =>
{
builder.Visible(true);
builder.Format("{0}%");
builder.Template("<#= dataItem.Name #><br/><#= value #>%");
})
.ValueAxis(va => va.Numeric().Labels(a => a.Format("{0}%")).Min(0).Max(100)
)
)
#section BelowTelerikScriptRegistrar
{
<script type="text/javascript">
function setAverageScoresColours() {
var data = $('#AverageScores').data("tChart").options.series[0].dataItems;
if (data != null) {
for (var i = 0; i < data.length; i++) {
var averageScore = data[i];
$($($('div#AverageScores svg g')[i]).children('path')[0]).attr('fill', '#' + averageScore.Colour);
$($($('div#AverageScores svg g')[i]).children('path')[0]).attr('stroke', '#' + averageScore.Colour);
}
}
}
$(document).ready(function () {
setAverageScoresColours();
})
</script>
}
The section BelowTelerikScriptRegistrar must happen after the Html.Telerik().ScriptRegistrar() is called.
This will work in Chrome, Firefox and IE10. I have noticed there is a problem with multiple chart and the timings around the generation of the SVG. Unfortunately you might have to wrap setAverageScoresColours() in a setTimeout function to ensure the SVG has been generated, but it seems to work with just one chart.
A bit hacky, but easier than managing lots of series.
And for KendoUI (which I have edited for...):
<div class="chart-wrapper">
<div id="chart"></div>
</div>
<script>
function createChart() {
$("#chart").kendoChart({
theme: $(document).data("kendoSkin") || "default",
title: {
text: "Internet Users"
},
legend: {
position: "bottom"
},
seriesDefaults: {
type: "column"
},
series: [{
name: "World",
data: [15.7, 16.7, 20, 23.5, 26.6]
}],
valueAxis: {
labels: {
format: "{0}%"
}
},
categoryAxis: {
categories: [2005, 2006, 2007, 2008, 2009]
},
tooltip: {
visible: true,
format: "{0}%"
}
});
}
$(document).ready(function () {
setTimeout(function () {
// Initialize the chart with a delay to make sure
// the initial animation is visible
createChart();
$($($('div#chart svg g')[0]).children('path')[0]).attr('fill', '#123');
$($($('div#chart svg g')[1]).children('path')[0]).attr('fill', '#321');
$($($('div#chart svg g')[2]).children('path')[0]).attr('fill', '#213');
$($($('div#chart svg g')[3]).children('path')[0]).attr('fill', '#312');
$($($('div#chart svg g')[4]).children('path')[0]).attr('fill', '#132');
}, 400);
});
</script>
Another way you can do it at runtime is using function which returns color.
API reference
Here is an example code:
<div id="chart"></div>
<script>
$("#chart").kendoChart({
series: [{
data: [1, 2],
color: function(point) {
if (point.value > 1) {
return "red";
}
// use the default series theme color
}
}]
});
</script>
This is not currently possible with current KendoUI version.
It's on their todo-list.
http://www.kendoui.com/forums/dataviz/chart/change-bar-column-color-for-each-point.aspx
There can be a kind of workaround, as said in the thread I've put here, it would be to describe a series for each color you need. It looks very inefficient to me, but it's currently the only way to do it. If you have only 1 chart, you could do it. Else, wait for a new version of KendoUI with this feature.
Telerik have recently released a Kendo UI Data Vis Theme Roller
http://demos.kendoui.com/themebuilder/dataviz.html