Datamap - Change color depending on value - javascript

I came across a datamap example here and trying to edit it. I need to change the state color depending on the value, ranging from dark blue to light blue.
At the moment,
fills: {
'lightBlue': '#cc4731',
'justBlue': '#306596',
'deepBlue': '#667faf',
'mediumBlue': '#a9c0de',
'deepBlue': '#ca5e5b',
'defaultFill': '#eddc4e'
}
And the data has,
data: {
AZ: {
fillKey: 'lightBlue',
userVisits: 5
},
CO: {
fillKey: 'justBlue',
userVisits: 5
},
DE: {
fillKey: 'deepBlue',
userVisits: 32
},
....
}
But is there to generate shades of blue depending on the userVisits?

I don't think there is a an option to put logic in the fillkey selection. I'd recommend processing the data to assign a fillkey before giving it to Datamaps.
I made a codepen to demonstrate.
Also, the "fills" data has duplicate keys and hex values that do not match the color described.
var stateData = {
AZ: {
userVisits: 5
},
CO: {
userVisits: 15
},
DE: {
userVisits: 32
}
}
function addFillKey(mapData){
for (var mapDatum in mapData){
var userVisits = mapData[mapDatum].userVisits;
if(userVisits < 10){
mapData[mapDatum].fillKey = "lightBlue"
}else if(userVisits < 20){
mapData[mapDatum].fillKey = "justBlue"
}else{
mapData[mapDatum].fillKey = "mediumBlue"
}
}
}
addFillKey(stateData);
var map = new Datamap({
element: document.getElementById('container'),
scope: 'usa',
fills: {
'lightBlue': '#cc4731',
'justBlue': '#306596',
'deepBlue': '#667faf',
'mediumBlue': '#a9c0de',
'deepBlue': '#ca5e5b',
'defaultFill': '#eddc4e'
},
data: stateData
});

Related

CanvasJs Doughnut Chart loading issue on page reload. But works fine in page redirection

I'm implementing a doughnut chart with CanvasJs in a ReactJs App.
Collected following code from CanvasJs's github repo
var React = require("react");
var CanvasJS = require("./canvasjs.min");
CanvasJS = CanvasJS.Chart ? CanvasJS : window.CanvasJS;
class CanvasJSChart extends React.Component {
static _cjsContainerId = 0;
constructor(props) {
super(props);
this.options = props.options ? props.options : {};
this.containerProps = props.containerProps
? props.containerProps
: { width: "100%", position: "relative" };
this.containerProps.height =
props.containerProps && props.containerProps.height
? props.containerProps.height
: this.options.height
? this.options.height + "px"
: "400px";
this.chartContainerId =
"canvasjs-react-chart-container-" + CanvasJSChart._cjsContainerId++;
}
async componentDidMount() {
//Create Chart and Render
this.chart = await new CanvasJS.Chart(this.chartContainerId, this.options);
this.chart.render();
console.log("CHart", this.chart);
if (this.props.onRef) this.props.onRef(this.chart);
}
shouldComponentUpdate(prevProps) {
// //Check if Chart-options has changed and determine if component has to be updated
// return !(nextProps.options === this.options);
if (prevProps.options !== this.props.options) {
return false;
}
else {
return true;
}
}
componentWillUnmount() {
//Destroy chart and remove reference
this.chart.destroy();
if (this.props.onRef) this.props.onRef(undefined);
}
render() {
return <div id={this.chartContainerId} style={this.containerProps} />;
}
}
var CanvasJSReact = {
CanvasJSChart: CanvasJSChart,
CanvasJS: CanvasJS,
};
export default CanvasJSReact;
I'm passing options to the component in the following manner
const options = {
animationEnabled: true,
subtitles: [
{
text: "",
verticalAlign: "center",
fontSize: 24,
dockInsidePlotArea: true,
},
],
data: [
{
type: "doughnut",
indexLabel: "{name}: {percentage}",
yValueFormatString: "'$'#,###",
dataPoints: [{ name: "Unsatisfied", y: 5 },
{ name: "Very Unsatisfied", y: 31 },
{ name: "Very Satisfied", y: 40 },
{ name: "Satisfied", y: 17 },
{ name: "Neutral", y: 7 }],
},
],
};
USE THIS UPPER COMPONENT
<CanvasJSChart options={options} />
When I'm passing dataPoints (with static data) in my code, the chart loads fine.
But the issue occurs when I try to use dynamic data. My dynamic data has only one dataPoint this point of time
// Array of data points
[{
name: "FNBO Evergreen® Rewards Visa® Card",
percentage:"100%",
y: 20000
}]
On Page reload the chart is not rendering. But, it appears back if routed from another page or window size is changed.
The issue can be easily seen the following loom video
https://www.loom.com/share/754b51dae7b04cb29a87a969a961fefc
Note: In all the cases shown in video, we do receive data from backend. But this issue occurs in some of the cases

t[this.activeSeriesIndex].data[0] is undefined in ApexCharts. How to correctly build the series array?

I'm a beginner in Vue and I'm using vue-apex chart to create a chart in my application. I want to display in chart, the values of the two component's properties "uncorrectAns" and "correctAns" that I compute thanks to a specific method (computeStat()).
<template>
<apexcharts width="500" type="bar" :options="chartOptions" :series="series"></apexcharts>
</template>
<script>
export default {
name: 'Results',
components: {
apexcharts: VueApexCharts
},
data() {
return {
results: '',
correctAns: 0,
uncorrectAns: 0,
chartOptions: {
chart: {
id: 'vuechart-example'
},
xaxis: {
categories: ['Correct Answers', 'Uncorrect Answers']
}
},
series: [
{
name: 'series-1',
data: [this.correctAns, this.uncorrectAns]
}
]
}
},
methods: {
computeStat() {
var i
for (i = 0; i < this.results.length; i = i + 1) {
if (this.results[i].answerCorrect == true) {
this.correctAns = this.correctAns + 1
} else {
this.uncorrectAns = this.uncorrectAns + 1
}
}
}
},
created() {
this.results = this.$route.params.output
this.computeStat()
var i
for (i = 0; i < this.results.length; i = i + 1) {
console.log('bestPractice ' + i + ':' + this.results[i].bestPract)
}
}
}
</script>
When I run the application, the chart isn't displayed and I get this error message on the browser console:
I would like to know the nature of this error and if there is a correct way to display "correctAns" and "uncorrectAns" values in the chart.
There's a couple of problems here around your series property...
When you define series, both this.correctAns and this.uncorrectAns are undefined (this is the source of your problem)
Because series is statically defined, it will never update as you make changes to this.correctAns and this.uncorrectAns
The solution is to convert series into a computed property. Remove it from data and add
computed: {
series () {
return [
{
name: 'series-1',
data: [this.correctAns, this.uncorrectAns]
}
]
}
}
Demo ~ https://jsfiddle.net/ynLfabdz/
Given you seem to be treating results as an array, you should initialise it as such instead of an empty string, ie
results: [], // not ''
I fixed the issue by simple check if the array is undefined then return empty if not return the chart with my values
const Amount = [
{
name: 'Salary Amount',
data: salary[0] === undefined ? [] : salary
},
{
name: 'Over Time Amount',
data: overTime[0] === undefined ? [] : overTime
},
true
]

AmCharts 4 - get data from point on map

I start new project on AmCharts 4 maps, i want get data when i click on selected point. Now i have event on click but i don't know how get data from array, for example id and title.
// Create image series
var imageSeries = chart.series.push(new am4maps.MapImageSeries());
// Create a circle image in image series template so it gets replicated to all new images
var imageSeriesTemplate = imageSeries.mapImages.template;
var circle = imageSeriesTemplate.createChild(am4core.Circle);
//create circle/points
circle.radius = 5;
circle.fill = am4core.color("#000000");
circle.strokeWidth = 3;
circle.nonScaling = true;
circle.tooltipText = "{title}" + "{id}";
// Set prope fields
imageSeriesTemplate.propertyFields.latitude = "latitude";
imageSeriesTemplate.propertyFields.longitude = "longitude";
// example data cities
imageSeries.data = [{
"latitude": 48.856614,
"longitude": 2.352222,
"title": "Paris",
"id": 102
}, {
"latitude": 47.856614,
"longitude": 2.352222,
"title": "second Paris",
"id": 104
}];
//click on point event
circle.events.on("hit", function(ev) {
// HERE, WHAT CAN I DO??
console.log("clicked on ", ev.target);
}, this);
That would be:
imageSeriesTemplate.events.on("hit", (ev)=>{
console.log(ev.target.dataItem.dataContext.title)
})
#VermaAman, ran into the same problem, and found out the onHit should be added to the Circle, i'm using config, so it looks like this:
{
type: "MapImageSeries",
mapImages: {
children: [
{
type: "Circle",
radius: 4,
stroke: "#somecolor",
strokeWidth: 2,
nonScaling: true,
tooltipText: "{title}",
events: {
hit: function (ev: any) {
console.log(ev.target.dataItem.dataContext);
},
},
},
],
propertyFields: {
latitude: "latitude",
longitude: "longitude",
},
},
data: areas,
},

unable to hide the data as expected based on the selection

When user click on Hide Laptop stacked bar radio button, the stacked bar displayed for Laptop(blue color) should be hidden and when clicked on ALL radio button all bars should be displayed. But currently when i click on Hide Laptop stacked bar, the Shipping data is not dispalyed and even the Legend name for shipping is showing wrong when clicked on ALL radio button after Hide Laptop radio button.
Please find the demo here
js code:
angular.module('myApp', ['googlechart'])
.controller('myController', function($scope) {
var chart1 = {};
var variableCol = {
id: "laptop-id",
label: "Laptop",
type: "number"
};
chart1.type = "ColumnChart";
chart1.displayed = false;
var valueSelected;
$scope.newValue = function(value) {
console.log(value);
console.log(chart1.data.cols.length);
valueSelected = value;
if(value == 'few' && chart1.data.cols.length == 5) {
alert("Laptop data should not be shown" );
chart1.data.cols.pop();
} else {
chart1.data.cols.push(variableCol);
}
}
//if the ALL radio button is selected all the stacked bars should be shown
//if SDL radio button is selected, show only server,desktop,laptop but onmouse over show the shipping details tooo
chart1.data = {
"cols": [{
id: "month",
label: "Month",
type: "string"
},variableCol,
{
id: "desktop-id",
label: "Desktop",
type: "number"
}, {
id: "server-id",
label: "Server",
type: "number"
}, {
id: "cost-id",
label: "Shipping",
type: "number"
}],
"rows": [{
c: [{
v: "January"
}, {
v: 19,
f: "42 items"
}, {
v: 12,
f: "Ony 12 items"
}, {
v: 7,
f: "7 servers"
}, {
v: 4
}]
}, {
c: [{
v: "February"
}, {
v: 13
}, {
v: 1,
f: "1 unit (Out of stock this month)"
}, {
v: 12
}, {
v: 2
}]
}, {
c: [{
v: "March"
}, {
v: 24
}, {
v: 5
}, {
v: 11
}, {
v: 6
}
]
}]
};
chart1.options = {
"title": "Sales per month",
"isStacked": "true",
focusTarget: 'category',
"fill": 20,
"displayExactValues": true,
colors: ['blue', 'green', 'pink', 'brown'],
"vAxis": {
"title": "Sales unit",
"gridlines": {
"count": 10
}
},
"hAxis": {
"title": "Date"
}
};
$scope.myChart = chart1;
}).value('googleChartApiConfig', {
version: '1.1',
optionalSettings: {
packages: ['bar'],
language: 'en'
}
});
You are calling array.pop, which removes the last element from the array. The laptop element is at position 1. Here's a snippet of how you would search for the variableCol index, and then splice the array removing that element. That's the safest way to do this since you'll ensure you are finding that particular column.
So far, these solutions are not solving for the data
Without regard for colors
if(value == 'few' && chart1.data.cols.length == 5) {
//alert("Laptop data should not be shown" );
var idx = chart1.data.cols.indexOf(variableCol);
chart1.data.cols.splice(idx, 1);
console.log("var col at " + idx);
}
Here's a working plnkr
Keeping Blue Color for laptop
This version will keep the laptop being blue (position does change though).
if (value == 'few' && chart1.data.cols.length == 5) {
//alert("Laptop data should not be shown" );
var colIdx = chart1.data.cols.indexOf(variableCol);
chart1.data.cols.splice(colIdx, 1);
var colorIdx = chart1.options.colors.indexOf("blue");
chart1.options.colors.splice(colorIdx, 1);
} else {
chart1.data.cols.push(variableCol);
chart1.options.colors.push("blue");
}

link elements in joint.js dissapear when mousing over them.

I am buillding an FSA application in joint.js using the fsa plugin. However, whenever I mouse over the links, they disappear.
This is the relevant javascript code:
function link(source, target, label, maxsize) {
var vertices = []
if (source.id == target.id) {
vertices = [{ x:source.attributes.position.x+10*maxsize, y:source.attributes.position.y-40 }, { x:source.attributes.position.x+10*maxsize, y:source.attributes.position.y+40 }];
}
var w = parseInt(label,10);
if (source.id == init.id || target.id == term.id)
label = "";
var cell = new joint.shapes.fsa.Arrow({
source: { id: source.id },
target: { id: target.id },
labels: [{ position: .5, attrs: { text: { text: label || '', 'font-weight': 'bold' } } }],
vertices: vertices || []
});
cell.weight = w;
return cell;
}
How do I fix this?
This seems you must be getting some error to the browser console. Can you post it here? It looks like something else is wrong, not the code that you posted. However, I see you're accessing source.attributes.position.x directly. Note that this is not part of the public API. You should use source.get('position').x.

Categories