Tooltip information shown on hover over pointin scatter plot

1,243 views
Skip to first unread message

arvind kumar

unread,
Dec 15, 2015, 10:07:58 AM12/15/15
to vega-js
I am trying to create a tooltip dialog to be shown when I hover over a point in the scatter plot, similar to the below image:



 The code to the vega json spec can be found here (this can be pasted in the vega editor):

I have been able to get text on hover over the point.

I have tried making a 'rect' type mark, but the rectangle appears when I hover over the area taken up by the rectangle, instead of appearing only when I hover over the mark.

I am at my wit's end. Any help would be great. 

Thanks,
Arvind

Roy I

unread,
Dec 15, 2015, 11:25:34 AM12/15/15
to vega-js

arvind kumar

unread,
Dec 17, 2015, 10:09:56 AM12/17/15
to vega-js
Hi Roy,

I was able to create tooltip, but I am not able to set the filter correctly to show only the relevant tooltips on mouse hover. Can you see if the filter 'test' expression is okay?

"transform": [
        {
          "type": "filter", 
          "test": "datum.Revenue == currentX  && datum.EBIT_Margin_Percentage == currentY"
        }]


When I set the test expression as '<=' it works. But this shows all the tooltips with x and y values less than the X and Y of current mouse position. 




Thanks,
Arvind

Roy I

unread,
Dec 18, 2015, 9:25:24 AM12/18/15
to vega-js
Here is a working example of your data that includes tooltip and legend.

For tooltip, define signal for mouseover mark item (instead of mousemove).

For legend, the Brand icons (Unicode char) and Brand names are specified as explicit values in Vega spec (workaround for now because not using Vega "symbol")

Notes: 
1. Set Vega renderer: "canvas" (legend disappears if use renderer: "svg" -- Vega bug?)

2. Your original sample data have duplicated values for Customer Name and ID 

3. The Vega spec here will run in online Vega Editor (v2.3.1)



--------------------------

{
  "width": 800,
  "height": 500,
  "viewport": [900,565],
  "data": [
    {
      "name": "polaris",
      "values": [


        {
          "EBIT_Margin_Percentage": 0.157591659,
          "Direct_Customer_Margin_Percentage": 0.215736741,
          "Gross_Margin_Percentage": 0.273482796,
          "Net_Revenue": 261.3415014,
          "Revenue": 485974308,
          "Product_Category": "Category 1",
          "Product_Brand": "Brand 1",
          "Product_Type": "Base 1",
          "Customer_ID": 2073,
          "Customer_Name": "Customer 71",
          "Customer_Division": "Customer Division 1",
          "Customer_Segment": "Customer Segment 2",
          "Customer_Channel": "Convenience",
          "YEAR": 2014
        },

        {
          "EBIT_Margin_Percentage": 0.535598434,
          "Direct_Customer_Margin_Percentage": 0.586116449,
          "Gross_Margin_Percentage": 0.662798607,
          "Net_Revenue": 380.7709344,
          "Revenue": 3918232318,
          "Product_Category": "Category 1",
          "Product_Brand": "Brand 1",
          "Product_Type": "Base 1",
          "Customer_ID": 2049,
          "Customer_Name": "Customer 49",
          "Customer_Division": "Customer Division 1",
          "Customer_Segment": "Customer Segment 1",
          "Customer_Channel": "Grocery",
          "YEAR": 2014
        },


        {
          "EBIT_Margin_Percentage": 0.006290887,
          "Direct_Customer_Margin_Percentage": 0.057646786,
          "Gross_Margin_Percentage": 0.074200668,
          "Net_Revenue": 185.0931896,
          "Revenue": 7089137576,
          "Product_Category": "Category 1",
          "Product_Brand": "Brand 2",
          "Product_Type": "Base 1",
          "Customer_ID": 2056,
          "Customer_Name": "Customer 55",
          "Customer_Division": "Customer Division 1",
          "Customer_Segment": "Customer Segment 2",
          "Customer_Channel": "Grocery",
          "YEAR": 2012
        },

       {
          "EBIT_Margin_Percentage": 0.043192134,
          "Direct_Customer_Margin_Percentage": 0.1226068,
          "Gross_Margin_Percentage": 0.155391206,
          "Net_Revenue": 155.6333682,
          "Revenue": 3508581508,
          "Product_Category": "Category 1",
          "Product_Brand": "Brand 1",
          "Product_Type": "Base2",
          "Customer_ID": 2025,
          "Customer_Name": "Customer 27",
          "Customer_Division": "Customer Division 1",
          "Customer_Segment": "Customer Segment 1",
          "Customer_Channel": "Value",
          "YEAR": 2013
        },

        {
          "EBIT_Margin_Percentage": 0.107188683,
          "Direct_Customer_Margin_Percentage": 0.160930201,
          "Gross_Margin_Percentage": 0.189590501,
          "Net_Revenue": 179.863111,
          "Revenue": 516474456,
          "Product_Category": "Category 1",
          "Product_Brand": "Brand 2",
          "Product_Type": "Base 1",
          "Customer_ID": 2050,
          "Customer_Name": "Customer 5",
          "Customer_Division": "Customer Division 1",
          "Customer_Segment": "Customer Segment 2",
          "Customer_Channel": "Mass",
          "YEAR": 2013
        },
        {
          "EBIT_Margin_Percentage": 0.196238882,
          "Direct_Customer_Margin_Percentage": 0.287904899,
          "Gross_Margin_Percentage": 0.314938029,
          "Net_Revenue": 234.5323982,
          "Revenue": 4324485256,
          "Product_Category": "Category 1",
          "Product_Brand": "Brand 2",
          "Product_Type": "Base 1",
          "Customer_ID": 2021,
          "Customer_Name": "Customer 22",
          "Customer_Division": "Customer Division 1",
          "Customer_Segment": "Customer Segment 2",
          "Customer_Channel": "Grocery",
          "YEAR": 2013
        }


 


      ]
    },

{
"name": "data_tooltip",
"source": "polaris",
        "transform": [
{
"type": "filter", 
"test": "datum._id == signal_point.datum['_id']"
}
]
}
  ],
  
  
  "signals": [
  {
"name": "signal_point",
"init": {"expr": "{x: 0, y: 0, datum: {} }"}, 
"streams": [
{
"type": "@mark_point:mouseover",
"expr": "{x: eventX(), y: eventY(), datum: eventItem().datum}"

},
{
"type": "@mark_point:mouseout",
"expr": "{x: 0, y: 0, datum: {} }"
}
}
  ],
  
  
  "scales": [
    {
      "name": "x",
      "range": "width",
      "domain": {"data": "polaris","field": "Revenue"}
    },
    {
      "name": "y",
      "range": "height",
      "domain": {"data": "polaris","field": "EBIT_Margin_Percentage"}
    },
    {
      "name": "colors",
      "type": "ordinal",
      "domain": {"data": "polaris","field": "Customer_Channel"},
      "range": "category10"
    },
    {
      "name": "shapes",
      "type": "ordinal",
      "domain": {"data": "polaris","field": "Product_Brand"},
      "range": ["☆","⌂","❀","和","☮",""]


    }
  ],
  
  
  "axes": [
    {
      "type": "x",
      "scale": "x",
      "offset": 1,
      "tickSize": 5,
 "layer": "back",
      "title": "Revenue"
    },
    {
      "type": "y",
      "scale": "y",
      "offset": 5,
      "ticks": 5,
 "layer": "back",
      "title": "EBT Margin"
    }
  ],
  
  
  "legends": [
    {
      "shape": "shapes",
      "title": "Brand",
 "offset": 0.5,

 "values": ["\u2606 Brand 1 (A)", "\u2302  Brand 2 (B)"
],
      "properties": {
        "symbols": {
          "fillOpacity": {"value": 0.0},
          "stroke": {"value": "#001"}
        },
"title": {
"fontSize": {"value": 13}
},
"labels": {
"fontSize": {"value": 12},
"x": {"value": 3}
}
      }
    },
    {
      "fill": "colors",
      "title": "Customer Channel",
 "offset": 0.5,
      "properties": {
        "symbols": {
          "fillOpacity": {"value": 0.5},
          "stroke": {"value": "transparent"}
        },
"title": {
"fontSize": {"value": 13}
},
"labels": {
"fontSize": {"value": 12}
}
      }
    }
  ],
  
  
  "marks": [
    {
"name": "mark_point",
      "type": "text",
      "from": {"data": "polaris"},
      "properties": {
        "update": {
          "x": {"scale": "x","field": "Revenue"},
          "y": {"scale": "y","field": "EBIT_Margin_Percentage"},
          "align": {"value": "center"},
          "baseline": {"value": "middle"},
          "fontSize": {"value": 20},
          "text": {"scale": "shapes","field": "Product_Brand"},
          "stroke": {"scale": "colors","field": "Customer_Channel"},
          "strokeOpacity": {"value": 0.5},
          "fill": {"scale": "colors","field": "Customer_Channel"},
          "fillOpacity": {"value": 0.2}
        },
        "hover": {
          "stroke": {"value": "#f00"},
          "strokeOpacity": {"value": 1},
          "fill": {"scale": "colors","field": "Customer_Channel"},
          "fillOpacity": {"value": 0.8}
        }
      }
    },
    {
      "type": "rule",
      "from": {
        "data": "polaris",
        "transform": [
          {
            "type": "aggregate",
            "summarize": [
              {
                "field": "Revenue",
                "ops": ["mean"],
                "as": ["mean"]
              }
            ]
          }
        ]
      },
      "properties": {
        "update": {
          "stroke": {"value": "#000"},
          "strokeWidth": {"value": 1},
          "strokeDash": {"value": [10,5]},
          "x": {"scale": "x","field": "mean"},
          "y": {"value": 0},
          "y2": {"field": {"group": "height"}}
        }
      }
    },


{
      "type": "group",

"from": {"data": "data_tooltip",
"transform": [
{
"type": "formula", 
"field": "ff_x",
"expr": "signal_point.x > 650 ? signal_point.x - 260 : signal_point.x + 10" 
},
{
"type": "formula", 
"field": "ff_y",
"expr": "signal_point.y > 400 ? signal_point.y - 100 : signal_point.y + 20" 
}
]
      },
 
      "properties": {
        "update": {
 "x": {"field": "ff_x"},
 "y": {"field": "ff_y"},
          "width": {"value": 250},
          "height": {"value": 80},
          "fill": {"value": "#ffa"},
          "fillOpacity": {"value": 0.85},
          "stroke": {"value": "#aaa"},
          "strokeWidth": {"value": 0.5}
        }
      },
 
    "marks": [
{
          "type": "text",
          "properties": {
            "update": {
              "x": {"value": 6},
              "y": {"value": 15},
              "text": {
                "template": "Product Brand: {{signal_point.datum['Product_Brand']}}"
              },
              "fill": {"value": "black"},
              "align": {"value": "left"}
            }
          }
        },
{
          "type": "text",
          "properties": {
            "update": {
              "x": {"value": 6},
              "y": {"value": 30},
              "text": {
                "template": "Customer Name: {{signal_point.datum['Customer_Name']}} (ID: {{signal_point.datum['Customer_ID']}})"
              },
              "fill": {"value": "black"},
              "align": {"value": "left"},
 "fontWeight": {"value": "bold"}
            }
          }
        },
        {
          "type": "text",
          "properties": {
            "update": {
              "x": {"value": 6},
              "y": {"value": 45},
              "text": {
                "template": "EBIT Margin: {{signal_point.datum['EBIT_Margin_Percentage'] | number: '.0p'}}"
              },
              "fill": {"value": "black"},
              "align": {"value": "left"}
            }
          }
        },
{
          "type": "text",
          "properties": {
            "update": {
              "x": {"value": 6},
              "y": {"value": 60},
              "text": {
"template": "Revenue: {{signal_point.datum['Revenue'] | number: \",.0f\" }}"
},
              "fill": {"value": "black"}  
            }
          }
        },
{
          "type": "text",
          "properties": {
            "update": {
              "x": {"value": 6},
              "y": {"value": 75},
              "text": {
                "template": "Channel: {{signal_point.datum['Customer_Channel']}}"
              },
              "fill": {"value": "black"},
              "align": {"value": "left"}
            }
          }
        }
      ]
    }
  ]
}




On Tuesday, December 15, 2015 at 10:07:58 AM UTC-5, arvind kumar wrote:

arvind kumar

unread,
Dec 21, 2015, 1:12:18 AM12/21/15
to vega-js
Thanks a lot, Roy.

~Arvind
Message has been deleted

satish chauhan

unread,
May 9, 2017, 12:59:16 AM5/9/17
to vega-js
Hi,

Thank you for link. It really help me to create tooltip in vega3.
There is small problem in my tooltip. When we click on extreme X point it hide the tooltip.

How can we move tooltip from right to left side ?

Thanks in advance.

satish chauhan

unread,
May 9, 2017, 8:27:44 AM5/9/17
to vega-js
Hi Again,

Shift tooltip to left and right on bases of signal events.

if x-coordinate > width/2
  - display tooltip to left side by set tooltip offset "-< tooltip width> " i.e -160
else
  - display tooltip to right side by set tooltip offset "<tooltip width> " i.e 10

- update tooltip marks as well.
  

signal:
======

  signals: [
    {
      name: 'signal_tooltip',
      value: {x: 0, y: 0, datum: {}},
      on: [
        {
          events: 'rect:mouseover',
          update: '{x: x() > width/2 ? -160 : 10, y: y() > height/2 ? -50 : 10, datum: datum}'
        },
        {
          events: 'rect:mouseout',
          update: '{x: 0, y: 0, datum: {}}'
        }
      ]
    }

mark:
=====

    {
      type: 'group',
      from : {
        data: 'tooltip'
      },
      interactive: false,
      encode: {
        update: {
          x: {scale: 'x', field: 'time', offset: { signal: 'signal_tooltip.x'}},
          y: {scale: 'y', field: 'median', offset: { signal: 'signal_tooltip.y'}},
Reply all
Reply to author
Forward
0 new messages