Сценарий анимации: Рисование контура корзины Заполнение цветом контура Последовательное появление 5-ти цветных полосок Исчезновение полосок в обратном порядке. Зацикливание появления, исчезновения цветных полосок. Как реализовать данный сценарий анимации иконки используя одну из технологий, указанный в метках вопроса? Поздравляем победителя конкурса UModeL и обладателя галочки Sevastopol' как автора работы наиболее точно выполнившего все пункты конкурсного задания
Ответ
let s = c.width, // размер иконки w = s / 2.3, // ширина блока h = s / 13, // высота блока start = Date.now(), // время старта fall = 900, // продолжительность падения одного блока spring = 150, // продолжительность эффекта пружины jump = 2000, // продолжительность "прыжка" в конце jumpDelay = 2700, // задержка срабатываня прыжка delay = i => i * (600 - i * 50), // задержка между падениями clamp = (v, t) => Math.min(1, Math.max(0, v) / t), // приведение к интервалу 0 - 1 ctx = c.getContext("2d") function draw() { let time = Date.now() - start // timestamp кадра ctx.clearRect(0, 0, s, s) // очистка ctx.fillStyle = "white" // цвет блоков и корзины // блоки [0, 1, 2, 3, 4].forEach(block => { // падение let t = clamp(time - delay(block), fall) // интервал времени падения let y = s * (t * t * t * 1.5 - 1.65 - .1 * block) // сглаживание y = t^3 // эффект пружины for (let i = 0 i < 5 i++) { // столько раз сколько блоков t = clamp(time - fall - delay(i), spring) - .6 // время срабатывания y += (1 - t * t) * s * .09 // сглаживание y = 1 - t^2 } // подпрыгивание t = clamp(time - jumpDelay, jump) // время срабатывания // веселая функция сглаживания "elastic" t = Math.pow(2, -10 * t) * Math.sin((t - .4 / 4) * (2 * Math.PI) / .4) + 1 let r = t * block * .075 * Math.PI // угол для каждого блока let x = s * .6 - Math.cos(r) * s * .6 // положение по х y -= Math.sin(r) * s * .6 - s * .1 * block * t // положение по y // отрисовка ctx.save() ctx.translate(s / 2 + x, s / 2 + y) ctx.rotate(r) ctx.fillRect(-w / 2, -h / 2, w, h) ctx.restore() }) // корзина let y = s * 0.14 [ [-w / 2 - h * 2, y, h, s * 0.25], [w / 2 + h, y, h, s * 0.25], [-w / 2 - h * 2, y + s * 0.2, w + h * 4, h] ] .forEach(r => ctx.fillRect(s / 2 + r[0], s / 2 + r[1], r[2], r[3])) requestAnimationFrame(draw) } addEventListener('click', () => start = Date.now()) draw()