老刘 发表于 2020-6-30 11:19

[HTA][算法实战008]多段贝塞尔曲线变换特效

本帖最后由 老刘 于 2020-6-30 12:56 编辑



创意来自于vicyang兄,论坛不让放链接就不放了。
Windows系统建议保存为hta,其它系统可以保存为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 = 12;   //字体大小
            var lngBufferWidth = 80;    //缓冲区列数
            var lngBufferHeight = 60;   //缓冲区行数
            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 = new Array();
                  for (var x = 0; x < lngBufferWidth; x++) {
                        arrBuffer = ' ';   //全角空格
                  }
                }

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

                //准备绘制。
                //初始化随机控制点。
                for (var i = 0; i <= 3; i++) {
                  arrPoints = NewControlPoint();
                  arrPoints = 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 = arrPoints;
                            //此处让新的控制点2作为旧控制点3关于旧控制点4/新控制点1的对称点,增加曲线平滑度。
                            arrPoints = new Point(
                              2 * arrPoints.x - arrPoints.x,
                              2 * arrPoints.y - arrPoints.y
                            );
                            //其它从控制点随机获得。
                            for (var j = 2; j <= 3; j++) {
                              arrPoints = NewControlPoint();
                            }
                        }
                  } else {
                        numServantT += numMoveSpeed;
                  }
                  //算一下主控制点。
                  for (var i = 0; i <= 3; i++) {
                        arrPoints = ThirdOrderBezierCurve(
                            numServantT,
                            arrPoints,
                            arrPoints,
                            arrPoints,
                            arrPoints
                        );
                  }
                  //绘制缓冲区。
                  //从缓冲区擦除老点。
                  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, " ");
                        }
                  }
                  //绘制新点到缓冲区。
                  for (var t = 0; t <= 1; t += 1 / (lngPointNumber - 1)) {
                        var NewPoint = ThirdOrderBezierCurve(
                            t,
                            arrPoints,
                            arrPoints,
                            arrPoints,
                            arrPoints
                        );
                        //绘制新点并入队。
                        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.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 = charText;
                return;
            }

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

jb937158168 发表于 2020-6-30 11:30

奈何没有文化 只能说一句nb

imcuer 发表于 2020-6-30 11:41

很牛很漂亮!

lz132 发表于 2020-6-30 12:04

虽然看不懂,但是感觉好厉害的样子
页: [1]
查看完整版本: [HTA][算法实战008]多段贝塞尔曲线变换特效