Vega Lite / Kibana - Area Mark shows no values - elasticsearch

I have a pretty straightforward problem but I'm totally new to Vega/Vega-Lite and the tutorials examples don't help me much to resolve my issue.
When I try to display my floating point values only Mark: Point/Bar seems to work. Everything else that demands a connection between neighboring points seems to fail, like "Area" or "Line".
What have I missed in order to connect my values to a Area-Chart?
Aggregation? Layer? Is the timestamp values calculation wrong?
{
"$schema": "https://vega.github.io/schema/vega-lite/v4.json",
"data": {
"url": {
"%context%": true,
"%timefield%": "#timestamp",
"index": "default-*",
"body": {"size": 10000, "_source": ["#timestamp", "numericData"]}
},
"format": {"property": "hits.hits"}
},
"transform": [
{"calculate": "toDate(datum._source['#timestamp'])", "as": "time"}
],
"vconcat": [
{
"width": 1200,
"mark": {"type": "area", "line": true, "point": true},
"encoding": {
"x": {
"field": "time",
"scale": {"domain": {"selection": "brush"}},
"type": "temporal",
"axis": {"title": ""}
},
"y": {
"field": "_source.numericData",
"type": "quantitative",
"scale": {"domain": [0, 10]}
}
}
},
{
"width": 1200,
"height": 60,
"mark": {"type": "area", "line": true, "point": true}, // <-- only points are rendered :(
"selection": {"brush": {"type": "interval", "encodings": ["x"]}},
"encoding": {
"x": {"field": "time", "type": "temporal"},
"y": {
"field": "_source.numericData",
"type": "quantitative",
"formatType": "String",
"axis": {"tickCount": 3, "grid": false}
}
}
}
]
}
Points are visible - the values are there but the Area doesn't get rendered because, I suspect, I need to tell Vega Lite to interpret the numerical float values on Y to be interpreted over the whole timefield.

You didn't share your data, so I can only guess why this is happening. But one reason you might see this result is if there are null values interspersed in your data. Here is a simple example of this (open in editor):
{
"data": {
"values": [
{"x": 1, "y": 1},
{"x": 2, "y": null},
{"x": 3, "y": 2},
{"x": 4, "y": null},
{"x": 5, "y": 3},
{"x": 6, "y": null}
]
},
"mark": {"type": "area", "point": true, "line": true},
"encoding": {
"x": {"field": "x", "type": "quantitative"},
"y": {"field": "y", "type": "quantitative"}
}
}
Unlike ponts, lines and areas are defined not via single values, but via adjacent values. Because there are no pairs of adjacent non-null values, there is no place where a line or area will be drawn.
If this is the case, you can remove the null points with an appropriate filter transform (open in editor):
{
"data": {
"values": [
{"x": 1, "y": 1},
{"x": 2, "y": null},
{"x": 3, "y": 2},
{"x": 4, "y": null},
{"x": 5, "y": 3},
{"x": 6, "y": null}
]
},
"transform": [{"filter": "isValid(datum.y)"}],
"mark": {"type": "area", "point": true, "line": true},
"encoding": {
"x": {"field": "x", "type": "quantitative"},
"y": {"field": "y", "type": "quantitative"}
}
}

Related

How to use field value as a color value in vega lite pie chart?

I came across this pie chart vega lite visualization:
{
"$schema": "https://vega.github.io/schema/vega-lite/v5.json",
"description": "A simple pie chart with labels.",
"data": {
"values": [
{"category": "a", "value": 4},
{"category": "b", "value": 6},
{"category": "c", "value": 10},
{"category": "d", "value": 3},
{"category": "e", "value": 7},
{"category": "f", "value": 8}
]
},
"encoding": {
"theta": {"field": "value", "type": "quantitative", "stack": true},
"color": {"field": "category", "type": "nominal", "legend": null}
},
"layer": [{
"mark": {"type": "arc", "outerRadius": 80}
}, {
"mark": {"type": "text", "radius": 90},
"encoding": {
"text": {"field": "category", "type": "nominal"}
}
}]
}
It renders as follows:
My data contains color key:
{
"$schema": "https://vega.github.io/schema/vega-lite/v5.json",
"description": "A simple pie chart with labels.",
"data": {
"values": [
{"category": "a", "value": 4, "color": "rgb(121, 199, 227)"},
{"category": "b", "value": 6, "color": "rgb(140, 129, 22)"},
{"category": "c", "value": 10, "color": "rgb(96, 43, 199)"},
{"category": "d", "value": 3, "color": "rgb(196, 143, 99)"},
{"category": "e", "value": 7, "color": "rgb(12, 103, 19)"},
{"category": "f", "value": 8, "color": "rgb(196, 243, 129)"}
]
},
"encoding": {
"theta": {"field": "value", "type": "quantitative", "stack": true},
"color": {"field": "color", "type": "nominal", "legend": null}
},
"layer": [{
"mark": {"type": "arc", "outerRadius": 80}
}, {
"mark": {"type": "text", "radius": 90},
"encoding": {
"text": {"field": "category", "type": "nominal"}
}
}]
}
I want to use the rgb() color value specified in this color key's value to color individual pie. I tried specifying this field in color channel: "field": "color".
"color": {"field": "color", "type": "nominal", "legend": null}
However, no use. It still renders the same as above. How can use color value specified in field's value as actual color?
PS: Link to above visualization.
The documentation says:
To directly encode the data value, the scale property can be set to null.
So you need to set the scale to null.
{
"$schema": "https://vega.github.io/schema/vega-lite/v5.json",
"description": "A simple pie chart with labels.",
"data": {
"values": [
{"category": "a", "value": 4, "color": "rgb(121, 199, 227)"},
{"category": "b", "value": 6, "color": "rgb(140, 129, 22)"},
{"category": "c", "value": 10, "color": "rgb(96, 43, 199)"},
{"category": "d", "value": 3, "color": "rgb(196, 143, 99)"},
{"category": "e", "value": 7, "color": "rgb(12, 103, 19)"},
{"category": "f", "value": 8, "color": "rgb(196, 243, 129)"}
]
},
"encoding": {
"theta": {"field": "value", "type": "quantitative", "stack": true},
"color": {"field": "color", "type": "nominal", "legend": null, "scale":null}
},
"layer": [
{"mark": {"type": "arc", "outerRadius": 80}},
{
"mark": {"type": "text", "radius": 90},
"encoding": {"text": {"field": "category", "type": "nominal"}}
}
]
}
This outputs:

Add legend to Bullet Chart in vega-lite

I have been trying to add a legend to the following example in Vega-lite. The visualization has a facet and each bar has independent axis. Each bar has different segments with different colors. When I tried to add a legend, it changes the color defined in each mark to the first mark and the legend overlap.
This is the example without changes:
{
"$schema": "https://vega.github.io/schema/vega-lite/v5.json",
"data": {
"values": [
{"title":"Revenue", "subtitle":"US$, in thousands", "ranges":[150,225,300],"measures":[220,270],"markers":[250]},
{"title":"Profit", "subtitle":"%", "ranges":[20,25,30],"measures":[21,23],"markers":[26]},
{"title":"Order Size", "subtitle":"US$, average", "ranges":[350,500,600],"measures":[100,320],"markers":[550]},
{"title":"New Customers", "subtitle":"count", "ranges":[1400,2000,2500],"measures":[1000,1650],"markers":[2100]},
{"title":"Satisfaction", "subtitle":"out of 5", "ranges":[3.5,4.25,5],"measures":[3.2,4.7],"markers":[4.4]}
]
},
"facet": {
"row": {
"field": "title", "type": "ordinal",
"header": {"labelAngle": 0, "title": ""}
}
},
"spacing": 10,
"spec": {
"encoding": {
"x": {
"type": "quantitative",
"scale": {"nice": false},
"title": null
}
},
"layer": [{
"mark": {"type": "bar", "color": "#eee"},
"encoding": {"x": {"field": "ranges[2]"}}
},{
"mark": {"type": "bar", "color": "#ddd"},
"encoding": {"x": {"field": "ranges[1]"}}
},{
"mark": {"type": "bar", "color": "#ccc"},
"encoding": {"x": {"field": "ranges[0]"}}
},{
"mark": {"type": "bar", "color": "lightsteelblue", "size": 10},
"encoding": {"x": {"field": "measures[1]"}}
},{
"mark": {"type": "bar", "color": "steelblue", "size": 10},
"encoding": {"x": {"field": "measures[0]"}}
},{
"mark": {"type": "tick", "color": "black"},
"encoding": {"x": {"field": "markers[0]"}}
}]
},
"resolve": {"scale": {"x": "independent"}},
"config": {"tick": {"thickness": 2}}
}
Here the changes I did without success because it change the color defined in the first 2 mark rather than having two separate scales for each mark
{
"$schema": "https://vega.github.io/schema/vega-lite/v5.json",
"data": {
"values": [
{"title":"Revenue", "subtitle":"US$, in thousands", "ranges":[150,225,300],"measures":[220,270],"markers":[250]},
{"title":"Profit", "subtitle":"%", "ranges":[20,25,30],"measures":[21,23],"markers":[26]},
{"title":"Order Size", "subtitle":"US$, average", "ranges":[350,500,600],"measures":[100,320],"markers":[550]},
{"title":"New Customers", "subtitle":"count", "ranges":[1400,2000,2500],"measures":[1000,1650],"markers":[2100]},
{"title":"Satisfaction", "subtitle":"out of 5", "ranges":[3.5,4.25,5],"measures":[3.2,4.7],"markers":[4.4]}
]
},
"facet": {
"row": {
"field": "title", "type": "ordinal",
"header": {"labelAngle": 0, "title": ""}
}
},
"spacing": 10,
"spec": {
"encoding": {
"x": {
"type": "quantitative",
"scale": {"nice": false},
"title": null
}
},
"layer": [{
"mark": {"type": "bar", "color": "#eee"},
"encoding": {
"x": {"field": "ranges[2]"},
"color":{
"field":"ranges[2]",
"type":"quantitative",
"legend":{
"orient": "right"
}
}
}
},{
"mark": {"type": "bar", "color": "#ddd"},
"encoding": {
"x": {"field": "ranges[1]"},
"color":{
"field":"ranges[1]",
"type":"quantitative",
"legend":{
"orient": "right"
}
}
}
},{
"mark": {"type": "bar", "color": "#ccc"},
"encoding": {"x": {"field": "ranges[0]"}}
},{
"mark": {"type": "bar", "color": "lightsteelblue", "size": 10},
"encoding": {"x": {"field": "measures[1]"}}
},{
"mark": {"type": "bar", "color": "steelblue", "size": 10},
"encoding": {"x": {"field": "measures[0]"}}
},{
"mark": {"type": "tick", "color": "black"},
"encoding": {"x": {"field": "markers[0]"}}
}]
},
"resolve": {"scale": {"x": "independent"}},
"config": {"tick": {"thickness": 2}}
}
Anyone has experience creating this type of legend
Thanks
I have added a color and legend to each mark to make the point that the gradient displayed is not related to the marks defined in the visualization
{
"$schema": "https://vega.github.io/schema/vega-lite/v5.json",
"data": {
"values": [
{
"title": "Revenue",
"subtitle": "US$, in thousands",
"ranges": [150, 225, 300],
"measures": [220, 270],
"markers": [250]
},
{
"title": "Profit",
"subtitle": "%",
"ranges": [20, 25, 30],
"measures": [21, 23],
"markers": [26]
},
{
"title": "Order Size",
"subtitle": "US$, average",
"ranges": [350, 500, 600],
"measures": [100, 320],
"markers": [550]
},
{
"title": "New Customers",
"subtitle": "count",
"ranges": [1400, 2000, 2500],
"measures": [1000, 1650],
"markers": [2100]
},
{
"title": "Satisfaction",
"subtitle": "out of 5",
"ranges": [3.5, 4.25, 5],
"measures": [3.2, 4.7],
"markers": [4.4]
}
]
},
"facet": {
"row": {
"field": "title",
"type": "ordinal",
"header": {"labelAngle": 0, "title": ""}
}
},
"spacing": 10,
"spec": {
"encoding": {
"x": {"type": "quantitative", "scale": {"nice": false}, "title": null}
},
"layer": [
{
"mark": {"type": "bar", "fill": "red"},
"encoding": {
"x": {"field": "ranges[2]"},
"color": {
"field": "ranges[2]",
"type": "quantitative",
"legend": {"orient": "right"}
}
}
},
{
"mark": {"type": "bar", "fill": "green"},
"encoding": {
"x": {"field": "ranges[1]"},
"color": {
"field": "ranges[1]",
"type": "quantitative",
"legend": {"orient": "right"}
}
}
},
{
"mark": {"type": "bar", "fill": "yellow"},
"encoding": {
"x": {"field": "ranges[0]"},
"color": {
"field": "ranges[0]",
"type": "quantitative",
"legend": {"orient": "right"}
}
}
},
{
"mark": {"type": "bar", "fill": "blue", "size": 10},
"encoding": {
"x": {"field": "measures[1]"},
"color": {
"field": "measures[1]",
"type": "quantitative",
"legend": {"orient": "right"}
}
}
},
{
"mark": {"type": "bar", "fill": "violet", "size": 10},
"encoding": {
"x": {"field": "measures[0]"},
"color": {
"field": "measures[0]",
"type": "quantitative",
"legend": {"orient": "right"}
}
}
},
{
"mark": {"type": "tick", "fill": "black"},
"encoding": {"x": {"field": "markers[0]"}}
}
]
},
"resolve": {"scale": {"x": "independent"}},
"config": {"tick": {"thickness": 2}}
}
I have changed the color given in mark to fill which seemed to resolve the issue.
Below is the config or refer editor:
{
"$schema": "https://vega.github.io/schema/vega-lite/v5.json",
"data": {
"values": [
{
"title": "Revenue",
"subtitle": "US$, in thousands",
"ranges": [150, 225, 300],
"measures": [220, 270],
"markers": [250]
},
{
"title": "Profit",
"subtitle": "%",
"ranges": [20, 25, 30],
"measures": [21, 23],
"markers": [26]
},
{
"title": "Order Size",
"subtitle": "US$, average",
"ranges": [350, 500, 600],
"measures": [100, 320],
"markers": [550]
},
{
"title": "New Customers",
"subtitle": "count",
"ranges": [1400, 2000, 2500],
"measures": [1000, 1650],
"markers": [2100]
},
{
"title": "Satisfaction",
"subtitle": "out of 5",
"ranges": [3.5, 4.25, 5],
"measures": [3.2, 4.7],
"markers": [4.4]
}
]
},
"facet": {
"row": {
"field": "title",
"type": "ordinal",
"header": {"labelAngle": 0, "title": ""}
}
},
"spacing": 10,
"spec": {
"encoding": {
"x": {"type": "quantitative", "scale": {"nice": false}, "title": null}
},
"layer": [
{
"mark": {"type": "bar", "fill": "#eee"},
"encoding": {
"x": {"field": "ranges[2]"},
"color": {
"field": "ranges[2]",
"type": "quantitative",
"legend": {"orient": "right"}
}
}
},
{
"mark": {"type": "bar", "fill": "#ddd"},
"encoding": {
"x": {"field": "ranges[1]"},
"color": {
"field": "ranges[1]",
"type": "quantitative",
"legend": {"orient": "right"}
}
}
},
{
"mark": {"type": "bar", "fill": "#ccc"},
"encoding": {"x": {"field": "ranges[0]"}}
},
{
"mark": {"type": "bar", "fill": "lightsteelblue", "size": 10},
"encoding": {"x": {"field": "measures[1]"}}
},
{
"mark": {"type": "bar", "fill": "steelblue", "size": 10},
"encoding": {"x": {"field": "measures[0]"}}
},
{
"mark": {"type": "tick", "fill": "black"},
"encoding": {"x": {"field": "markers[0]"}}
}
]
},
"resolve": {"scale": {"x": "independent"}},
"config": {"tick": {"thickness": 2}}
}
I managed to create a legend as I was expecting. I create another visualization mark bar and create a fake legend there, and using hcol, I concatenate this to the existing graph
{
"$schema": "https://vega.github.io/schema/vega-lite/v5.json",
"data": {
"values": [
{
"title": "Revenue",
"subtitle": "US$, in thousands",
"ranges": [150, 225, 300],
"measures": [220, 270],
"markers": [250]
},
{
"title": "Profit",
"subtitle": "%",
"ranges": [20, 25, 30],
"measures": [21, 23],
"markers": [26]
},
{
"title": "Order Size",
"subtitle": "US$, average",
"ranges": [350, 500, 600],
"measures": [100, 320],
"markers": [550]
},
{
"title": "New Customers",
"subtitle": "count",
"ranges": [1400, 2000, 2500],
"measures": [1000, 1650],
"markers": [2100]
},
{
"title": "Satisfaction",
"subtitle": "out of 5",
"ranges": [3.5, 4.25, 5],
"measures": [3.2, 4.7],
"markers": [4.4]
}
]
},
"hconcat": [{
"data": {
"values": [
{
"color": "green",
"phase": 1,
"name": "Green"
},
{
"color": "silver",
"phase": 1,
"name": "Silver"
},
{
"color": "violet",
"phase": 1,
"name": "Violet"
},
{
"color": "yellow",
"phase": 1,
"name": "Yellow"
},
{
"color": "red",
"phase": 1,
"name": "Red"
}
]
},
"mark": "bar",
"width": 50,
"encoding": {
"y": {
"field": "name",
"type": "nominal",
"axis": {"title": null}
},
"x": {
"field": "phase",
"type": "quantitative",
"axis": null
},
"color": {
"field": "color",
"type": "nominal",
"scale": null,
"legend": null
}
}
},{
"facet": {
"row": {
"field": "title",
"type": "ordinal",
"header": {"labelAngle": 0, "title": ""}
}
},
"spacing": 10,
"spec": {
"encoding": {
"x": {"type": "quantitative", "scale": {"nice": false}, "title": null}
},
"layer": [
{
"mark": {"type": "bar", "fill": "red"},
"encoding": {
"x": {"field": "ranges[2]"}
}
},
{
"mark": {"type": "bar", "fill": "yellow"},
"encoding": {
"x": {"field": "ranges[1]"}
}
},
{
"mark": {"type": "bar", "fill": "violet"},
"encoding": {"x": {"field": "ranges[0]"}}
},
{
"mark": {"type": "bar", "fill": "silver", "size": 10},
"encoding": {"x": {"field": "measures[1]"}}
},
{
"mark": {"type": "bar", "fill": "green", "size": 10},
"encoding": {"x": {"field": "measures[0]"}}
},
{
"mark": {"type": "tick", "fill": "black"},
"encoding": {"x": {"field": "markers[0]"}}
}
]
},
"resolve": {"scale": {"x": "independent"}}
}],
"config": {"tick": {"thickness": 2}}
}

Vega-lite heat map change the color, location, test

Good time of day!
formerly = Vega-lite heat map text properties
1)How to build a new X2-axis in this scheme, which takes into account the original X-axis
{"window": [{"op": "count", "field": "x", "as": "x2"}], "groupby": ["y"]}
{
"$schema": "https://vega.github.io/schema/vega-lite/v2.4.3.json",
"config": {"view": {"height": 300, "width": 400}},
"data": {
"values": [
{"x": "X1", "y": "Y1", "z": 1,"Name":"Name3"}
{"x": "X3", "y": "Y1", "z": 9,"Name":"Name2"}
{"x": "X3", "y": "Y1", "z": 25,"Name":"Name1"}
{"x": "X0", "y": "Y2", "z": 1,"Name":"Name1"}
{"x": "X1", "y": "Y2", "z": 2,"Name":"Name1"}
{"x": "X4", "y": "Y2", "z": 20,"Name":"Name1"}
{"x": "X5", "y": "Y2", "z": 40,"Name":"Name1"}
]
},
"transform": [
{"window": [{"op": "count", "field": "x", "as": "x2"}], "groupby": ["y"]}
{"window": [{"op": "count", "field": "Name", "as": "x7"}], "groupby": ["x","y"]}
{
"calculate": "'https://google.com/search?q='+datum.y",
"as": "web"
}
],
"encoding": {
"x": {"field": "x2", "type": "ordinal", "title": "X"},
"y": {"field": "y", "type": "ordinal", "title": "Y"}
},
"layer": [
{
"mark": "rect",
"encoding": {
"color": {
"field": "z",
"scale": {"scheme": "redyellowgreen"},
"type": "quantitative"
}
"tooltip": [
{"field": "x", "type": "ordinal", title: "text"}
{"field": "y", "type": "ordinal", title: "text1"}
{"field": "z", "type": "ordinal", title: "text2"}
]
"href": {"field": "web"}
}
},
{
"mark": {"type": "text", "fontSize": 10, "dy": -20},
"encoding": {
"text": {"field": "x"},
"color": {"value": "black"}
}
},
{
"mark": {"type": "text", "fontSize": 20, "dy": 40},
"encoding": {
"text": {"field": "x7"},
"color": {"value": "black"}
}
},
{
"mark": {"type": "text", "fontSize": 20, "dy": 20},
"encoding": {
"text": {"field": "z", "type": "quantitative"},
"color": {"value": "black"}
}
}
]
}
2)how to make clear color boundaries? like here:
I use it:
"color": {"aggregate": "average","field": "z", "type": "quantitative","format": ".0f", "scale": { "domain": [0,20,25,35],"range": ["#6ce165", "#E0ED15", "#ED9715", "#CE4334"]}}
3) how to add text here:
{
"mark": {"type": "text", "fontSize": 20, "dy": 40},
"encoding": {
"text": {"field": "x7"},+ Text????
"color": {"value": "black"}
}
},
Please only ask one question per post. I do not understand what you are asking in the first or third part of your question, so I will answer the second.
You can make the color scale discrete using a binned encoding:
"encoding": {
"color": {
"field": "z",
"scale": {"scheme": "redyellowgreen"},
"type": "ordinal",
"bin": true
}
}
Here is the result (Vega Editor):

How to set locale (globally) in Vega

I would like to configure the locale for a visualization in Vega. I need a German number format, which means that I need a comma (,) as decimal separator. Without any configuration in Vega, a decimal point (.) is used as separator.
Here is a complete working example which shows a simple bar chart. As you can see in the image below, I want to format the numbers on the y-Axis and the values inside the bars with two decimal places.
How can I set a specific locale (e.g. German) either globally for the whole visualization or for each number format separately? (I would prefer a global setting.)
(Note: You can use the Vega Editor to paste and try out my bar chart example.)
{
"width": 600,
"height": 300,
"padding": {"top": 10, "left": 35, "bottom": 30, "right": 10},
"data": [
{
"name": "table",
"values": [
{"x": 1, "y": 0.5},
{"x": 2, "y": 0.8},
{"x": 3, "y": 0.3},
{"x": 4, "y": 0.6}
]
}
],
"scales": [
{
"name": "x",
"type": "ordinal",
"range": "width",
"domain": {"data": "table", "field": "x"},
"padding": 0.1
},
{
"name": "y",
"type": "linear",
"range": "height",
"domain": {"data": "table", "field": "y"}
}
],
"axes": [
{"type": "x", "scale": "x"},
{"type": "y", "scale": "y", "format": ".2f"}
],
"marks": [
{
"type": "rect",
"from": {"data": "table"},
"properties": {
"enter": {
"x": {"scale": "x", "field": "x"},
"width": {"scale": "x", "band": true, "offset": -1},
"y": {"scale": "y", "field": "y"},
"y2": {"scale": "y", "value": 0}
},
"update": {
"fill": {"value": "steelblue"}
}
}
},
{
"type": "text",
"from": {"mark": "bars"},
"properties": {
"enter": {
"y": {"field": "y", "offset": 10},
"x": {"field": "x"},
"dx": {"field": "width", "mult": 0.6},
"fill": {"value": "white"},
"align": {"value": "right"},
"baseline": {"value": "middle"},
"text": {"template": "{{datum.datum.y | number:'.2f'}}"}
}
}
}
]
}
I found a pull request in the Vega GitHub repository which allows to set the number and time locale. Also runtime changes are supported.
Example for changing the number format to German:
vg.util.format.numberLocale({
decimal: ",",
thousands: ".",
grouping: [3],
currency: ["", "\xa0€"]
});
Example for changing the time format to German:
vg.util.format.timeLocale({
dateTime: "%A, der %e. %B %Y, %X",
date: "%d.%m.%Y",
time: "%H:%M:%S",
periods: ["AM", "PM"], // unused
days: ["Sonntag", "Montag", "Dienstag", "Mittwoch", "Donnerstag", "Freitag", "Samstag"],
shortDays: ["So", "Mo", "Di", "Mi", "Do", "Fr", "Sa"],
months: ["Januar", "Februar", "März", "April", "Mai", "Juni", "Juli", "August", "September", "Oktober", "November", "Dezember"],
shortMonths: ["Jan", "Feb", "Mrz", "Apr", "Mai", "Jun", "Jul", "Aug", "Sep", "Okt", "Nov", "Dez"]
});

Forced directed D3 Graph setting specific image for each node

Hi I have gone through few questions and possible solutions of putting image as node in forced directed. But all of them are either putting randomly or one image for all. Is there any way i can assign particular image to particular node? Basically i am creating dynamically and fetching data from database. Any help would be highly appreciated.
hi just click the load button and heres the sample of what you want http://jsfiddle.net/elviz/V6Qr8/91/
function loadImage() {
if (LoadData) {
root = {
"name": "physics",
"imageURL": "",
"type": "user",
"children": [{
"name": "DragForce",
"imageURL": "",
"size": 1082,
"type": "user"
}, {
"name": "GravityForce",
"imageURL": "",
"size": 1336,
"type": "user"
}, {
"name": "IForce",
"imageURL": "",
"size": 319,
"type": "user"
}, {
"name": "NBodyForce",
"imageURL": "",
"size": 10498,
"type": "user"
}, {
"name": "Node 1",
"imageURL": "",
"type": "user",
"children": [{
"name": "DragForce 1.1",
"imageURL": "",
"size": 1082,
"type": "chat"
}, {
"name": "DragForce 1.2",
"imageURL": "",
"size": 1082,
"type": "message"
}]
},
{
"name": "Particle",
"imageURL": "",
"size": 2822,
"type": "user"
}, {
"name": "Simulation",
"imageURL": "",
"size": 9983,
"type": "user"
}, {
"name": "Node 2",
"imageURL": "",
"type": "user",
"children": [{
"name": "DragForce 2.1",
"imageURL": "",
"size": 1082,
"type": "message"
}, {
"name": "DragForce 2.2",
"imageURL": "",
"size": 1082,
"type": "message"
}]
},
{
"name": "Spring",
"imageURL": "",
"size": 2213,
"type": "user"
}, {
"name": "SpringForce",
"imageURL": "",
"size": 1681,
"type": "user"
}, {
"name": "Node 3",
"imageURL": "",
"type": "user",
"children": [{
"name": "DragForce 2.1",
"imageURL": "",
"size": 1082,
"type": "chat"
}, {
"name": "DragForce 3.2",
"imageURL": "",
"size": 1082,
"type": "chat"
}]
}]
};
Try as shown in fiddle:
http://jsfiddle.net/cyril123/n28k7oqo/3/
You can specify your data as and pass the image as shown below
var graph = {
"nodes": [
{"x": 469, "y": 410, 'img': "https://cdn1.iconfinder.com/data/icons/industry-2/96/Mine-512.png"},
{"x": 493, "y": 364, 'img': "https://cdn0.iconfinder.com/data/icons/ikooni-outline-free-basic/128/free-09-128.png"},
{"x": 442, "y": 365, 'img': "https://cdn0.iconfinder.com/data/icons/ikooni-outline-free-basic/128/free-17-128.png"},
{"x": 467, "y": 314, 'img': "https://cdn0.iconfinder.com/data/icons/ikooni-outline-free-basic/128/free-22-128.png"},
{"x": 477, "y": 248, 'img': "https://cdn0.iconfinder.com/data/icons/ikooni-outline-free-basic/128/free-13-128.png"},
{"x": 425, "y": 207, 'img': "https://cdn1.iconfinder.com/data/icons/industry-2/96/Mine-512.png"},
{"x": 402, "y": 155, 'img': "https://cdn0.iconfinder.com/data/icons/ikooni-outline-free-basic/128/free-03-128.png"},
{"x": 369, "y": 196, 'img': "https://cdn1.iconfinder.com/data/icons/industry-2/96/Mine-512.png"},
{"x": 350, "y": 148, 'img': "https://cdn1.iconfinder.com/data/icons/industry-2/96/Mine-512.png"},
{"x": 539, "y": 222, 'img': "https://cdn1.iconfinder.com/data/icons/industry-2/96/Mine-512.png"},
{"x": 594, "y": 235, 'img': "https://cdn0.iconfinder.com/data/icons/ikooni-outline-free-basic/128/free-23-128.png"},
{"x": 582, "y": 185, 'img': "https://cdn1.iconfinder.com/data/icons/industry-2/96/Mine-512.png"},
{"x": 633, "y": 200, 'img': "https://cdn1.iconfinder.com/data/icons/industry-2/96/Mine-512.png"}
],
"links": [
{"source": 0, "target": 1},
{"source": 1, "target": 2},
{"source": 2, "target": 0},
{"source": 1, "target": 3},
{"source": 3, "target": 2},
{"source": 3, "target": 4},
{"source": 4, "target": 5},
{"source": 5, "target": 6},
{"source": 5, "target": 7},
{"source": 6, "target": 7},
{"source": 6, "target": 8},
{"source": 7, "target": 8},
{"source": 9, "target": 4},
{"source": 9, "target": 11},
{"source": 9, "target": 10},
{"source": 10, "target": 11},
{"source": 11, "target": 12},
{"source": 12, "target": 10}
]
}
Explanation
The x and y in the json is the probable place where you want to place the circle. Imagine you don't have x and y for any of the nodes; in such case don't pass the x and y in JSON. Something like this:
..."nodes": [
{
'img': "https://cdn1.iconfinder.com/data/icons/industry-2/96/Mine-512.png"
}, ....
Regarding the img pass the url of the image you wish to see on the node.
Like I have done above.
This will append the image to the node group:
//make groups which will hold the image and the circle
nodes = node.data(graph.nodes)
.enter().append("g");
//make a node circle in the group
var circles = nodes.append("circle")
.attr("class", "node")
.attr("r", 12)
.on("dblclick", dblclick)
.call(drag);
//make images in the group
var images = nodes.append("svg:image")
.attr("xlink:href",function(d) {return d.img})
.attr("height", "20")
.attr("width", "20");
The node group is the group which contains the circle and the image.
Like in my Arda family tree I load the images locally by the name of the person. So every person has it's own picture.
Also make sure that you have the onerror in HTML used to show a default image when the wanted image is deleted or something else. Otherwhise the Google Chrome shows an ugly red cross. Just as a tip =)
If you have any further question, just ask.

Resources