多段Bézier曲线变换效果 HTML实现

回复
头像
老刘001
初来炸道
初来炸道
帖子: 6
注册时间: 2017年03月17日 23:58
联系:

多段Bézier曲线变换效果 HTML实现

帖子 老刘001 »

图片
图片
编写思路来源:http://www.code-by.org/viewtopic.php?f=43&t=109
windows系统建议保存为HTA,非windows系统可以保存为html。
<!doctype html>
<html lang="zh_CN" id="main">
    <head>
        <title>多段贝塞尔曲线变换(创意:Vicyang;HTML实现:老刘)</title>
        <HTA:APPLICATION
            APPLICATIONNAME="Bezier Curve Variation"
            ID="BezierCurveVariation"
            VERSION="1.0"
            INNERBORDER="no"/>
        <style>
            html, body {
                /*不要边框*/
                margin: 0;
                border: 0;
                padding: 0;
                
                /*不要滚动条*/
                overflow-y: hidden;
                overflow-x: hidden;

                /*自动换行*/
                word-wrap: break-word;
                word-break: break-all;
            }
            
            p {
                margin: 0px;
            }
            
            #TextArea {
                background-color: #222222;
                color: white;
                
                font-family: 'Microsoft YaHei';
                letter-spacing: 0px;
                /*font-size: 12px;
                line-height: 12px;*/
                color: chartreuse;
                
                height: 100%;
                position: relative;
                margin: 0 auto;
                border: 0;
                padding: 0;
            }
        </style>
    </head>
    <body>
        <div id="TextArea"></div>
        <script language="JavaScript">
            //设置区。
            var lngFontSize = 8;   //字体大小
            var lngBufferWidth = 150;    //缓冲区列数
            var lngBufferHeight = 100;   //缓冲区行数
            var lngPointNumber = 8; //绘制点数
            var numMoveSpeed = 0.03;    //移动紧密度
            var lngLayer = 15;   //轨迹保留层数
            var lngSleep = 30;  //绘制延时

            function Point(x, y) {
                this.x = x;
                this.y = y;
            }

            window.onload = function () {
                //调整窗口布局。
                window.resizeTo(lngBufferWidth * lngFontSize, lngBufferHeight * lngFontSize);
                window.resizeTo(
                    2 * lngBufferWidth * lngFontSize - document.documentElement.clientWidth,
                    2 * lngBufferHeight * lngFontSize - document.documentElement.offsetHeight
                );
                document.getElementById('main').style.width = (lngBufferWidth * lngFontSize).toString() + 'px';
                document.getElementById('main').style.height = (lngBufferHeight * lngFontSize).toString() + 'px';
                document.body.style.width = (lngBufferWidth * lngFontSize).toString() + 'px';
                document.body.style.height = (lngBufferHeight * lngFontSize).toString() + 'px';
                document.getElementById('TextArea').style.fontSize = lngFontSize.toString() + 'px';
                document.getElementById('TextArea').style.lineHeight = lngFontSize.toString() + 'px';
                

                //创建缓冲区数组。
                //arrBuffer[缓冲区索引][该缓冲区横坐标][该缓冲区纵坐标]
                var arrBuffer = new Array();
                for (var y = 0; y < lngBufferHeight; y++) {
                    arrBuffer[y] = new Array();
                    for (var x = 0; x < lngBufferWidth; x++) {
                        arrBuffer[y][x] = '&#12288;';   //全角空格
                    }
                }

                //创建控制点数组。
                //主控制点绘制主轨迹,从控制点控制主控制点按从轨迹移动。
                //主从轨迹均为三阶贝塞尔曲线。
                //arrPoints[0-3主轨迹控制点索引][0-3该控制点对应的从轨迹的从控制点,4该控制点]
                var arrPoints = new Array();
                for (var i = 0; i <= 3; i++) {
                    arrPoints[i] = new Array();
                }
                

                //准备绘制。
                //初始化随机控制点。
                for (var i = 0; i <= 3; i++) {
                    arrPoints[i][2] = NewControlPoint();
                    arrPoints[i][3] = NewControlPoint();
                }
                var numServantT = 20011228 //4个从轨迹统一的参数t,超过1时会求新随机点并置0。
                var lngUsingBufferIndex = 0;
                //创建老点队列并填充。
                var queueOldPoints = new Array()
                for (var i = 0; i <= lngLayer * lngPointNumber; i++) {
                    queueOldPoints.push(new Point(-1, -1)); //填充无效点。
                }


                //循环绘制。
                setInterval(function () {
                    //若主控制点移动完成,则生成新路径。
                    if (numServantT > 1) {
                        numServantT = 0;
                        for (var i = 0; i <= 3; i++) {
                            //设置新的从轨迹接上旧的。
                            //即将旧轨迹终点作为新轨迹起点。
                            arrPoints[i][0] = arrPoints[i][3];
                            //此处让新的控制点2作为旧控制点3关于旧控制点4/新控制点1的对称点,增加曲线平滑度。
                            arrPoints[i][1] = new Point(
                                2 * arrPoints[i][3].x - arrPoints[i][2].x,
                                2 * arrPoints[i][3].y - arrPoints[i][2].y
                            );
                            //其它从控制点随机获得。
                            for (var j = 2; j <= 3; j++) {
                                arrPoints[i][j] = NewControlPoint();
                            }
                        }
                    } else {
                        numServantT += numMoveSpeed;
                    }
                    //算一下主控制点。
                    for (var i = 0; i <= 3; i++) {
                        arrPoints[i][4] = ThirdOrderBezierCurve(
                            numServantT,
                            arrPoints[i][0],
                            arrPoints[i][1],
                            arrPoints[i][2],
                            arrPoints[i][3]
                        );
                    }
                    //绘制缓冲区。
                    //从缓冲区擦除老点。
                    for (var t = 0; t <= 1; t += 1 / (lngPointNumber - 1)) {
                        var OldPoint = queueOldPoints.shift();
                        if (OldPoint.x >= 0 && OldPoint.x < lngBufferWidth && OldPoint.y >= 0 && OldPoint.y < lngBufferHeight) {
                            DrawPoint(arrBuffer, OldPoint, "&#12288;");
                        }
                    }
                    //绘制新点到缓冲区。
                    for (var t = 0; t <= 1; t += 1 / (lngPointNumber - 1)) {
                        var NewPoint = ThirdOrderBezierCurve(
                            t,
                            arrPoints[0][4],
                            arrPoints[1][4],
                            arrPoints[2][4],
                            arrPoints[3][4]
                        );
                        //绘制新点并入队。
                        if (NewPoint.x >= 0 && NewPoint.x < lngBufferWidth && NewPoint.y >= 0 && NewPoint.y < lngBufferHeight) {
                            DrawPoint(arrBuffer, NewPoint, "ABCDEFGHIJKLMNOPQRSTUVWXYZ".charAt(RandomInteger(0,26)));
                        }
                        queueOldPoints.push(NewPoint);
                    }

                    //绘制结果。
                    var strBuffer = '';
                    for (var i = 0; i < lngBufferHeight; i++) {
                        strBuffer += arrBuffer[i].join('') + '<br>';
                    }
                    document.getElementById('TextArea').innerHTML = strBuffer;
                }, lngSleep);
            }

            function ThirdOrderBezierCurve(t, p0, p1, p2, p3) {
                //三阶贝塞尔曲线计算函数。
                return new Point(
                    p0.x * (1 - t) * (1 - t) * (1 - t) + 3 * p1.x * t * (1 - t) * (1 - t) + 3 * p2.x * t * t * (1 - t) + p3.x * t * t * t,
                    p0.y * (1 - t) * (1 - t) * (1 - t) + 3 * p1.y * t * (1 - t) * (1 - t) + 3 * p2.y * t * t * (1 - t) + p3.y * t * t * t
                );
            }

            function DrawPoint(arrBuffer, objPoint, charText) {
                //在arrBuffer中画点。(其实就是修改数组)
                //alert(objPoint.y + ' ' + objPoint.x);
                arrBuffer[Math.floor(objPoint.y)][Math.floor(objPoint.x)] = charText;
                return;
            }

            function ArrayDeepCopy(obj) {
                //数组深拷贝函数(支持多维数组)。
                var out = [], i = 0, len = obj.length;
                for (; i < len; i++) {
                    if (obj[i] instanceof Array) {
                        out[i] = ArrayDeepCopy(obj[i]);
                    }
                    else out[i] = obj[i];
                }
                return out;
            }

            function NewControlPoint() {
                //获得新随机控制点。
                return NewRandomPoint(0,lngBufferWidth,0,lngBufferHeight);
                //24game的建议:将控制点范围限定在与缓冲区同心、宽高均为缓冲区宽高2/3的矩形内。
                //这样可以避免主轨迹溢出屏幕。
                //但由于对称,无法很好的限制,所以不采纳。
                //return NewRandomPoint(
                //    Math.floor(lngBufferWidth / 6),
                //    Math.floor(lngBufferWidth * 5 / 6),
                //    Math.floor(lngBufferHeight / 6), 
                //    Math.floor(lngBufferHeight * 5 / 6)
                //);
            }

            function NewRandomPoint(lngRangeXStart, lngRangeXEnd, lngRangeYStart, lngRangeYEnd) {
                //获得新随机点。
                return new Point(
                    RandomInteger(lngRangeXStart, lngRangeXEnd),
                    RandomInteger(lngRangeYStart, lngRangeYEnd)
                );
            }

            function RandomInteger(lngStart, lngEnd) {
                //获得以lngStart为下界(含lngStart),lngEnd为上界(不含lngEnd)的随机整数。
                return lngStart + Math.floor(Math.random() * (lngEnd - lngStart));
            }

        </script>
    </body>
</html>
上次由 523066680 在 2021年10月14日 21:20,总共编辑 1 次。
原因: 修改BBCode标签
头像
523066680
Administrator
Administrator
帖子: 573
注册时间: 2016年07月19日 12:14
联系:

Re: 多段Bézier曲线变换效果 HTML实现

帖子 523066680 »

好久没有学习了 :shy
头像
rubyish
渐入佳境
渐入佳境
帖子: 52
注册时间: 2018年04月23日 09:58
联系:

Re: 多段Bézier曲线变换效果 HTML实现

帖子 rubyish »

漂亮. :exciting4 :exciting4 :exciting4
$_
回复

在线用户

正浏览此版面之用户: 没有注册用户 和 0 访客