數據採用Float32Array保存。html
http://www.ieyebrain.com:8080/upload/scroll.htmlhtml5
1 分頁機制canvas
用一個Pager的類來操做。函數
function Pager(buf, pageSize) {
this.buf = buf;
this.pageSize = pageSize;
this.viewStart = -1;
this.getView = function(pos) {
if (this.viewStart >= 0 && pos >= this.viewStart && pos < this.viewStart + this.pageSize) {
console.log('cache hit');
return true;
} else {
var view = this.buf.subarray(pos, pos + this.pageSize);
this.viewStart = pos;
console.log('cache miss, get view again length is ' + view.length);
return view;
}
};
}this
getView函數能夠返回任何位置一個頁面數據。內部維護一個cache,當移動不大的時候就不會切換View。firefox
2 頁面元素orm
html5種。用兩個div元素,第一個爲真實圖形,第二個只是爲了提供大範圍的滾動條。
<div id="divWave" style="overflow-x:hidden">
<canvas id='waveform' height="100" width="32766" ></canvas>
</div>
<div id="divWaveOut" style="overflow-x:auto">
<canvas id='waveform-out' height="1" width="3276600" ></canvas>
</div>htm
3 將大範圍的滾動條scroll事件轉化爲對視圖的局部滾動或者換頁操做。事件
waveOut.addEventListener('scroll', function(e) {
e.preventDefault();
var pos = this.scrollLeft;
onGobalSeek(pos);
return false;
}, true
);get
4 視圖更新函數
function onGobalSeek(newPos) {
var oldPos = pager.viewStart;
var view = pager.getView(newPos);
if ('boolean' == typeof view) { //頁面內局部滾動
var leftOld = waveObj.container.scrollLeft;
var leftNew = newPos - oldPos;
waveObj.container.scrollLeft = leftNew;
console.log('just scroll it from ' + leftOld + ' -> ' + leftNew);
} else { //換頁
waveObj.drawShape(view);
waveObj.container.scrollLeft = 0;
console.log('redraw it');
}
}
5 繪圖
function drawShape(buf){
var ctx = this.ctx;
this.waveform.width = this.waveform.width;
//此爲重要細節。firefox中,若是用clearRect不會馬上更新畫面。
ctx.beginPath();
var y = ~~(buf[0]);
ctx.moveTo(0, y);
for (var i = 1; i < buf.length; i++) {
y = ~~(buf[i]);
ctx.lineTo(i, y);
}
ctx.stroke();
ctx.closePath();
}
另外:
http://www.ieyebrain.com:8080/audio/wavesurfer.js/
對wavesurfer.js的使用,和增長編輯功能。