Toggle navigation
在线编辑器
在线代码
文本比较
jQuery下载
前端库
在线手册
登录/注册
下载代码
html
css
js
分享到微信朋友圈
X
html
css
body { font-family: Arial, Helvetica, "Liberation Sans", FreeSans, sans-serif; background-color: #000; margin:0; padding:0; border-width:0; cursor: pointer; }
JavaScript
"use strict"; window.addEventListener("load",function() { const sqWidthMin = 5; // length of square side 5..sqWidthMax const sqWidthMax = 10; // length of square side sqWidthMin..50 const DHUE = 2; // integer 1-10 - hue change by step const DLUM = 1; // 0.1 - 5 - lightness change by step const SPEED = 2; // 0 to 100 let canv, ctx; // canvas and context let maxx, maxy; // canvas dimensions let sqWidth, sqRad; // square side length, quarter of circle radius (1/2 sqWidth) let grid; let nbx, nby; let hnbx, hnby; // number of squares in the half of the width, height of the canvas let groups; let listReachable; // for animation let events; let colorMode; // 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 randomElement(array) { return array[intAlea(0, array.length)]; } // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - function arrayShuffle (array) { /* randomly changes the order of items in an array only the order is modified, not the elements */ let k1, temp; for (let k = array.length - 1; k >= 1; --k) { k1 = intAlea(0, k + 1); temp = array[k]; array[k] = array[k1]; array[k1] = temp; } // for k return array } // arrayShuffle //------------------------------------------------------------------------ function Square (kx, ky, color) { /* constructor */ this.color = color ? color : `hsl(${intAlea(360)},100%,50%)`; this.kx = kx; this.ky = ky; this.kxc = kx - hnbx; this.kyc = ky - hnby; this.xc = maxx / 2 + this.kxc * sqWidth; // center of square this.yc = maxy / 2 + this.kyc * sqWidth; } // Square // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Square.prototype.lineFromTo = function (sd1, sd2) { /* DOES DRAW lines in this.Square draws required symmetrical lines if cell on symmetry axis */ const hSide = sqWidth / 2; ctx.strokeStyle = `hsl(${this.evolColor.hue}, 100%,${this.evolColor.lum}% )`; ctx.lineWidth = 1.5; // this.evolColor.width; if ((sd1 ^ sd2) == 2) { // opposite edges : draw a straight line if (mabs(this.kxc) != mabs(this.kyc)) { // if not on 45° axis ctx.beginPath(); ctx.moveTo (this.xc + [0,1,0,-1][sd1] * hSide, this.yc + [-1,0,1,0][sd1] * hSide); ctx.lineTo (this.xc + [0,1,0,-1][sd2] * hSide, this.yc + [-1,0,1,0][sd2] * hSide); ctx.stroke(); } else { // /* if (this.kxc == this.kyc) { // drawQuarter(this, 0); // drawQuarter(this, 2); } else { // drawQuarter(this, 1); // drawQuarter(this, 3); } */ } return; } // quarter of circle // re-arrange sd1 - sd2 for 'good' order if ((sd1 + 1) % 4 != sd2) [sd1, sd2] = [sd2, sd1]; // turn positively sd2 -> sd1 drawQuarter(this, sd2); if (this.kyc == 0) drawQuarter(this,[3,2,1,0] [sd2]); // symm with respect to horiz axis if (this.kxc == 0) drawQuarter(this,[1,0,3,2] [sd2]); // symm with respect to vert axis if (this.kxc == this.kyc) { // symm around 1st bisector if (sd2 == 1) drawQuarter(this,3); else if (sd2 == 3) drawQuarter(this,1); } if (this.kxc == -this.kyc) { // symm around 1st bisector if (sd2 == 0) drawQuarter(this,2); else if (sd2 == 2) drawQuarter(this,0); } function drawQuarter (cell, sd) { // turns clockwise around corner sd ctx.beginPath(); ctx.arc ( cell.xc + [-1,1,1,-1][sd] * hSide, cell.yc + [-1,-1,1,1][sd] * hSide, hSide, sd * mPIS2, (sd + 1) * mPIS2); ctx.stroke(); } } // Square.prototype.lineFromTo // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Square.prototype.fillSquare = function () { /* DOES NOT (no longer) fill this Square but draws an arc or segment in the previous one */ let prevCell, sdTo; this.drawn = true; if (this.sd === undefined) return ; // no previous cell ! if (this.neighbours[this.sd] === undefined ) return; // no previous cell ! prevCell = this.neighbours[this.sd]; // drawing will occur in prevCell sdTo = this.sd ^ 2; // this.sd as seen from the other side if (prevCell.sd === undefined) return; // prevCell.lineFromTo (prevCell.sd, sdTo); // if 'this' is on an axis, draw with the symmetrical sd too if ((this.kxc == 0 && (this.sd == 3 || this.sd == 1)) || (this.kyc == 0 && (this.sd == 0 || this.sd == 2)) ) { prevCell = this.neighbours[this.sd ^ 2]; // drawing will occur in prevCell sdTo = this.sd; if (prevCell.sd === undefined) return; // prevCell.lineFromTo (prevCell.sd, sdTo); } if (this.kxc == this.kyc) { prevCell = this.neighbours[[3,2,1,0][this.sd]]; // drawing will occur in prevCell sdTo = [1,0,3,2][this.sd]; // this.sd as seen from the other side if (prevCell.sd === undefined) return; // prevCell.lineFromTo (prevCell.sd, sdTo); } if (this.kxc == -this.kyc) { prevCell = this.neighbours[[1,0,3,2][this.sd]]; // drawing will occur in prevCell sdTo = [3,2,1,0][this.sd]; // this.sd as seen from the other side if (prevCell.sd === undefined) return; // prevCell.lineFromTo (prevCell.sd, sdTo); } } // Square.prototype.fillSquare //------------------------------------------------------------------------ function nextColor(evolColor) { let hue = evolColor.hue; let dhue = evolColor.dhue; let lum = evolColor.lum; let dlum = evolColor.dlum; let width = evolColor.width; let dWidth = evolColor.dWidth; let color; switch (colorMode) { case 0: color = `hsl(${hue},100%,50%)`; hue = (hue + dhue) % 360; break; case 1: color = `hsl(${hue},100%,${lum}%)`; lum += dlum; if (lum > 80) dlum = -mabs(dlum); if (lum < 40) dlum = mabs(dlum); break; case 2: color = `hsl(${hue},100%,${lum}%)`; lum += dlum; if (lum > 80) dlum = -mabs(dlum); if (lum < 40) dlum = mabs(dlum); hue = (hue + dhue) % 360; break; } // switch width += dWidth; if (width > 2.5) dWidth = -mabs(dWidth); if (width < 0.5) dWidth = mabs(dWidth); return {hue: hue, dhue: dhue, lum: lum, dlum: dlum, width: width, dWidth: dWidth, color: color}; } // returnColor //------------------------------------------------------------------------ let animate; { // scope for animate let animState = 0; let listReachable; let currCell, evolColor; animate = function(tStamp) { let tinit; let event; let neighGroups; let nextCell; let refPair, sd; let kx, ky, kxc, kyc; event = events.pop(); if (event && event.event == 'reset') animState = 0; if (event && event.event == 'click') animState = 0; window.requestAnimationFrame(animate) tinit = performance.now(); do { switch (animState) { case 0 : if (startOver()) { ++animState; evolColor = {}; evolColor.hue = intAlea(360); evolColor.dhue = intAlea(2) ? DHUE : (360 - DHUE); evolColor.lum = intAlea(40,80); evolColor.dlum = intAlea(2) ? -DLUM : DLUM; evolColor.width = alea(0.5, 2.5); evolColor.dWidth = 0.1; evolColor = nextColor(evolColor); } break; case 1: currCell = grid[hnby][hnbx]; currCell.evolColor = evolColor; listReachable = [currCell]; ++animState; case 2 : if (listReachable.length == 0) { animState += 10; // finished ! break; } currCell = listReachable.shift(); if (currCell.drawn) break; // already drawn evolColor = currCell.evolColor; ++animState; break; case 3 : currCell.group.forEach (cell => cell.fillSquare(evolColor)); // make list of all neighbour groups neighGroups = new Set(); currCell.group.forEach (cell => { cell.neighbours.forEach (neighCell => { if (! neighCell.drawn) // keep only unvisited cells; neighGroups.add(neighCell.group); }); // cell.neighbours.forEach }); // currCell.group.forEach if (neighGroups.size == 0){ // no neighbours available --animState; // go back and fetch in listReachable break; } // put those groups in a random order neighGroups = arrayShuffle([...neighGroups]); // change into Array evolColor = nextColor(evolColor); // attribute new color to all neighbours (all cells of all neighbour groups) neighGroups.forEach(group => { refPair = {}; group.forEach(cell => { cell.evolColor = evolColor; /* find a pair of neighbour cells, one belonging to currCell.group, and the other to group */ if (!refPair.from) { // only need one pair currCell.group.forEach(grpCell => { if (refPair.from) return; sd = cell.neighbours.indexOf(grpCell); if (sd != -1) { refPair.from = grpCell; refPair.to = cell; refPair.sd = sd; } }); // curCell.group.forEach } // if (!refPair.from) }); // group.forEach // based on refPair, assign a 'from' side to all cells of this group // ref cell refPair.to.sd = sd; kxc = refPair.to.kxc; kyc = refPair.to.kyc; kx = refPair.to.kx; ky = refPair.to.ky; // im1 kx = hnbx - kxc; ky = refPair.to.ky; grid[ky][kx].sd = [0,3,2,1][sd]; // im2 kx = refPair.to.kx; ky = hnby - kyc; grid[ky][kx].sd = [2,1,0,3][sd]; // im3 kx = hnbx - kxc; ky = hnby - kyc; grid[ky][kx].sd = [2,3,0,1][sd]; // im4 kx = hnbx + kyc; ky = hnby + kxc; if (ky >= 0 && ky < nby && kx >= 0 && kx < nbx) { grid[ky][kx].sd = [3,2,1,0][sd]; } // im5 kx = hnbx - kyc; ky = hnby + kxc; if (ky >= 0 && ky < nby && kx >= 0 && kx < nbx) { grid[ky][kx].sd = [1,2,3,0][sd]; } // im6 kx = hnbx + kyc; ky = hnby - kxc; if (ky >= 0 && ky < nby && kx >= 0 && kx < nbx) { grid[ky][kx].sd = [3,0,1,2][sd]; } // im7 kx = hnbx - kyc; ky = hnby - kxc; if (ky >= 0 && ky < nby && kx >= 0 && kx < nbx) { grid[ky][kx].sd = [1,0,3,2][sd]; } }); // neighGroups.forEach for (let k = 1; k < neighGroups.length; ++k) { listReachable.push([...(neighGroups[k])][0]); // push 1 cell of every group - but first } nextCell = [...(neighGroups[0])][0]; // 1st cell of 1st group is next current cell currCell = nextCell; break; } // switch } while ((animState == 2 || animState == 3) && (performance.now() - tinit < SPEED)); } // animate } // scope for animate //------------------------------------------------------------------------ function createGrid() { let kx1, ky1, cell; grid = []; for (let ky = 0; ky < nby; ++ky) { grid[ky] = []; for (let kx = 0; kx < nbx; ++kx) { grid[ky][kx] = new Square (kx, ky); } // for kx } // for ky // calculate neighbours for (let ky = 0; ky < nby; ++ky) { for (let kx = 0; kx < nbx; ++kx) { cell = grid[ky][kx]; cell.neighbours = []; ky1 = ky - 1; // neighbour side 0 if (ky1 >= 0) cell.neighbours[0] = grid[ky1][kx]; kx1 = kx + 1; // neighbour side 1 if (kx1 < nbx ) cell.neighbours[1] = grid[ky][kx1]; ky1 = ky + 1; // neighbour side 2 if (ky1 < nby) cell.neighbours[2] = grid[ky1][kx]; kx1 = kx - 1; // neighbour side 3 if (kx1 >= 0) cell.neighbours[3] = grid[ky][kx1]; }; // for kx }; // for ky // create groups for (let ky = 0; ky < nby; ++ky) { for (let kx = 0; kx < nbx; ++kx) { cell = grid[ky][kx]; if (cell.group) continue; cell.group = new Set([cell]); // myself addToGroup (cell.group, hnbx - cell.kxc, cell.ky); addToGroup (cell.group, cell.kx, hnby - cell.kyc); addToGroup (cell.group, hnbx - cell.kxc, hnby - cell.kyc); addToGroup (cell.group, hnbx + cell.kyc, hnby + cell.kxc); addToGroup (cell.group, hnbx + cell.kyc, hnby - cell.kxc); addToGroup (cell.group, hnbx - cell.kyc, hnby + cell.kxc); addToGroup (cell.group, hnbx - cell.kyc, hnby - cell.kxc); }; // for kx }; // for ky } // createGrid //------------------------------------------------------------------------ function addToGroup (group, kx, ky) { if (kx < 0 || ky < 0 || kx >= nbx || ky >= nby) return; // out of grid, do not add group.add(grid[ky][kx]); grid[ky][kx].group = group; } // addToGroup //------------------------------------------------------------------------ function nextColor(evolColor) { let hue = evolColor.hue; let dhue = evolColor.dhue; let lum = evolColor.lum; let dlum = evolColor.dlum; let width = evolColor.width; let dWidth = evolColor.dWidth; let color; switch (colorMode) { case 0: color = `hsl(${hue},100%,50%)`; hue = (hue + dhue) % 360; lum = 50; break; case 1: color = `hsl(${hue},100%,${lum}%)`; lum += dlum; if (lum > 80) dlum = -mabs(dlum); if (lum < 20) dlum = mabs(dlum); break; case 2: color = `hsl(${hue},100%,${lum}%)`; lum += dlum; if (lum > 80) dlum = -mabs(dlum); if (lum < 40) dlum = mabs(dlum); hue = (hue + dhue) % 360; break; } // switch width += dWidth; if (width > 2.5) dWidth = -mabs(dWidth); if (width < 0.5) dWidth = mabs(dWidth); return {hue: hue, dhue: dhue, lum: lum, dlum: dlum, width: width, dWidth: dWidth, color: color}; } // returnColor //------------------------------------------------------------------------ function startOver() { // canvas dimensions maxx = window.innerWidth; maxy = window.innerHeight; canv.width = maxx; canv.height = maxy; ctx.lineJoin = 'bevel'; ctx.lineCap = 'round'; sqWidth = alea(sqWidthMin, sqWidthMax); sqRad = sqWidth / 2; hnby = mfloor (maxy / sqWidth / 2); // the full array has 2 * hnbx + 1 rows hnbx = mfloor (maxx / sqWidth / 2); nbx = 1 + 2 * hnbx; nby = 1 + 2 * hnby; if (nbx < 3 || nby < 3) return false; ctx.clearRect(0,0,maxx,maxy); colorMode = intAlea(3); createGrid(); return true; } // startOver //------------------------------------------------------------------------ function mouseClick (event) { events.push({event:'click'});; } // mouseMove //------------------------------------------------------------------------ //------------------------------------------------------------------------ // beginning of execution { canv = document.createElement('canvas'); canv.style.position="absolute"; document.body.appendChild(canv); ctx = canv.getContext('2d'); canv.setAttribute ('title','click me'); } // création CANVAS canv.addEventListener('click',mouseClick); // just for initial position events = [{event:'reset'}]; requestAnimationFrame (animate); }); // window load listener
粒子
时间
文字
hover
canvas
3d
游戏
音乐
火焰
水波
轮播图
鼠标跟随
动画
css
加载动画
导航
菜单
按钮
滑块
tab
弹出层
统计图
svg
×
Close
在线代码下载提示
开通在线代码永久免费下载,需支付20jQ币
开通后,在线代码模块中所有代码可终身免费下!
您已开通在线代码永久免费下载,关闭提示框后,点下载代码可直接下载!
您已经开通过在线代码永久免费下载
对不起,您的jQ币不足!可通过发布资源 或
直接充值获取jQ币
取消
开通下载
<!doctype html> <html> <head> <meta charset="utf-8"> <title>canvas刺绣4-jq22.com</title> <script src="https://www.jq22.com/jquery/jquery-1.10.2.js"></script> <style>
</style> </head> <body>
<script>
</script>
</body> </html>
2012-2021 jQuery插件库版权所有
jquery插件
|
jq22工具库
|
网页技术
|
广告合作
|
在线反馈
|
版权声明
沪ICP备13043785号-1
浙公网安备 33041102000314号