I have a Google chart: bubble chart.
I want to add a custom HTML tooltip, with the specified value relative to the point:
<div class="clearfix>
<h3>Metric: []</h3>
<h4>ID comes here: []</h4>
<h4>X Axis Value comes here: []</h4>
<h4>Y Axis Value comes here: []</h4>
<h4>Volume comes here: []</h4>
</div>
Currently it shows a default tooltip, which is not arranged in the way i want. And I cannot edit the fields also.
I want to use Custom HTML tooltip, but sadly it is not supported by Google charts in bubble chart as of yet.
Any way to achieve the same.
MY CODE
JSFIDDLE Demo
<html>
<head>
<script type="text/javascript" src="https://www.google.com/jsapi"></script>
<script type="text/javascript">
google.load("visualization", "1", {
packages: ["corechart"]
});
google.setOnLoadCallback(drawChart);
function drawChart() {
var data = google.visualization.arrayToDataTable([
["ID", "X Axis Value", "Y Axis Value", "Metric", "Volume"],
["Range: 2-5", 3, 2.5, "Value Provider", 300],
["Range: 2-5", 4, 2.5, "Third Provider", 239],
["Range: 3-8", 3, 7.4, "Second Provider", 344],
["Range: 5-8", 5, 7.3, "Value Provider", 324],
["Range: 2-10", 9, 2.32, "Third Provider", 765],
["Range: 2-5", 5, 3, "Value Provider", 342],
]);
var options = {
title: 'Range Volume',
hAxis: {
title: 'X Axis'
},
vAxis: {
title: 'Y Axis'
},
bubble: {
textStyle: {
fontSize: 11,
color:'transparent'
}
}
};
var chart = new google.visualization.BubbleChart(document.getElementById('chart_div'));
chart.draw(data, options);
}
</script>
</head>
<body>
<div id="chart_div" style="width: 100%; height: 90vh;"></div>
</body>
Basically you need some kind of mousetracker to know where tooltip should be shown and you need two listeners like this:
google.visualization.events.addListener chart, 'onmouseover', mouseoverHandler
google.visualization.events.addListener chart, 'onmouseout', mouseoutHandler
and you should add id='tooltip' to your tooltip with css like:
#tooltip {
display: none;
position: absolute;
padding: 10px;
border: 1px solid #ddd;
background: white;
width: 350px;
-webkit-box-shadow: 0 0 5px #ddd;
-moz-box-shadow: 0 0 5px #ddd;
box-shadow: 0 0 5px #ddd;
z-index: 1;
}
javascript:
var $tooltip = $('#tooltip')
mouseoverHandler = function(event) {
metric = data.getValue(event.row, 3);
id = data.getValue(event.row, 0);
xAxis = data.getValue(event.row, 1);
yAxis = data.getValue(event.row, 2);
volume = data.getValue(event.row, 4);
$tooltip.find('h3').append(metric);
$tooltip.css({
top: y,
left: x
}).show();
};
mouseoutHandler = function() {
$tooltip.hide();
};
x and y are your mouse cords taken from some kind of mouse tracker like: Javascript - Track mouse position.
title = data.getValue(event.row, 3); is line where you take data from your data from your chart and you have to insert this data into your tooltip the way you want it to be inserted. I hope it will help.
Related
I am trying to learn how to use the interact.js library and I cant get the resizing example to be draggable. I can resize the div ".resize-drag" but I don´t know how to get it draggable. Can anyone tell me is wrong with my code?
This code is only so that I can learn to implement the resize example provided at http://interactjs.io/ So far I´ve tried using npm instead of the script tag. When I copied the example below from the top of the interact.js website and renamed the element ".item" in the interact claus but that did not work
interact('.item').draggable({
onmove(event) {
console.log(event.pageX,
event.pageY)
}
})
I suspected it might be a syntax error so I also tried adding semicolon behind the function but that didn´t seem to be the problem. Please have a look at my entire code below to see what I have done wrong.
<!DOCTYPE html>
<!--
To change this license header, choose License Headers in Project
Properties.
To change this template file, choose Tools | Templates
and open the template in the editor.
-->
<html>
<head>
<meta charset="UTF-8">
<title></title>
<style>
.resize-drag {
background-color: #29e;
color: white;
font-size: 20px;
font-family: sans-serif;
border-radius: 8px;
padding: 20px;
margin: 30px 20px;
width: 120px;
/* This makes things *much* easier */
box-sizing: border-box;
}
.resize-container {
display: inline-block;
width: 100%;
height: 240px;
background-color: lightblue;
}
</style>
<script
src="https://unpkg.com/interactjs#1.3.4/dist/interact.min.js"></script>
<script type="text/javascript">
interact('.resize-drag').draggable({
onmove(event) {
console.log(event.pageX,
event.pageY)
}
})
interact('.resize-drag')
.draggable({
onmove: window.dragMoveListener,
restrict: {
restriction: 'parent',
elementRect: { top: 0, left: 0, bottom: 1, right: 1 }
},
})
.resizable({
// resize from all edges and corners
edges: { left: true, right: true, bottom: true, top: true },
// keep the edges inside the parent
restrictEdges: {
outer: 'parent',
endOnly: true,
},
// minimum size
restrictSize: {
min: { width: 100, height: 50 },
},
inertia: true,
})
.on('resizemove', function (event) {
var target = event.target,
x = (parseFloat(target.getAttribute('data-x')) || 0),
y = (parseFloat(target.getAttribute('data-y')) || 0);
// update the element's style
target.style.width = event.rect.width + 'px';
target.style.height = event.rect.height + 'px';
// translate when resizing from top or left edges
x += event.deltaRect.left;
y += event.deltaRect.top;
target.style.webkitTransform = target.style.transform =
'translate(' + x + 'px,' + y + 'px)';
target.setAttribute('data-x', x);
target.setAttribute('data-y', y);
target.textContent = Math.round(event.rect.width) + '\u00D7' +
Math.round(event.rect.height);
});
</script>
</head>
<body>
<div class="resize-container">
<div class="resize-drag">
Resize from any edge or corner
</div>
</div>
</body>
</html>
I want to be able to drag the div and not just resize it.
I recently struggled with that as well, and it turned out that the 'resizing' code blurbs don't have all the code. The js is missing window.dragMoveListener and dragMoveListener, which is found in the 'dragging' section.
Specifically you need to add this
function dragMoveListener (event) {
var target = event.target,
// keep the dragged position in the data-x/data-y attributes
x = (parseFloat(target.getAttribute('data-x')) || 0) + event.dx,
y = (parseFloat(target.getAttribute('data-y')) || 0) + event.dy;
// translate the element
target.style.webkitTransform =
target.style.transform =
'translate(' + x + 'px, ' + y + 'px)';
// update the posiion attributes
target.setAttribute('data-x', x);
target.setAttribute('data-y', y);
}
// this is used later in the resizing and gesture demos
window.dragMoveListener = dragMoveListener;
If you look at this bar chart from Google's help documentation and hover over the 2011 bar, a tooltip pops up.
Notice that the y-axis is labeled "Sales: 1,500" while the x-axis has no label. How can I add a label to the x-axis so that it says "Year: 2011"?
I would prefer to use the default tooltips rather than the html tooltips.
there are only a couple options, when not using html tooltips...
1) use a tooltip column role and provide the content of the tooltip in the data table...
see following working snippet...
google.charts.load('current', {
packages: ['corechart']
}).then(function () {
var dataTable = new google.visualization.DataTable();
dataTable.addColumn('string', 'Year');
dataTable.addColumn('number', 'Sales');
dataTable.addColumn({type: 'string', role: 'tooltip'});
dataTable.addRows([
['2010', 600, 'Year: 2010\nSales: 600'],
['2011', 1500, 'Year: 2011\nSales: 1500'],
['2012', 800, 'Year: 2012\nSales: 800'],
['2013', 1000, 'Year: 2013\nSales: 1000']
]);
var chart = new google.visualization.ColumnChart(document.getElementById('chart_div'));
chart.draw(dataTable);
});
<script src="https://www.gstatic.com/charts/loader.js"></script>
<div id="chart_div"></div>
2) use numbers instead of strings for the x-axis,
then you can use object notation to provide both the x-axis value (v:) and formatted value (f:)
{v: 2010, f: 'Year: 2010'}
the tooltip will display the formatted value by default
see following working snippet...
google.charts.load('current', {
packages: ['corechart']
}).then(function () {
var dataTable = new google.visualization.DataTable();
dataTable.addColumn('number', 'Year');
dataTable.addColumn('number', 'Sales');
dataTable.addRows([
[{v: 2010, f: 'Year: 2010'}, 600],
[{v: 2011, f: 'Year: 2011'}, 1500],
[{v: 2012, f: 'Year: 2012'}, 800],
[{v: 2013, f: 'Year: 2013'}, 1000]
]);
var chart = new google.visualization.ColumnChart(document.getElementById('chart_div'));
chart.draw(dataTable, {
hAxis: {
format: '0',
ticks: dataTable.getDistinctValues(0)
}
});
});
<script src="https://www.gstatic.com/charts/loader.js"></script>
<div id="chart_div"></div>
major drawback to both options above, you cannot style the tooltip
1) nothing is bold
2) both label and value are bold (Year: 2011)
best results will come by using html tooltips,
following is an example of building the tooltips dynamically, using a DataView...
google.charts.load('current', {
packages: ['corechart']
}).then(function () {
var dataTable = new google.visualization.DataTable();
dataTable.addColumn('string', 'Year');
dataTable.addColumn('number', 'Sales');
dataTable.addRows([
['2010', 600],
['2011', 1500],
['2012', 800],
['2013', 1000]
]);
// build data view columns
var viewColumns = [];
for (var col = 0; col < dataTable.getNumberOfColumns(); col++) {
addColumn(col);
}
function addColumn(col) {
// add data table column
viewColumns.push(col);
// add tooltip column
if (col > 0) {
viewColumns.push({
type: 'string',
role: 'tooltip',
calc: function (dt, row) {
// build custom tooltip
var tooltip = '<div class="ggl-tooltip"><div>';
tooltip += dt.getColumnLabel(0) + ': <span>';
tooltip += dt.getValue(row, 0) + '</span></div>';
tooltip += '<div>' + dt.getColumnLabel(col) + ': <span>';
tooltip += dt.getFormattedValue(row, col) + '</span></div></div>';
return tooltip;
},
p: {html: true}
});
}
}
var dataView = new google.visualization.DataView(dataTable);
dataView.setColumns(viewColumns);
var chart = new google.visualization.ColumnChart(document.getElementById('chart_div'));
// use data view to draw chart
chart.draw(dataView.toDataTable(), {
tooltip: {
isHtml: true
}
});
});
.ggl-tooltip {
background-color: #ffffff;
border: 1px solid #e0e0e0;
font-family: Arial, Helvetica;
font-size: 14px;
padding: 12px 12px 12px 12px;
}
.ggl-tooltip div {
margin-top: 4px;
}
.ggl-tooltip span {
font-weight: bold;
}
<script src="https://www.gstatic.com/charts/loader.js"></script>
<div id="chart_div"></div>
I'm working on MapBoxgl and I want to add several markers.
Here is my index.html:
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8" />
<link href=" /assets/css/bootstrap.min.css " rel="stylesheet" />
<link href=" /assets/css/mapbox-gl.css " rel="stylesheet" />
<link href=" /assets/css/main.css " rel="stylesheet" />
</head>
<body>
<div id="map"></div>
<script src="/assets/js/mapbox-gl.js"></script>
<script src="/assets/js/map-style.js"></script>
</body>
</html>
This is map-style.js:
var map = new mapboxgl.Map({
container: 'map',
center: [57.3221, 33.5928],
zoom: 5,
style: style
});
var geojson = {
type: 'FeatureCollection',
features: [{
type: 'Feature',
geometry: {
type: 'Point',
coordinates: [30.61, 46.28]
},
properties: {
title: 'point 1',
description: 'point 1 Description',
message: 'point1',
iconSize: [25, 25]
}
},
{
type: 'Feature',
geometry: {
type: 'Point',
coordinates: [30.62, 46.2845]
},
properties: {
title: 'point 2',
description: 'point 2 Description',
message: 'point 2',
iconSize: [25, 25]
}
}]
};
map.on('load', function () {
// add markers to map
geojson.features.forEach(function(marker) {
// create a DOM element for the marker
var el = document.createElement('div');
el.className = 'markers';
el.style.backgroundImage = 'url(assets/marker-azure.png)';
//el.style.width = marker.properties.iconSize[0] + 'px';
el.style.height = marker.properties.iconSize[1] + 'px';
el.addEventListener('click', function() {
window.alert(marker.properties.message);
});
// add marker to map
new mapboxgl.Marker(el)
.setLngLat(marker.geometry.coordinates)
.addTo(map);
});
});
And following is main.css portion related to map and marker:
#map { position:absolute; top:0; bottom:0; width:100% }
.markers {
display: absolute;
border: none;
border-radius: 50%;
cursor: pointer;
padding: 0;
}
So, my problem is that when I add width property to markers, their icon be displayed correctly (with a bit stretch) but they are in wrong coordinate and move on zoom, like picture below:
On the other hand, if width property is eliminated, they are in right place and does not move on zooming, but they are very stretched and in fact as wide as screen (following image):
It's noteworthy that I've used bootstrap. Can it be the reason of this? If not, what's the problem?
Thanks
import 'mapbox-gl/dist/mapbox-gl.css';
Adding import css works for me.
I found the solution and share it here with others who will encounter this problem. The problem caused because of using a not-most-recent version of the library. After upgrading to the latest release, I could get rid of that problem.
Note that these kinds of problems sometimes occur, when you use npm. Make sure that the library is downloaded completely and It's the latest release.
Latest releases of MapBox can be found at here.
had similar issue, the marker seemed to change position on zoom in/out, fixed it by setting offset, thought to share if it can help others, here is the fiddle
// add marker to map
var m = new mapboxgl.Marker(el, {offset: [0, -50/2]});
m.setLngLat(coordinates);
m.addTo(map);
(Using mapbox 1.13.0)
I had a similar issue where the popups weren't displaying and would change position based on zoom.
Mapbox officially states that you need to include the css file to have markers and popups work as expected.
https://docs.mapbox.com/mapbox-gl-js/guides/install/
HOWEVER, you can also copy that css directly into a component and use that as an element. For example:
export default function MarkerMapTest(props) {
const mapContainer = React.useRef(null)
const map = React.useRef(null)
const elemRef = React.useRef(null)
React.useEffect(() => {
map.current = new mapboxgl.Map({
container: mapContainer.current,
style: "mapbox://styles/mapbox/dark-v10",
center: [151.242, -33.9132],
zoom: 14,
})
const marker = new mapboxgl.Marker({
element: elemRef.current,
})
.setLngLat([151.242, -33.9132])
.addTo(map.current)
}, [])
return (
<div
style={{ width: 600, height: 600, backgroundColor: "gray" }}
ref={mapContainer}
>
<div
style={{
width: 30,
height: 30,
borderRadius: 15,
backgroundColor: "red",
position: "absolute", // !
top: 0, // !
left: 0, // !
}}
ref={elemRef}
/>
</div>
In my case the svg I used had some space around the real content. That way it seemed for me that the marker was moving. A simple fix was to remove the space around the content (e.g. with the "Resize page to drawing or selection" option of inkscape: https://graphicdesign.stackexchange.com/a/21638)
Also it is important to set display: block on the svg-marker. See: https://stackoverflow.com/a/39716426/11603006
I need your help, i try use "pattern" in Highcharts to use background in bars, but the images don't fill the space that i wanna.
Bar Chart Example
I wanna know, how i do to leave the image with -90° than the way that is? And how i do to leave the image with height 100% and width 25%?
And beyond that i wanna of know, how i print the screen without lose the quality in image, because when i press "ctrl+p" i see all all blurred.
Print blurred
Follow below the current code:
<!DOCTYPE html>
<html>
<head>
<title>HighCharts - Pattern Color</title>
<meta http-equiv="Content-Type" contetn="text/html;" charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<link rel="stylesheet" href="http://code.jquery.com/ui/1.9.1/themes/base/jquery-ui.css" />
<script src="https://code.jquery.com/jquery-2.2.4.min.js"></script>
<script src="https://code.jquery.com/ui/1.9.1/jquery-ui.js"></script>
<script src="https://code.highcharts.com/highcharts.js"></script>
<script src="https://highcharts.github.io/pattern-fill/pattern-fill.js"></script>
<script src="https://code.highcharts.com/modules/exporting.js"></script>
</head>
<body>
<script type="text/javascript">
$(document).ready(function() {
Highcharts.chart('container', {
chart: {
type: 'bar',
backgroundColor: null
},
title: {
text: 'Como você está?'
},
xAxis: {
categories: ['']
},
yAxis: {
min: 0,
title: {
text: ''
}
},
legend: {
reversed: true
},
plotOptions: {
series: {
stacking: 'percent',
dataLabels: {
enabled: true,
format: '<b>{point.percentage:.2f}%</b>',
//point.percentage:.1f
color: (Highcharts.theme && Highcharts.theme.dataLabelsColor) || 'white'
}
}
},
series: [{
name: 'Alegre',
data: [30],
color: {
pattern: 'http://emoticons.topfriends.biz/favicon.png',
width: '30',
height: '30'
}
// color: '#B22222'
}, {
name: 'Feliz',
data: [30],
color: {
pattern: 'https://t4.ftcdn.net/jpg/01/58/30/09/240_F_158300957_MhRWEx1vDO6SPVHdGS4dqNG7nLP8rdZ4.jpg',
width: '30',
height: '30'
}
// color: '#2E8B57'
}]
});
});
</script>
<div id="container" style="min-width: 80%; height: 200px; max-width: 80%; margin: 0 auto"></div>
</body>
</html>
Since now i thanks!
1. PATTERN FILL ADJUSTMENT
Refer to this live working example: http://jsfiddle.net/kkulig/opa73k8L/
Full code:
var redrawEnabled = true,
ctr = 0;
$('#container').highcharts({
chart: {
events: {
render: function() {
if (redrawEnabled) {
redrawEnabled = false;
var chart = this,
renderer = chart.renderer;
chart.series[0].points.forEach(function(p) {
var widthRatio = p.shapeArgs.width / p.shapeArgs.height,
id = 'pattern-' + p.index + '-' + ctr;
var pattern = renderer.createElement('pattern').add(renderer.defs).attr({
width: 1,
height: widthRatio,
id: id,
patternContentUnits: 'objectBoundingBox'
});
renderer.image('http://emoticons.topfriends.biz/favicon.png', 0, 0, 1, widthRatio).attr({
}).add(pattern);
p.update({
color: 'url(#' + id + ')'
}, false);
});
ctr++;
chart.redraw();
redrawEnabled = true;
}
}
}
},
series: [{
type: 'bar',
borderWidth: 1,
borderColor: '#000000',
data: [10, 29.9, 71.5]
}]
});
In the redraw event I iterate all the points, create a separate pattern for every point based on its width/height ratio, apply pattern and redraw the chart.
On every redraw new set of patters are created which is not an elegant solution (old ones should be replaced instead). ctr variable is used to create unique name for each pattern.
redrawEnabled serves to prevent infinite recursive loop because chart.redraw() also calls the render event.
In my opinion the easiest way to have the rotated image is to simply provide the already rotated one.
API references:
https://api.highcharts.com/highcharts/chart.events.render
https://api.highcharts.com/class-reference/Highcharts.SVGRenderer#createElement
https://api.highcharts.com/class-reference/Highcharts.SVGRenderer#image
2. PRINTING ISSUE
It seems to be a bug reported here: https://github.com/highcharts/pattern-fill/issues/20
I need a one column column-chart that has a vertical axis from 0 to 150000 and a bar that fills it (they have met their deductible completely). I thought I had what I read to do this as below, but that gives me a vertical axis of 0 to 400,000 and a bar up to 150,000.
Alternatively, I could use suggestions on how to display a single field whereas one can pay in full or in 4 payments to meet that deductible.
PLEASE help!
<script type="text/javascript">
google.charts.load('current', {'packages':['corechart']});
google.charts.setOnLoadCallback(barDisassembly);
function barDisassembly() {
var data = google.visualization.arrayToDataTable([
['Categories', 'Disassembly Fee'],
['N-1701', 150000]
]);
var options = {
chart: {
width: 200,
height: 400,
legend: { position: 'top', maxLines: 3 },
vAxis: {
viewWindowMode:'explicit',
viewWindow:{
max:150000,
min:0
}
}
}
};
var bar = new google.visualization.ColumnChart(document.getElementById('bar_disassembly'));
bar.draw(data, options);
}
</script>
Remove chart from the options.
The only configuration options associated with chart are subtitle and title...
google.charts.load('current', {'packages':['corechart']});
google.charts.setOnLoadCallback(barDisassembly);
function barDisassembly() {
var data = google.visualization.arrayToDataTable([
['Categories', 'Disassembly Fee'],
['N-1701', 150000]
]);
var options = {
width: 400,
height: 400,
legend: {
position: 'top',
maxLines: 3
},
vAxis: {
viewWindow: {
max: 150000,
min: 0
}
}
};
var bar = new google.visualization.ColumnChart(document.getElementById('bar_disassembly'));
bar.draw(data, options);
}
<script src="https://www.gstatic.com/charts/loader.js"></script>
<div id="bar_disassembly"></div>