| <!DOCtype html> | |
| <html> | |
| <style> | |
| * { | |
| box-sizing: border-box; | |
| } | |
| html, | |
| body { | |
| height: 100%; | |
| width: 100%; | |
| } | |
| body { | |
| margin: 0; | |
| overflow: hidden; | |
| } | |
| </style> | |
| <body> | |
| <script> | |
| "use strict"; | |
| function getFullScreenParams(ctx) { | |
| const { width, height } = ctx.canvas; | |
| return [0, 0, width, height]; | |
| } | |
| function getCtxUtils(ctx) { | |
| function clear() { | |
| const params = getFullScreenParams(ctx); | |
| ctx.clearRect(...params); | |
| } | |
| function save(callback) { | |
| ctx.save(); | |
| callback(); | |
| ctx.restore(); | |
| } | |
| function drawPath(callback) { | |
| ctx.beginPath(); | |
| callback(); | |
| ctx.closePath(); | |
| } | |
| return { | |
| clear, | |
| save, | |
| drawPath | |
| }; | |
| } | |
| function initCanvas(resizeCallback, parent = document.body) { | |
| function create() { | |
| const canvas = document.createElement('canvas'); | |
| const ctx = canvas.getContext('2d'); | |
| return [canvas, ctx]; | |
| } | |
| function resize() { | |
| const { clientHeight, clientWidth } = parent; | |
| canvas.height = clientHeight; | |
| canvas.width = clientWidth; | |
| resizeCallback(); | |
| } | |
| function append() { | |
| parent.innerHTML = ''; | |
| parent.appendChild(canvas); | |
| } | |
| const [canvas, ctx] = create(); | |
| resize(); | |
| append(); | |
| window.addEventListener('resize', resize); | |
| return ctx; | |
| } | |
| class Curve { | |
| constructor(origin, angle, length = 400) { | |
| this.angle = angle; | |
| this.length = length; | |
| this._angleOffset = 40; | |
| this.percentage = 0; | |
| this.speed = (Math.random() * 0.005) + 0.0005; | |
| this.randColor = () => { | |
| const { floor, random } = Math; | |
| return ['cyan', 'magenta', 'yellow'][floor(random() * 3)]; | |
| }; | |
| this.getEndPoint = () => { | |
| const { cos, sin } = Math; | |
| const x = cos(this.angle) * this.length; | |
| const y = sin(this.angle) * this.length; | |
| return [x, y]; | |
| }; | |
| this.getStartControlPoint = () => { | |
| const { cos, sin } = Math; | |
| const angle = this.angle - (this._angleOffset / 60); | |
| const length = this.length / 3; | |
| const x = cos(angle) * length; | |
| const y = sin(angle) * length; | |
| return [x, y]; | |
| }; | |
| this.getEndControlPoint = () => { | |
| const { cos, sin } = Math; | |
| const angle = this.angle + (this._angleOffset / 60); | |
| const length = (this.length / 3) * 2; | |
| const x = cos(angle) * length; | |
| const y = sin(angle) * length; | |
| return [x, y]; | |
| }; | |
| this.animate = () => { | |
| function getXY() { | |
| const x = cubicN(percentage, 0, startControlPoint[0], endControlPoint[0], end[0]); | |
| const y = cubicN(percentage, 0, startControlPoint[1], endControlPoint[1], end[1]); | |
| return [x, y]; | |
| } | |
| // cubic helper formula | |
| function cubicN(T, a, b, c, d) { | |
| const t2 = T * T; | |
| const t3 = t2 * T; | |
| return a + (-a * 3 + T * (3 * a - a * T)) * T + (3 * b + T * (-6 * b + b * 3 * T)) * T + (c * 3 - c * 3 * T) * t2 + d * t3; | |
| } | |
| const { startControlPoint, endControlPoint, end, percentage } = this; | |
| if (!this.isComplete) { | |
| this.percentage += this.speed; | |
| this.currentPoint = getXY(); | |
| } | |
| }; | |
| this.start = origin; | |
| this.currentPoint = [0, 0]; | |
| this.end = this.getEndPoint(); | |
| this.startControlPoint = this.getStartControlPoint(); | |
| this.endControlPoint = this.getEndControlPoint(); | |
| this.color = this.randColor(); | |
| } | |
| get isComplete() { | |
| return this.percentage >= 1; | |
| } | |
| } | |
| class Burst { | |
| constructor(x, y) { | |
| this.curves = []; | |
| this.render = (ctx) => { | |
| function renderCurve(curve) { | |
| const { currentPoint, endControlPoint, startControlPoint, end } = curve; | |
| save(() => { | |
| drawPath(() => { | |
| ctx.moveTo(0, 0); | |
| ctx.strokeStyle = 'rgba(80,80,80,0.4)'; | |
| ctx.bezierCurveTo(...startControlPoint, ...endControlPoint, ...end); | |
| ctx.stroke(); | |
| }); | |
| }); | |
| save(() => { | |
| ctx.translate(x, y); | |
| drawPath(() => { | |
| let [xi, yi] = currentPoint; | |
| xi -= x; | |
| yi -= y; | |
| ctx.fillStyle = curve.color; | |
| ctx.moveTo(0, 0); | |
| ctx.arc(xi, yi, 4, 0, Math.PI * 2); | |
| ctx.fill(); | |
| }); | |
| }); | |
| } | |
| function renderCurves() { | |
| save(() => { | |
| ctx.translate(x, y); | |
| curves.forEach(renderCurve); | |
| }); | |
| } | |
| function renderBackground() { | |
| save(() => { | |
| ctx.translate(0, 0); | |
| ctx.fillStyle = '#101219'; | |
| drawPath(() => ctx.fillRect(...getFullScreenParams(ctx))); | |
| }); | |
| } | |
| const { clear, save, drawPath } = getCtxUtils(ctx); | |
| const { curves, x, y } = this; | |
| clear(); | |
| renderBackground(); | |
| renderCurves(); | |
| }; | |
| this._x = x; | |
| this._y = y; | |
| this.create(); | |
| } | |
| get x() { return this._x; } | |
| set x(value) { | |
| this._x = value; | |
| if (this.onPositionChange) | |
| this.onPositionChange(); | |
| } | |
| get y() { return this._y; } | |
| set y(value) { | |
| this._y = value; | |
| if (this.onPositionChange) | |
| this.onPositionChange(); | |
| } | |
| create() { | |
| const chunkSize = 6 / 32; | |
| for (let i = 0; i <= 6; i += chunkSize) { | |
| this.curves.push(new Curve([this.x, this.y], i, 1300)); | |
| } | |
| } | |
| } | |
| window.onload = init; | |
| function init() { | |
| function animate() { | |
| burst.curves.forEach((curve, i) => { | |
| if (curve.isComplete) { | |
| const chunkSize = 6 / 32; | |
| const newCurve = new Curve([burst.x, burst.y], i * chunkSize, 1300); | |
| burst.curves.splice(i, 1, newCurve); | |
| } | |
| else { | |
| curve.animate(); | |
| } | |
| }); | |
| burst.render(ctx); | |
| requestAnimationFrame(animate); | |
| } | |
| let [cx, cy] = [window.innerWidth / 2, window.innerHeight / 2]; | |
| const burst = new Burst(cx, cy); | |
| const ctx = initCanvas(() => { | |
| [cx, cy] = [window.innerWidth / 2, window.innerHeight / 2]; | |
| burst.x = cx; | |
| burst.y = cy; | |
| }); | |
| burst.render(ctx); | |
| requestAnimationFrame(animate); | |
| } | |
| </script> | |
| </body> | |
| </html> |
Move along Curve html css java Code
Friday, August 04, 2023
0
Tags

Please don't spam comments Thank You.