• html--全魔乱舞


    DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN">
    <HTML>
     <HEAD>
      <TITLE> New Document TITLE>
      <META NAME="Generator" CONTENT="EditPlus">
      <META NAME="Author" CONTENT="">
      <META NAME="Keywords" CONTENT="">
      <META NAME="Description" CONTENT="">
      <style>html, body {
    	overflow: hidden;
    	touch-action: none;
    	content-zooming: none;
    	position: absolute;
    	margin: 0;
    	padding: 0;
    	width: 100%;
    	height: 100%;
    	background: #000;
    }
    
    #screen {
    	position: absolute;
    	width: 100vh;
    	height: 100vh;
    	max-height: 100vw;
    	max-width: 100vw;
    	margin: auto;
    	top: 0;
    	bottom: 0;
    	left: 0;
    	right: 0;
    	user-select: none;
    }
    #screen canvas {
    	position: relative;
    	float: left;
    	display: block;
    	width: 28.7vmin;
    	height: 28.7vmin;
    	background:#222;
    	margin-left: 3vmin;
    	margin-top: 3vmin;
    	border-radius: 3vmin;
    }style>
     HEAD>
    
     <BODY><div id="screen">div>
      <script>"use strict";
    {
    	const Box = class {
    		constructor(container, i) {
    			this.canvas = document.createElement("canvas");
    			container.appendChild(this.canvas);
    			this.width = this.canvas.width = this.canvas.offsetWidth;
    			this.height = this.canvas.height = this.canvas.offsetHeight;
    			this.ctx = this.canvas.getContext("2d");
    			this.ctx.lineCap = "round";
    			this.points = Array.from(
    				{ length: 12 },
    				_ => new Box.Point(this.width * 0.5, this.width * 0.5)
    			);
    			this.constraints = [];
    			this.color = `hsl(${10 * i}, 70%, 30%)`;
    			// links p1, p2, length, width
    			const links = [
    				[0, 1, 6, 5],
    				[1, 2, 5, 4],
    				[3, 7, 10, 6],
    				[7, 8, 7, 4],
    				[3, 9, 10, 6],
    				[9, 10, 7, 4],
    				[0, 4, 5, 0],
    				[0, 3, 7, 9],
    				[0, 5, 6, 5],
    				[5, 6, 5, 4],
    				[4, 11, 0.1, 11]
    			];
    			// constaints: p1, p2, p3, angle, range
    			const p2 = Math.PI / 2;
    			const p3 = Math.PI / 3;
    			[
    				[0, 4, 11, 0, 0, 0],
    				[4, 0, 3, 0, 1, 0.05],
    				[3, 0, 4, 0, 1, 0.05],
    				[3, 0, 1, p2, p2 * 4, 0],
    				[0, 1, 2, -p2, p3, 0.05],
    				[3, 0, 5, p2, p2 * 4, 0],
    				[0, 5, 6, -p2, p3, 0.05],
    				[0, 3, 7, -p3 + 0.5, p2, 0.05],
    				[0, 3, 9, -p3 + 0.5, p2, 0.05],
    				[3, 7, 8, p2, p3, 0.05],
    				[3, 9, 10, p2, p3, 0.05]
    			].forEach(p => {
    				this.constraints.push(new Box.Constraint(this, links, p, this.width / 30));
    			});
    		}
    		run() {
    			this.ctx.setTransform(0, 1, 1, 0, 0, 0);
    			this.ctx.clearRect(0, 0, this.width + 1, this.height + 1);
    			this.ctx.globalCompositeOperation = "lighter";
    			for (const constraint of this.constraints) constraint.solve();
    			for (const point of this.points) point.integrate();
    		}
    	};
    	Box.Point = class {
    		constructor(x, y) {
    			this.x = x;
    			this.y = y;
    			this.xb = x;
    			this.yb = y
    			this.w = 0;
    		}
    		integrate() {
    			const vx = (this.x - this.xb) * 0.995;
    			const vy = (this.y - this.yb) * 0.995;
    			this.xb = this.x;
    			this.yb = this.y;
    			this.x += vx;
    			this.y += vy;
    		}
    	};
    	Box.Constraint = class {
    		constructor(box, links, p, s) {
    			this.ctx = box.ctx;
    			this.p1 = box.points[p[0]];
    			this.p2 = box.points[p[1]];
    			this.p3 = box.points[p[2]];
    			this.m = 0;
    			this.angle = p[3];
    			this.range = p[4];
    			this.force = p[5];
    			const link1 = this.link(links, p[0], p[1]);
    			const link2 = this.link(links, p[1], p[2]);
    			this.len1 = link1[2] * s;
    			this.len2 = link2[2] * s;
    			this.width = link2[3] * s * 0.5;
    			if (this.width * 0.5 > this.p3.w) this.p3.w = this.width * 0.5;
    			this.shape = document.createElement("canvas");
    			if (this.width) {
    				this.shape.width = this.len2 + this.width;
    				this.shape.height = this.width;
    				const ict = this.shape.getContext("2d");
    				ict.lineCap = "round";
    				ict.strokeStyle = box.color;
    				ict.beginPath();
    				ict.lineWidth = this.width * 0.9;
    				ict.moveTo(this.width * 0.5, this.width * 0.5);
    				ict.lineTo(this.len2 + this.width * 0.5, this.width * 0.5);
    				ict.stroke();
    			}
    		}
    		link(links, p0, p1) {
    			for (const link of links) {
    				if (
    					(p0 === link[0] && p1 === link[1]) ||
    					(p1 === link[0] && p0 === link[1])
    				)
    					return link;
    			}
    		}
    		solve() {
    			const a1 = Math.atan2(this.p2.y - this.p1.y, this.p2.x - this.p1.x);
    			const b1 = Math.atan2(this.p3.y - this.p2.y, this.p3.x - this.p2.x);
    			const c = this.angle - (b1 - a1);
    			const d = c > Math.PI ? c - 2 * Math.PI : c < -Math.PI ? c + 2 * Math.PI : c;
    			const e = Math.abs(d) > this.range ? (-Math.sign(d) * this.range + d) * this.force : 0;
    			const cos1 = Math.cos(a1 - e);
    			const sin1 = Math.sin(a1 - e);
    			const x1 = this.p1.x + (this.p2.x - this.p1.x) * 0.5;
    			const y1 = this.p1.y + (this.p2.y - this.p1.y) * 0.5;
    			this.p1.x = x1 - cos1 * this.len1 * 0.5;
    			this.p1.y = y1 - sin1 * this.len1 * 0.5;
    			this.p2.x = x1 + cos1 * this.len1 * 0.5;
    			this.p2.y = y1 + sin1 * this.len1 * 0.5;
    			this.m += 0.0005 * (Math.random() - 0.5);
    			this.m *= 0.99;
    			const a2 = this.m + Math.atan2(this.p2.y - this.p3.y, this.p2.x - this.p3.x) + e;
    			const cos2 = Math.cos(a2);
    			const sin2 = Math.sin(a2);
    			const x2 = this.p3.x + (this.p2.x - this.p3.x) * 0.5;
    			const y2 = this.p3.y + (this.p2.y - this.p3.y) * 0.5;
    			this.p3.x = x2 - cos2 * this.len2 * 0.5;
    			this.p3.y = y2 - sin2 * this.len2 * 0.5;
    			this.p2.x = x2 + cos2 * this.len2 * 0.5;
    			this.p2.y = y2 + sin2 * this.len2 * 0.5;
    			if (this.width) {
    				this.ctx.setTransform(cos2, sin2, -sin2, cos2, this.p2.x, this.p2.y);
    				this.ctx.drawImage(
    					this.shape,
    					-this.len2 - this.width * 0.5,
    					-this.width * 0.5
    				);
    			}
    		}
    	};
    	const screen = document.querySelector("#screen");
    	const boxes = Array.from({ length: 9 }, (v, i) => new Box(screen, i));
    	const run = () => {
    		requestAnimationFrame(run);
    		for (const box of boxes) box.run();
    	};
    	run();
    }script>
     BODY>
    HTML>
    
    
    

    在这里插入图片描述

    在这里插入图片描述

    在这里插入图片描述

    在这里插入图片描述

    在这里插入图片描述
    在这里插入图片描述

    在这里插入图片描述

    在这里插入图片描述

    在这里插入图片描述

    在这里插入图片描述

    在这里插入图片描述
    在这里插入图片描述
    在这里插入图片描述

    在这里插入图片描述

    在这里插入图片描述

  • 相关阅读:
    leetcode做题笔记145. 二叉树的后序遍历
    除静电离子风刀的工作原理及应用
    一个SpringBoot问题就干趴下了?我却凭着这份PDF文档吊打面试官(Spring Boot知识点+详解)
    时序数据库 IoTDB 发布端边云原生解决方案,有效优化工业互联网数据上传时效与资源消耗...
    瑞格尔侯爵酒庄连续两年蝉联2022世界最佳葡萄园第二
    关于软件物料清单(SBOM),你所需要了解的一切
    qt之事件循环与线程的关系
    U9二次开发之BP定时任务插件开发
    今年最后一次PMP考试!想升职加薪抓紧!
    crm项目创建与搭建MyBatis逆向工程根据数据库生成model
  • 原文地址:https://blog.csdn.net/stqer/article/details/139316815