数据采用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的使用,和增长编辑功能。