Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Exposing more events #145

Closed
aderidder opened this issue Dec 24, 2015 · 25 comments
Closed

Exposing more events #145

aderidder opened this issue Dec 24, 2015 · 25 comments
Labels
feature something new
Milestone

Comments

@aderidder
Copy link

Hi,

From a recent community post, I learned that the January release will probably support a brushing feature, which is great.
I think it would be really useful if you'd expose more events, such as double-click, as this would allow us to better control the desired functionality.

Thanks,
Sander

@etpinard
Copy link
Contributor

@aderidder thanks again for the suggestion.

Adding more events is definitely on our roadmap. The only things blocking us at the moment, is the fact that each plotly.js plot type (cartesian, geo, gl, ...) has its own event emitting internals.

Some work should be dedicated to generalizing our internals before exposing more events.

@etpinard
Copy link
Contributor

@ifll please comment here if you any suggestions about other potential plotly.js events. Thank you.

@ifll
Copy link

ifll commented Feb 16, 2016

What about having the "plotly_zommin", "plotly_zoomout", "plotly_pan", etc... events?

This would help a lot to control the user interaction with the plot

Thank you!

@mmek123
Copy link

mmek123 commented Feb 25, 2016

when graph is in edit mode would like to get events like
title Edited, X/Y axis edited , annotations edited

also would highly benefit from having a event when you hover over the extrapolated graph points.. currently its only on data points..

thanks..

On Wed, Feb 17, 2016 at 3:25 AM, ifll [email protected] wrote:

What about having the "plotly_zommin", "plotly_zoomout", "plotly_pan",
etc... events?

This would help a lot to control the user interaction with the plot

Thank you!


Reply to this email directly or view it on GitHub
#145 (comment).

@czellweg
Copy link

I second @mmek123 comments: we currently want to reload data based on zoom-events but not when relayouting. At the moment, we can't distinguish whether the relayout was caused by an actual zoom-in or simply the user changing the size of the browser window (which will cause a relayout as the plot is responsive).

We'd love to see the following:

  • plotly_zoomin, plotly_zoomout, plotly_pan, plotly_scale_x, plotly_scale_y

It would be great if all the available data of the current view port to the plot is made available such as start-x, end-x, start-y, end-y etc.

Can you make a statement about a possible roadmap for this?

@etpinard
Copy link
Contributor

etpinard commented Jul 6, 2016

From @mdfederici in #722 with PoC in #721

It is desirable for my container to receive notifications when a user has edited an annotation in an editable graph by moving, rotating or changing length [using a new plotly_editannotation event]

Response in #722 (comment)

@etpinard
Copy link
Contributor

From @paneyi in #788

It would be great to expose the original event along with the data in Plotly events.
One practical example would be to know if the user was pressing any special keys when clicking and act accordingly, like add to a selection.

var acummulate = originalEvent.altKey || originalEvent.ctrlKey || originalEvent.shiftKey || originalEvent.metaKey

@paneyi
Copy link

paneyi commented Jul 28, 2016

Also it would be useful to be able to click on the background of the chart and get the coordinates, in order to create more points in an interactive way.

@etpinard
Copy link
Contributor

@paneyi

it would be useful to be able to click on the background of the chart and get the coordinates

You might want to check out http://codepen.io/etpinard/pen/EyydEj

@paneyi
Copy link

paneyi commented Jul 28, 2016

Thank you @etpinard, I already saw that but it wasn't enough. Whenever you zoom, it stops working.

@etpinard
Copy link
Contributor

Maybe relayout event data should list the current visible point on the graph as described in http://community.plot.ly/t/get-datapoints-in-currently-zoomed-view/259/

@etpinard
Copy link
Contributor

From @CalvinFernandez in #935

It would be super useful to have the computed tooltip positioning information provided to the hover callback. It would help a lot with rendering our own custom tooltips.

@etpinard
Copy link
Contributor

From @smalesys in #1138 :

Sounds logical to me to have two distinct events here. I think maybe the names can be confusing, since "doubleclick" sounds general and "deselect" is specific, while they are actually both on the same level (im not sure if i am clear here haha).

But i admit that i have no idea for renaming the event. Maybe unzoom or resetplot but i don't think that this will englobe all the use cases of the event. I guess just mentionning it in the doc should be enough for the users.

@etpinard
Copy link
Contributor

From @destradafilm in #1471

I'm working on a SCATTERPLOT and adding some user interactions.

'plotly_click' is only called when a user clicks a point

plotly_selected' is also called when a user clicks either a blank area of the plot OR when a user clicks a point (but returns an empty data obj)

I feel like it makes more sense to call 'plotly_click' no matter where you click on the chart, return data if a point is clicked, but return empty data if no points are clicked.

I'm asking for this feature for some interactions on my scatterplot.

For example:
If a user clicks a point, color the point 'red'

easy, since I can use the data.points[0] to find which marker to color
If a user clicks an empty part of the chart, reset the 'selected' points and color it back to original color.

I can use 'if data == undefined' then color all points back to original color', but problem is data == undefined if I click a point, or click an empty place in chart...'plotly_click' is never called here

@etpinard
Copy link
Contributor

etpinard commented Apr 3, 2017

From @destradafilm's #1548

To expose more reliable p2c functionality, I wrote:

What I think we should do: is add another plotly_ event (e.g. plotly_mouse) that would get fired on anytime you mouse over a graph with or without triggering plotly_hover.

@BruceSherwood
Copy link

I gather that there’s currently no way to detect overall mouse down and mouse up events, which are important for being able to pause incremental graphing and a synchronous animation during the time that the mouse button is down. Is that a future possibility?

@jensb
Copy link

jensb commented Feb 7, 2018

Please also expose some "before" edit events, especially when editing text (annotations, legends, titles etc). I would like to be able to let users edit placeholder text or select from a list of template strings to be inserted instead of just editing text. In this case I need to change the text being edited before edit mode is activated (and replace it again when edit mode is closed).
Thanks!

@etu29414
Copy link

etu29414 commented Apr 9, 2018

Hello everyone,
i would like add an event when i click on a trace.
for exemple when i click on a trace, i show an alert “you click on trace X”.

for example:
i would like that if i click on red trace there an alert but not on black point
image

thanks !

@Pierre-Bartet
Copy link

Any progress on this ? It's a deal breaker.

@ccssmnn
Copy link

ccssmnn commented Sep 3, 2020

I want to plot a server generated histogram in a bar plot that is getting more refined when the user zooms in by updating the data object. Unfortunately I run into an endless loop, because using the update event as a trigger for loading a new refinement (based on new x-min and x-max) does fire everytime the plot is drawn with new data.

I don't see any way right now to avoid the endless loop without a dedicated zoom event. Is there anything happening? Is there something I could provide?

@alexcjohnson
Copy link
Collaborator

@ccssmnn can you hold onto the range from the previous call, and abort the request for new data if the range hasn't actually changed? Something like this is what's typically done.

@jensb
Copy link

jensb commented Sep 3, 2020

This should be doable using uirevision:
https://plotly.com/javascript/uirevision/

@ccssmnn
Copy link

ccssmnn commented Sep 7, 2020

Thank you for the fast replies @alexcjohnson & @jensb

I have prepared a Sandbox showing what I've got so far. Here is the Sandbox
In case the link is not working properly I will show the code at the bottom if this comment.

The problem with this solution seems to be that the update event is fired several times after a zoom event with different xmin/xmax values. I would expect one call for the zoom and another one that is triggered because the data changes if we zoom enough. But because there are more calls the user does not nessecarily end up at the expected range after zoom.

import React, { useState, useEffect, useCallback } from "react";
import "./styles.css";
import Plot from "react-plotly.js";

function binning(nBins, data, xMin, xMax) {
  const lower = xMin === undefined ? Math.min(...data) : xMin;
  const upper = xMax === undefined ? Math.max(...data) : xMax;

  const count = new Array(nBins).fill(0);
  data.forEach((value) => {
    if (value >= lower && value <= upper) {
      const bin = Math.floor(
        (Math.abs(value - lower) * nBins) / Math.abs(upper - lower)
      );
      count[bin] = count[bin] + 1;
    }
  });
  const binMean = new Array(nBins).fill(0);
  binMean.forEach((_, i) => {
    binMean[i] = lower + (i * (upper - lower)) / nBins;
  });
  const binWidth = Math.abs(upper - lower) / nBins;
  return [count, binMean, binWidth];
}

function randomNormal() {
  const [u, v] = [1 - Math.random(), 1 - Math.random()];
  return Math.sqrt(-2.0 * Math.log(u)) * Math.cos(2.0 * Math.PI * v);
}

export default function App() {
  const [data, setData] = useState([]);
  const [loading, setLoading] = useState(false);
  const requestData = useCallback(async () => {
    setLoading(true);
    const arr = [];
    for (let i = 0; i < 200; i++) {
      arr.push(randomNormal());
    }
    console.log(arr);
    setDataArr(arr);
    setLoading(false);
  }, []);
  const [layout, setLayout] = useState({ autosize: true });
  const [dataArr, setDataArr] = useState([]);
  const [xMin, setXMin] = useState(undefined);
  const [xMax, setXMax] = useState(undefined);
  useEffect(() => {
    const [count, mean, width] = binning(50, dataArr, xMin, xMax);
    setData([
      {
        x: mean,
        y: count,
        width: new Array(count.length).fill(width),
        type: "bar"
      }
    ]);
    setLayout({
      autosize: true,
      xaxis: {
        range: [xMin, xMax]
      }
    });
  }, [dataArr, xMin, xMax]);
  return (
    <div className="App">
      <h1>Plot Updating on Zoom</h1>
      <button onClick={requestData}>
        {loading ? "Loading..." : "Request Data"}
      </button>
      <Plot
        data={data}
        layout={layout}
        useResizeHandler
        style={{ width: "100%", height: "100%" }}
        onDoubleClick={() => {
          setXMin(undefined);
          setXMax(undefined);
        }}
        onUpdate={(figure) => {
          console.log(
            `onUpdate:
              - old Xmin ${xMin}
              - old Xmax ${xMax}
              - new Xmin ${figure.layout.xaxis?.range?.[0]}
              - new Xmax ${figure.layout.xaxis?.range?.[1]}
            `
          );
          const newXMax = figure.layout.xaxis?.range?.[1];
          const newXMin = figure.layout.xaxis?.range?.[0];
          if (newXMax === undefined || newXMin === undefined) return;
          if (xMax === undefined || xMin === undefined) {
            setXMax(newXMax);
            setXMin(newXMin);
            return;
          }
          const overlap = Math.max(
            0,
            Math.abs(Math.min(newXMax, xMax) - Math.max(newXMin, xMin))
          );
          const currentRange = Math.abs(xMax - xMin);
          const newRange = Math.abs(newXMax - newXMin);
          if (overlap / currentRange < 0.7 || overlap / newRange < 0.7) {
            setXMax(newXMax);
            setXMin(newXMin);
          }
        }}
      />
    </div>
  );
}

@jackparmer
Copy link
Contributor

This issue has been tagged with NEEDS SPON$OR

A community PR for this feature would certainly be welcome, but our experience is deeper features like this are difficult to complete without the Plotly maintainers leading the effort.

Sponsorship range: $15k-$20k

What Sponsorship includes:

  • Completion of this feature to the Sponsor's satisfaction, in a manner coherent with the rest of the Plotly.js library and API
  • Tests for this feature
  • Long-term support (continued support of this feature in the latest version of Plotly.js)
  • Documentation at plotly.com/javascript
  • Possibility of integrating this feature with Plotly Graphing Libraries (Python, R, F#, Julia, MATLAB, etc)
  • Possibility of integrating this feature with Dash
  • Feature announcement on community.plotly.com with shout out to Sponsor (or can remain anonymous)
  • Gratification of advancing the world's most downloaded, interactive scientific graphing libraries (>50M downloads across supported languages)

Please include the link to this issue when contacting us to discuss.

@gvwilson
Copy link
Contributor

gvwilson commented Jun 5, 2024

Hi - this issue has been sitting for a while, so as part of our effort to tidy up our public repositories I'm going to close it. If it's still a concern, we'd be grateful if you could open a new issue (with a short reproducible example if appropriate) so that we can add it to our stack. Cheers - @gvwilson

@gvwilson gvwilson closed this as completed Jun 5, 2024
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
feature something new
Projects
None yet
Development

No branches or pull requests