oxjs/source/UI/js/Video/VideoPreview.js

198 lines
6.8 KiB
JavaScript
Raw Permalink Normal View History

2011-11-05 16:46:53 +00:00
'use strict';
2012-05-21 10:38:18 +00:00
/*@
2012-05-31 10:32:54 +00:00
Ox.VideoPreview <f> Video Preview
2012-05-21 10:38:18 +00:00
options <o> Options
self <o> Shared private variable
([options[, self]]) -> <o:Ox.Element> Video Preview
click <!> click
2012-05-21 10:38:18 +00:00
@*/
2011-08-08 13:58:19 +00:00
Ox.VideoPreview = function(options, self) {
self = self || {};
var that = Ox.Element({}, self)
.defaults({
duration: 0,
getFrame: null,
fps: 25,
2011-09-18 06:50:54 +00:00
frameRatio: 16/9,
height: 256,
2011-09-29 17:25:50 +00:00
position: void 0,
scaleToFill: false,
2011-08-08 13:58:19 +00:00
timeline: '',
2013-02-11 06:33:40 +00:00
videoTooltip: null,
2011-09-18 06:50:54 +00:00
width: 256
2011-08-08 13:58:19 +00:00
})
.options(options || {})
2012-05-28 19:35:41 +00:00
.update({
height: function() {
that.css({height: self.options.height + 'px'});
self.$frame.css(getFrameCSS());
},
position: function() {
self.$frame.attr({src: self.options.getFrame(self.options.position)});
},
width: function() {
that.css({width: self.options.width + 'px'});
stopLoading();
self.$frame.attr({src: self.options.getFrame()})
.css(getFrameCSS());
self.$timeline && self.$timeline.css({width: self.options.width + 'px'});
2012-05-28 19:35:41 +00:00
}
})
2011-09-19 12:29:06 +00:00
.addClass('OxVideoPreview')
.css({
width: self.options.width + 'px',
height: self.options.height + 'px'
});
2011-08-08 13:58:19 +00:00
self.loaded = [];
self.queue = [];
2013-12-06 21:15:04 +00:00
self.$frameElement = Ox.$('<div>')
2011-08-08 13:58:19 +00:00
.addClass('OxFrame')
.appendTo(that);
2013-12-06 21:15:04 +00:00
self.$frame = Ox.$('<img>')
2011-09-29 17:25:50 +00:00
.attr({src: self.options.getFrame(self.options.position)})
2011-09-18 06:50:54 +00:00
.css(getFrameCSS())
.appendTo(self.$frameElement);
2011-08-08 13:58:19 +00:00
2012-06-10 18:18:03 +00:00
if (self.options.timeline) {
self.$timeline = $('<img>')
.addClass('OxTimeline')
.attr({src: self.options.timeline})
.css({width: self.options.width + 'px'})
.appendTo(that);
}
2011-08-08 13:58:19 +00:00
self.$interface = Ox.Element({
tooltip: function(event) {
2012-01-30 20:48:19 +00:00
// e.offsetX does not work in Firefox
2013-02-11 06:27:37 +00:00
var position = getPosition(event.clientX - that.offset().left),
2013-02-11 06:33:40 +00:00
tooltip = Ox.isFunction(self.options.videoTooltip)
? self.options.videoTooltip() : self.options.videoTooltip;
2012-01-30 20:48:19 +00:00
self.$frame.attr({src: getClosestFrame(position)});
self.timeout && clearTimeout(self.timeout);
self.timeout = setTimeout(function() {
self.$frame.attr({src: self.options.getFrame(position)});
}, 250);
2013-02-11 07:23:12 +00:00
return '<div style="text-align: center">'
2013-02-11 06:27:37 +00:00
+ (tooltip ? tooltip + '<br>' : '')
2013-08-08 13:51:48 +00:00
+ '<span class="OxLight">' + Ox.formatDuration(position, 2) + '</span>'
2013-02-11 06:06:24 +00:00
+ '</div>';
2011-08-08 13:58:19 +00:00
}
})
.addClass('OxInterface')
2012-05-28 14:06:22 +00:00
.on({
2011-08-08 13:58:19 +00:00
click: click,
mouseenter: startLoading,
mouseleave: function() {
stopLoading();
2012-01-30 20:59:07 +00:00
self.$frame.attr({src: self.options.getFrame(self.options.position)});
2011-08-08 13:58:19 +00:00
}
})
.bindEvent({
touchend: touchend,
touchmove: touchmove,
touchstart: startLoading
})
.appendTo(that);
2011-08-08 13:58:19 +00:00
function click(e) {
that.triggerEvent('click', {
2011-09-18 06:50:54 +00:00
// e.offsetX does not work in Firefox
2011-08-17 18:57:58 +00:00
position: getPosition(e.clientX - that.offset().left)
2011-08-08 13:58:19 +00:00
});
}
2012-01-30 20:48:19 +00:00
function getClosestFrame(position) {
return self.loaded.length == 0
? self.options.getFrame(self.options.position)
: self.loaded.sort(function(a, b) {
return Math.abs(a.position - position) - Math.abs(b.position - position);
})[0].frame;
}
2011-09-18 06:50:54 +00:00
function getFrameCSS() {
var css = {},
elementWidth = self.options.width,
elementHeight = self.options.height - (self.options.timeline ? 16 : 0),
elementRatio = elementWidth / elementHeight,
frameRatio = self.options.frameRatio,
frameIsWider = frameRatio > elementRatio;
if (self.options.scaleToFill) {
css.width = frameIsWider ? elementHeight * frameRatio : elementWidth;
css.height = frameIsWider ? elementHeight : elementWidth / frameRatio;
css.marginLeft = frameIsWider ? (elementWidth - css.width) / 2 : 0;
css.marginTop = frameIsWider ? 0 : (elementHeight - css.height) / 2;
} else {
css.width = frameIsWider ? elementWidth : elementHeight * frameRatio;
css.height = frameIsWider ? elementWidth / frameRatio : elementHeight;
css.marginLeft = frameIsWider ? 0 : (elementWidth - css.width) / 2;
css.marginTop = frameIsWider ? (elementHeight - css.height) / 2 : 0;
2011-09-18 06:50:54 +00:00
}
return Ox.map(css, function(value) {
return Math.round(value) + 'px';
});
2011-09-18 06:50:54 +00:00
}
2011-08-08 13:58:19 +00:00
function getPosition(x) {
return Math.round(
2011-09-18 06:50:54 +00:00
self.options.duration * x / self.options.width * self.options.fps
2011-08-08 13:58:19 +00:00
) / self.options.fps;
}
function startLoading() {
var last,
2011-09-18 06:50:54 +00:00
steps = [Math.round(self.options.width / 2)];
2011-08-08 13:58:19 +00:00
while ((last = steps[steps.length - 1]) > 1) {
steps.push(Math.round(last / 2));
}
steps.forEach(function(step) {
2011-09-18 06:50:54 +00:00
Ox.loop(0, self.options.width, step, function(x) {
2012-01-30 20:48:19 +00:00
var position = getPosition(x),
frame = self.options.getFrame(position);
2012-05-21 06:40:40 +00:00
if (!self.loaded.some(function(image) {
return image.frame == frame;
}) && !self.queue.some(function(image) {
return image.frame == frame;
})) {
2012-01-30 20:48:19 +00:00
self.queue.push({frame: frame, position: position});
2011-08-08 13:58:19 +00:00
}
});
});
2012-01-30 20:48:19 +00:00
self.queue.length && loadFrame();
2011-08-08 13:58:19 +00:00
function loadFrame() {
2012-01-30 20:48:19 +00:00
var image = self.queue.shift();
2011-08-08 13:58:19 +00:00
$('<img>')
.load(function() {
2012-01-30 20:48:19 +00:00
self.loaded.push(image);
2011-08-08 13:58:19 +00:00
self.queue.length && loadFrame();
})
2012-01-30 20:48:19 +00:00
.attr({src: image.frame})
2011-08-08 13:58:19 +00:00
}
}
function stopLoading() {
self.queue = [];
2012-01-30 20:59:07 +00:00
self.timeout && clearTimeout(self.timeout);
2011-08-08 13:58:19 +00:00
}
function touchend(e) {
var position = getPosition(e.clientX - that.offset().left);
stopLoading();
self.$frame.attr({src: getClosestFrame(position)});
that.triggerEvent('click', {
position: position
});
}
function touchmove(e) {
var position = getPosition(e.clientX - that.offset().left);
self.$frame.attr({src: getClosestFrame(position)});
}
2011-08-08 13:58:19 +00:00
return that;
2011-08-17 18:57:58 +00:00
};