Echarts: set default options for all series - echarts

let's say I have 4 columns (series) of data I need to display as lines.
value,series1,series2,series3,series4
V1,0,10,4,12
V2,8,13,15,10
V3,5,10,5,12
V4,12,7,8,12
V5,10,10,2,12
Echarts graph as lines
Is there an option to set in one sentence all settings for all series ?
the manual way is, for example:
xAxis: {type:'category'},
series:[{type:'line'},{type:'line'},{type:'line'},{type:'line'}],
... and I'm loooking for a simple way to set:
all series: {type:'line'}

The only way to achieve that is doing something like that:
var data = [
[V1,0,10,4,12],
[V2,8,13,15,10],
[V3,5,10,5,12],
[V4,12,7,8,12],
[V5,10,10,2,12]
];
var defaultSeries = [];
for (var i = 0; i < data.length; i++) {
defaultSeries.push({ type: 'line' });
}
var option = {
xAxis: {type:'category'},
series: defaultSeries,
}
myChart.setOption(option);

Related

How to change data point color of Birt line chart for those points which are below marker line through script

I am using Birt line chart where I want to achieve something like this How to format series labels of a BIRT chart by script
I want to show the points which are below marker line in red color just like this link has mentioned.
Modify fillColor of marker.
Code Snippet:
beforeGeneration: function(options)
{
var throughTargetPercent = this.getReportVariable("through_target_percent");
for(var i = 0 ; i < options.series.length ; i++){
var data = options.series[i].data;
var len = data.length;
for (var j=0; j < len; j++){
if(data[j].y < throughTargetPercent) {
data[j]= {
y: data[j].y,
marker: {
fillColor: "yellow"
}
}
}
}
}
},
Hope it helps!

syncfusion ej chart redraw [n] undefined

I am using ASP MVC and I have a ej chart built in script, and I need to refresh its content:
my chart is built like this:
var modelSummaryList = getMySummaryModel();
var summaryChartDataManager = ej.DataManager(($scope.FirstLoad && IsCurrentUserDpiUser()) ? null : modelSummaryList);
jQuery("#MySummaryChart").ejChart({
range: { min: summaryChartDataManager == null ? -1 : summaryChartDataManager.ChartMin, max: summaryChartDataManager == null ? 1 : summaryChartDataManager.ChartMax },
series: [{
name: "MTM",
tooltip: {
visible: true,
format: "#point.x#: #point.y# #series.name#"
},
dataSource: summaryChartDataManager,
xName: "CtpyShort",
yName: "MTM"
}, {
name: "Threshold",
tooltip: {
visible: true,
format: "#point.x#: #point.y# #series.name#"
},
dataSource: summaryChartDataManager,
xName: "CtpyShort",
yName: "Threshold"
}, {
name: "My Held/(Posted)",
tooltip: {
visible: true,
format: "#point.x#: #point.y# #series.name#"
},
dataSource: summaryChartDataManager,
xName: "CtpyShort",
yName: "Held"
}],
type: 'column',
});
which is working good, but upon filter and change of data, I need to redraw the chart so I did this:
$scope.RefreshChart = function (data) {
var chart = $("#MySummaryChart").ejChart("instance");
chart.model.range.min = data.MyTradeSummaryVM.ChartMin;
chart.model.range.max = data.MyTradeSummaryVM.ChartMax;
for (var s = 0; s <= chart.model.series.length - 1; s++) {
var pts = IsCurrentUserDpiUser() ? $.grep(data.MyTradeSummaryVM, function (item) {
return item.ClientID == localStorage.getItem("MyPosting_client_sticky");
}) : data.MyTradeSummaryVM;
chart.model.series[s].points = [];
for (var p = 0; p <= pts.length - 1; p++) {
var newPt = new Object();
newPt.x = pts[p].CtpyShort;
if (chart.model.series[s].name == "MTM")
newPt.y = pts[p].MTM;
else if (chart.model.series[s].name == "Threshold")
newPt.y = pts[p].Threshold;
else if (chart.model.series[s].name == "My Held/(Posted)")
newPt.y = pts[p].Held;
newPt.visible = true;
chart.model.series[s].points.push(newPt);
}
}
chart.redraw();
};
which throws the error TypeError: n[0] is undefined on the chart.redraw() line, and I am stumped. Please note that the RefreshChart() works if I build the chart via cshtml and not javascript like this:
#(Html.EJ().Chart("MySummaryChart")
.PrimaryXAxis(pr => pr.Title(tl => tl.Text("")))
.PrimaryYAxis(pr => pr.Range(ra => ra.Max(Model.ChartMax).Min(Model.ChartMin)).Title(tl => tl.Text("")))
.CommonSeriesOptions(cr => cr.Type(SeriesType.Column).EnableAnimation(true).Marker(mr => mr.DataLabel(dt => dt.Visible(true).EnableContrastColor(true)))
.Tooltip(tt => tt.Visible(true).Format("#point.x# : #point.y# #series.name# ")))
.Series(sr =>
{
.
.
.
})
.Load("loadTheme")
.IsResponsive(true)
.Size(sz => sz.Height("400"))
.Legend(lg => { lg.Visible(true).Position(LegendPosition.Bottom); }))
but I am opting to use JS coz I need to handle null and firstload(meaning no data should appear on the chart upon first load, and unless user picks a client(filter), no data should be loaded. Which I cant seem to make it work if via html, I couldn't erase the chart xaxisregions label along with other data, the only things erased are the main Y axis points but not labels.
We have analyzed the reported scenario. We would like to you know that, when the data for chart is bind using dataSource, then while refreshing the chart with new data, you need to bind the data to series.dataSource property not to series.points, so that only chart will refresh properly. We have prepared a sample with respect the above scenario. Find the code snippet to achieve this requirement.
<input type="button" id="refreshChart" onclick="refresh()" value="Refresh Chart" />
function refresh(sender) {
var chart = $("#MySummaryChart").ejChart("instance");
for (var s = 0; s <= chart.model.series.length - 1; s++) {
//Obtained random data,
var pts = GetData().data;
var newPt = [];
for (var p = 0; p <= pts.length - 1; p++) {
if (chart.model.series[s].name == "MTM")
newPt.push({ "CtpyShort": pts[p].CtpyShort, "MTM": pts[p].MTM });
else if (chart.model.series[s].name == "Threshold")
newPt.push({ "CtpyShort": pts[p].CtpyShort, "Threshold": pts[p].Threshold });
else if (chart.model.series[s].name == "My Held/(Posted)")
newPt.push({ "CtpyShort": pts[p].CtpyShort, "Held": pts[p].Held });
}
//Assign the updated data to dataSource property
chart.model.series[s].dataSource = newPt;
}
chart.redraw();
}
In the above code in a button click event, we have refreshed the chart data. Here you need to assign the x value to CtpyShort and y values of three series to MTM, Threshold and Held, since we have mapped these properties while rendering the chart initially.
Screenshot before updating data:
Screenshot after updating data:
Sample for reference can be find from below link.
Sample Link
If you face still any concern, kindly revert us by modifying the above sample with respect to your scenario or provide your sample with replication steps which will helpful in further analysis and provide you the solution sooner.
Thanks,
Dharani.

How to remove L.rectangle(boxes[i])

I few days ago I implement a routingControl = L.Routing.control({...}) which works perfect for my needs. However I need for one of my customer also the RouteBoxer which I was also able to implement it. Now following my code I wants to remove the boxes from my map in order to draw new ones. However after 2 days trying to find a solution I've given up.
wideroad is a param that comes from a dropdown list 10,20,30 km etc.
function routeBoxer(wideroad) {
this.route = [];
this.waypoints = []; //Array for drawBoxes
this.wideroad = parseInt(wideroad); //Distance in km
this.routeArray = routingControl.getWaypoints();
for (var i=0; i<routeArray.length; i++) {
waypoints.push(routeArray[i].latLng.lng + ',' + routeArray[i].latLng.lat);
}
this.route = loadRoute(waypoints, this.drawRoute);
}; //End routeBoxer()
drawroute = function (route) {
route = new L.Polyline(L.PolylineUtil.decode(route)); // OSRM polyline decoding
boxes = L.RouteBoxer.box(route, this.wideroad);
var bounds = new L.LatLngBounds([]);
for (var i = 0; i < boxes.length; i++) {
**L.rectangle(boxes[i], {color: "#ff7800", weight: 1}).addTo(this.map);**
bounds.extend(boxes[i]);
}
console.log('drawRoute:',boxes);
this.map.fitBounds(bounds);
return route;
}; //End drawRoute()
loadRoute = function (waypoints) {
var url = '//router.project-osrm.org/route/v1/driving/';
var _this = this;
url += waypoints.join(';');
var jqxhr = $.ajax({
url: url,
data: {
overview: 'full',
steps: false,
//compression: false,
alternatives: false
},
dataType: 'json'
})
.done(function(data) {
_this.drawRoute(data.routes[0].geometry);
//console.log("loadRoute.done:",data);
})
.fail(function(data) {
//console.log("loadRoute.fail:",data);
});
}; //End loadRoute()
Well, my problem is now how to remove previously drawn boxes in order to draw new ones because of changing the wideroad using a dropdown list. Most of this code I got from the leaflet-routeboxer application.
Thanks in advance for your help...
You have to keep a reference to the rectangles so you can manipulate them (remove them) later. Note that neither Leaflet nor Leaflet-routeboxer will do this for you.
e.g.:
if (this._currentlyDisplayedRectangles) {
for (var i = 0; i < this._currentlyDisplayedRectangles.length; i++) {
this._currentlyDisplayedRectangles[i].remove();
}
} else {
this._currentlyDisplayedRectangles = [];
}
for (var i = 0; i < boxes.length; i++) {
var displayedRectangle = L.rectangle(boxes[i], {color: "#ff7800", weight: 1}).addTo(this.map);
bounds.extend(boxes[i]);
this._currentlyDisplayedRectangles.push(displayedRectangle);
}
If you don't store a reference to the L.rectangle() instance, you obviously won't be able to manipulate it later. This applies to other Leaflet layers as well - not storing explicit references to Leaflet layers is a usual pattern in Leaflet examples.

Leaflet Marker Cluster add weight to marker

I have a leaflet map and I am using the Leaflet.markerCluster plugin to cluster my markers. I have some markers that represent multiple points on the same location. Unfortunately when it gets clustered it only represents one single point. Is there a way to add a weight to each marker? So that the cluster sees it as more than one point?
Basically I am hoping for a clusterWeight property like the follwing:
var newMarker = L.marker(coordinates, {
icon: myIcon,
clusterWeight: 5
});
This propety does not exist however. Anyoneknow of a work around? Thanks!
First you will need to create a marker that supports custom properties. You can do this by extending the default L.Marker like so:
var weightMarker = L.Marker.extend({
options: {
customWeight: 0
}
});
Then you can make use of Leaflet.markercluster's iconCreateFunction to create a custom cluster marker, by changing what is displayed on the marker:
var markers = L.markerClusterGroup({
iconCreateFunction: function(cluster) {
// iterate all markers and count
var markers = cluster.getAllChildMarkers();
var weight = 0;
for (var i = 0; i < markers.length; i++) {
if(markers[i].options.hasOwnProperty("customWeight")){
weight += markers[i].options.customWeight;
}
}
var c = ' marker-cluster-';
if (weight < 10) {
c += 'small';
} else if (weight < 100) {
c += 'medium';
} else {
c += 'large';
}
// create the icon with the "weight" count, instead of marker count
return L.divIcon({
html: '<div><span>' + weight + '</span></div>',
className: 'marker-cluster' + c, iconSize: new L.Point(40, 40)
});
}
});
Demo: https://jsfiddle.net/chk1/0hq1t13t/

Chart.js and long labels

I use Chart.js to display a Radar Chart. My problem is that some labels are very long :
the chart can't be display or it appears very small.
So, is there a way to break lines or to assign a max-width to the labels?
Thank you for your help!
For Chart.js 2.0+ you can use an array as label:
Quoting the DOCs:
"Usage: If a label is an array as opposed to a string i.e. [["June","2015"], "July"] then each element is treated as a seperate line."
var data = {
labels: [["My", "long", "long", "long", "label"], "another label",...],
...
}
With ChartJS 2.1.6 and using #ArivanBastos answer
Just pass your long label to the following function, it will return your label in an array form, each element respecting your assigned maxWidth.
/**
* Takes a string phrase and breaks it into separate phrases
* no bigger than 'maxwidth', breaks are made at complete words.
*/
function formatLabel(str, maxwidth){
var sections = [];
var words = str.split(" ");
var temp = "";
words.forEach(function(item, index){
if(temp.length > 0)
{
var concat = temp + ' ' + item;
if(concat.length > maxwidth){
sections.push(temp);
temp = "";
}
else{
if(index == (words.length-1)) {
sections.push(concat);
return;
}
else {
temp = concat;
return;
}
}
}
if(index == (words.length-1)) {
sections.push(item);
return;
}
if(item.length < maxwidth) {
temp = item;
}
else {
sections.push(item);
}
});
return sections;
}
console.log(formatLabel("This string is a bit on the longer side, and contains the long word Supercalifragilisticexpialidocious for good measure.", 10))
To wrap the xAxes label, put the following code into optoins. (this will split from white space and wrap into multiple lines)
scales: {
xAxes: [
{
ticks: {
callback: function(label) {
if (/\s/.test(label)) {
return label.split(" ");
}else{
return label;
}
}
}
}
]
}
You can write a javascript function to customize the label:
// Interpolated JS string - can access value
scaleLabel: "<%=value%>",
See http://www.chartjs.org/docs/#getting-started-global-chart-configuration
Unfortunately there is no solution for this until now (April 5th 2016).
There are multiple issues on Chart.js to deal with this:
https://github.com/nnnick/Chart.js/issues/358 (closed with fix)
https://github.com/nnnick/Chart.js/issues/608 (closed with no fix)
https://github.com/nnnick/Chart.js/issues/358 (closed with no fix)
https://github.com/nnnick/Chart.js/issues/780 (closed with no fix)
https://github.com/nnnick/Chart.js/issues/752 (closed with no fix)
This is a workaround: Remove x-axis label/text in chart.js
It seems you might be actually be talking about data labels and not the scale labels. In this case you'd want to use the pointLabelFontSize option. See below example:
var ctx = $("#myChart").get(0).getContext("2d");
var data = {
labels: ["Eating", "Sleeping", "Coding"],
datasets: [
{
label: "First",
strokeColor: "#f00",
pointColor: "#f00",
pointStrokeColor: "#fff",
pointHighlightFill: "#fff",
pointHighlightStroke: "#ccc",
data: [45, 59, 90]
},
{
label: "Second",
strokeColor: "#00f",
pointColor: "#00f",
pointStrokeColor: "#fff",
pointHighlightFill: "#fff",
pointHighlightStroke: "#ccc",
data: [68, 48, 40]
}
]
};
// This is the important part
var options = {
pointLabelFontSize : 20
};
var myRadarChart = new Chart(ctx).Radar(data, options);
Finally you may want to play with the dimensions of your < canvas > element as I've found sometimes giving the Radar chart more height helps the auto scaling of everything.
I found the best way to manipulate the labels on the radar chart was by using the pointlabels configuration from Chartjs.
let skillChartOptions = {
scale: {
pointLabels: {
callback: (label: any) => {
return label.length > 5 ? label.substr(0, 5) + '...' : label;
},
}, ...
}, ...
}
I'd like to further extend on Fermin's answer with a slightly more readable version. As previously pointed out, it's possible to give Chart.js an array of strings to make it wrap the text. To make this array of strings from a longer string, I propose this function:
function chunkString(str, maxWidth){
const sections = [];
const words = str.split(" ");
let builder = "";
for (const word of words) {
if(word.length > maxWidth) {
sections.push(builder.trim())
builder = ""
sections.push(word.trim())
continue
}
let temp = `${builder} ${word}`
if(temp.length > maxWidth) {
sections.push(builder.trim())
builder = word
continue
}
builder = temp
}
sections.push(builder.trim())
return sections;
}
const str = "This string is a bit on the longer side, and contains the long word Supercalifragilisticexpialidocious for good measure."
console.log(str)
console.log(chunkString(str, 10))
.as-console-wrapper {
max-height: 100vh!important;
}
For most of the recent versions of chart.js, the labels can be mentioned as array of arrays. That's your labels can be:
labels = [['a', 'label1'],['the', 'lable2'],label3] '$'
You can use following function which is fast and compatible across all versions for converting your labels array into array of array in case the labels contain multiple words:
function splitLongLabels(labels){
//labels = ["ABC PQR", "XYZ"];
var i = 0, len = labels.length;
var splitlabels = labels;
while (i < len) {
var words = labels[i].trim().split(' ');
if(words.length>1){
for(var j=0; j<words.length; j++){
}
splitlabels[i] = words;
}
i++
}
return splitlabels;
}