El Dude
El Dude

Reputation: 5618

D3 timeScale path get proper click location

I am using d3.timeScale to plot a time sequence of data.

    this.x = d3Scale.scaleTime(
      [1, this.width - this.margin.right - this.margin.left])
      .domain( 
          [timeParser('00:01'),
           timeParser('23:59')]);

    this.g.append('path')
      .datum(currentData)
      .attr('fill', 'none')
      .attr('stroke', '#3880ff')
      .attr('stroke-width', 8)
      .attr('d', d3Shape.line()
        // @ts-ignore
        .x( (d) => {
          return this.x(timeParser(d.time)); })
        // @ts-ignore
        .y( (d: D3TidePlotData) => {
          return this.y(d.height);
        })
      ).on('click', (e) => {
        console.log(e);
      });

The plot looks good, the domain of this.x.range() => [1, 670] . However, when I capture the click onto the path / line, no x value of the event will be in the range of the timeScale . The x positions of the clicks do not reflect the this.x.range at all and are in ~ [52,309].

I would expect a click captured for path to be relative to the path coordinate range / origin. But that does not seem to be the case... ?

I need to map the clicked location back onto the data in order to interpolate positions between the sampled data yet I do not understand how to map the event location onto the timeScale in order to invert it to get the correct x-axis date. Below is what a click into the center returns.

MouseEvent
altKey: false
bubbles: true
button: 0
buttons: 0
cancelBubble: false
cancelable: true
clientX: 192
clientY: 613
composed: true
ctrlKey: false
currentTarget: path
defaultPrevented: false
detail: 1
eventPhase: 2
fromElement: null
isTrusted: true
layerX: 182
layerY: 567
metaKey: false
movementX: 0
movementY: 0
offsetX: 182
offsetY: 66
pageX: 192
pageY: 613
path: (37) [path, g, svg, div#chart, slot, document-fragment, ion-col.ios.hydrated, slot, document-fragment, ion-row.ios.hydrated, slot, document-fragment, ion-grid.ios.hydrated, slot, main.inner-scroll.scroll-y.overscroll, document-fragment, ion-content.ios.overscroll.hydrated, app-plot, app-tide, slot, main.inner-scroll.scroll-y.overscroll, document-fragment, ion-content.ion-bottom-drawer-scrollable-content.ios.overscroll.hydrated, ion-bottom-drawer, app-map.ion-page, slot, document-fragment, ion-router-outlet#main-content.split-pane-main.menu-content.menu-content-overlay.hydrated, slot, document-fragment, ion-split-pane.ios.split-pane-ios.hydrated, ion-app.ios.ion-page.hydrated, app-root, body, html.plt-iphone.plt-ios.plt-mobile.plt-mobileweb.ios.hydrated, document, Window]
relatedTarget: null
returnValue: true
screenX: 581
screenY: 732
shiftKey: false
sourceCapabilities: InputDeviceCapabilities {firesTouchEvents: true}
srcElement: path
target: path
timeStamp: 432937.55500001134
toElement: path
type: "click"
view: Window {0: Window, window: Window, self: Window, document: document, name: "", location: Location, …}
which: 1
x: 192
y: 613

Upvotes: 0

Views: 63

Answers (1)

El Dude
El Dude

Reputation: 5618

I ended up converting the click location to svg manually for I am running in ionic where no d3.mouse lib was available. Essentially had to convert the true svg width into the viewport width in my script + incorporate the corresponding ratio of the d3 margin etc.

Upvotes: 0

Related Questions