1
+ < ! doctype html >
2
+ < html lang = "zh_CN" id = "main" >
3
+ < head >
4
+ < title > 多段贝塞尔曲线变换(创意:Vicyang;HTML实现:老刘)</ title >
5
+ < HTA :APPLICATION
6
+ APPLICATIONNAME = "Bezier Curve Variation"
7
+ ID = "BezierCurveVariation"
8
+ contextMenu = "no"
9
+ BORDER = "none"
10
+ innerBorder = "no"
11
+ SHOWINTASKBAR = "yes"
12
+ SINGLEINSTANCE = "yes"
13
+ SYSMENU = "no"
14
+ VERSION = "1.0"
15
+ WINDOWSTATE = "maximize" />
16
+ < style >
17
+ html, body {
18
+ /*不要边框*/
19
+ margin : 0 ;
20
+ border : 0 ;
21
+ padding : 0 ;
22
+
23
+ /*不要滚动条*/
24
+ overflow - y : hidden ;
25
+ overflow - x : hidden ;
26
+
27
+ /*自动换行*/
28
+ word - wrap : break - word ;
29
+ word - break : break - all ;
30
+ }
31
+
32
+ p {
33
+ margin : 0 px ;
34
+ }
35
+
36
+ #TextArea {
37
+ background - color : #222222 ;
38
+ color : white ;
39
+
40
+ font - family : 'Microsoft YaHei' ;
41
+ letter - spacing : 0 px ;
42
+ /*font-size: 12px;
43
+ line-height: 12px;*/
44
+ color : chartreuse ;
45
+
46
+ height : 100 % ;
47
+ position : relative ;
48
+ margin : 0 auto ;
49
+ border : 0 ;
50
+ padding : 0 ;
51
+ }
52
+ </style >
53
+ </head >
54
+ < body >
55
+ < div id = "TextArea "> </div >
56
+ < script language = "JavaScript ">
57
+ //设置区。
58
+ var lngFontSize = 12 ; //字体大小
59
+ var lngBufferWidth = 160 ; //缓冲区列数
60
+ var lngBufferHeight = 90 ; //缓冲区行数
61
+ var lngPointNumber = 6 ; //绘制点数
62
+ var numMoveSpeed = 0.04 ; //移动紧密度
63
+ var lngLayer = 10 ; //轨迹保留层数
64
+ var lngSleep = 30 ; //绘制延时
65
+
66
+ function Point ( x , y ) {
67
+ this . x = x ;
68
+ this . y = y ;
69
+ }
70
+
71
+ window . onload = function ( ) {
72
+ //调整窗口布局。
73
+ window . resizeTo ( lngBufferWidth * lngFontSize , lngBufferHeight * lngFontSize ) ;
74
+ window . resizeTo (
75
+ 2 * lngBufferWidth * lngFontSize - document . documentElement . clientWidth ,
76
+ 2 * lngBufferHeight * lngFontSize - document . documentElement . offsetHeight
77
+ ) ;
78
+ document . getElementById ( 'main ') . style . width = ( lngBufferWidth * lngFontSize ) . toString ( ) + 'px ';
79
+ document . getElementById ( 'main ') . style . height = ( lngBufferHeight * lngFontSize ) . toString ( ) + 'px ';
80
+ document . body . style . width = ( lngBufferWidth * lngFontSize ) . toString ( ) + 'px ';
81
+ document . body . style . height = ( lngBufferHeight * lngFontSize ) . toString ( ) + 'px ';
82
+ document . getElementById ( 'TextArea ') . style . fontSize = lngFontSize . toString ( ) + 'px ';
83
+ document . getElementById ( 'TextArea ') . style . lineHeight = lngFontSize . toString ( ) + 'px ';
84
+
85
+
86
+ //创建缓冲区数组。
87
+ //arrBuffer[缓冲区索引][该缓冲区横坐标][该缓冲区纵坐标]
88
+ var arrBuffer = new Array ( ) ;
89
+ for ( var y = 0 ; y < lngBufferHeight ; y ++ ) {
90
+ arrBuffer [ y ] = new Array ( ) ;
91
+ for ( var x = 0 ; x < lngBufferWidth ; x ++ ) {
92
+ arrBuffer [ y ] [ x ] = ' '; //全角空格
93
+ }
94
+ }
95
+
96
+ //创建控制点数组。
97
+ //主控制点绘制主轨迹,从控制点控制主控制点按从轨迹移动。
98
+ //主从轨迹均为三阶贝塞尔曲线。
99
+ //arrPoints[0-3主轨迹控制点索引][0-3该控制点对应的从轨迹的从控制点,4该控制点]
100
+ var arrPoints = new Array ( ) ;
101
+ for ( var i = 0 ; i <= 3 ; i ++ ) {
102
+ arrPoints [ i ] = new Array ( ) ;
103
+ }
104
+
105
+
106
+ //准备绘制。
107
+ //初始化随机控制点。
108
+ for ( var i = 0 ; i <= 3 ; i ++ ) {
109
+ arrPoints [ i ] [ 2 ] = NewControlPoint ( ) ;
110
+ arrPoints [ i ] [ 3 ] = NewControlPoint ( ) ;
111
+ }
112
+ var numServantT = 20011228 //4个从轨迹统一的参数t,超过1时会求新随机点并置0。
113
+ var lngUsingBufferIndex = 0 ;
114
+ //创建老点队列并填充。
115
+ var queueOldPoints = new Array ( )
116
+ for ( var i = 0 ; i <= lngLayer * lngPointNumber ; i ++ ) {
117
+ queueOldPoints . push ( new Point ( - 1 , - 1 ) ) ; //填充无效点。
118
+ }
119
+
120
+
121
+ //循环绘制。
122
+ setInterval ( function ( ) {
123
+ //若主控制点移动完成,则生成新路径。
124
+ if ( numServantT > 1 ) {
125
+ numServantT = 0 ;
126
+ for ( var i = 0 ; i <= 3 ; i ++ ) {
127
+ //设置新的从轨迹接上旧的。
128
+ //即将旧轨迹终点作为新轨迹起点。
129
+ arrPoints [ i ] [ 0 ] = arrPoints [ i ] [ 3 ] ;
130
+ //此处让新的控制点2作为旧控制点3关于旧控制点4/新控制点1的对称点,增加曲线平滑度。
131
+ arrPoints [ i ] [ 1 ] = new Point (
132
+ 2 * arrPoints [ i ] [ 3 ] . x - arrPoints [ i ] [ 2 ] . x ,
133
+ 2 * arrPoints [ i ] [ 3 ] . y - arrPoints [ i ] [ 2 ] . y
134
+ ) ;
135
+ //其它从控制点随机获得。
136
+ for ( var j = 2 ; j <= 3 ; j ++ ) {
137
+ arrPoints [ i ] [ j ] = NewControlPoint ( ) ;
138
+ }
139
+ }
140
+ } else {
141
+ numServantT += numMoveSpeed ;
142
+ }
143
+ //算一下主控制点。
144
+ for ( var i = 0 ; i <= 3 ; i ++ ) {
145
+ arrPoints [ i ] [ 4 ] = ThirdOrderBezierCurve (
146
+ numServantT ,
147
+ arrPoints [ i ] [ 0 ] ,
148
+ arrPoints [ i ] [ 1 ] ,
149
+ arrPoints [ i ] [ 2 ] ,
150
+ arrPoints [ i ] [ 3 ]
151
+ ) ;
152
+ }
153
+ //绘制缓冲区。
154
+ //从缓冲区擦除老点。
155
+ for ( var t = 0 ; t <= 1 ; t += 1 / ( lngPointNumber - 1 ) ) {
156
+ var OldPoint = queueOldPoints . shift ( ) ;
157
+ if ( OldPoint . x >= 0 && OldPoint . x < lngBufferWidth && OldPoint . y >= 0 && OldPoint . y < lngBufferHeight ) {
158
+ DrawPoint ( arrBuffer , OldPoint , " ") ;
159
+ }
160
+ }
161
+ //绘制新点到缓冲区。
162
+ for ( var t = 0 ; t <= 1 ; t += 1 / ( lngPointNumber - 1 ) ) {
163
+ var NewPoint = ThirdOrderBezierCurve (
164
+ t ,
165
+ arrPoints [ 0 ] [ 4 ] ,
166
+ arrPoints [ 1 ] [ 4 ] ,
167
+ arrPoints [ 2 ] [ 4 ] ,
168
+ arrPoints [ 3 ] [ 4 ]
169
+ ) ;
170
+ //绘制新点并入队。
171
+ if ( NewPoint . x >= 0 && NewPoint . x < lngBufferWidth && NewPoint . y >= 0 && NewPoint . y < lngBufferHeight ) {
172
+ DrawPoint ( arrBuffer , NewPoint , "ABCDEFGHIJKLMNOPQRSTUVWXYZ ". charAt ( RandomInteger ( 0 , 26 ) ) ) ;
173
+ }
174
+ queueOldPoints . push ( NewPoint ) ;
175
+ }
176
+
177
+ //绘制结果。
178
+ var strBuffer = '';
179
+ for ( var i = 0 ; i < lngBufferHeight ; i ++ ) {
180
+ strBuffer += arrBuffer [ i ] . join ( '') + '< br > ';
181
+ }
182
+ document . getElementById ( 'TextArea ') . innerHTML = strBuffer ;
183
+ } , lngSleep ) ;
184
+ }
185
+
186
+ function ThirdOrderBezierCurve ( t , p0 , p1 , p2 , p3 ) {
187
+ //三阶贝塞尔曲线计算函数。
188
+ return new Point (
189
+ 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 ,
190
+ 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
191
+ ) ;
192
+ }
193
+
194
+ function DrawPoint ( arrBuffer , objPoint , charText ) {
195
+ //在arrBuffer中画点。(其实就是修改数组)
196
+ //alert(objPoint.y + ' ' + objPoint.x);
197
+ arrBuffer [ Math . floor ( objPoint . y ) ] [ Math . floor ( objPoint . x ) ] = charText ;
198
+ return ;
199
+ }
200
+
201
+ function ArrayDeepCopy ( obj ) {
202
+ //数组深拷贝函数(支持多维数组)。
203
+ var out = [ ] , i = 0 , len = obj . length ;
204
+ for ( ; i < len ; i ++ ) {
205
+ if ( obj [ i ] instanceof Array ) {
206
+ out [ i ] = ArrayDeepCopy ( obj [ i ] ) ;
207
+ }
208
+ else out [ i ] = obj [ i ] ;
209
+ }
210
+ return out ;
211
+ }
212
+
213
+ function NewControlPoint ( ) {
214
+ //获得新随机控制点。
215
+ return NewRandomPoint ( 0 , lngBufferWidth , 0 , lngBufferHeight ) ;
216
+ //24game的建议:将控制点范围限定在与缓冲区同心、宽高均为缓冲区宽高2/3的矩形内。
217
+ //这样可以避免主轨迹溢出屏幕。
218
+ //但由于对称,无法很好的限制,所以不采纳。
219
+ //return NewRandomPoint(
220
+ // Math.floor(lngBufferWidth / 6),
221
+ // Math.floor(lngBufferWidth * 5 / 6),
222
+ // Math.floor(lngBufferHeight / 6),
223
+ // Math.floor(lngBufferHeight * 5 / 6)
224
+ //);
225
+ }
226
+
227
+ function NewRandomPoint ( lngRangeXStart , lngRangeXEnd , lngRangeYStart , lngRangeYEnd ) {
228
+ //获得新随机点。
229
+ return new Point (
230
+ RandomInteger ( lngRangeXStart , lngRangeXEnd ) ,
231
+ RandomInteger ( lngRangeYStart , lngRangeYEnd )
232
+ ) ;
233
+ }
234
+
235
+ function RandomInteger ( lngStart , lngEnd ) {
236
+ //获得以lngStart为下界(含lngStart),lngEnd为上界(不含lngEnd)的随机整数。
237
+ return lngStart + Math . floor ( Math . random ( ) * ( lngEnd - lngStart ) ) ;
238
+ }
239
+
240
+ </script >
241
+ </body >
242
+ </html >
0 commit comments