core/skin/m2.yurecnt.ru/js/core_fx.js

707 lines
16 KiB
JavaScript
Raw Normal View History

2023-04-09 19:52:26 +05:00
;(function(window){
var defaultOptions = {
time: 1.0,
step: 0.05,
type: 'linear',
allowFloat: false
}
/*
options: {
start: start value or {param: value, param: value}
finish: finish value or {param: value, param: value}
time: time to transform in seconds
type: linear|accelerated|decelerated|custom func name
callback,
callback_start,
callback_complete,
step: time between steps in seconds
allowFloat: false|true
}
*/
BX.fx = function(options)
{
this.options = options;
if (null != this.options.time)
this.options.originalTime = this.options.time;
if (null != this.options.step)
this.options.originalStep = this.options.step;
if (!this.__checkOptions())
return false;
this.__go = BX.delegate(this.go, this);
this.PARAMS = {};
}
BX.fx.prototype.__checkOptions = function()
{
if (typeof this.options.start != typeof this.options.finish)
return false;
if (null == this.options.time) this.options.time = defaultOptions.time;
if (null == this.options.step) this.options.step = defaultOptions.step;
if (null == this.options.type) this.options.type = defaultOptions.type;
if (null == this.options.allowFloat) this.options.allowFloat = defaultOptions.allowFloat;
this.options.time *= 1000;
this.options.step *= 1000;
if (typeof this.options.start != 'object')
{
this.options.start = {_param: this.options.start};
this.options.finish = {_param: this.options.finish};
}
var i;
for (i in this.options.start)
{
if (null == this.options.finish[i])
{
this.options.start[i] = null;
delete this.options.start[i];
}
}
if (!BX.type.isFunction(this.options.type))
{
if (BX.type.isFunction(window[this.options.type]))
this.options.type = window[this.options.type];
else if (BX.type.isFunction(BX.fx.RULES[this.options.type]))
this.options.type = BX.fx.RULES[this.options.type];
else
this.options.type = BX.fx.RULES[defaultOptions.type];
}
return true;
}
BX.fx.prototype.go = function()
{
var timeCurrent = new Date().valueOf();
if (timeCurrent < this.PARAMS.timeFinish)
{
for (var i in this.PARAMS.current)
{
this.PARAMS.current[i][0] = this.options.type.apply(this, [{
start_value: this.PARAMS.start[i][0],
finish_value: this.PARAMS.finish[i][0],
current_value: this.PARAMS.current[i][0],
current_time: timeCurrent - this.PARAMS.timeStart,
total_time: this.options.time
}]);
}
this._callback(this.options.callback);
if (!this.paused)
this.PARAMS.timer = setTimeout(this.__go, this.options.step);
}
else
{
this.stop();
}
}
BX.fx.prototype._callback = function(cb)
{
var tmp = {};
cb = cb || this.options.callback;
for (var i in this.PARAMS.current)
{
tmp[i] = (this.options.allowFloat ? this.PARAMS.current[i][0] : Math.round(this.PARAMS.current[i][0])) + this.PARAMS.current[i][1];
}
return cb.apply(this, [null != tmp['_param'] ? tmp._param : tmp]);
}
BX.fx.prototype.start = function()
{
var i,value, unit;
this.PARAMS.start = {};
this.PARAMS.current = {};
this.PARAMS.finish = {};
for (i in this.options.start)
{
value = +this.options.start[i];
unit = (this.options.start[i]+'').substring((value+'').length);
this.PARAMS.start[i] = [value, unit];
this.PARAMS.current[i] = [value, unit];
this.PARAMS.finish[i] = [+this.options.finish[i], unit];
}
this._callback(this.options.callback_start);
this._callback(this.options.callback);
this.PARAMS.timeStart = new Date().valueOf();
this.PARAMS.timeFinish = this.PARAMS.timeStart + this.options.time;
this.PARAMS.timer = setTimeout(BX.delegate(this.go, this), this.options.step);
return this;
}
BX.fx.prototype.pause = function()
{
if (this.paused)
{
this.PARAMS.timer = setTimeout(this.__go, this.options.step);
this.paused = false;
}
else
{
clearTimeout(this.PARAMS.timer);
this.paused = true;
}
}
BX.fx.prototype.stop = function(silent)
{
silent = !!silent;
if (this.PARAMS.timer)
clearTimeout(this.PARAMS.timer);
if (null != this.options.originalTime)
this.options.time = this.options.originalTime;
if (null != this.options.originalStep)
this.options.step = this.options.originalStep;
this.PARAMS.current = this.PARAMS.finish;
if (!silent) {
this._callback(this.options.callback);
this._callback(this.options.callback_complete);
}
}
/*
type rules of animation
- linear - simple linear animation
- accelerated
- decelerated
*/
/*
params: {
start_value, finish_value, current_time, total_time
}
*/
BX.fx.RULES =
{
linear: function(params)
{
return params.start_value + (params.current_time/params.total_time) * (params.finish_value - params.start_value);
},
decelerated: function(params)
{
return params.start_value + Math.sqrt(params.current_time/params.total_time) * (params.finish_value - params.start_value);
},
accelerated: function(params)
{
var q = params.current_time/params.total_time;
return params.start_value + q * q * (params.finish_value - params.start_value);
}
}
/****************** effects realizaion ************************/
/*
type = 'fade' || 'scroll' || 'scale' || 'fold'
*/
BX.fx.hide = function(el, type, opts)
{
el = BX(el);
if (typeof type == 'object' && null == opts)
{
opts = type;
type = opts.type
}
if (!opts) opts = {};
if (!BX.type.isNotEmptyString(type))
{
el.style.display = 'none';
return;
}
var fxOptions = BX.fx.EFFECTS[type](el, opts, 0);
fxOptions.callback_complete = function () {
if (opts.hide !== false)
el.style.display = 'none';
if (opts.callback_complete)
opts.callback_complete.apply(this, arguments);
}
return (new BX.fx(fxOptions)).start();
}
BX.fx.show = function(el, type, opts)
{
el = BX(el);
if (typeof type == 'object' && null == opts)
{
opts = type;
type = opts.type
}
if (!opts) opts = {};
if (!BX.type.isNotEmptyString(type))
{
el.style.display = 'block';
return;
}
var fxOptions = BX.fx.EFFECTS[type](el, opts, 1);
fxOptions.callback_complete = function () {
if (opts.show !== false)
el.style.display = 'block';
if (opts.callback_complete)
opts.callback_complete.apply(this, arguments);
}
return (new BX.fx(fxOptions)).start();
}
BX.fx.EFFECTS = {
scroll: function(el, opts, action)
{
if (!opts.direction) opts.direction = 'vertical';
var param = opts.direction == 'horizontal' ? 'width' : 'height';
var val = parseInt(BX.style(el, param));
if (isNaN(val))
{
val = BX.pos(el)[param];
}
if (action == 0)
var start = val, finish = opts.min_height ? parseInt(opts.min_height) : 0;
else
var finish = val, start = opts.min_height ? parseInt(opts.min_height) : 0;
return {
'start': start,
'finish': finish,
'time': opts.time || defaultOptions.time,
'type': 'linear',
callback_start: function () {
if (BX.style(el, 'position') == 'static')
el.style.position = 'relative';
el.style.overflow = 'hidden';
el.style[param] = start + 'px';
el.style.display = 'block';
},
callback: function (val) {el.style[param] = val + 'px';}
}
},
fade: function(el, opts, action)
{
var fadeOpts = {
'time': opts.time || defaultOptions.time,
'type': action == 0 ? 'decelerated' : 'linear',
'start': action == 0 ? 1 : 0,
'finish': action == 0 ? 0 : 1,
'allowFloat': true
};
if (BX.browser.IsIE() && !BX.browser.IsIE9())
{
fadeOpts.start *= 100; fadeOpts.finish *= 100; fadeOpts.allowFloat = false;
fadeOpts.callback_start = function() {
el.style.display = 'block';
el.style.filter += "progid:DXImageTransform.Microsoft.Alpha(opacity=" + fadeOpts.start + ")";
};
fadeOpts.callback = function (val) {
(el.filters['DXImageTransform.Microsoft.alpha']||el.filters.alpha).opacity = val;
}
}
else
{
fadeOpts.callback_start = function () {
el.style.display = 'block';
}
fadeOpts.callback = function (val) {
el.style.opacity = el.style.KhtmlOpacity = el.style.MozOpacity = val;
};
}
return fadeOpts;
},
fold: function (el, opts, action) // 'fold' is a combination of two consequential 'scroll' hidings.
{
if (action != 0) return;
var pos = BX.pos(el);
var coef = pos.height / (pos.width + pos.height);
var old_opts = {time: opts.time || defaultOptions.time, callback_complete: opts.callback_complete, hide: opts.hide};
opts.type = 'scroll';
opts.direction = 'vertical';
opts.min_height = opts.min_height || 10;
opts.hide = false;
opts.time = coef * old_opts.time;
opts.callback_complete = function()
{
el.style.whiteSpace = 'nowrap';
opts.direction = 'horizontal';
opts.min_height = null;
opts.time = old_opts.time - opts.time;
opts.hide = old_opts.hide;
opts.callback_complete = old_opts.callback_complete;
BX.fx.hide(el, opts);
}
return BX.fx.EFFECTS.scroll(el, opts, action);
},
scale: function (el, opts, action)
{
var val = {width: parseInt(BX.style(el, 'width')), height: parseInt(BX.style(el, 'height'))};
if (isNaN(val.width) || isNaN(val.height))
{
var pos = BX.pos(el)
val = {width: pos.width, height: pos.height};
}
if (action == 0)
var start = val, finish = {width: 0, height: 0};
else
var finish = val, start = {width: 0, height: 0};
return {
'start': start,
'finish': finish,
'time': opts.time || defaultOptions.time,
'type': 'linear',
callback_start: function () {
el.style.position = 'relative';
el.style.overflow = 'hidden';
el.style.display = 'block';
el.style.height = start.height + 'px';
el.style.width = start.width + 'px';
},
callback: function (val) {
el.style.height = val.height + 'px';
el.style.width = val.width + 'px';
}
}
}
}
// Color animation
//
// Set animation rule
// BX.fx.colorAnimate.addRule('animationRule1',"#FFF","#faeeb4", "background-color", 100, 1, true);
// BX.fx.colorAnimate.addRule('animationRule2',"#fc8282","#ff0000", "color", 100, 1, true);
// Params: 1 - animation name, 2 - start color, 3 - end color, 4 - count step, 5 - delay each step, 6 - return color on end animation
//
// Animate color for element
// BX.fx.colorAnimate(BX('element'), 'animationRule1,animationRule2');
var defaultOptionsColorAnimation = {
arStack: {},
arRules: {},
globalAnimationId: 0
}
BX.fx.colorAnimate = function(element, rule, back)
{
if (element == null)
return;
animationId = element.getAttribute('data-animation-id');
if (animationId == null)
{
animationId = defaultOptionsColorAnimation.globalAnimationId;
element.setAttribute('data-animation-id', defaultOptionsColorAnimation.globalAnimationId++);
}
var aRuleList = rule.split(/\s*,\s*/);
for (var j = 0; j < aRuleList.length; j++)
{
rule = aRuleList[j];
if (!defaultOptionsColorAnimation.arRules[rule]) continue;
var i=0;
if (!defaultOptionsColorAnimation.arStack[animationId])
{
defaultOptionsColorAnimation.arStack[animationId] = {};
}
else if (defaultOptionsColorAnimation.arStack[animationId][rule])
{
i = defaultOptionsColorAnimation.arStack[animationId][rule].i;
clearInterval(defaultOptionsColorAnimation.arStack[animationId][rule].tId);
}
if ((i==0 && back) || (i==defaultOptionsColorAnimation.arRules[rule][3] && !back)) continue;
defaultOptionsColorAnimation.arStack[animationId][rule] = {'i':i, 'element': element, 'tId':setInterval('BX.fx.colorAnimate.run("'+animationId+'","'+rule+'")', defaultOptionsColorAnimation.arRules[rule][4]),'back':Boolean(back)};
}
}
BX.fx.colorAnimate.addRule = function (rule, startColor, finishColor, cssProp, step, delay, back)
{
defaultOptionsColorAnimation.arRules[rule] = [
BX.util.hex2rgb(startColor),
BX.util.hex2rgb(finishColor),
cssProp.replace(/\-(.)/g,function(){return arguments[1].toUpperCase();}),
step,
delay || 1,
back || false
];
};
BX.fx.colorAnimate.run = function(animationId, rule)
{
element = defaultOptionsColorAnimation.arStack[animationId][rule].element;
defaultOptionsColorAnimation.arStack[animationId][rule].i += defaultOptionsColorAnimation.arStack[animationId][rule].back?-1:1;
var finishPercent = defaultOptionsColorAnimation.arStack[animationId][rule].i/defaultOptionsColorAnimation.arRules[rule][3];
var startPercent = 1 - finishPercent;
var aRGBStart = defaultOptionsColorAnimation.arRules[rule][0];
var aRGBFinish = defaultOptionsColorAnimation.arRules[rule][1];
element.style[defaultOptionsColorAnimation.arRules[rule][2]] = 'rgb('+
Math.floor( aRGBStart['r'] * startPercent + aRGBFinish['r'] * finishPercent ) + ','+
Math.floor( aRGBStart['g'] * startPercent + aRGBFinish['g'] * finishPercent ) + ','+
Math.floor( aRGBStart['b'] * startPercent + aRGBFinish['b'] * finishPercent ) +')';
if ( defaultOptionsColorAnimation.arStack[animationId][rule].i == defaultOptionsColorAnimation.arRules[rule][3] || defaultOptionsColorAnimation.arStack[animationId][rule].i ==0)
{
clearInterval(defaultOptionsColorAnimation.arStack[animationId][rule].tId);
if (defaultOptionsColorAnimation.arRules[rule][5])
BX.fx.colorAnimate(defaultOptionsColorAnimation.arStack[animationId][rule].element, rule, true);
}
}
/*
options = {
delay: 100,
duration : 3000,
start : { scroll : document.body.scrollTop, left : 0, opacity : 100 },
finish : { scroll : document.body.scrollHeight, left : 500, opacity : 10 },
transition : BitrixAnimation.makeEaseOut(BitrixAnimation.transitions.quart),
step : function(state)
{
document.body.scrollTop = state.scroll;
button.style.left = state.left + "px";
button.style.opacity = state.opacity / 100;
},
complete : function()
{
button.style.background = "green";
}
}
options =
{
delay : 20,
duration : 4000,
transition : BXAnimation.makeEaseOut(BXAnimation.transitions.quart),
progress : function(progress)
{
document.body.scrollTop = Math.round(topMax * progress);
button.style.left = Math.round(leftMax * progress) + "px";
button.style.opacity = (100 + Math.round((opacityMin - 100) * progress)) / 100;
},
complete : function()
{
button.style.background = "green";
}
}
*/
BX.easing = function(options)
{
this.options = options;
this.timer = null;
};
BX.easing.prototype.animate = function()
{
if (!this.options || !this.options.start || !this.options.finish ||
typeof(this.options.start) != "object" || typeof(this.options.finish) != "object"
)
return null;
for (var propName in this.options.start)
{
if (typeof(this.options.finish[propName]) == "undefined")
{
delete this.options.start[propName];
}
}
this.options.progress = function(progress) {
var state = {};
for (var propName in this.start)
state[propName] = Math.round(this.start[propName] + (this.finish[propName] - this.start[propName]) * progress);
if (this.step)
{
this.step(state);
}
};
this.animateProgress();
};
BX.easing.prototype.stop = function(completed)
{
if (this.timer)
{
cancelAnimationFrame(this.timer);
this.timer = null;
if (completed)
{
this.options.complete && this.options.complete();
}
}
};
BX.easing.prototype.animateProgress = function()
{
if (!window.requestAnimationFrame)
{
//For old browsers we skip animation
this.options.progress(1);
this.options.complete && this.options.complete();
return;
}
var start = null;
var delta = this.options.transition || BX.easing.transitions.linear;
var duration = this.options.duration || 1000;
var animation = BX.proxy(function(time) {
if (start === null)
{
start = time;
}
var progress = (time - start) / duration;
if (progress > 1)
{
progress = 1;
}
this.options.progress(delta(progress));
if (progress == 1)
{
this.stop(true);
}
else
{
this.timer = requestAnimationFrame(animation);
}
}, this);
this.timer = requestAnimationFrame(animation);
};
BX.easing.makeEaseInOut = function(delta)
{
return function(progress) {
if (progress < 0.5)
return delta( 2 * progress ) / 2;
else
return (2 - delta( 2 * (1-progress) ) ) / 2;
}
};
BX.easing.makeEaseOut = function(delta)
{
return function(progress) {
return 1 - delta(1 - progress);
};
};
BX.easing.transitions = {
linear : function(progress)
{
return progress;
},
quad : function(progress)
{
return Math.pow(progress, 2);
},
cubic : function(progress) {
return Math.pow(progress, 3);
},
quart : function(progress)
{
return Math.pow(progress, 4);
},
quint : function(progress)
{
return Math.pow(progress, 5);
},
circ : function(progress)
{
return 1 - Math.sin(Math.acos(progress));
},
back : function(progress)
{
return Math.pow(progress, 2) * ((1.5 + 1) * progress - 1.5);
},
elastic: function(progress)
{
return Math.pow(2, 10 * (progress-1)) * Math.cos(20 * Math.PI * 1.5/3 * progress);
},
bounce : function(progress)
{
for(var a = 0, b = 1; 1; a += b, b /= 2) {
if (progress >= (7 - 4 * a) / 11) {
return -Math.pow((11 - 6 * a - 11 * progress) / 4, 2) + Math.pow(b, 2);
}
}
}};
})(window);