目录
一、程序代码
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<!-- 声明文档类型为XHTML 1.0 Transitional -->
<html xmlns="http://www.w3.org/1999/xhtml"> <!-- 定义文档命名空间为XHTML -->
<head>
<title>视觉盛宴</title> <!-- 设置页面标题为“视觉盛宴” -->
<script type="text/javascript">
window.onload = function () { // 当窗口加载完成时执行以下代码
C = Math.cos; // 缓存Math对象的cos函数
S = Math.sin; // 缓存Math对象的sin函数
U = 0; // 设置变量U的初始值为0(用于记录鼠标位置)
w = window; // 将window对象缓存在变量w中
j = document; // 将document对象缓存在变量j中
d = j.getElementById("c"); // 获取id为"c"的Canvas元素,并将其缓存在变量d中
c = d.getContext("2d"); // 获取Canvas绘图上下文,并将其缓存在变量c中
W = d.width = w.innerWidth; // 设置Canvas的宽度为窗口的宽度,并将其缓存在变量W中
H = d.height = w.innerHeight; // 设置Canvas的高度为窗口的高度,并将其缓存在变量H中
c.fillRect(0, 0, W, H); // 在Canvas上绘制一个黑色的矩形,覆盖整个画布(默认)
c.globalCompositeOperation = "lighter"; // 设置全局合成操作为"lighter",即颜色叠加模式
c.lineWidth = 0.2; // 设置线条宽度为0.2
c.lineCap = "round"; // 设置线条的端点样式为圆形
var bool = 0, t = 0; // 定义两个变量bool和t,初始值分别为0
d.onmousemove = function (e) { // 当鼠标在Canvas上移动时执行以下代码
if(window.T) { // 如果变量T存在,则执行以下代码
if(D==9) { D=Math.random()*15; f(1); } // 如果变量D等于9,则将变量D设置为一个0到15之间的随机数,并调用函数f(1)
clearTimeout(T); // 清除计时器T
}
X = e.pageX; // 获取鼠标的X坐标,并将其缓存在变量X中
Y = e.pageY; // 获取鼠标的Y坐标,并将其缓存在变量Y中
a=0; // 将变量a的值设置为0
b=0; // 将变量b的值设置为0
A = X, // 将变量A的值设置为鼠标的X坐标
B = Y; // 将变量B的值设置为鼠标的Y坐标
R=(e.pageX/W * 999>>0)/999; // 计算半径R,根据鼠标的X坐标和窗口宽度的比例计算得出
r=(e.pageY/H * 999>>0)/999; // 计算半径r,根据鼠标的Y坐标和窗口高度的比例计算得出
U=e.pageX/H * 360 >>0; // 计算角度U,根据鼠标的X坐标和窗口高度的比例计算得出,并取整数部分
D=9; // 将变量D的值设置为9
g = 360 * Math.PI / 180; // 将变量g的值设置为360度对应的弧度值
T = setInterval(f = function (e) { // 创建一个定时器T,每16毫秒执行一次函数f
c.save(); // 保存当前的绘图状态
c.globalCompositeOperation = "source-over"; // 设置合成操作为"source-over",即覆盖模式
if(e!=1) { // 如果传入的参数不等于1,则执行以下代码
c.fillStyle = "rgba(0,0,0,0.02)"; // 设置填充颜色为半透明黑色
c.fillRect(0, 0, W, H); // 在Canvas上绘制一个黑色的矩形,覆盖整个画布(默认)
}
c.restore(); // 恢复之前保存的绘图状态
i = 25; while(i --) { // 循环25次执行以下代码
c.beginPath(); // 开始一个新的路径
if(D > 450 || bool) { // 如果变量D大于450或bool为真,则执行以下代码
if(!bool) { // 如果bool为假,则执行以下代码
bool = 1; // 将bool设置为真
}
if(D < 0.1) { // 如果变量D小于0.1,则执行以下代码
bool = 0; // 将bool设置为假
}
t -= g; // 减小角度t的值
D -= 0.1; // 减小半径D的值
}
if(!bool) { // 如果bool为假,则执行以下代码
t += g; // 增加角度t的值
D += 0.1; // 增加半径D的值
}
q = (R / r - 1) * t; // 计算变量q的值,用于创建hypotrochoid(参考:http://en.wikipedia.org/wiki/Hypotrochoid)
x = (R - r) * C(t) + D * C(q) + (A + (X - A) * (i / 25)) + (r - R); // 计算x坐标的值,根据hypotrochoid公式计算得出
y = (R - r) * S(t) - D * S(q) + (B + (Y - B) * (i / 25)); // 计算y坐标的值,根据hypotrochoid公式计算得出
if (a) { // 如果变量a的值存在,则执行以下代码
c.moveTo(a, b); // 将当前绘图点移动到变量a和b所表示的位置
c.lineTo(x, y) // 绘制一条直线到坐标(x, y)
}
c.strokeStyle = "hsla(" + (U % 360) + ",100%,50%,0.75)"; // 设置线条颜色为根据角度U计算得出的彩虹色
c.stroke(); // 绘制线条
a = x; // 将变量a的值设置为x坐标的值
b = y; // 将变量b的值设置为y坐标的值
}
U -= 0.5; // 减小角度U的值
A = X; // 将变量A的值设置为鼠标的X坐标
B = Y; // 将变量B的值设置为鼠标的Y坐标
}, 16); // 定时器每16毫秒执行一次函数f
}
j.onkeydown = function(e) { a=b=0; R += 0.05 } // 当按下键盘时执行以下代码,将变量a和b的值都设为0,并将半径R增加0.05
d.onmousemove({pageX:300, pageY:290}) // 模拟鼠标移动事件,设置pageX为300,pageY为290
}
</script>
</head>
<body>
<canvas id="c"></canvas> <!-- 创建一个id为"c"的Canvas元素 -->
</body>
</html>
二、代码原理
该代码利用Canvas的绘图功能和数学函数,创建了一个动态的彩色线条效果,能够根据鼠标的移动和键盘的操作呈现不同的视觉效果。它使用了数学函数来计算线条的坐标和角度,并根据鼠标位置和窗口大小进行动态调整。代码首先获取Canvas元素,并设置其宽度和高度为窗口的宽度和高度。然后设置绘图上下文的属性,如颜色叠加模式、线条宽度和端点样式。在鼠标移动事件中,根据鼠标的位置计算出各种参数,包括半径、角度和颜色。然后使用循环和数学函数绘制彩色线条,线条的位置和颜色会随着时间和鼠标移动而变化。
- 声明文档类型为XHTML 1.0 Transitional。
- 定义文档命名空间为XHTML。
- 设置页面标题为“视觉盛宴”。
- 在
<head>
标签内包含了一个JavaScript脚本。 - JavaScript脚本中,使用了一些全局变量和函数。
window.onload
事件处理函数会在窗口加载完成后执行。- 在函数中,缓存了一些常用的对象和元素,如
Math
对象、window
对象、document
对象和Canvas
元素。 - 设置了Canvas的宽高为窗口的宽高。
- 使用Canvas的上下文进行绘制操作。
- 创建了一个鼠标移动事件处理函数,当鼠标在Canvas上移动时执行一些操作。
- 创建了一个定时器,每16毫秒执行一次函数
f
。 - 函数
f
中,保存了当前的绘图状态,并设置了合成操作和样式。 - 使用
while
循环绘制一些形状,并根据鼠标位置和其他参数计算出坐标值。 - 更新一些变量的值。
- 在按键事件处理函数中,更新了一些变量的值。
- 模拟了一次鼠标移动事件。
三、运行效果