oxjs/source/Ox.UI/js/Video/Ox.VideoPreview.js
2011-09-19 12:29:06 +00:00

133 lines
4 KiB
JavaScript

// vim: et:ts=4:sw=4:sts=4:ft=javascript
Ox.VideoPreview = function(options, self) {
self = self || {};
var that = Ox.Element({}, self)
.defaults({
duration: 0,
getFrame: null,
fps: 25,
frameRatio: 16/9,
height: 256,
scaleToFill: false,
timeline: '',
width: 256
})
.options(options || {})
.addClass('OxVideoPreview')
.css({
width: self.options.width + 'px',
height: self.options.height + 'px'
});
self.loaded = [];
self.queue = [];
self.$frame = $('<img>')
.addClass('OxFrame')
.attr({src: self.options.getFrame()})
.css(getFrameCSS())
.appendTo(that.$element);
self.$timeline = $('<img>')
.addClass('OxTimeline')
.attr({src: self.options.timeline})
.css({width: self.options.width + 'px'})
.appendTo(that.$element);
self.$interface = Ox.Element({
tooltip: function(event) {
//event.offsetX does not work in Firefox
// fixme: use layerX then
var position = getPosition(event.clientX - that.offset().left);
self.$frame.attr({src: self.options.getFrame(position)});
return Ox.formatDuration(position, 2);
}
})
.addClass('OxInterface')
.bind({
click: click,
mouseenter: startLoading,
mouseleave: function() {
self.$frame.attr({src: self.options.getFrame()});
stopLoading();
}
})
.appendTo(that.$element);
function click(e) {
that.triggerEvent('click', {
// e.offsetX does not work in Firefox
position: getPosition(e.clientX - that.offset().left)
});
}
function getFrameCSS() {
var css = {};
if (!self.options.scaleToFill) {
css.width = self.options.width;
css.height = Math.round(css.width / self.options.frameRatio);
css.marginTop = Math.floor((self.options.height - 16 - css.height) / 2);
} else {
css.height = self.options.height - 16;
css.width = Math.round(css.height * self.options.frameRatio);
css.marginLeft = Math.floor((self.options.width - css.width) / 2);
}
return Ox.map(css, function(value) {
return value + 'px';
});
}
function getPosition(x) {
return Math.round(
self.options.duration * x / self.options.width * self.options.fps
) / self.options.fps;
}
function startLoading() {
var last,
steps = [Math.round(self.options.width / 2)];
while ((last = steps[steps.length - 1]) > 1) {
steps.push(Math.round(last / 2));
}
steps.forEach(function(step) {
Ox.loop(0, self.options.width, step, function(x) {
var frame = self.options.getFrame(getPosition(x));
if (
self.loaded.indexOf(frame) == -1
&& self.queue.indexOf(frame) == -1
) {
self.queue.push(frame);
}
});
});
loadFrame();
function loadFrame() {
$('<img>')
.load(function() {
self.loaded.push(self.queue.shift());
self.queue.length && loadFrame();
})
.attr({src: self.queue[0]});
}
}
function stopLoading() {
self.queue = [];
}
self.setOption = function(key, value) {
if (key == 'height') {
self.$frame.css(getFrameCSS());
} else if (key == 'width') {
self.$frame.attr({src: self.options.getFrame()})
.css(getFrameCSS());
self.$timeline.css({width: value + 'px'});
stopLoading();
}
}
return that;
};