Помогите с диаграммой на canvas
Пользуясь canvas-ом получилось следующее, теперь не могу:
1. Cделать 5 разных кругов. 2. Hужно чтобы каждый загружался по очереди, сначала первый полностью, потом второй и так далее..А всего их было 5. 3. Cделать чтобы они начинали загружаться только если ты доходишь до них на странице. HTML<canvas id="canvas" width="300" height="300"></canvas> window.onload = function(){ var canvas = document.getElementById("canvas"); var ctx = canvas.getContext("2d"); var W = canvas.width; var H = canvas.height; var degrees = 0; var new_degrees = 0; var difference = 0; var color = "lightblue"; var bgcolor = "#222"; var text; var animation_loop, redraw_loop; function init() { ctx.clearRect(0, 0, W, H); ctx.beginPath(); ctx.strokeStyle = bgcolor; ctx.lineWidth = 4; ctx.arc(W/2, H/2, 60, 0, Math.PI*2, false); ctx.stroke(); var radians = degrees * Math.PI / 180; ctx.beginPath(); ctx.strokeStyle = color; ctx.lineWidth = 4; ctx.arc(W/2, H/2, 60, 0 - 90*Math.PI/180, radians - 90*Math.PI/180, false); ctx.stroke(); ctx.fillStyle = color; ctx.font = "45px bebas"; text = Math.floor(degrees/360*100) + "%"; text_width = ctx.measureText(text).width; ctx.fillText(text, W/2 - text_width/2, H/2 + 15); } function draw() { if(typeof animation_loop != undefined) clearInterval(animation_loop); new_degrees = 126; difference = new_degrees - degrees; animation_loop = setInterval(animate_to, 1000/difference); } function animate_to() { if(degrees < new_degrees) degrees++; else degrees--; if(degrees == new_degrees) clearInterval(animation_loop); init(); } draw(); }; |
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>Title</title> </head> <body> <canvas class="canvas" data-color="lightblue" data-bg-color="#222" data-percent="35" width="300" height="300"></canvas> <canvas class="canvas" data-color="lightblue" data-bg-color="#222" data-percent="99" width="300" height="300"></canvas> <canvas class="canvas" data-color="lightblue" data-bg-color="#222" data-percent="62" width="300" height="300"></canvas> <canvas class="canvas" data-color="lightblue" data-bg-color="#222" data-percent="22" width="300" height="300"></canvas> <canvas class="canvas" data-color="lightblue" data-bg-color="#222" data-percent="72" width="300" height="300"></canvas> <canvas class="canvas" data-color="lightblue" data-bg-color="#222" data-percent="12" width="300" height="300"></canvas> <canvas class="canvas" data-color="lightblue" data-bg-color="#222" data-percent="82" width="300" height="300"></canvas> <canvas class="canvas" data-color="lightblue" data-bg-color="#222" data-percent="55" width="300" height="300"></canvas> <canvas class="canvas" data-color="lightblue" data-bg-color="#222" data-percent="45" width="300" height="300"></canvas> <script> /** * @class Circle * @constructor */ var Circle = function (canvas, callback) { /** * @type {HTMLCanvasElement} * @private */ this._canvas = canvas; /** * @type {CanvasRenderingContext2D} * @private */ this._ctx = canvas.getContext('2d'); /** * @type {number} * @private */ this._animateSpeed = 20; /** * @type {number} * @private */ this._endProgress = Number(this._canvas.getAttribute('data-percent')); /** * @type {string} * @private */ this._bgColor = this._canvas.getAttribute('data-bg-color'); /** * @type {string} * @private */ this._color = this._canvas.getAttribute('data-color'); /** * @type {Array<function>} * @private */ this._onReadyCallbacks = []; /** * @type {boolean} * @private */ this._isReady = false; /** * @type {function} * @private */ this._onEndAnimation = callback; /** * @type {number} * @private */ this._radius = this._canvas.width / 2 - 3; /** * @type {number} * @private */ this._width = this._canvas.width; /** * @type {number} * @private */ this._height = this._canvas.height; this._onScroll = this._onScroll.bind(this); this._initialize(); }; /** * @lends Circle# */ Circle.prototype = { setReady: function () { this._isReady = true; this._onReadyCallbacks.forEach(function (callback) { callback.call(this); }, this); this._onReadyCallbacks = []; }, /** * @param {function} callback * @private */ _onReady: function (callback) { if (this._isReady) { callback.call(this); } else { this._onReadyCallbacks.push(callback); } }, /** * @returns {boolean} * @private */ _isVisible: function () { var scroll = this._getScrollTop(); var offset = this._canvas.offsetTop; return (scroll < offset) && (scroll + innerHeight > offset + this._canvas.height); }, /** * @returns {number} * @private */ _getScrollTop: function () { return document.body.scrollTop || document.documentElement.scrollTop; }, /** * @private */ _animate: function () { var time = this._endProgress * this._animateSpeed; Circle._animate({ duration: time, step: this._redraw.bind(this), complete: this._onEndAnimation }); window.removeEventListener('scroll', this._onScroll, false); }, /** * @private */ _clear: function () { this._canvas.width = this._canvas.width; }, /** * @param {number} progress * @private */ _draw: function (progress) { var angleStart = - Math.PI / 2; var angleEnd = angleStart + (2 * Math.PI * this._endProgress / 100) * progress; this._ctx.beginPath(); this._ctx.strokeStyle = this._bgColor; this._ctx.lineWidth = 4; this._ctx.arc(this._width / 2, this._height / 2, this._radius, 0, Math.PI * 2, false); this._ctx.stroke(); this._ctx.beginPath(); this._ctx.strokeStyle = this._color; this._ctx.lineWidth = 4; this._ctx.arc(this._width / 2, this._height / 2, this._radius, angleStart, angleEnd, false); this._ctx.stroke(); this._ctx.fillStyle = this._color; this._ctx.font = "45px bebas"; var text = Math.floor(this._endProgress * progress) + "%"; var text_width = this._ctx.measureText(text).width; this._ctx.fillText(text, this._width / 2 - text_width / 2, this._height / 2 + 15); }, /** * @param {number} progress * @private */ _redraw: function (progress) { this._clear(); this._draw(progress); }, _setHandlers: function () { window.addEventListener('scroll', this._onScroll, false); }, _onScroll: function () { if (this._isVisible()) { this._animate(); } }, /** * @private */ _initialize: function () { this._onReady(function () { if (this._isVisible()) { this._animate(); } else { this._setHandlers(); } }); this._draw(0); } }; /** * @param {Object} options * @param {function} options.step * @param {number} options.duration * @param {function} options.complete * @param {function} [options.timeFunction] * @private * @static */ Circle._animate = function (options) { var start = Date.now(); // сохранить время начала requestAnimationFrame(function tick() { var timePassed = Date.now() - start; var progress = timePassed / options.duration; var timeFunction = options.timeFunction || function (progress) { return progress; }; progress = progress > 1 ? 1 : progress; options.step(timeFunction(progress)); if (progress === 1) { options.complete(); } else { requestAnimationFrame(tick); } }); }; window.onload = function () { var canvases = Array.prototype.slice.call(document.querySelectorAll('.canvas')); var circles = []; var animateEndCount = 0; var onEnd = function () { animateEndCount++; if (circles[animateEndCount]) { circles[animateEndCount].setReady(); } }; canvases.forEach(function (canvas) { circles.push(new Circle(canvas, onEnd)); }); circles[0].setReady(); }; </script> </body> </html> |
tsigel,
а почему не так например var start = performance.now(); // сохранить время начала requestAnimationFrame(function tick(time) { var timePassed = time - start; |
рони,
performance появился не так давно, я к нему ещё не привык) По привычке написал как раньше |
Часовой пояс GMT +3, время: 19:17. |