canvas实现彩色立体波浪形背景效果代码
代码语言:html
所属分类:背景
代码描述:canvas实现彩色立体波浪形背景效果代码,点击可切换。
下面为部分代码预览,完整代码请点击下载或在bfwstudio webide中打开
<!DOCTYPE html>
<html lang="en" >
<head>
<meta charset="UTF-8">
<style>
body {
font-family: Arial, Helvetica, "Liberation Sans", FreeSans, sans-serif;
background-color: #000;
margin: 0;
padding: 0;
border-width: 0;
overflow: hidden;
}
</style>
</head>
<body translate="no">
<script >
"use strict";
let canv, ctx; // canvas and context
let maxx, maxy; // canvas dimensions
let radius; // hexagons radius (and side length)
let grid; // array of hexagons
let nbx, nby; // grid size (in elements, not pixels)
let orgx, orgy;
let perx, pery, pergrid;
let colorMode = 0;
let globalHue;
// for animation
let messages;
// shortcuts for Math.
const mrandom = Math.random;
const mfloor = Math.floor;
const mround = Math.round;
const mceil = Math.ceil;
const mabs = Math.abs;
const mmin = Math.min;
const mmax = Math.max;
const mPI = Math.PI;
const mPIS2 = Math.PI / 2;
const mPIS3 = Math.PI / 3;
const m2PI = Math.PI * 2;
const m2PIS3 = Math.PI * 2 / 3;
const msin = Math.sin;
const mcos = Math.cos;
const matan2 = Math.atan2;
const mhypot = Math.hypot;
const msqrt = Math.sqrt;
const rac3 = msqrt(3);
const rac3s2 = rac3 / 2;
//------------------------------------------------------------------------
function alea(mini, maxi) {
// random number in given range
if (typeof maxi == "undefined") return mini * mrandom(); // range 0..mini
return mini + mrandom() * (maxi - mini); // range mini..maxi
}
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
function intAlea(mini, maxi) {
// random integer in given range (mini..maxi - 1 or 0..mini - 1)
//
if (typeof maxi == "undefined") return mfloor(mini * mrandom()); // range 0..mini - 1
return mini + mfloor(mrandom() * (maxi - mini)); // range mini .. maxi - 1
}
function lerp(p0, p1, alpha) {
return {
x: p0.x * (1 - alpha) + p1.x * alpha,
y: p0.y * (1 - alpha) + p1.y * alpha };
}
//------------------------------------------------------------------------
class ExtremeFilter {
/* tracks extreme points to build a linear gradient in direction given by constructor
let D the oriented straight line passing by (0,0) in direction D
makes projection of filtered points on D
keeps track of points whose projection has min and max abscissa on D
*/
constructor(angle = 0) {
this.min = Infinity;
this.max = -Infinity;
this.c = Math.cos(angle);
this.s = Math.sin(angle);
}
filter(p) {
let absc = p.x * this.c + p.y * this.s;
if (absc < this.min) {
this.min = absc;
this.pmin = p;
}
if (absc > this.max) {
this.max = absc;
this.pmax = p;
}
} // filter
filterArc(xc, yc, radius, starta, enda, ccw) {
/* uses same signature as CanvasRenderingContext2D.arc
does not accurately find extreme values, but filters a few points along the arc.
Inaccuracy does not matter that much for a gradient
*/
let x, y, a;
// make angles increasing along arc
if (ccw) [starta, enda] = [enda, starta];
while (enda < starta) enda += m2PI;
while (enda > starta + m2PI) enda -= m2PI;
const ndiv = mceil((enda - starta) / 0.4); // vill divide arc in angles < 0.4 rad (0.4 : arbitrary value)
if (ndiv == 0) ndiv = 1; // will do some extra work, but who cares ?
for (let k = 0; k <= ndiv; ++k) {
a = starta + k * (enda - starta) / ndiv;
this.filter({ x: xc + radius * mcos(a), y: yc + radius * msin(a) });
}
} // filterArc
getLinearGradient() {
/* creates a gradient without filling the stop points */
let delta = this.max - this.min;
return ctx.createLinearGradient(
this.pmin.x,
this.pmin.y,
this.pmin.x + delta * this.c,
this.pmin.y + delta * this.s);
}}
// ExtremeFilter
//------------------------------------------------------------------------
/* angles useful for the arcs */
const deltaAng0 = Math.acos(msqrt(2 / 3));
// const deltaAng1 = mPIS3 - deltaAng0;
class Hexagon {
constructor(kx, ky) {
this.kx = kx;
this.ky = ky;
// this.rot = intAlea(6); // random orientation
this.rot = pergrid[ky % pery][kx % perx].rot;
this.arcTypes = [];
this.exits = [];
this.turn = [];
for (let k = 0; k < 6; ++k) {
this.exits[(k + this.rot) % 6] = ([5, 4, 1, 2, 3, 0][k] + this.rot) % 6;
this.turn[(k + this.rot) % 6] = [2, 0, 2, 2, 2, -2][k]; // in 1/6th of turn
this.arcTypes[(k + this.rot) % 6] = ["l", "b", "b", "b", "b", "l"][k];
/* encoding for arcTypes l/b = little/big */
}
this.size();
this.lines = [];
} // Hexagon.constructor
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
size() {
// coordinates of centre
this.xc = orgx + this.kx * 1.5 * radius;
this.yc = orgy + this.ky * radius * rac3;
if (this.kx & 1) this.yc -= radius * rac3s2; // odd columns, centre is a bit higher
this.vertices = new Array(6).fill(0).map((v, k) => ({
x: this.xc + radius * mcos((k - 2) * mPI / 3),
y: this.yc + radius * msin((k - 2) * mPI / 3) }));
this.vertices[6] = this.vertices[0]; // makes things easier by avoiding many "% 6" in calculating other calculations
this.middle = new Array(6).
fill(0).
map((p, k) => lerp(this.vertices[k], this.vertices[k + 1], 0.5));
this.extCenters = new Array(6).fill(0).map((v, k) => ({
x: this.xc + rac3 * radius * mcos(k * mPI / 3 - mPIS2),
y: this.yc + rac3 * radius * msin(k * mPI / 3 - mPIS2) }));
} // Hexagon.prototype.size
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
drawLittleArc(kCenter) {
ctx.beginPath();
ctx.arc(
this.vertices[kCenter].x,
this.vertices[kCenter].y,
radius / 2,
kCenter * mPI / 3,
(kCenter + 2) * mPIS3);
ctx.stroke();
}
drawBigArc(kCenter) {
ctx.beginPath();
ctx.arc(
this.extCenters[kCenter].x,
this.extCenters[kCenter].y,
1.5 * radius,
(kCenter + 1) * mPI / 3,
(kCenter + 2) * mPIS3);
ctx.stroke();
}
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
drawArcs() {
let c, radius, a0, a1, ccw;
ctx.lineWidth = 2;
ctx.strokeStyle = "#fff";
for (let k = 0; k < 6; ++k) {
if ((k - this.rot + 6) % 6 == 5) continue;
({ c, radius, a0, a1, ccw } = this.getArcElements(k));
ctx.beginPath();
ctx.arc(c.x, c.y, radius, a0, a1, ccw);
ctx.stroke();
}
} //Hexagon.prototype.drawArcs
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
getArcElements(kEntry) {
// arcs are defined starting from kEntry
// returns (center, radius, a0,a1, ccw)
switch ((kEntry + 6 - this.rot) % 6) {
case 0:
return {
c: this.vertices[this.rot],
radius: 0.5 * radius,
a0: this.rot * mPIS3,
.........完整代码请登录后点击上方下载按钮下载查看
网友评论0