function InfiniteCanvas(options) { this.canvasWidth = options.canvasWidth || 256; this.maxPanelWidth = options.maxPanelWidth || 0; // needed for overlap this.height = options.height || 256; this.visibleRange = options.visibleRange || [64, 192]; this.canvasNumber = options.canvasNumber || 2; this.root = options.root || document.querySelector('body'); this.class = options.class || 'moving-canvas'; var _this = this; this.movingCanvases = Array.apply(null, new Array(this.canvasNumber)).map(function(ignore, i) { var elem = document.createElement('canvas'); var d = { offset: i * _this.canvasWidth, context: elem.getContext('2d'), cache: {} }; elem.__data__ = d; elem.setAttribute('class', _this.class); elem.setAttribute('width', _this.canvasWidth + _this.maxPanelWidth); elem.setAttribute('height', _this.height); elem.style.position = 'absolute'; elem.style.top = '0px'; elem.style.left = '0px'; elem.style.WebkitTransform = 'translateX(' + d.offset + 'px)'; _this.root.appendChild(elem); return elem; }); this.leftCanvas = this.movingCanvases[0]; this.rightCanvas = this.movingCanvases[1]; } InfiniteCanvas.prototype.flip = function flip() { var tmp = this.rightCanvas; this.rightCanvas = this.leftCanvas; this.leftCanvas = tmp; }; InfiniteCanvas.prototype.roll = function roll(elem, direction) { var d = elem.__data__; d.offset += direction * 2 * this.canvasWidth; elem.__data__.context.clearRect(0,0, this.canvasWidth + this.maxPanelWidth, this.height); elem.__data__.cache = {}; elem.style.WebkitTransform = 'translateX(' + d.offset + 'px)'; this.flip(); }; InfiniteCanvas.prototype.updateCanvasPositions = function updateCanvasPositions(visibleLow, visibleHigh) { if(this.leftCanvas.__data__.offset + this.canvasWidth <= visibleLow) { this.roll(this.leftCanvas, 1); } else if(this.rightCanvas.__data__.offset > visibleHigh) { this.roll(this.rightCanvas, -1); } }; InfiniteCanvas.prototype.context = function context(canvas) { return canvas.__data__.context; }; InfiniteCanvas.prototype.cache = function cache(canvas) { return canvas.__data__.cache; }; InfiniteCanvas.prototype.getCanvas = function getContext(offset) { return offset < this.rightCanvas.__data__.offset ? this.leftCanvas : this.rightCanvas; }; InfiniteCanvas.prototype.getContexts = function getContexts() { return [this.leftCanvas, this.rightCanvas].map(this.context.bind(this)); };