JSFiddle - React, Tailwind, and code Playground
by subzey
HTML
<canvas id="a" width="600" height="600"></canvas>
JavaScript
// Получаем главнй канвас и его контекст
// Имена a и c - стандарт де-факто
var a = document.getElementById('a');
var c = a.getContext('2d');
// Создаём вспомогательный канвас для паттерна
// Можно было бы использовать существующий,
// но это усложнит понимание кода
var patternCanvas = document.createElement('canvas');
patternCanvas.width = 16;
patternCanvas.height = 16;
var patternCtx = patternCanvas.getContext('2d');
patternCtx.globalAlpha = 0.25;
patternCtx.beginPath();
patternCtx.arc(8,8,6,0,7);
patternCtx.fill();
// Собственно, паттерн. С этого момента на вспомогательный канвас не пригодится
var pattern = c.createPattern(patternCanvas, 'repeat');
// Товсь - Ноль!
var demoStartTime = Date.now ? Date.now() : +new Date();
(function render(){
var currentTime = Date.now ? Date.now() : +new Date();
var timeDelta = currentTime - demoStartTime;
var angle = timeDelta / 1e3;
var scale = Math.cos(timeDelta / 2e3);
// Очистка канваса
a.width |= 0;
c.lineWidth = 5;
c.fillStyle = pattern;
// Левый верхний эллипс
c.save();
c.translate(150, 150);
c.rotate(angle);
c.scale(scale, 1);
c.beginPath();
c.arc(0, 0, 100, 0, 7);
// Заливаем сразу же
c.stroke();
c.restore();
// Правый верхний эллипс
c.save();
c.translate(450, 150);
c.rotate(angle);
c.scale(scale, 1);
c.beginPath();
c.arc(0, 0, 100, 0, 7);
c.restore();
// На этот раз перед заливкой сбросим трансформации
c.stroke();
// Левый нижний эллипс
c.save();
c.translate(150, 450);
c.rotate(angle);
c.scale(scale, 1);
c.beginPath();
c.arc(0, 0, 100, 0, 7);
// Заливаем сразу же
c.fill();
c.restore();
// Правый нижний эллипс
c.save();
c.translate(450, 450);
c.rotate(angle);
c.scale(scale, 1);
c.beginPath();
c.arc(0, 0, 100, 0, 7);
c.restore();
// Заливаем после восстановления матрицы трансформации
c.fill();
requestAnimationFrame(render);
})();