main.js 19 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577
  1. $(function () {
  2. // 初始化界面
  3. function init() {
  4. placeholderPic()
  5. sd1('.sd1')
  6. sd1('.sd2')
  7. sd2('.sd3')
  8. sd2('.sd4')
  9. jz()
  10. animate()
  11. }
  12. init()
  13. // 自定义字体大小
  14. function placeholderPic() {
  15. w = document.documentElement.clientWidth / 80;
  16. document.documentElement.style.fontSize = w + 'px';
  17. }
  18. // 闪电一,二
  19. function sd1(ele) {
  20. var width, height
  21. var step = 0;
  22. var canvas = document.createElement('canvas')
  23. var ctx = canvas.getContext('2d')
  24. var bg = [4, 10, 11]
  25. document.querySelector(ele).appendChild(canvas)
  26. setTimeout(() => {
  27. var timeID = setInterval(() => {
  28. pt1.x += 10;
  29. if (pt1.x > width - 10) {
  30. clearInterval(timeID)
  31. }
  32. }, 60);
  33. }, 1000)
  34. var pt1
  35. var pt2
  36. window.addEventListener('resize', setup)
  37. setup()
  38. function setup() {
  39. canvas.width = width = document.querySelector(ele).clientWidth
  40. canvas.height = height = document.querySelector(ele).clientHeight
  41. ctx.beginPath();
  42. ctx.rect(0, 0, width, height)
  43. ctx.fillStyle = `rgba(${bg[0]}, ${bg[1]}, ${bg[2]}, ${1})`
  44. ctx.fill()
  45. pt1 = { x: -20, y: height / 2 }//闪电起点
  46. pt2 = { x: -20, y: height / 2 } //闪电终点
  47. // draw()
  48. }
  49. setInterval(animate, 60)
  50. // window.requestAnimationFrame(animate);
  51. function blur(ctx, canvas, amt) {
  52. ctx.filter = `blur(${amt}px)`
  53. ctx.drawImage(canvas, 0, 0)
  54. ctx.filter = 'none'
  55. }
  56. function fade(ctx, amt, width, height) {
  57. ctx.beginPath();
  58. ctx.rect(0, 0, width, height)
  59. ctx.fillStyle = `rgba(${bg[0]}, ${bg[1]}, ${bg[2]}, ${amt})`
  60. ctx.fill()
  61. }
  62. function animate() {
  63. step++
  64. blur(ctx, canvas, 1)
  65. draw()
  66. fade(ctx, 0.1, width, height)
  67. // window.requestAnimationFrame(function(){animate()})
  68. }
  69. function draw() {
  70. var iterations = [pt1, pt2]
  71. var newiterations, i, j
  72. for (i = 0; i < 8; i++) {
  73. newiterations = [iterations[0]]
  74. for (j = 1; j < iterations.length; j++) {
  75. newiterations.push(getRandMidpoint(iterations[j - 1], iterations[j], 200 / (i * i + 1)))
  76. newiterations.push(iterations[j])
  77. }
  78. iterations = newiterations.concat([])
  79. }
  80. ctx.beginPath();
  81. ctx.moveTo(iterations[0].x, iterations[0].y);
  82. ctx.lineWidth = 2;
  83. ctx.strokeStyle = '#04e4c9';
  84. // ctx.strokeStyle = `hsla(${Math.sin( step / 30) * 120 + 50},${90}%,${70}%,1)`
  85. for (i = 1; i < iterations.length; i++) {
  86. ctx.lineTo(iterations[i].x, iterations[i].y);
  87. }
  88. ctx.stroke()
  89. ctx.closePath()
  90. }
  91. function getRandMidpoint(pa, pb, range) {
  92. var a = Math.atan2(pb.y - pa.y, pb.x - pa.x) + Math.PI / 2
  93. var half = { y: (pb.y - pa.y) / 2 + pa.y, x: (pb.x - pa.x) / 2 + pa.x }
  94. var offset = Math.random() * range / 3 - range / 6 //这里控制闪电的抖动幅度
  95. var ho = {
  96. x: Math.cos(a) * offset + half.x,
  97. y: Math.sin(a) * offset + half.y
  98. }
  99. return ho
  100. }
  101. }
  102. //
  103. //
  104. //
  105. // 闪电三,四
  106. function sd2(ele) {
  107. var width, height
  108. var step = 0;
  109. var canvas = document.createElement('canvas')
  110. var ctx = canvas.getContext('2d')
  111. var bg = [4, 10, 11]
  112. document.querySelector(ele).appendChild(canvas)
  113. setTimeout(() => {
  114. var timeID = setInterval(() => {
  115. pt1.x -= 10;
  116. if (pt1.x < 10) {
  117. clearInterval(timeID)
  118. }
  119. }, 60);
  120. }, 1000)
  121. var pt1
  122. var pt2
  123. window.addEventListener('resize', setup)
  124. setup()
  125. function setup() {
  126. canvas.width = width = document.querySelector(ele).clientWidth
  127. canvas.height = height = document.querySelector(ele).clientHeight
  128. ctx.beginPath();
  129. ctx.rect(0, 0, width, height)
  130. ctx.fillStyle = `rgba(${bg[0]}, ${bg[1]}, ${bg[2]}, ${1})`
  131. ctx.fill()
  132. pt1 = { x: width + 20, y: height / 2 }//闪电起点
  133. pt2 = { x: width + 20, y: height / 2 } //闪电终点
  134. // draw()
  135. }
  136. setInterval(animate, 60)
  137. // window.requestAnimationFrame(animate);
  138. function blur(ctx, canvas, amt) {
  139. ctx.filter = `blur(${amt}px)`
  140. ctx.drawImage(canvas, 0, 0)
  141. ctx.filter = 'none'
  142. }
  143. function fade(ctx, amt, width, height) {
  144. ctx.beginPath();
  145. ctx.rect(0, 0, width, height)
  146. ctx.fillStyle = `rgba(${bg[0]}, ${bg[1]}, ${bg[2]}, ${amt})`
  147. ctx.fill()
  148. }
  149. function animate() {
  150. step++
  151. blur(ctx, canvas, 1)
  152. draw()
  153. fade(ctx, 0.1, width, height)
  154. // window.requestAnimationFrame(function(){animate()})
  155. }
  156. function draw() {
  157. var iterations = [pt1, pt2]
  158. var newiterations, i, j
  159. for (i = 0; i < 8; i++) {
  160. newiterations = [iterations[0]]
  161. for (j = 1; j < iterations.length; j++) {
  162. newiterations.push(getRandMidpoint(iterations[j - 1], iterations[j], 200 / (i * i + 1)))
  163. newiterations.push(iterations[j])
  164. }
  165. iterations = newiterations.concat([])
  166. }
  167. ctx.beginPath();
  168. ctx.moveTo(iterations[0].x, iterations[0].y);
  169. ctx.lineWidth = 2;
  170. ctx.strokeStyle = '#04e4c9';
  171. // ctx.strokeStyle = `hsla(${Math.sin( step / 30) * 120 + 50},${90}%,${70}%,1)`
  172. for (i = 1; i < iterations.length; i++) {
  173. ctx.lineTo(iterations[i].x, iterations[i].y);
  174. }
  175. ctx.stroke()
  176. ctx.closePath()
  177. }
  178. function getRandMidpoint(pa, pb, range) {
  179. var a = Math.atan2(pb.y - pa.y, pb.x - pa.x) + Math.PI / 2
  180. var half = { y: (pb.y - pa.y) / 2 + pa.y, x: (pb.x - pa.x) / 2 + pa.x }
  181. var offset = Math.random() * range / 3 - range / 6 //这里控制闪电的抖动幅度
  182. var ho = {
  183. x: Math.cos(a) * offset + half.x,
  184. y: Math.sin(a) * offset + half.y
  185. }
  186. return ho
  187. }
  188. }
  189. // 加载动画
  190. function jz() {
  191. $('.jz1 ul li').each((index, item) => {
  192. item.style.opacity = 1 - index / 10;
  193. })
  194. setInterval(() => {
  195. $('.jz1 ul li').each((index, item) => {
  196. if (item.style.opacity == 0) {
  197. item.style.opacity = 1
  198. }
  199. item.style.opacity = parseFloat(item.style.opacity) - 0.1
  200. })
  201. }, 100)
  202. $('.jz2 ul li').each((index, item) => {
  203. item.style.opacity = 1 - index / 10;
  204. })
  205. setInterval(() => {
  206. $('.jz2 ul li').each((index, item) => {
  207. if (item.style.opacity == 0) {
  208. item.style.opacity = 1
  209. }
  210. item.style.opacity = parseFloat(item.style.opacity) - 0.1
  211. })
  212. }, 100)
  213. }
  214. // 中间背景动画
  215. function animate() {
  216. var App = {};
  217. App.setup = function () {
  218. // 创建canvas元素,并加入body中
  219. var canvas = document.createElement('canvas');
  220. this.filename = "spipa";
  221. // 控制canvas幕布的大小
  222. canvas.width = document.querySelector('.animate').clientWidth;
  223. canvas.height = document.querySelector('.animate').clientHeight;
  224. this.canvas = canvas;
  225. document.querySelector('.animate').appendChild(canvas);
  226. this.ctx = this.canvas.getContext('2d');
  227. this.width = this.canvas.width;
  228. this.height = this.canvas.height;
  229. this.dataToImageRatio = 1;
  230. this.ctx.imageSmoothingEnabled = false;
  231. this.ctx.webkitImageSmoothingEnabled = false;
  232. this.ctx.msImageSmoothingEnabled = false;
  233. this.xC = this.width / 2;
  234. this.yC = this.height / 2;
  235. this.stepCount = 0;
  236. this.particles = [];
  237. this.lifespan = 1000;
  238. this.popPerBirth = 1;
  239. this.maxPop = 200;
  240. this.birthFreq = 5;
  241. // Build grid
  242. this.gridSize = 8;// 运动坐标
  243. this.gridSteps = Math.floor(1000 / this.gridSize);
  244. this.grid = [];
  245. var i = 0;
  246. for (var xx = -500; xx < 500; xx += this.gridSize) {
  247. for (var yy = -500; yy < 500; yy += this.gridSize) {
  248. // 径向场,r的三角函数,最大值在r0附近
  249. var r = Math.abs(xx) + Math.abs(yy),//Math.sqrt(xx*xx+yy*yy),
  250. r0 = 3*w, //中间方形的大小
  251. field;
  252. if (r < r0) field = 255 / r0 * r;
  253. else if (r > r0) field = 255 - Math.min(255, (r - r0) / 2);
  254. this.grid.push({
  255. x: xx,
  256. y: yy,
  257. busyAge: 0,
  258. spotIndex: i,
  259. isEdge: (xx == -500 ? 'left' :
  260. (xx == (-500 + this.gridSize * (this.gridSteps - 1)) ? 'right' :
  261. (yy == -500 ? 'top' :
  262. (yy == (-500 + this.gridSize * (this.gridSteps - 1)) ? 'bottom' :
  263. false
  264. )
  265. )
  266. )
  267. ),
  268. field: field
  269. });
  270. i++;
  271. }
  272. }
  273. this.gridMaxIndex = i;
  274. this.initDraw();
  275. };
  276. App.evolve = function () {
  277. var time1 = performance.now();
  278. this.stepCount++;
  279. // Increment all grid ages
  280. this.grid.forEach(function (e) {
  281. if (e.busyAge > 0) e.busyAge++;
  282. });
  283. if (this.stepCount % this.birthFreq == 0 && (this.particles.length + this.popPerBirth) < this.maxPop) {
  284. this.birth();
  285. }
  286. App.move();
  287. App.draw();
  288. var time2 = performance.now();
  289. };
  290. App.birth = function () {
  291. var x, y;
  292. var gridSpotIndex = Math.floor(Math.random() * this.gridMaxIndex),
  293. gridSpot = this.grid[gridSpotIndex],
  294. x = gridSpot.x, y = gridSpot.y;
  295. var particle = {
  296. hue: -10,// + Math.floor(50*Math.random()),
  297. sat: 95,//30 + Math.floor(70*Math.random()),
  298. lum: 20 + Math.floor(40 * Math.random()),
  299. x: x, y: y,
  300. xLast: x, yLast: y,
  301. xSpeed: 0, ySpeed: 0,
  302. age: 0,
  303. ageSinceStuck: 0,
  304. attractor: {
  305. oldIndex: gridSpotIndex,
  306. gridSpotIndex: gridSpotIndex,// Pop at random position on grid
  307. },
  308. name: 'seed-' + Math.ceil(10000000 * Math.random())
  309. };
  310. this.particles.push(particle);
  311. };
  312. App.kill = function (particleName) {
  313. var newArray = _.reject(this.particles, function (seed) {
  314. return (seed.name == particleName);
  315. });
  316. this.particles = _.cloneDeep(newArray);
  317. };
  318. App.move = function () {
  319. for (var i = 0; i < this.particles.length; i++) {
  320. // Get particle
  321. var p = this.particles[i];
  322. // Save last position
  323. p.xLast = p.x; p.yLast = p.y;
  324. // Attractor and corresponding grid spot
  325. var index = p.attractor.gridSpotIndex,
  326. gridSpot = this.grid[index];
  327. // Maybe move attractor and with certain constraints
  328. if (Math.random() < 0.5) {
  329. // Move attractor
  330. if (!gridSpot.isEdge) {
  331. // Change particle's attractor grid spot and local move function's grid spot
  332. var topIndex = index - 1,
  333. bottomIndex = index + 1,
  334. leftIndex = index - this.gridSteps,
  335. rightIndex = index + this.gridSteps,
  336. topSpot = this.grid[topIndex],
  337. bottomSpot = this.grid[bottomIndex],
  338. leftSpot = this.grid[leftIndex],
  339. rightSpot = this.grid[rightIndex];
  340. // Choose neighbour with highest field value (with some desobedience...)
  341. var chaos = 30;
  342. var maxFieldSpot = _.maxBy([topSpot, bottomSpot, leftSpot, rightSpot], function (e) {
  343. return e.field + chaos * Math.random()
  344. });
  345. var potentialNewGridSpot = maxFieldSpot;
  346. if (potentialNewGridSpot.busyAge == 0 || potentialNewGridSpot.busyAge > 15) {// Allow wall fading
  347. //if (potentialNewGridSpot.busyAge == 0) {// Spots busy forever
  348. // Ok it's free let's go there
  349. p.ageSinceStuck = 0;// Not stuck anymore yay
  350. p.attractor.oldIndex = index;
  351. p.attractor.gridSpotIndex = potentialNewGridSpot.spotIndex;
  352. gridSpot = potentialNewGridSpot;
  353. gridSpot.busyAge = 1;
  354. } else p.ageSinceStuck++;
  355. } else p.ageSinceStuck++;
  356. if (p.ageSinceStuck == 10) this.kill(p.name);
  357. }
  358. // Spring attractor to center with viscosity
  359. var k = 8, visc = 0.4;
  360. var dx = p.x - gridSpot.x,
  361. dy = p.y - gridSpot.y,
  362. dist = Math.sqrt(dx * dx + dy * dy);
  363. // Spring
  364. var xAcc = -k * dx,
  365. yAcc = -k * dy;
  366. p.xSpeed += xAcc; p.ySpeed += yAcc;
  367. // Calm the f*ck down
  368. p.xSpeed *= visc; p.ySpeed *= visc;
  369. // Store stuff in particle brain
  370. p.speed = Math.sqrt(p.xSpeed * p.xSpeed + p.ySpeed * p.ySpeed);
  371. p.dist = dist;
  372. // Update position
  373. p.x += 0.1 * p.xSpeed; p.y += 0.1 * p.ySpeed;
  374. // Get older
  375. p.age++;
  376. // Kill if too old
  377. if (p.age > this.lifespan) {
  378. this.kill(p.name);
  379. this.deathCount++;
  380. }
  381. }
  382. };
  383. App.initDraw = function () {
  384. this.ctx.beginPath();
  385. this.ctx.rect(0, 0, this.width, this.height);
  386. this.ctx.fillStyle = 'transparent';
  387. this.ctx.fill();
  388. this.ctx.closePath();
  389. };
  390. App.draw = function () {
  391. this.drawnInLastFrame = 0;
  392. if (!this.particles.length) return false;
  393. this.ctx.beginPath();
  394. this.ctx.rect(0, 0, this.width, this.height);
  395. // this.ctx.fillStyle = 'transparent';
  396. this.ctx.fillStyle = 'rgba(12, 22, 25, 0.1)';
  397. this.ctx.fill();
  398. this.ctx.closePath();
  399. for (var i = 0; i < this.particles.length; i++) {
  400. // Draw particle
  401. var p = this.particles[i];
  402. var h, s, l, a;
  403. h = p.hue + this.stepCount / 30;
  404. s = p.sat;
  405. l = p.lum;
  406. a = 1;
  407. var last = this.dataXYtoCanvasXY(p.xLast, p.yLast),
  408. now = this.dataXYtoCanvasXY(p.x, p.y);
  409. var attracSpot = this.grid[p.attractor.gridSpotIndex],
  410. attracXY = this.dataXYtoCanvasXY(attracSpot.x, attracSpot.y);
  411. var oldAttracSpot = this.grid[p.attractor.oldIndex],
  412. oldAttracXY = this.dataXYtoCanvasXY(oldAttracSpot.x, oldAttracSpot.y);
  413. this.ctx.beginPath();
  414. this.ctx.strokeStyle = 'green';
  415. this.ctx.fillStyle = 'hsla(' + h + ', ' + s + '%, ' + l + '%, ' + a + ')';
  416. // Particle trail
  417. this.ctx.moveTo(last.x, last.y);
  418. this.ctx.lineTo(now.x, now.y);
  419. this.ctx.lineWidth = 1.5 * this.dataToImageRatio;
  420. this.ctx.stroke();
  421. this.ctx.closePath();
  422. // Attractor positions
  423. this.ctx.beginPath();
  424. this.ctx.lineWidth = 1.5 * this.dataToImageRatio;
  425. this.ctx.moveTo(oldAttracXY.x, oldAttracXY.y);
  426. this.ctx.lineTo(attracXY.x, attracXY.y);
  427. this.ctx.arc(attracXY.x, attracXY.y, 1.5 * this.dataToImageRatio, 0, 2 * Math.PI, false);
  428. //a /= 20;
  429. this.ctx.strokeStyle = 'green';
  430. this.ctx.fillStyle = 'green';
  431. //this.ctx.stroke();
  432. this.ctx.fill();
  433. this.ctx.closePath();
  434. // UI counter
  435. this.drawnInLastFrame++;
  436. }
  437. };
  438. App.dataXYtoCanvasXY = function (x, y) {
  439. var zoom = 1.6;
  440. var xx = this.xC + x * zoom * this.dataToImageRatio,
  441. yy = this.yC + y * zoom * this.dataToImageRatio;
  442. return { x: xx, y: yy };
  443. };
  444. setTimeout(function(){
  445. console.log(1123)
  446. App.setup();
  447. App.draw();
  448. var frame = function () {
  449. App.evolve();
  450. requestAnimationFrame(frame);
  451. };
  452. frame();
  453. },5000)
  454. /**
  455. * Some old util I use at times
  456. *
  457. * @param {Number} Xstart X value of the segment starting point
  458. * @param {Number} Ystart Y value of the segment starting point
  459. * @param {Number} Xtarget X value of the segment target point
  460. * @param {Number} Ytarget Y value of the segment target point
  461. * @param {Boolean} realOrWeb true if Real (Y towards top), false if Web (Y towards bottom)
  462. * @returns {Number} Angle between 0 and 2PI
  463. */
  464. segmentAngleRad = function (Xstart, Ystart, Xtarget, Ytarget, realOrWeb) {
  465. var result;// Will range between 0 and 2PI
  466. if (Xstart == Xtarget) {
  467. if (Ystart == Ytarget) {
  468. result = 0;
  469. } else if (Ystart < Ytarget) {
  470. result = Math.PI / 2;
  471. } else if (Ystart > Ytarget) {
  472. result = 3 * Math.PI / 2;
  473. } else { }
  474. } else if (Xstart < Xtarget) {
  475. result = Math.atan((Ytarget - Ystart) / (Xtarget - Xstart));
  476. } else if (Xstart > Xtarget) {
  477. result = Math.PI + Math.atan((Ytarget - Ystart) / (Xtarget - Xstart));
  478. }
  479. result = (result + 2 * Math.PI) % (2 * Math.PI);
  480. if (!realOrWeb) {
  481. result = 2 * Math.PI - result;
  482. }
  483. return result;
  484. }
  485. }
  486. })