Xiper

Блик

Автор: Евгений Рыжков Дата публикации:

Задача

Сделать пробегающий блик по надписи.

Решение

Делаем с помощью HTML5 Canvas. К примеру сделаем блик для заголовка:

<h1>Подопытный заголовок</h1>
h1 {
	position: relative;
	display: inline-block;	// это нужно чтобы проще подобрать скорость блика
}
#canvasBlik {
	position: absolute;
	top: 0;
	left: 0;
	z-index: 1;
}
/* 
	иницализация блика:
	el - элемент, к которому применяется эффект
	params - параметы:
		blikWidth - ширина блика
		blikAngle - угог наклона
		duration - продолжительность
 */
function blikInit(el, params) {
	var el = el,
			elH = el.height(),
			elW = el.innerWidth(),
			canvasForBlik;
	/* если блик к элементу еще не применялся
			добаялем canvas и скрываем текст
	*/
	if(el.find('canvas').length == 0)		
	{
		canvasForBlik = document.createElement('canvas');
		canvasForBlik.id = 'canvasBlik';
		el.wrapInner('<span style="opacity: 0; position: relative; z-index: 2"></span>');
		el.append(canvasForBlik);
		/* задаем размеры и позиционируем canvas */
		canvasForBlik.width=elW;
		canvasForBlik.height=elH;
	}
	else { // делать этого нет смысле
		canvasForBlik = document.getElementById('canvasBlik');
	}
	/* определяем параметры текста */
	var optFontName = el.css('fontFamily'),
			optFontSize = el.css('fontSize'),
			optFontColor = el.css('color'),
			optFontWeight = el.css('fontWeight'),
			optFontStyle = el.css('fontStyle'),
			optLineHeight = el.css('lineHeight'),
			optText = el.text();
	var ctx = canvasForBlik.getContext('2d');
	var blikWidth = params.blikWidth; // ширина блика
	/* 	создаем блик. тут же определяем его вид */
	var lineargradient = ctx.createLinearGradient(0,0,blikWidth,0);
	/* цвета блика */
	lineargradient.addColorStop(0, 'rgba(255, 255, 255, 0.5)'); 
	lineargradient.addColorStop(0.4, 'rgba(255, 255, 255, 1)');
	lineargradient.addColorStop(0.6, 'rgba(255, 255, 255, 1)'); 
	lineargradient.addColorStop(1, 'rgba(255, 255, 255, 0.5)'); 
	var blikAngle = params.blikAngle; // угол блика
	// параметры анимации
	var	anim,									// таймаут
		start,									// время старта
		now,										// текущее время
		duration = params.duration,							// продолжительность
		from = -20-blikWidth,					// стартовая позиция
		to = elW+blikWidth+20,					// финишная позиция
		progress = 0,								// прогресс анимации
		x;										// позиция в текущий момент времени
	// закон приращения аргумента (easing)
	function delta(param){
		return param;
	};
	// рендер
	function render(){
		now = new Date().getTime();
		progress = (now-start)/duration;
		x = (to - from)*delta(progress) + from;
		ctx.save();
		ctx.clearRect(0, 0, elW, elH);
		ctx.textBaseline = 'top';
		ctx.font = optFontStyle+' '+optFontWeight+' '+optFontSize+' '+optFontName;
		ctx.fillStyle = optFontColor;
		ctx.fillText(optText,0, 7);
		ctx.save();
		ctx.globalCompositeOperation = 'source-atop';
		ctx.translate(x, 0);
		ctx.fillStyle = lineargradient;
		ctx.rotate( blikAngle ); 
		ctx.fillRect(0,-50, blikWidth, elH+50);
		ctx.restore();
		// если не конец выполняем анимацию еще
		if (progress > 1) anim = setTimeout(arguments.callee, 0)
			// иначе заканчиваем анимацию
			else
			{
				clearTimeout(anim);
				progress = 0;
				el.find('canvas')
			};
	};
	start = new Date().getTime();
	render();
}
$(document).ready(function(){
blikInit($('h1'), {blikWidth: 100, blikAngle: Math.PI / 6, duration: 1500});
$('input').click(function()	{
	blikInit($('h1'), {blikWidth: 50, blikAngle: Math.PI / 6, duration: 800});
});
});
//requestAnimFrame
window.setAnimation = (function() {
return  window.requestAnimationFrame||
        window.webkitRequestAnimationFrame||
        window.mozRequestAnimationFrame||
        window.oRequestAnimationFrame||
        window.msRequestAnimationFrame||
        function(/* function */callback, /* DOMElement */element) {
            return window.setTimeout(callback, 1000 / 60);
        };
})();
//canсelRequestAnimFrame
window.clearAnimation = (function() {
return  window.cancelRequestAnimationFrame||
        window.webkitCancelRequestAnimationFrame||
        window.mozCancelRequestAnimationFrame||
        window.oCancelRequestAnimationFrame||
        window.msCancelRequestAnimationFrame||
        function(id){clearTimeout(id)}
})();

Демо пример. Поддерживается:

  • IE 9
  • Firefox 4+
  • Safari 5+
  • Chrome
  • iOs 4+
  • Android 3+