Has anyone changed the colors of the bar graph in xcharts? Any idea how to do so?
The plain navy blue is so boring:
http://tenxer.github.io/xcharts/examples/
Thanks,
Philip
Based on the documentation it does not appear the library has built in methods for styling the chart, but rather:
The best way to style charts is to start with the included stylesheet,
or use your browser's element inspector to see each elements CSS class
selectors that are available to use.
Each series has a class: .color0 through .colorN, so you could use the css to set the properties of each rectangle:
var data = {
"xScale": "ordinal",
"yScale": "linear",
"main": [
{
"className": ".pizza",
"data": [
{
"x": "Pepperoni",
"y": 4
},
{
"x": "Cheese",
"y": 8
}
]
}
]
};
var myChart = new xChart('bar', data, '#chart');
.color0 rect {
fill: orange !important;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/d3/3.4.11/d3.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/xcharts/0.3.0/xcharts.js"> </script>
<link rel="stylesheet" type="text/css" href="https://cdnjs.cloudflare.com/ajax/libs/xcharts/0.3.0/xcharts.css">
<figure style="width: 400px; height: 300px;" id="chart"></figure>
Alternatively, you could use a d3 selection to alter the colors:
d3.selectAll(".color0").selectAll("rect").style("fill","orange");
var data = {
"xScale": "ordinal",
"yScale": "linear",
"main": [
{
"className": ".pizza",
"data": [
{
"x": "Pepperoni",
"y": 4
},
{
"x": "Cheese",
"y": 8
}
]
}
]
};
var myChart = new xChart('bar', data, '#chart');
d3.selectAll(".color0").selectAll("rect").style("fill","orange");
<script src="https://cdnjs.cloudflare.com/ajax/libs/d3/3.4.11/d3.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/xcharts/0.3.0/xcharts.js"> </script>
<link rel="stylesheet" type="text/css" href="https://cdnjs.cloudflare.com/ajax/libs/xcharts/0.3.0/xcharts.css">
<figure style="width: 400px; height: 300px;" id="chart"></figure>
If you just want all rectangles to be a certain color, then d3.selectAll("rect").style("fill","color") will work.
In Xchart we can add color of the bar using seriesColors method.
CategoryChart chart = new CategoryChartBuilder()
.yAxisTitle("ABC Title")
.theme(Styler.ChartTheme.GGPlot2).build();
chart.getStyler().setSeriesColors(new Color[]{Color.blue, Color.cyan, Color.LIGHT_GRAY, new Color(224,43,54), new Color(24,43,124)});
Related
I am currently trying to make a simple visualization using Mapbox that is based on additional data provided by a local geojson file. I cannot upload this file to Mapbox and would like to keep it local.
I have used this base code from Mapbox that I have modified to include a local geojson file that is structured like this:
{"features": [{"geometry": null, "location": {"coordinates": [40.730610, -73.935242], "type": "Point"}, "properties": {"X": "1", "group": "1"}, "type": "Feature"},...}
I have modified the example code from Mapbox so that it is now:
<!DOCTYPE html>
<html>
<head>
<meta charset='utf-8' />
<title>Style circles with a data-driven property</title>
<meta name='viewport' content='initial-scale=1,maximum-scale=1,user-scalable=no' />
<script src='https://api.tiles.mapbox.com/mapbox-gl-js/v0.48.0/mapbox-gl.js'></script>
<script type="text/javascript" src="http://code.jquery.com/jquery-1.7.1.min.js"></script>
<link href='https://api.tiles.mapbox.com/mapbox-gl-js/v0.48.0/mapbox-gl.css' rel='stylesheet' />
<style>
body { margin:0; padding:0; }
#map { position:absolute; top:0; bottom:0; width:100%; }
</style>
</head>
<body>
<div id='map'></div>
<script>
mapboxgl.accessToken = 'pk.eyJ1IjoibG9ubmliZXNhbmNvbiIsImEiOiJjamxjaWNpOHQwMHV0M3FwaHhneGhvY2l2In0.7GxI8W_dnTKITNF4hEvZeQ';
var map = new mapboxgl.Map({
container: 'map',
style: 'mapbox://styles/mapbox/light-v9',
zoom: 12,
center: [-73.935242, 40.730610],
pitch: 20,
});
var url = "GeoObs.json.json"
map.on('load', function () {
var layers = map.getStyle().layers;
var labelLayerId;
for (var i = 0; i < layers.length; i++) {
if (layers[i].type === 'symbol' && layers[i].layout['text-field']) {
labelLayerId = layers[i].id;
break;
}
}
map.addSource("my_data", {
type: "geojson",
data: url //"./GeoObs.json",
/*cluster: true,
clusterMaxZoom: 15, // Max zoom to cluster points on
clusterRadius: 50 // Radius of each cluster when clustering points (defaults to 50)*/
});
map.addLayer({
'id': 'population',
'type': 'circle',
source: 'my_data',
'source-layer': 'my_data',
'paint': {
// make circles larger as the user zooms from z12 to z22
'circle-radius': {
'base': 1.75,
'stops': [[12, 2], [22, 180]]
},
// color circles by ethnicity, using a match expression
// https://www.mapbox.com/mapbox-gl-js/style-spec/#expressions-match
'circle-color': [
'match',
['get', 'group'],
'1', '#fbb03b',
'2', '#223b53',
'3', '#e55e5e',
'4', '#3bb2d0',
/* other */ '#ccc'
]
}
});
map.addLayer({
'id': '3d-buildings',
'source': 'composite',
'source-layer': 'building',
'filter': ['==', 'extrude', 'true'],
'type': 'fill-extrusion',
'minzoom': 15,
'paint': {
'fill-extrusion-color': '#aaa',
// use an 'interpolate' expression to add a smooth transition effect to the
// buildings as the user zooms in
'fill-extrusion-height': [
"interpolate", ["linear"], ["zoom"],
15, 0,
15.05, ["get", "height"]
],
'fill-extrusion-base': [
"interpolate", ["linear"], ["zoom"],
10, 0,
15.05, ["get", "min_height"]
],
'fill-extrusion-opacity': .6
}
}, labelLayerId);
});
</script>
</body>
</html>
I get the following error:
Error: Source layer "my_data" does not exist on source "my_data" as specified by style layer "population"
at i._validateLayer (style.js:274)
at i.addLayer (style.js:576)
at o.addLayer (map.js:1175)
at o.<anonymous> (index3.html:52)
at o.L.fire (evented.js:115)
at o._render (map.js:1619)
at map.js:1683
Can anyone point me in the direction of a possible mistake here and hopefully how to fix it. You can use the example geojson I gave you to try out this example. Just copy paste it into a file called: GeoObs.json if you want the code to right away give the same error.
As the error states, your GeoJSON source does not have a source layer. So you can remove the 'source-layer' property from the map.addLayer call.
Your GeoJSON also needs to be modified to a proper FeatureCollection:
{
"type": "FeatureCollection",
"features": [
{
"geometry": {
"type": "Point",
"coordinates": [
-73.935242,
40.730610
]
},
"properties": {
"X": "1",
"group": "1"
},
"type": "Feature"
}
]
}
For the population layer, comment out the line, because you do not have such a layer:
'source-layer': 'my_data',
And maybe you have an extra ".json" in the URL:
GeoObs.json.json
[ https://jsfiddle.net/c5nauwgx/ ]
This example from MapLibre helped me and also works with Mapbox GL JS. It adds a little interactivity to your map by giving you the option to select a local geojson file within the map.
https://maplibre.org/maplibre-gl-js-docs/example/local-geojson/
I created a chart with Billboard.js (a chart library based on d3 v4+).
My aim was to make the lines look dashed so I used this documentation for it.
Basically, I added this code:
const regions = {}
for(const item of baselineTitle) {
regions[item]=[];
regions[item].push({"style" : "dashed"});
}
inside bb.generate:
var chart = bb.generate({
"data": {
"type": "spline",
"x": "x",
"columns": columns,
"regions": regions
},
...
When the lines are not dashed everything it's fine. I have no line on the chart for null values.
When it is dashed, it has a line on zero for all null values.
This is how my chart looks like, I put yellow color where it shouldn't be a line because the values are null for that part.
The array containing the values for that line is this one:
0:"char id"
1:null
2:null
3:null
4:2230.181884765625
5:2230.181884765625
6:2230.181884765625
7:2230.181884765625
8:2230.181884765625
9:2230.181884765625
10:2230.181884765625
11:2230.181884765625
12:2230.181884765625
13:2230.181884765625
14:2230.181884765625
15:2230.181884765625
16:4568.82470703125
17:4870.001953125
18:4671.97607421875
19:4767.93603515625
20:4729.97607421875
21:4721.1591796875
22:4799.16357421875
23:4864.5068359375
24:3512.424072265625
25:2924.76513671875
26:3047.808837890625
27:3052.245361328125
28:3045.63427734375
29:2930.223388671875
30:2410.9541015625
31:2116.904052734375
32:2064.01806640625
33:2159.795654296875
34:2232.72412109375
35:2669.738037109375
36:3420.1669921875
37:4515.5537109375
38:4703.1435546875
39:4993.89501953125
40:5207.1259765625
41:5056.1904296875
42:5222.80517578125
43:5509.8447265625
44:5453.8798828125
45:5206.78466796875
46:5155.16748046875
47:5082.36083984375
48:4002.560302734375
49:3587.09716796875
50:3569.875732421875
51:3328.478515625
52:3167.501953125
53:2847.85009765625
54:2208.728759765625
55:2152.306396484375
56:2085.06640625
57:2145.009521484375
58:2170.032958984375
59:2666.60107421875
60:3379.564208984375
61:4388.9384765625
62:4549.611328125
63:5117.0029296875
64:5279.7353515625
65:5314.0751953125
66:5404.16552734375
67:5757.20068359375
68:5631.9619140625
69:5716.732421875
70:5763.24560546875
71:5598.005859375
72:null
73:null
74:null
75:null
76:null
77:null
78:null
79:null
80:null
81:null
82:null
83:null
84:null
85:null
86:null
87:null
88:null
89:null
90:null
91:null
92:null
93:null
94:null
95:null
96:null
97:null
98:null
99:null
Do you know what's the problem here?
If you don't need to set a specific region of the line to be dashed, with the css stroke-dasharrayattribute will be more easier to implement that.
https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/stroke-dasharray
Check out the below snippet.
bb.generate({
data: {
columns: [
["data1", 100, 200, 1000, 900, 500],
["data2", 20, 40, null, 300, 200]
],
type: "spline"
},
point: {
show: false
}
});
.bb-lines-data2 {
stroke-dasharray: 2 4;
stroke-width: 2px;
}
<!doctype html>
<html>
<head>
<script src="https://cdn.jsdelivr.net/npm/billboard.js/dist/billboard.pkgd.min.js"></script>
<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/billboard.js/dist/billboard.min.css">
</head>
<body>
<div id="chart"></div>
</body>
</html>
My javascript map is reading from a json stream that looks like this:
[{"title":"Site1","latitude":18.3764,"longitude":-67.1819},
{"title":"Site2","latitude":18.2001,"longitude":-65.8081},
{"title":"Site3","latitude":18.3878,"longitude":-66.0998}]
The points are being drawn correctly, so that's great.
To this json I'll be adding an inService field. The inService field will be any of the following options: [Monday, Tuesday, Sunday, Thursday] and the json will look like this:
[{"title":"Site1","latitude":18.3764,"longitude":-67.1819,"inService":"Monday"},
{"title":"Site2","latitude":18.2001,"longitude":-65.8081,"inService":"Tuesday"},
{"title":"Site3","latitude":18.3878,"longitude":-66.0998,"inService":"Sunday"},
{"title":"Site4","latitude":18.1246,"longitude":-66.2607,"inService":"Thursday"}]
At the amcharts website, I saw these two new icons: One that blinks and another that's a dot with a circle around it.
So my question is: Using the json above, how can I assign a blinking pin to the different types of values in inService?
For example:
Monday: blinking blue pin
Tuesday: blinking black pin
Sunday: white dot with a circle around it (no blink)
Thursday red dot with a circle around it (no blink)
And finally, we will be adding other types of status. How can I change the shapes? For example, the pins at the top will be squared instead of round?
Thanks for any help.
I tried using SO code preview, but it's not rendering the map. So I've also included it in jsfiddle:
AmCharts.makeChart("mapdiv", {
"type": "map",
"theme": "light",
"imagesSettings": {
"rollOverColor": "#089282",
"rollOverScale": 1,
"selectedScale": 0.5,
"selectedColor": "#089282",
"color": "#13564e",
"selectable": false,
"bringForwardOnHover": false
},
"areasSettings": {
"color": "#D3D3D3",
"autoZoom": true
},
"data": {
"map": "puertoRicoHigh",
"getAreasFromMap": true
},
"dataLoader": {
"url": "https://s3-us-west-2.amazonaws.com/s.cdpn.io/716619/30189.json",
"format": "json",
"showErrors": true,
"postProcess": function(data, config, map) {
// create a new dataProvider
var mapData = map.data;
// init images array
if (mapData.images === undefined)
mapData.images = [];
// create images out of loaded data
for(var i = 0; i < data.length; i++) {
var image = data[i];
image.type = "circle";
mapData.images.push(image);
}
return mapData;
}
}
});
#mapdiv {
width: 100%;
height: 300px;
<script src="https://www.amcharts.com/lib/3/ammap.js"></script>
<script src="https://www.amcharts.com/lib/3/maps/js/puertoRicoHigh.js"></script>
<script src="https://www.amcharts.com/lib/3/plugins/export/export.min.js"></script>
<link rel="stylesheet" href="https://www.amcharts.com/lib/3/plugins/export/export.css" type="text/css" media="all" />
<script src="https://www.amcharts.com/lib/3/themes/light.js"></script>
<script src="https://www.amcharts.com/lib/3/plugins/dataloader/dataloader.js"></script>
<div id="mapdiv"></div>
I wrote the following code. I have a json file on my server that is valid and looks like:
[
{
"data": [
{
"y": 1.0,
"x": 1451936340.0
},
{
"y": 1.0,
"x": 1451936400.0
},
{
"y": 1.0,
"x": 1451936460.0
}
]
}
]
I have the following code. I am trying to draw a line chart and overlay points on the line chart using renderer: 'multi' but I am hitting a lot of snags. I am a novice with JS and I do not understand where I am messing up. I think I need a callback function in my jQuery.ajax function but I am unsure. I appreciate any help.
<html>
<head>
<!-- css -->
<meta name="viewport" content="width=device-width, initial-scale=1">
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/rickshaw/1.5.1/rickshaw.min.css">
<!-- js -->
<script src="https://code.jquery.com/jquery-1.11.3.min.js"></script>
<script src="https://code.jquery.com/ui/1.11.4/jquery-ui.min.js"></script>
<script>
jQuery.noConflict();
</script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/d3/3.5.10/d3.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/rickshaw/1.5.1/rickshaw.min.js"></script>
</head>
<body>
<div style="margin:10px auto;width:auto;" id="chart_container">
<div id="chart"></div>
<div id="slider"></div>
<script>
var json = jQuery.ajax({
'url': "/assets/json/data.json",
'success': function(json) {
console.log(json[0].data);
}
});
var graph = new Rickshaw.Graph( {
element: document.getElementById("chart"),
renderer: 'multi',
height: 200,
width: 400,
series: [
{
name: "series 1",
data: json[0].data,
color: "rgba(255, 0, 0, 0.4)",
renderer: "line"
}, {
name: "series 2",
data: json[0].data,
color: "rgba(255, 0, 0, 0.4)",
renderer: "scatterplot"
}
]
} );
graph.render();
var slider = new Rickshaw.Graph.RangeSlider.Preview( {
graph: graph,
element: document.querySelector('#slider')
} );
var detail = new Rickshaw.Graph.HoverDetail( {
graph: graph
} );
graph.render();
</script>
</div>
</body>
There are a few things I would change here.
1.) jQuery.ajax returns a promise, not the raw data itself, so var json = jQuery.ajax(...) will not assign the json value you are expecting.
2.) pass a success callback function to properly access the JSON returned by the server
3.) Only call graph.render() once.
Javascript
jQuery.ajax({
'url': "/assets/json/data.json",
'success': renderGraph // callback for ajax success
});
// wrap graph creation logic in a function to be used as a callback
function renderGraph(json) {
var graph = new Rickshaw.Graph({
element: document.getElementById("chart"),
renderer: 'multi',
height: 200,
width: 400,
series: [{
name: "series 1",
data: json[0].data,
color: "rgba(255, 0, 0, 0.4)",
renderer: "line"
}, {
name: "series 2",
data: json[0].data,
color: "rgba(255, 0, 0, 0.4)",
renderer: "scatterplot"
}]
});
// remove this, only render once at the end
// graph.render();
var slider = new Rickshaw.Graph.RangeSlider.Preview({
graph: graph,
element: document.querySelector('#slider')
});
var detail = new Rickshaw.Graph.HoverDetail({
graph: graph
});
graph.render();
}
My plunker NVD3 chart
I'm using NVD3's multiChart chart. When I add additional area graphs into the chart, it appears that the legend pushes down the chart. The more graphs get added the more the chart appears scrunched.
Note how the Y axis in the 2 screenshot is almost 50% shorter than the original.
I tried removing the legend with CSS, but the chart still shortens:
.legendWrap {
display: none;
}
Even removed the legend with Javascript and still the chart gets scrunched:
removeElementsByClass('nv-legend');
function removeElementsByClass(className){
var elements = document.getElementsByClassName(className);
while(elements.length > 0){
elements[0].parentNode.removeChild(elements[0]);
}
}
Any idea how to solve this problem?
My full drawChart function:
function drawChart(res) {
console.log('res',res);
nv.addGraph(function() {
chart = nv.models.multiChart()
.margin({
top: 20,
right: 40,
bottom: 50,
left: 40
})
.interpolate("linear") // don't smooth out the lines
.color(d3.scale.category10().range());
chart.xAxis.tickFormat(function(d) {
return d3.time.format('%I:%M')(new Date(d));
});
chart.yAxis1.tickFormat(d3.format(',f'));
chart.yAxis2.tickFormat(function(d) {
return '$' + d3.format(',f')(d)
});
d3.select('svg#chart')
.datum(res)
.transition().duration(500).call(chart);
chart.tooltip.hidden(true);
chart.update();
d3.select('.lines2Wrap').node().parentNode.insertBefore(d3.select('.stack1Wrap').node(), d3.select('.lines2Wrap').node());
// Add top padding to xAxis timeline:
d3.selectAll('.nv-x.nv-axis > .nv-wrap.nv-axis > g > g.tick > text').each(function(d,i) {
d3.select(this).attr('dy', '1.5em');
});
d3.selectAll('.nv-x.nv-axis > .nv-wrap.nv-axis > .nv-axisMaxMin > text').each(function(d,i) {
d3.select(this).attr('dy', '1.5em');
});
nv.utils.windowResize(chart.update);
return chart;
});
}
You are correct, the legend is the cause of the problem. Instead of setting display: none in CSS, you can remove the legend entirely like this:
chart = nv.models.multiChart()
.margin({
top: 20,
right: 40,
bottom: 50,
left: 40
})
.showLegend(false) // don't show the legend
.interpolate("linear") // don't smooth out the lines
.color(d3.scale.category10().range());
Full working code here.
Anychart multichart complete code with custom theme
<!doctype html>
<html>
<head>
<script src="https://cdn.anychart.com/js/7.14.3/anychart-bundle.min.js"></script>
<link rel="stylesheet" href="https://cdn.anychart.com/css/latest/anychart-ui.min.css">
<div id="container"></div>
<style>
html, body, #containerss {
width: 100%;
height: 100%;
margin: 0;
padding: 0;
}
</style>
</head>
<body>
<div id="containerss"></div>
<script type="text/javascript">
anychart.onDocumentReady(function() {
// create variable for custom theme
var customTheme = {
// define settings for bar charts
"column": {
// set chart title
"title": {
"text": "Column Chart",
"enabled": true
},
// settings for default x axis
"defaultXAxisSettings": {
// set x axis title
"title": {
"text": "Retail Channel",
"enabled": true
}
},
// settings for default y axis
"defaultYAxisSettings": {
// set axis name
"title": {
"text": "Sales",
"enabled": true
}
}
}
};
// data
var data = anychart.data.set([
["Department Stores", 63, 87,87],
["Discount Stores", 72, 66,42],
]);
// apply custom theme
anychart.theme(customTheme);
// append a theme
anychart.appendTheme(additional_theme);
// set chart type
chart = anychart.column();
// set data
seriesData_1 = data.mapAs({x: [0], value: [1]});
seriesData_2 = data.mapAs({x: [0], value: [2]});
seriesData_3 = data.mapAs({x: [0], value: [3]});
chart.column(seriesData_1);
chart.column(seriesData_2);
chart.column(seriesData_3);
// set container and draw chart
chart.container("containerss");
chart.draw();
});
additional_theme = {
"column": {
"palette": {
"type": "distinct",
"items": ["red", "#8a9597",'#000']
}
}
};
</script>
</body>
</html>