Waveform
by PhilQ
HTML
<script src="//cdnjs.cloudflare.com/ajax/libs/wavesurfer.js/1.4.0/wavesurfer.min.js"></script>
<link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/font-awesome/4.7.0/css/font-awesome.min.css">
<div id="waveform"></div>
<div id="markers">
<a href="#" class="segment start" data-label="A" style="left: 15%;"></a>
<a href="#" class="marker" style="left: 18%;"></a>
<a href="#" class="marker" style="left: 25%;"></a>
<a href="#" class="segment end" data-label="A" style="left: 27%;"></a>
<a href="#" class="segment start" data-label="B" style="left: 55%;"></a>
<a href="#" class="marker" style="left: 58%;"></a>
<a href="#" class="marker" style="left: 62%;"></a>
<a href="#" class="marker" style="left: 75%;"></a>
<a href="#" class="segment end" data-label="B" style="left: 77%;"></a>
</div>
<div id="player_status">Hoi</div>
<br /><br /><br /><br /><br /><br /><br /><br /><br /><br />
<button onclick="$('.segment').slice(0,2).attr('data-label', 'XX');">Change data</button>
SCSS
*,:before,:after{margin:0;padding:0;box-sizing:border-box;}
// @import url('https://fonts.googleapis.com/css?family=Fredoka+One|Inconsolata:400,700');
@import url('https://fonts.googleapis.com/css?family=Alegreya+Sans:400,400i,700,700i,900,900i|Alegreya:400,400i,700,700i,900,900i');
/*
font-family: 'Alegreya Sans', sans-serif;
font-family: 'Alegreya', serif;
font-family: 'Fredoka One', cursive;
font-family: 'Inconsolata', monospace;
*/
body {
font-family: sans-serif;
background-color: #212121; //#263238;
}
#player_status {
position: fixed;
top: 25%;
left: 50%;
transform-origin: 50% 50%;
transform: translate(-50%,-50%) scale(1); //0.2
color: #fff;
font-family: 'Alegreya Sans', sans-serif;
font-family: 'Alegreya', serif;
font-weight: bold;
font-size: 32px;
padding: 15px 25px;
background: rgba(0,0,0, 0.3);
border-radius: 6px;
opacity: 0;
transition: all 0.15s ease 0s;
pointer-events: none;
&.blink {
transform: translate(-50%,-50%) scale(1);
opacity: 1;
transition: all 0s linear 0s;
}
}
@keyframes spin {
from {transform:rotate(0deg);}
to {transform:rotate(359deg);}
}
#waveform {
display: block;
width: 100%;
height: 128px;
position: fixed;
top: 10px;
left: 0px;
wave {
opacity: 0;
transition: opacity 0.35s ease;
}
&:before {
content: '';
position: absolute;
top: 50%;
left: 50%;
width: 40px;
height: 40px;
margin-top: -20px;
margin-left: -20px;
border-radius: 50%;
border: 4px solid rgba(#fff, 0.3);
border-top-color: transparent;
opacity: 1;
transition: opacity 0.35s ease;
animation: spin 1s infinite linear;
}
&:after {
content: '';
position: absolute;
top: 100%;
margin-top: 20px;
left: 0px;
width: 100%;
border-top: 1px solid rgba(0,0,0, 0.3);
border-bottom: 1px solid rgba(255,255,255, 0.05);
}
&.ready {
wave {
opacity: 1;
}
&:before {
opacity: 0;
}
wave:nth-child(1) {
position: absolute !important;
z-index: 1;
top: 0px;
height:...
JavaScript
/*
speaker = {
'id': 1,
'name': ,
'gender': ,
'color': ,
};
marker = {
'stamp': ,
'speaker': null/1,
'message': ,
};
*/
/**
* Takes a positive integer and returns the corresponding column name.
* @param {number} num The positive integer to convert to a column name.
* @return {string} The column name.
*/
function num2alp(num) {
for (var ret = '', a = 1, b = 26; (num -= a) >= 0; a = b, b *= 26) {
ret = String.fromCharCode(parseInt((num % b) / a) + 65) + ret;
}
return ret;
}
function alp2num(s) {
for (var ret = 0, p=0, c=s.length; p<c; p++ ) {
ret += ( (s.charCodeAt(c-(p+1)) - 64) * Math.pow(26, p) );
}
return ret;
}
$.fn.blink = function (count) {
var $this = $(this);
count = count - 1 || 0;
$this
.stop( true )
.css({opacity: 1})
.delay(100)
.animate({opacity: 0}, 350, function () {
if (count > 0) {
$this.blink(count);
}
});
};
function bindMarkerEvents( objs ) {
objs.on('mousedown', function(e){
var $this = $(this);
marker_x = e.pageX- ($this.offset()).left;
$(window).on('mousemove.drag', function(ev){
ev.preventDefault();
$this.css('left', Math.max(0, Math.min(wave_width, (ev.pageX - marker_x))) +'px');
}).on('mouseup.drag blur.drag', function(ev){
$(window).off('mousemove.drag mouseup.drag blur.drag');
});
}).on('dblclick', function(e){
wavesurfer.seekTo( ($(this).offset()).left / wave_width );
});
}
var wavesurfer,
skip_amount = 1,
skip_amount_count = 0,
skip_amount_timer,
segment_count = 1,
wave_width = 0,
marker_x = 0;
$(window).on('keydown.volume', function(e){
if ( true ) {
if ( e.which == 38 || e.which == 40 ) {
e.preventDefault();
var v = wavesurfer.getVolume();
v = (e.which == 38) ? v+0.1 : v-0.1;
v = Math.min(1, Math.max(0, v)).toFixed(1);
$('#player_status').html( 'Volume ' + (v*100) + '%' ).blink();
wavesurfer.setVolume( v );
/*
if ( 0 < v ) {
wavesurfer.setMute(false);
} else...