首页 > 其他分享 >前端 js + html + css 特效 001

前端 js + html + css 特效 001

时间:2024-12-09 23:45:04浏览次数:4  
标签:canvas ang target window pos js 001 html Math

<!DOCTYPE html>
<html lang="en" >
<head>
<title>Code The World - Electric strings</title>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<script>
    window.requestAnimFrame = (function() {
        return (
            window.requestAnimationFrame ||
            window.webkitRequestAnimationFrame ||
            window.mozRequestAnimationFrame ||
            window.oRequestAnimationFrame ||
            window.msRequestAnimationFrame ||
            function(callback) { window.setTimeout(callback); }
        );
    });

    function init(elem_id) {
        let canvas = document.getElementById(elem_id),
            c = canvas.getContext("2d"),
            w = (canvas.width = window.innerWidth),
            h = (canvas.height = window.innerHeight);
        c.fillStyle = "rgba(30,30,30,1)";
        c.fillRect(0, 0, w, h);
        return {c:c, canvas:canvas};
    }
</script>
<!-- 引入外部css文件 -->
<link rel="stylesheet" type="text/css" href="./style.css">
</head>
<body>
<canvas id="canvas"></canvas>
<!-- 引入外部JavaScript文件 -->
<script type="text/javascript" src="./script.js"></script>
</body>
</html>
body, html {
    margin: 0 px;
    padding: 0 px;
    position: fixed;
    background: rgb(30,30,30);
}
window.onload = function() {
    let c = init("canvas").c,
        canvas = init("canvas").canvas,
        w = (canvas.width = window.innerWidth),
        h = (canvas.height = window.innerHeight),
        mouse = { x: false, y: false },
        last_mouse = {};
    // initiation

    function dist(p1x, p1y, p2x, p2y) {
        return Math.sqrt(Math.pow(p2x - p1x, 2) + Math.pow(p2y - p1y, 2));
    }

    class segment {
        constructor(parent, l, a, first) {
            this.first = first;
            if (first) {
                this.pos = {
                    x: parent.x,
                    y: parent.y
                };
            } else {
                this.pos = {
                    x: parent.nextPos.x,
                    y: parent.nextPos.y
                };
            }
            this.l = l;
            this.ang = a;
            this.nextPos = {
                x: this.pos.x + this.l * Math.cos(this.ang),
                y: this.pos.y + this.l * Math.sin(this.ang)
            };
        }
        update(t) {
            this.ang = Math.atan2(t.y - this.pos.y, t.x - this.pos.x);
            this.pos.x = t.x + this.l * Math.cos(this.ang - Math.PI);
            this.pos.y = t.y + this.l * Math.sin(this.ang - Math.PI);
            this.nextPos.x = this.pos.x + this.l * Math.cos(this.ang);
            this.nextPos.y = this.pos.y + this.l * Math.sin(this.ang);
        }
        fallback(t) {
            this.pos.x = t.x;
            this.pos.y = t.y;
            this.nextPos.x = this.pos.x + this.l * Math.cos(this.ang);
            this.nextPos.y = this.pos.y + this.l * Math.sin(this.ang);
        }
        show() {
            c.lineTo(this.nextPos.x, this.nextPos.y);
        }
    }

    class tentacle {
        constructor(x, y, l, n, a) {
            this.x = x;
            this.y = y;
            this.l = l;
            this.n = n;
            this.t = {};
            this.rand = Math.random();
            this.segments = [new segment(this, this.l / this.n, 0, true)];
            for (let i = 1; i < this.n; i++) {
                this.segments.push(
                    new segment(this.segments[i - 1], this.l / this.n, 0, false)
                );
            }
        }
        move(last_target, target) {
            this.angle = Math.atan2(target.y - this.y,target.x - this.x);
            this.dt = dist(last_target.x, last_target.y, target.x, target.y) + 5;
            this.t = {
                x: target.x - 0.8 * this.dt * Math.cos(this.angle),
                y: target.y - 0.8 * this.dt * Math.sin(this.angle)
            };
            if (this.t.x) {
                this.segments[this.n - 1].update(this.t);
            } else {
                this.segments[this.n - 1].update(target);
            }
            for (let i = this.n - 2; i >= 0; i--) {
                this.segments[i].update(this.segments[i + 1].pos);
            }
            if (
                dist(this.x, this.y, target.x, target.y) <=
                this.l + dist(last_target.x, last_target.y, target.x, target.y)
            ) {
                this.segments[0].fallback({ x: this.x, y: this.y });
                for (let i = 1; i < this.n; i++) {
                    this.segments[i].fallback(this.segments[i - 1].nextPos);
                }
            }
        }
        show(target) {
            if (dist(this.x, this.y, target.x, target.y) <= this.l) {
                c.globalCompositeOperation = "color-dodge";
                c.beginPath();
                c.lineTo(this.x, this.y);
                for (let i = 0; i < this.n; i++) {
                    this.segments[i].show();
                }
                c.strokeStyle = "hsl("+(this.rand * 60 + 180)+",100%," + (this.rand * 60 + 25) + "%)";
                c.lineWidth = this.rand * 2;
                c.lineCap  = "round";
                c.lineJoin = "round";
                c.stroke();
                c.globalCompositeOperation = "source-over";
            }
        }
        show2(target) {
            c.beginPath();
            if (dist(this.x, this.y, target.x, target.y) <= this.l) {
                c.arc(this.x, this.y, 2 * this.rand + 1, 0, 2 * Math.PI);
                c.fillStyle = "white";
            } else {
                c.arc(this.x, this.y, this.rand * 2, 0, 2 * Math.PI);
                c.fillStyle = "darkcyan";
            }
            c.fill();
        }
    }

    let maxl = 300,
        minl = 50,
        n = 30,
        numt = 500, // 特性点的个数 500
        tent = [],
        clicked = false,
        target = { x: 0, y: 0 },
        last_target = {},
        t = 0,
        q = 10;

    for (let i = 0; i < numt; i++) {
        tent.push(
            new tentacle(
                Math.random() * w,
                Math.random() * h,
                Math.random() * (maxl - minl) + minl,
                n,
                Math.random() * 2 * Math.PI
            )
        );
    }
    function draw() {
        //animation
        if (mouse.x) {
            target.errx = mouse.x - target.x;
            target.erry = mouse.y - target.y;
        } else {
            target.errx = w / 2 + (h / 2 - q) * Math.sqrt(2) * Math.cos(t) / (Math.pow(Math.sin(t), 2) + 1) - target.x;
            target.erry = h / 2 + (h / 2 - q) * Math.sqrt(2) * Math.cos(t) * Math.sin(t) / (Math.pow(Math.sin(t), 2) + 1) - target.y;
        }

        target.x += target.errx / 10;
        target.y += target.erry / 10;

        t += 0.01;

        c.beginPath();
        c.arc(target.x, target.y, dist(last_target.x, last_target.y, target.x, target.y)+5, 0, 2 * Math.PI);
        c.fillStyle = "hsl(210,100%,80%)";
        c.fill();

        for (i = 0; i < numt; i++) {
            tent[i].move(last_target, target);
            tent[i].show2(target);
        }
        for (i = 0; i < numt; i++) {
            tent[i].show(target);
        }
        last_target.x = target.x;
        last_target.y = target.y;
    }

    canvas.addEventListener(
        "mousemove",
        function(e) {
            last_mouse.x = mouse.x;
            last_mouse.y = mouse.y;
            mouse.x = e.pageX - this.offsetLeft;
            mouse.y = e.pageY - this.offsetTop;
        }, false
    );

    canvas.addEventListener("mouseleave", function(e) { mouse.x = false; mouse.y = false; });
    canvas.addEventListener("mousedown", function(e) { clicked = true; }, false);
    canvas.addEventListener("mouseup", function(e) { clicked = false; }, false);

    function loop() {
        window.requestAnimFrame(loop);
        // c.fillStyle="rgba(30,30,30,0.1)";
        // c.fillRect(0, 0, w, h);
        c.clearRect(0, 0, w, h);
        draw();
    }

    window.addEventListener("resize", function() {
        (w = canvas.width = window.innerWidth),
        (h = canvas.height = window.innerHeight);
        loop();
    });

    loop();
    setInterval(loop, 1000 / 60);
};

 

标签:canvas,ang,target,window,pos,js,001,html,Math
From: https://www.cnblogs.com/Hpp918039/p/18596269

相关文章

  • 省级城镇化率面板数据(2001-2022年)
    城镇化率是指一个国家(地区)城镇的常住人口占该国家(地区)总人口的比例,是衡量城镇化水平高低,反映城镇化进程的一个重要指标。城镇化率是一个重要的经济和社会发展指标,能够反映一个国家或地区的城市化进程和水平。通过比较不同时间或地区的城镇化率,可以了解城市化的发展趋势和差异,为......
  • HTML列表
    HTML列表无序列表:此项目使用粗体圆点进行标记使用<ul>标签<ul><li>这是一个无序列表</li><li>333333</li></ul>有序列表:此项目使用数字进行标记使用<ol>标签<ol><li>这是一个有序列表</li><li>717</li></ol>自定义列表:自定义列表不仅仅是一列项目,而是项......
  • HTML框架
    HTML框架通过使用框架,可以在同一个浏览器窗口中显示不止一个页面<iframesrc="URL"></iframe>该URL指向不同的网页iframe-设置高度与宽度height和width属性用来定义iframe标签的高度与宽度属性默认以像素为单位,也可以按照其他比例设置移除边框frameborder属性用来定义i......
  • node.js毕设城科毕业生就业管理系统app程序+论文
    本系统(程序+源码+数据库+调试部署+开发环境)带文档lw万字以上,文末可获取源码系统程序文件列表开题报告内容一、选题背景关于毕业生就业管理系统的研究,现有研究主要以就业信息平台或就业指导网站等为主,专门针对城科毕业生就业管理系统app的研究较少。在国内外就业形势日益复......
  • node.js毕设城市出行行程智能推荐系统程序+论文
    本系统(程序+源码+数据库+调试部署+开发环境)带文档lw万字以上,文末可获取源码系统程序文件列表开题报告内容一、选题背景关于城市出行行程智能推荐系统的研究,现有研究主要以单一出行方式的优化或通用的路径规划为主,专门针对整合多种出行方式并依据用户个性化需求来智能推荐......
  • node.js毕设城市房屋租赁出售系统程序+论文
    本系统(程序+源码+数据库+调试部署+开发环境)带文档lw万字以上,文末可获取源码系统程序文件列表开题报告内容一、选题背景关于城市房屋租赁出售系统的研究,现有研究多集中于房地产市场的宏观分析或传统交易模式的局部优化。专门针对整合城市房屋租赁与出售业务于一体,借助信息......
  • JS-7 typeof 运算符
    数值:number、字符串:string、布尔值:bookan、对象:objectJavaScript有三种方法,可以确定一个值到底是什么类型,而我们现在需要接触到的就是typeof1、数值返回numbertypeo123//"number"2、字符串返回stringtypeof'123'//"string"3、布尔值返回booleantypeof......
  • JS-6 数据类型
    数据类型:数值、字符串、布尔值、undefined、null、对象1、数据类型分类JavaScript语言的每一个值,都属于某一种数据类型。JavaScript的数据类型,共有六种。(ES6又新增了第七种Symbol类型的值和第八种BIglnt类型)2、数据类型分类原始分类(基础类型):数值、字符串、布尔值。......
  • JS代码片段-Array数组克隆的几种方法
    JavaScript自身提供了几种克隆数组的方法,以下做了汇总,以作参考:1.展开运算符(...) ES6引入了展开运算符(...),这是创建数组浅克隆最常见的方法。leta=[1,2,3,4,5];letb=[...a];2.Array.from()leta=[1,2,3,4,5];letb=Array.from(a);3.Array.prototype.s......
  • Node.js 事件循环
    事件循环是Node.js处理非阻塞I/O操作的核心机制,使得单线程能够高效处理多个并发请求。Node.js是基于单线程的JavaScript运行时,利用事件循环来处理异步操作,如文件读取、网络请求和数据库查询。事件循环使得Node.js能够非阻塞地运行代码、处理多个连接、以及执行异步......