I'm creating a bubble chart using chartjs. I am able to create tooltips that describe each of the bubbles, but users of my chart may not be able to hover over it to see the tooltip. The BubbleData object format doesn't include a label element (I put one in anyway - no luck), I've tried the "labels" element for the Chart Data object (even though the docs say this is for Category labels - you never know!), and everything I can think of to put label on the bubble.
Is there a tooltip configuration that makes all the tooltips visible at all times? This would work for me as well.
Thanks;
Glenn
I was looking for the same thing and figured out how to do it.
add in the datasets the title:"dataTitle3" you want to show.
use the data labeling plugin.
simple code manipulation achieves what you want using
dataset.title
I have made a sample but I think you could find out how and represent the data you want if you play with: external link
new Chart(document.getElementById("bubble-chart"), {
type: 'bubble',
data: {
labels: "Africa",
datasets: [{
label: ["China"],
backgroundColor: "rgba(255,221,50,0.2)",
borderColor: "rgba(255,221,50,1)",
title: "dataTitle1", //adding the title you want to show
data: [{
x: 21269017,
y: 5.245,
r: 15
}]
}, {
label: ["Denmark"],
backgroundColor: "rgba(60,186,159,0.2)",
borderColor: "rgba(60,186,159,1)",
title: "dataTitle2",
data: [{
x: 258702,
y: 7.526,
r: 10
}]
}, {
label: ["Germany"],
backgroundColor: "rgba(0,0,0,0.2)",
borderColor: "#000",
title: "dataTitle3", //adding the title you want to show
data: [{
x: 3979083,
y: 6.994,
r: 15
}]
}, {
label: ["Japan"],
backgroundColor: "rgba(193,46,12,0.2)",
borderColor: "rgba(193,46,12,1)",
title: "dataTitle4", //adding the title you want to show
data: [{
x: 4931877,
y: 5.921,
r: 15
}]
}]
},
options: {
title: {
display: true,
text: 'Predicted world population (millions) in 2050'
},
scales: {
yAxes: [{
scaleLabel: {
display: true,
labelString: "Happiness"
}
}],
xAxes: [{
scaleLabel: {
display: true,
labelString: "GDP (PPP)"
}
}]
}
}
});
Chart.plugins.register({
afterDatasetsDraw: function(chart, easing) {
var ctx = chart.ctx;
chart.data.datasets.forEach(function(dataset, i) {
var meta = chart.getDatasetMeta(i);
if (meta.type == "bubble") { //exclude scatter
meta.data.forEach(function(element, index) {
// Draw the text in black, with the specified font
ctx.fillStyle = 'rgb(0, 0, 0)';
var fontSize = 13;
var fontStyle = 'normal';
var fontFamily = 'Helvetica Neue';
ctx.font = Chart.helpers.fontString(fontSize, fontStyle, fontFamily);
// Just naively convert to string for now
var dataString = dataset.data[index].toString();
// Make sure alignment settings are correct
ctx.textAlign = 'center';
ctx.textBaseline = 'middle';
var padding = 15;
var position = element.tooltipPosition();
ctx.fillText(dataset.title, position.x, position.y - (fontSize / 2) - padding);
});
} //if
});
}
});
<canvas id="bubble-chart" width="800" height="800"></canvas>
<script src="https://cdnjs.cloudflare.com/ajax/libs/Chart.js/3.9.1/chart.min.js" integrity="sha512-ElRFoEQdI5Ht6kZvyzXhYG9NqjtkmlkfYk0wr6wHxU9JEHakS7UJZNeml5ALk+8IKlU6jDgMabC3vkumRokgJA==" crossorigin="anonymous" referrerpolicy="no-referrer"></script>
ChartJs has a plugin now for this.
https://github.com/chartjs/chartjs-plugin-datalabels
Just install it using nuget or bower and add the reference of it. It wil automatically set z as label
The sytax has changed with chart.js V3 in a few places so I thought I'd share my variation on the chosen answer.
Chart.register({
id: 'permanentLabel',
afterDatasetsDraw: function (chart, args, options) {
var ctx = chart.ctx
chart.data.datasets.forEach(function (dataset, i) {
var meta = chart.getDatasetMeta(i)
if (meta.type == 'bubble') {
meta.data.forEach(function (element, index) {
ctx.textAlign = 'center'
ctx.textBaseline = 'middle'
var position = element.tooltipPosition()
ctx.fillText(dataset.data[index].label.toString(), position.x, position.y - dataset.data[index].r - Chart.defaults.font.size)
})
}
})
},
})
I have an some extra code, to avoid overlapping of labels.
var labelPlugin = {
myTimeout: null,
getNewYPostion:function(item, alreadyUsed, fontSize){
for(let i of alreadyUsed){
if((item.y_from >= i.y_from && item.y_from <= i.y_to) || (item.y_to>= i.y_from && item.y_to <= i.y_to)){
if((item.x_from >= i.x_from && item.x_from <= i.x_to) || (item.x_to>= i.x_from && item.x_to <= i.x_to)){
item.y_from=i.y_to+(fontSize*0.1);
item.y_to=item.y_from+fontSize;
return this.getNewYPostion(item, alreadyUsed, fontSize);
}
}
}
return item;
},
afterDatasetsDraw: function (chart, args, options) {
var ctx = chart.ctx;
var that=this;
clearTimeout(this.myTimeout);
this.myTimeout = setTimeout(function () {
var alreadyUsed = [];
chart.data.datasets.forEach(function (dataset, i) {
var txt = dataset.label;
var txtSize = ctx.measureText(txt).width;
var meta = chart.getDatasetMeta(i);
if (meta.type === "bubble") { //exclude scatter
var fontSize = 10;
var fontStyle = 'normal';
var fontFamily = 'Helvetica Neue';
ctx.font = Chart.helpers.fontString(fontSize, fontStyle, fontFamily);
ctx.fillStyle = 'rgb(0, 0, 0)';
ctx.textAlign = 'left';
ctx.textBaseline = 'middle';
var padding, position, x_from, x_to, y, y_from, y_to;
meta.data.forEach(function (element, index) {
padding = element.options.radius;
position = element.tooltipPosition();
x_from = position.x + padding + 5; // left
x_to = x_from + txtSize; // left
y = position.y; // top
y_from = y - (fontSize * 0.5);
y_to = y + (fontSize * 0.5);
var item={
'y_from': y_from,
'y_to': y_to,
'x_from': x_from,
'x_to': x_to,
};
item=that.getNewYPostion(item, alreadyUsed, fontSize);
alreadyUsed.push(item);
ctx.fillText(txt, item.x_from, item.y_from+(0.5*fontSize));
});
}
});
}, 500);
}
};
In 2022 the current version is 3.9.1 here is a working snippet:
const $canvas = document.getElementById('chart')
const popData = {
datasets: [{
label: ['Deer Population'],
data: [{
x: 100,
y: 0,
r: 25,
label: 'Russia',
}, {
x: 60,
y: 30,
r: 20,
label: 'China',
}, {
x: 40,
y: 60,
r: 25,
label: 'Canada',
}, {
x: 80,
y: 80,
r: 40,
label: 'US',
}, {
x: 20,
y: 30,
r: 25,
label: 'Africa',
}, {
x: 0,
y: 100,
r: 5,
label: 'Europe',
}],
backgroundColor: "#FF9966"
}]
};
const bubbleChart = new Chart($canvas, {
type: 'bubble',
data: popData
});
const fontSize = Chart.defaults.font.size
Chart.register({
id: 'permanentLabel',
afterDatasetsDraw: (chart, args, options) => {
const ctx = chart.ctx
ctx.textAlign = 'center'
ctx.textBaseline = 'middle'
chart.data.datasets.forEach((dataset, i) => {
const meta = chart.getDatasetMeta(i)
if (meta.type !== 'bubble') return
meta.data.forEach((element, index) => {
const item = dataset.data[index]
const position = element.tooltipPosition()
ctx.fillText(item.label.toString(), position.x, position.y - item.r - fontSize)
})
})
},
})
<script src="https://cdnjs.cloudflare.com/ajax/libs/Chart.js/3.9.1/chart.min.js"></script>
<canvas id="chart" width="600" height="180"></canvas>
I'm try to use tooltip in a element inside a iframe(generated by htmleditor component).
This is i'm trying:
Ext.tip.QuickTipManager.init();
Ext.create('Ext.form.HtmlEditor', {
width: 750,
height: 250,
renderTo: Ext.getBody(),
listeners: {
afterrender: function () {
this.getToolbar().add([{
xtype: "combobox",
flex: 1,
displayField: "name",
valueField: "value",
store: {
data: [{
name: "#NAME# (User's name)",
value: "#NAME#"
}]
}
}, {
xtype: "button",
text: "Add",
handler: function () {
var value = this.prev().getValue();
var htmlEditor = this.up("htmleditor");
if (value) {
var id = Ext.id();
value = "<span id=\"" + id + "\" style=\"cursor:pointer;\">" + value + "</span>";
htmlEditor.insertAtCursor(value);
var doc = htmlEditor.getDoc();
var elSpan = doc.getElementById(id);
var tTip = Ext.create("Ext.tip.ToolTip", {
html: "User's name tooltip.",
shadow: false,
scope: doc
});
elSpan.addEventListener("mouseover", function () {
tTip.showAt(elSpan.offsetLeft, elSpan.offsetTop)
});
elSpan.addEventListener("mouseleave", function () {
tTip.hide();
});
}
}
}])
}
}
});
But, when the component is shown, it appear in wrong position. See on the fiddle.
Sencha Fiddle: https://fiddle.sencha.com/#view/editor&fiddle/1vj4
I found a solution!
elSpan.addEventListener("mouseover", function (e) {
var x = e.pageX;
var y = e.pageY;
var region = htmlEditor.getRegion();
x += region.x;
y += region.y;
tTip.showAt([x, y]);
});
I am using
var modalWindow = new Ext.Window({
title: "Window",
items: [
{html: "<div id='example'>Hello</div> "}
]
});
modalWindow.show();
to open a modal window. I need fadein/fadeout features on this window.
Please help..
This should do it:
var modalWindow = new Ext.Window({
title: "Window",
width: 400,
height: 300,
html: "<div id='example'>Hello</div> ",
listeners : {
show : function(window) {
window.getEl().setOpacity(0);
window.getEl().fadeIn({duration: 2000});
},
beforeclose : function(window) {
if(!window.shouldClose) {
window.getEl().fadeOut({duration: 2000, callback: function() {
window.shouldClose = true;
window.close();
}});
}
return window.shouldClose ? true : false;
}
}
});
modalWindow.show();
Here is the Label object
,
label: {
rotate: {
degrees: 90
},
renderer: function(v){
var toolTip = Ext.create('Ext.tip.ToolTip', {
target: this,
html: v,
anchor: 'left',
dismissDelay: 0,
showDelay: 0,
autoHide: false
});
toolTip.on('show', function(){
var timeout;
toolTip.getEl().on('mouseout', function(){
timeout = window.setTimeout(function(){
toolTip.hide();
}, 500);
});
toolTip.getEl().on('mouseover', function(){
window.clearTimeout(timeout);
});
Ext.get(targetId).on('mouseout', function(){
timeout = window.setTimeout(function(){
toolTip.hide();
}, 500);
});
});
if(v.length>10)
return Ext.util.Format.substr(v,0,10) +'...' ;
}
}
This code is not not creating the tool tip. No error occurs. Is there any other method to create the category label tool tip.
Thanks,
Anish
launch: function() {
// The following is accomplished with the Google Map API
var position = new google.maps.LatLng(12.9833, 77.5833), //Sencha HQ
infowindow = new google.maps.InfoWindow({
content: 'bengaluru'
}),
//Tracking Marker Image
image = new google.maps.MarkerImage(
'resources/images/point.png',
new google.maps.Size(32, 31),
new google.maps.Point(0, 0),
new google.maps.Point(16, 31)
),
shadow = new google.maps.MarkerImage(
'resources/images/shadow.png',
new google.maps.Size(64, 52),
new google.maps.Point(0, 0),
new google.maps.Point(-5, 42)
),
trackingButton = Ext.create('Ext.Button', {
iconMask: true,
iconCls: 'locate'
}),
trafficButton = Ext.create('Ext.Button', {
iconMask: true,
pressed: true,
iconCls: 'maps'
}),
toolbar = Ext.create('Ext.Toolbar', {
docked: 'top',
ui: 'light',
defaults: {
iconMask: true
},
items: [
{
xtype:'button',
id:'calculate',
text:'calculate',
handler:function(){
alert('hello');
}
}
]
});
var mapdemo = Ext.create('Ext.Map', {
mapOptions : {
center : new google.maps.LatLng(37.381592, 122.135672), //nearby San Fran
zoom : 12,
mapTypeId : google.maps.MapTypeId.ROADMAP,
navigationControl: true,
navigationControlOptions: {
style: google.maps.NavigationControlStyle.DEFAULT
}
},
plugins : [
new Ext.plugin.google.Tracker({
trackSuspended: true, //suspend tracking initially
allowHighAccuracy: false,
marker: new google.maps.Marker({
position: position,
title: 'My Current Location',
shadow: shadow,
icon: image
})
}),
new Ext.plugin.google.Traffic()
],
listeners: {
maprender: function(comp, map) {
var marker = new google.maps.Marker({
position: position,
title : 'Sencha HQ',
map: map
});
google.maps.event.addListener(marker, 'click', function() {
infowindow.open(map, marker);
});
setTimeout(function() {
map.panTo(position);
}, 1000);
}
}
});
Any ideas how can i measure distance between two destinations whose latitude and longitude are know........
this code is taken from the example provided by the sencha touch2 with little modification.
Its for sencha touch 2
try google.maps.geometry.spherical.computeDistanceBetween(from:LatLng, to:LatLng, radius?:number)
radius is the earth's radius = 6371000 metres (average)