Многие наверняка используют индикаторы процесса, например, когда передаете/получаете какие-нибудь данные через AJAX.
Однажды я озадачился, чтобы при нажатии на кнопку, которая отправляет данные формы на сервер, внутри неё появился этот самый индикатор. Изначально фон был однотонный, но в любой момент дизайнеры могли заменить его на другой, либо вообще сделать градиент.
Делать специальный GIF под каждую ситуацию довольно глупо. Поэтому правильное решение — использовать Canvas.
В первые же минуты, я наткнулся на этот JavaScript модуль, с помощью которого можно хоть загенерироваться подобными индикаторами:
Но проблему это не решило, не с технической конечно стороны, а с дизайнерской. Человек, занимающийся этими вопросами настаивал, чтобы по кругу бегали не кружочки, а палочки, как тут:
Изначально я наткнулся на эту библиотеку, но в ней реализовано много функций, которые я даже не планировал использовать. Поиски пришлось продолжить.
В итоге я наткнулся на одну запись, которая почти решала мою проблему.
Убрав лишнее, добавив нужное, я с удовольствием поделюсь решением с вами.
Пример использования. В нужном месте, ставим тег canvas:
И создаем экземпляр класса CanvasIndicator:
Как видно, конструктор CanvasIndicator принимает два параметра: первый обязательно — холст, где собственно и будет происходить действие. Второй параметр опционален — это объект, свойства которого являются конфигурацией индикатора.
Подробнее о свойствах:
bars — количество блоков
innerRadius — внутренний радиус
size — массив, где первый элемент — это ширина блока, а второй — его высота
rgb — цвет индикатора, задается массивом из трех элементов, где Red, Green, Blue — соответственно
fps — количество кадров в секунду, чем больше значение, тем быстрее крутится индикатор
Ну и непосредственно код библиотеки CanvasIndicator.js
Посмотреть пример можно здесь.
Скачать библиотеку можно тут
Однажды я озадачился, чтобы при нажатии на кнопку, которая отправляет данные формы на сервер, внутри неё появился этот самый индикатор. Изначально фон был однотонный, но в любой момент дизайнеры могли заменить его на другой, либо вообще сделать градиент.
Делать специальный GIF под каждую ситуацию довольно глупо. Поэтому правильное решение — использовать Canvas.
В первые же минуты, я наткнулся на этот JavaScript модуль, с помощью которого можно хоть загенерироваться подобными индикаторами:
Но проблему это не решило, не с технической конечно стороны, а с дизайнерской. Человек, занимающийся этими вопросами настаивал, чтобы по кругу бегали не кружочки, а палочки, как тут:
Изначально я наткнулся на эту библиотеку, но в ней реализовано много функций, которые я даже не планировал использовать. Поиски пришлось продолжить.
В итоге я наткнулся на одну запись, которая почти решала мою проблему.
Убрав лишнее, добавив нужное, я с удовольствием поделюсь решением с вами.
Пример использования. В нужном месте, ставим тег canvas:
<canvas id="loader"></canvas>
И создаем экземпляр класса CanvasIndicator:
new CanvasIndicator(document.getElementById("loader"),{
bars:11,
innerRadius:4,
size:[2,5],
rgb:[255,255,255],
fps:10
});
Как видно, конструктор CanvasIndicator принимает два параметра: первый обязательно — холст, где собственно и будет происходить действие. Второй параметр опционален — это объект, свойства которого являются конфигурацией индикатора.
Подробнее о свойствах:
bars — количество блоков
innerRadius — внутренний радиус
size — массив, где первый элемент — это ширина блока, а второй — его высота
rgb — цвет индикатора, задается массивом из трех элементов, где Red, Green, Blue — соответственно
fps — количество кадров в секунду, чем больше значение, тем быстрее крутится индикатор
Ну и непосредственно код библиотеки CanvasIndicator.js
function CanvasIndicator(el, opt) {
this.ctx = el.getContext("2d");
this.currentOffset = 0;
var defaults = {
bars: 11,
innerRadius: 4,
size: [2, 5],
rgb: [255, 255, 255],
fps: 10
}
if (typeof(opt) == 'object') {
defaults.bars = opt.bars ? opt.bars : defaults.bars;
defaults.innerRadius = opt.innerRadius ? opt.innerRadius : defaults.innerRadius;
defaults.size = opt.size ? opt.size : defaults.size;
defaults.rgb = opt.rgb ? opt.rgb : defaults.rgb;
defaults.fps = opt.fps ? opt.fps : defaults.fps;
}
this.opt = defaults;
this.w = this.opt.size[1] + this.opt.innerRadius;
el.setAttribute("width", this.w * 2);
el.setAttribute("height", this.w * 2);
(function nextAnimation(obj) {
obj.currentOffset = (obj.currentOffset + 1) % obj.opt.bars;
obj.draw(obj.currentOffset);
setTimeout(function () {
nextAnimation(obj);
}, 1000 / obj.opt.fps);
})(this);
}
CanvasIndicator.prototype.makeRGBA = function () {
return "rgba(" + [].slice.call(arguments, 0).join(",") + ")";
}
CanvasIndicator.prototype.drawBlock = function (barNo) {
this.ctx.fillStyle = this.makeRGBA(this.opt.rgb[0], this.opt.rgb[1], this.opt.rgb[2], (this.opt.bars + 1 - barNo) / (this.opt.bars + 1));
this.ctx.fillRect(-this.opt.size[0] / 2, 0, this.opt.size[0], this.opt.size[1]);
}
CanvasIndicator.prototype.calculatePosition = function (barNo) {
angle = 2 * barNo * Math.PI / this.opt.bars;
return {
y: (this.opt.innerRadius * Math.cos(-angle)),
x: (this.opt.innerRadius * Math.sin(-angle)),
angle: angle
};
}
CanvasIndicator.prototype.draw = function (offset) {
this.clearFrame();
this.ctx.save();
this.ctx.translate(this.w, this.w);
for (var i = 0; i < this.opt.bars; i++) {
var curbar = (offset + i) % this.opt.bars,
pos = this.calculatePosition(curbar);
this.ctx.save();
this.ctx.translate(pos.x, pos.y);
this.ctx.rotate(pos.angle);
this.drawBlock(i);
this.ctx.restore();
}
this.ctx.restore();
}
CanvasIndicator.prototype.clearFrame = function () {
this.ctx.clearRect(0, 0, this.ctx.canvas.clientWidth, this.ctx.canvas.clientHeight);
}
Посмотреть пример можно здесь.
Скачать библиотеку можно тут