I have a chart. There is no mouseOver event in chart options, but I need to get mouse coordinates when I move cursor. For example, I want to show coordinates on xAxis and yAxis. Is it possible?
You can catch mousevent on the div which contain highcharts.
http://jsfiddle.net/5KHaj/2/
$('#highcharts-0').mouseover(function(e){
$('#report').html(e.clientX + ' ' + e.clientY);
});
Get the normal mouse coordinates then calculate the relative position.
document.body.onmousemove = function (event) {
var x = event.target.x - <your_chart_element>.getBoundingClientRect().left
var y = event.target.y - <your_chart_element>.getBoundingClientRect().top
}
Related
I am trying to implement a 'click anywhere' feature in plotly so that I can get the coordinates on user clicks anywhere on plotly charts. The current "official" plotly functionality only works when users click on a plotted data point, but I want to register clicks e.g. on the background white canvas.
Shiny click events for plots can do that, but surprisingly this doesn't seem to exist yet in plotly.
I made some research and found the following codepen implementation which comes close: https://codepen.io/tim-logan/pen/yLXgpyp
#JS
var d3 = Plotly.d3;
var gd = document.getElementById('graph');
Plotly.plot('graph', [{
y: [2, 1, 2]
}])
.then(attach);
function attach() {
var xaxis = gd._fullLayout.xaxis;
var yaxis = gd._fullLayout.yaxis;
var l = gd._fullLayout.margin.l;
var t = gd._fullLayout.margin.t;
gd.addEventListener('mousemove', function(evt) {
var xInDataCoord = xaxis.p2c(evt.x - l);
var yInDataCoord = yaxis.p2c(evt.y - t);
console.log(evt.x, l)
Plotly.relayout(gd, 'title', ['x: ' + xInDataCoord, 'y : ' + yInDataCoord].join('<br>'));
});
}
# HTML
<head>
<script src="https://cdn.plot.ly/plotly-latest.min.js"></script>
</head>
<body>
<div style="padding-left: 100px; margin-left: 100px">
<div id="graph"></div>
</div>
</body>
However, as the creator of the codepen pointed out, the click coordinates are not precises as they don't take into account the padding / margin:
One issue with the example workaround is that it doesn't account for padding/margin in parent objects.
I've taken the example and added a parent div that has both padding and margin on the left side, this then skews the value of the x-axis value, and is clearly something that would need to be handled in such a solution as is suggested here.
According to the flot documentation this should be possible for plot objects by subtracting the plot offset from the coordinates:
https://github.com/flot/flot/blob/master/API.md#plot-methods
See e.g. the following excerpt:
Various things are stuffed inside an axis object, e.g. you could use getAxes().xaxis.ticks to find out what the ticks are for the xaxis. Two other useful attributes are p2c and c2p, functions for transforming from data point space to the canvas plot space and back. Both returns values that are offset with the plot offset.
or:
offset()
Returns the offset of the plotting area inside the grid relative to the document, useful for instance for calculating mouse positions (event.pageX/Y minus this offset is the pixel position inside the plot).
I tried to implement a workaround based on offset(), but since my js knownledge is not too good I couldn't get a working version of the code.
Would somebody be able to provide a workaround to fix the offset problem?
I managed to remove the offset by getting the parent box's dimensions. See following example which fixed the above codepen:
var d3 = Plotly.d3;
var gd = document.getElementById('graph');
Plotly.plot('graph', [{
y: [2, 1, 2]
}])
.then(attach);
function attach() {
gd.addEventListener('mousemove', function(evt) {
var bb = evt.target.getBoundingClientRect();
var x = gd._fullLayout.xaxis.p2d(evt.clientX - bb.left);
var y = gd._fullLayout.yaxis.p2d(evt.clientY - bb.top);
Plotly.relayout(gd, 'title', ['x: ' + x, 'y : ' + y].join('<br>'));
});
}
Fixed codepen here: https://codepen.io/flaviofusero/pen/BaZRgzO
Adapted from sleighsoft's implementation here: plotly click events from anywhere on the plot
I have an absolutely positioned leading line within a relatively positioned div. I need to move the leading line horizonatally as the mouse moves using d3. Since d3.event requires the elements to be positioned within g elements, I am trying to use d3.mouse to move the leading line. However, the dragging behaviour is very erratic and flickers too much. I cannot seem to figure out what is causing this.
var drag = d3.behavior
.drag()
.on('drag', function(event) {
dragMoveNew(this);
})
d3.select(".grid").call(drag);
function dragMoveNew(elem) {
var x = d3.mouse(elem)[0];
$(elem).css('left', x);
}
Here is the jsfiddle link
https://jsfiddle.net/u4koenra/
Use d3.event.x
function dragMoveNew(elem) {
//var x = d3.mouse(elem)[0];
var x = d3.event.x;
$(elem).css('left', x);
}
I'm using d3.js library and I'm having a problem implementing what the client needs.
Here's client request they want to "black circles to "follow" the mouse when you hover over it.
I don't know if d3.js library has this kind feature I can only see, on mouse drag.
I've added my sample code in JSFiddle see below:
node.on("mousemove", function(){
var coords = d3.mouse(this);
//node.attr('transform', 'translate(' + coords[0] + ',' + coords[1] + ')';
nodes.call(force.drag);
});
jsFiddle : https://jsfiddle.net/glenmongaya/4pjaeko3/5/
Thanks for you help.
You want a mouse-over to behave like a drag?
node.on("mousemove", function(d){
d3.event.stopPropagation(); // stop the default event handling
d.fixed = true; // fix the moused over node
var coords = d3.mouse(this.parentNode); // get mouse position
d.px = coords[0]; d.py = coords[1]; // set position
force.resume(); // resume layout
});
Updated fiddle.
Using Highstock is it possible to drag the chart and load the data asynchronously?
I've seen the async demo on the highcharts website http://jsfiddle.net/hcharge/5zPLV/
However this uses the navigator/scrollbar to move the chart along the series and loads the data when you stop sliding it along, Ideally I want to use the panning capability of highstock to move along instead of the navigator as it takes up too much space.
Playing around with the demo if I turn off the navigator and scrollbar and disable the zoomtype: x then as soon as you start dragging the chart it tries to fetch the data, making the chart unusable. Here is a fiddle of that http://jsfiddle.net/hcharge/6YSvk/
navigator: {enabled: false}, scrollbar: {enabled: false}
Ideally we'd need to know when the user starts dragging and when they stop then load the data.
Is this even possible to do? Thanks
I think this is possible, but it won't be easy.
As you wrote, you should start with detecting drag & drop. It's not possible using build-in options, but we can add our own event listeners. Take a look at this code:
new Highcharts.StockChart({
// here comes your chart options, but we can pass callback function as the second parameter
}, function (chart) {
var report = document.getElementById('report'), // just an element to display current extremes
xAxis = chart.xAxis[0],
startX;
function drag(e) {
e = chart.tracker.normalizeMouseEvent(e);
startX = e.chartX;
}
function drop(e) {
e = chart.tracker.normalizeMouseEvent(e);
var delta = e.chartX - startX,
extremes = xAxis.getExtremes(),
newMin = Math.round(extremes.min - delta),
newMax = Math.round(extremes.max - delta);
// display extremes retrieved by panning
report.innerHTML = "<b>From:</b> " + new Date(newMin) + " <b>to:</b> " + new Date(newMax);
}
// bind events
Highcharts.addEvent(chart.container, 'mousedown', drag);
Highcharts.addEvent(chart.container, 'mouseup', drop);
});
Simply we detect mouseDown & mouseUp events, then calculate the difference, translate difference to x data and finally, substract difference from extremes.
Here you can find the jsfiddle demo with code posted above: http://jsfiddle.net/dSEAA/1/
To make #slawekkolodziej's example work, you need to translate the delta into ms on the xAxis, then update the xAxis extremes like so:
window.chart = new Highcharts.StockChart({
// chart options go here
}, function(chart) {
var xAxis = chart.xAxis[0],
startX;
function drag(e) {
e = chart.pointer.normalize(e);
startX = e.chartX;
}
function drop(e) {
e = chart.pointer.normalize(e);
var delta = e.chartX - startX,
extremes = xAxis.getExtremes(),
deltaMs = (extremes.max - extremes.min) / chart.plotWidth * delta,
newMin = Math.round(extremes.min - deltaMs),
newMax = Math.round(extremes.max - deltaMs);
xAxis.setExtremes(newMin, newMax)
}
Highcharts.addEvent(chart.container, 'mousedown', drag);
Highcharts.addEvent(chart.container, 'mouseup', drop);
});
});
Here's a working example with async data loading: http://jsfiddle.net/xw7goLj4/5/
using http://www.flotcharts.org/ to realize a complex scatterplot graphic with zoom/pan functionalities, i would like to set mouse position at specific coordinates (by example: when doing a zoom in, I would like that cursor would positioned at the center of canvass).
It ssem this function doesn't work:
function setMousePosition(pos) {
var x = pos.x;
var y = pos.y;
var pointX = ( Math.floor(plot.offset().left + plot.p2c(pos).left) );
var pointY = ( Math.floor(plot.offset().top + plot.p2c(pos).top) );
$("#placeholder").mouseXPos( pointX ).`mouseYPos`( pointY );
About mouseXPos and mouseYPos, firebug say:
TypeError: placeholder.mouseXPos is not a function
So my question is: there is a way in javascript or jquery to set mouse coordinates inside a graphic area ?
The mouse position cannot be set/changed via JavaScript.
There is no any mechanism to place a cusror to specific position programmatically in Javascript