<!DOCTYPE html>
<html>
  <head>
    <link rel="stylesheet" href="style.css">
    <script src="https://cdnjs.cloudflare.com/ajax/libs/vue/2.5.16/vue.js"></script>
  </head>
  <body>
    <h1>Hello Plunker!</h1>
    <div id="app">
      <form>
        <button type="button" @click="start">Start</button>
        <button type="button" @click="stop">Stop</button>
        <div class="scope-type">
        <h3>描画タイプ</h3>
        <label><input type="radio" value="svg" v-model="scopeType">SVG</label>
        <label><input type="radio" value="canvas" v-model="scopeType">Canvas</label>
        </div>
      </form>
      <div class="oscilloscopes">
        <svg
          v-if="scopeType === 'svg'"
          ref="scope"
          :width="size.width"
          :height="size.height"
          xmlns="http://www.w3.org/2000/svg"
          baseProfile="full"
          >
          <path :d="svg.path" stroke="#00F23E" stroke-width="3" fill="none"></path>
        </svg>
        <canvas
          v-if="scopeType === 'canvas'"
          ref="scope"
          :width="size.width"
          :height="size.height">
        </canvas>
      </div>
      <div class="fps-checker">
        <span>{{ fps }}fps</span>
      </div>
    </div>
    <script src="script.js"></script>
  </body>
</html>




new Vue({
  el: '#app',
  data() {
    return {
      size: {
        width: 400,
        height: 256
      },
      scopeType: 'svg',
      svg: {
        path: ''
      },
      canvas: {
        ctx: null
      },
      audio: {
        ctx: new AudioContext(),
        osc: null,
        analyser: null,
        running: false
      },
      fps: 0
    }
  },
  methods: {
    start() {
      this.audio.running = true;
      this.audio.analyser = this.audio.ctx.createAnalyser();
      this.audio.analyser.connect(this.audio.ctx.destination);
      this.audio.analyser.fftSize = 128;
      this.audio.osc = this.audio.ctx.createOscillator();
      this.audio.osc.connect(this.audio.analyser);
      this.audio.osc.start();
      switch (this.scopeType) 
      {
      case 'svg':
        this.drawSVG();
      break;
      case 'canvas':
        this.drawCanvas();
      break;
      }
    },
    stop() {
      this.audio.osc.stop();
      this.audio.running = false;
    },
    drawSVG() {
      const bufferLength = this.audio.analyser.frequencyBinCount;
      const update = () => {
    		let data = new Uint8Array(bufferLength);
        this.audio.analyser.getByteTimeDomainData(data);
        let d = 'M';
        data.forEach((p, i) => {
        	d += `${i * (this.size.width / bufferLength)} ${p},`;
        });
        this.svg.path = d;
        if (this.audio.running)
        {
          window.requestAnimationFrame(update.bind(this));
        }
      };
      window.requestAnimationFrame(update.bind(this));
    },
    drawCanvas() {
      const ctx = this.$refs.scope.getContext('2d');
      ctx.lineWidth = 3;
      ctx.strokeStyle = '#00F23E';
      const bufferLength = this.audio.analyser.frequencyBinCount
      const update = () => {
        ctx.clearRect(0, 0, this.size.width, this.size.height);
        ctx.save();
        ctx.moveTo(0, this.size.height / 2);
        ctx.beginPath();
        let data = new Uint8Array(bufferLength);
        this.audio.analyser.getByteTimeDomainData(data);
        data.forEach((p, i) => {
          ctx.lineTo(i * (this.size.width / bufferLength), p);
        });
        ctx.stroke();
        ctx.restore();
        if (this.audio.running)
        {
          window.requestAnimationFrame(update.bind(this));
        }
      };
      window.requestAnimationFrame(update.bind(this));
    }
  }
});




svg {
  background-color: #333333;
}
canvas {
  background-color: #333333;
}