Search code examples
javascriptreactjsamcharts

Pass data from ReactAudioPlayer to Amcharts slider?


I am trying to combine controls of amcharts to the react audio player.
Here, I have amcharts line graph with a slider. Now I am trying control the slider in such a way that whenever I hit the play button of react audio player, I could move the slider with the audio player's seeker. I hope, this makes sense to you.

import React from "react";
import ReactAudioPlayer from "react-audio-player";
import audio from "/home/aniruddha/workspace/playwith_audio/anni_web_player/src/audio.flac";

import * as am4core from "@amcharts/amcharts4/core";
import * as am4charts from "@amcharts/amcharts4/charts";
import am4themes_spiritedaway from "@amcharts/amcharts4/themes/spiritedaway";
import am4themes_animated from "@amcharts/amcharts4/themes/animated";

/* Chart code */
// Themes begin
am4core.useTheme(am4themes_spiritedaway);
am4core.useTheme(am4themes_animated);

class App extends React.Component {

  constructor(props) {
    super(props);
    this.state = {slider: 1586169460800};
  }
  
  componentDidMount() {
    let chart = am4core.create("chartdiv", am4charts.XYChart);

    // Add data
    chart.data = this.generateChartData();

    // Create axes
    let dateAxis = chart.xAxes.push(new am4charts.DateAxis());

    let valueAxis = chart.yAxes.push(new am4charts.ValueAxis());

    // Create series
    let series = chart.series.push(new am4charts.LineSeries());
    series.dataFields.valueY = "visits";
    series.dataFields.dateX = "date";
    series.strokeWidth = 1;
    series.minBulletDistance = 10;
    series.tooltipText = "{valueY}";
    series.fillOpacity = 0.1;
    series.tooltip.pointerOrientation = "vertical";
    series.tooltip.background.cornerRadius = 20;
    series.tooltip.background.fillOpacity = 0.5;
    series.tooltip.label.padding(12, 12, 12, 12);

    let seriesRange = dateAxis.createSeriesRange(series);
    seriesRange.contents.strokeDasharray = "2,3";
    seriesRange.contents.stroke = chart.colors.getIndex(8);
    seriesRange.contents.strokeWidth = 1;

    let pattern = new am4core.LinePattern();
    pattern.rotation = -45;
    pattern.stroke = seriesRange.contents.stroke;
    pattern.width = 1000;
    pattern.height = 1000;
    pattern.gap = 6;
    seriesRange.contents.fill = pattern;
    seriesRange.contents.fillOpacity = 0.5;

    // Add scrollbar
    chart.scrollbarX = new am4core.Scrollbar();

    // add range
    let range = dateAxis.axisRanges.push(new am4charts.DateAxisDataItem());
    range.grid.stroke = chart.colors.getIndex(0);
    range.grid.strokeOpacity = 1;
    range.bullet = new am4core.ResizeButton();
    range.bullet.background.fill = chart.colors.getIndex(0);
    range.bullet.background.states.copyFrom(
      chart.zoomOutButton.background.states
    );
    range.bullet.minX = 0;
    range.bullet.adapter.add("minY", function (minY, target) {
      target.maxY = chart.plotContainer.maxHeight;
      target.maxX = chart.plotContainer.maxWidth;
      return chart.plotContainer.maxHeight;
    });

    range.bullet.events.on("dragged", function () {
      range.value = dateAxis.xToValue(range.bullet.pixelX);
      seriesRange.value = range.value;
      console.log(seriesRange.value)
    });

    let firstTime = chart.data[0].date.getTime();
    let lastTime = chart.data[chart.data.length - 1].date.getTime();
    let date = new Date(firstTime + (lastTime - firstTime) / 2);

    range.date = date;

    seriesRange.date = date;
    seriesRange.endDate = chart.data[chart.data.length - 1].date;

    this.chart = chart
    console.log(this.state.slider);
    
    this.setState({ seriesRange } )
    console.log(this.state.slider);
    range.value = this.state.slider;
    seriesRange.value = this.state.slider;
  }

  generateChartData() {
    let chartData = [];
    let firstDate = new Date();
    firstDate.setDate(firstDate.getDate() - 200);
    let visits = 1200;
    for (var i = 0; i < 200; i++) {

      let newDate = new Date(firstDate);
      newDate.setDate(newDate.getDate() + i);

      visits += Math.round(
        (Math.random() < 0.5 ? 1 : -1) * Math.random() * 10
      );

      chartData.push({
        date: newDate,
        visits: visits,
      });
    }
    return chartData;
  }
  
  sound(event){
    console.log(event.timeStamp);
         
    //this.setState({slider: 1586025000000 })
    
  }

  seek(event){
    console.log(event);
  }

  lis(event){
    console.log(event);
  }

  componentWillUnmount() {
    if (this.chart) {
      this.chart.dispose();
    }
  }


  render() {
    return (
      <div>
        <div id="chartdiv" style={{ width: "100%", height: "500px" }}></div>
        <ReactAudioPlayer src={audio} onPlay={this.sound} onListen={this.lis} onSeeked={this.seek} controls></ReactAudioPlayer>
      </div>
    );
  }
}

export default App;

I am not able to access this.setState({slider: 1586025000000 }) in the sound function. I am quite new to react. Please any suggestion is welcome;


Solution

  • You need to wrap your callbacks with arrow functions that call your methods directly (or call bind: this.sound.bind(this)) so that it resolves to the correct this scope:

    <ReactAudioPlayer 
      src="{audio}" 
      onPlay={(ev) => this.sound(ev)} 
      onListen={(ev) => this.lis(ev)} 
      onSeeked={(ev) => this.seek(ev)} 
    controls></ReactAudioPlayer>