UNPKG

wavesurfer.js

Version:

Interactive navigable audio visualization using Web Audio and Canvas

167 lines (140 loc) 6.46 kB
(function (root, factory) { if (typeof define === 'function' && define.amd) { define(['wavesurfer'], factory); } else { root.WaveSurfer.Timeline = factory(root.WaveSurfer); } }(this, function (WaveSurfer) { 'use strict'; WaveSurfer.Timeline = { init: function (params) { this.params = params; var wavesurfer = this.wavesurfer = params.wavesurfer; if (!this.wavesurfer) { throw Error('No WaveSurfer intance provided'); } var drawer = this.drawer = this.wavesurfer.drawer; this.container = 'string' == typeof params.container ? document.querySelector(params.container) : params.container; if (!this.container) { throw Error('No container for WaveSurfer timeline'); } this.width = drawer.width; this.height = this.params.height || 20; this.notchPercentHeight = this.params.notchPercentHeight || 90; this.primaryColor = this.params.primaryColor || '#000'; this.secondaryColor = this.params.secondaryColor || '#c0c0c0'; this.primaryFontColor = this.params.primaryFontColor || '#000'; this.secondaryFontColor = this.params.secondaryFontColor || '#000'; this.fontFamily = this.params.fontFamily || 'Arial'; this.fontSize = this.params.fontSize || 10; this.createWrapper(); this.createCanvas(); this.render(); wavesurfer.drawer.wrapper.onscroll = this.updateScroll.bind(this); wavesurfer.on('redraw', this.render.bind(this)); }, createWrapper: function () { var wsParams = this.wavesurfer.params; this.wrapper = this.container.appendChild( document.createElement('wave') ); this.drawer.style(this.wrapper, { display: 'block', position: 'relative', userSelect: 'none', webkitUserSelect: 'none', height: this.height + 'px' }); if (wsParams.fillParent || wsParams.scrollParent) { this.drawer.style(this.wrapper, { width: '100%', overflowX: 'hidden', overflowY: 'hidden' }); } var my = this; this.wrapper.addEventListener('click', function (e) { e.preventDefault(); var relX = 'offsetX' in e ? e.offsetX : e.layerX; my.fireEvent('click', (relX / my.wrapper.scrollWidth) || 0); }); }, createCanvas: function () { var canvas = this.canvas = this.wrapper.appendChild( document.createElement('canvas') ); this.timeCc = canvas.getContext('2d'); this.wavesurfer.drawer.style(canvas, { position: 'absolute', zIndex: 4 }); }, render: function () { this.updateCanvasStyle(); this.drawTimeCanvas(); }, updateCanvasStyle: function () { var width = Math.round(this.drawer.wrapper.scrollWidth / this.wavesurfer.params.pixelRatio); this.canvas.width = width; this.canvas.height = this.height; this.canvas.style.width = width + 'px'; }, drawTimeCanvas: function() { var backend = this.wavesurfer.backend, wsParams = this.wavesurfer.params, duration = backend.getDuration(); if (wsParams.fillParent && !wsParams.scrollParent) { var width = this.drawer.getWidth(); var pixelsPerSecond = width/duration; } else { var width = backend.getDuration() * wsParams.minPxPerSec; var pixelsPerSecond = wsParams.minPxPerSec; } pixelsPerSecond = pixelsPerSecond / wsParams.pixelRatio; if (duration > 0) { var curPixel = 0, curSeconds = 0, totalSeconds = parseInt(duration, 10) + 1, timeInterval = (pixelsPerSecond < 10) ? 10 : 1, formatTime = function(seconds) { if (seconds/60 > 1) { var minutes = parseInt(seconds / 60), seconds = parseInt(seconds % 60); seconds = (seconds < 10) ? '0' + seconds : seconds; return '' + minutes + ':' + seconds; } else { return seconds; } }; var height1 = this.height - 4, height2 = (this.height * (this.notchPercentHeight / 100.0)) - 4; for (var i = 0; i < totalSeconds/timeInterval; i++) { if (i % 10 == 0) { this.timeCc.fillStyle = this.primaryColor; this.timeCc.fillRect(curPixel, 0, 1, height1); this.timeCc.font = this.fontSize + 'px ' + this.fontFamily; this.timeCc.fillStyle = this.primaryFontColor; this.timeCc.fillText(formatTime(curSeconds), curPixel + 5, height1); } else if (i % 10 == 5) { this.timeCc.fillStyle = this.secondaryColor; this.timeCc.fillRect(curPixel, 0, 1, height1); this.timeCc.font = this.fontSize + 'px ' + this.fontFamily; this.timeCc.fillStyle = this.secondaryFontColor; this.timeCc.fillText(formatTime(curSeconds), curPixel + 5, height1); } else { this.timeCc.fillStyle = this.secondaryColor; this.timeCc.fillRect(curPixel, 0, 1, height2); } curSeconds += timeInterval; curPixel += pixelsPerSecond * timeInterval; } } }, updateScroll: function(e){ this.wrapper.scrollLeft = e.target.scrollLeft; } }; WaveSurfer.util.extend(WaveSurfer.Timeline, WaveSurfer.Observer); return WaveSurfer.Timeline; }));