css画布星空
Because it works on a pixel-by-pixel basis, canvas
is perfectly suited to making extremely detailed images algorithmically. A good example is a starfield background; a very simple one can be built based by merely deciding if a canvas random pixel is white or not.
由于canvas
是逐像素工作的,因此它非常适合通过算法制作极其详细的图像。 星空背景是一个很好的例子。 可以仅通过确定画布随机像素是否为白色来构建非常简单的像素。
Unlike most other articles on The New Code, the goal of this piece is not to show a complete example, but to improve the code in incremental steps. This is in contrast to the approach of many of my students, who often seek a single, “perfect” solution rather than taking the time to build from something simple (but well-structured) into a more complex, nuanced production.
与大多数其他有关“新代码”的文章不同,本文的目的不是显示完整的示例,而是以渐进的方式改进代码。 这与我许多学生的方法形成鲜明对比,我的学生经常寻求单一的“完美”解决方案,而不是花时间将简单(但结构良好)的东西构建成更复杂,细致的产品。
Let’s say we have a 750 × 500 pixel element with an
id
:
假设我们有一个750×500像素的id
元素:
Unlike almost every other element, should be sized using attributes, rather than CSS; sizing the elements with styles alone causes scaling issues, as the
element has its own default size that is distorted by using CSS
width
and height
as its only dimension information.
与几乎所有其他元素不同, 应该使用attribute而不是CSS来确定大小; 仅使用样式调整元素大小会导致缩放问题,因为
元素具有其自己的默认大小,该默认大小通过使用CSS
width
和height
作为其唯一的尺寸信息而失真。
And some CSS to fill it with black:
还有一些用黑色填充CSS:
canvas {
background: #111;
}
To start, we’ll identify the canvas, tell JavaScript what context we are drawing in, and determine the total number of stars:
首先,我们将确定画布,告诉JavaScript我们正在绘制的上下文,并确定星星总数:
var canvas = document.getElementById("starfield"),
context = canvas.getContext("2d"),
stars = 200;
To create the stars themselves, we’ll create a simple loop that draws 1 pixel × 1 pixel squares randomly within the limits of the canvas:
为了自己创建星星,我们将创建一个简单的循环 ,在画布的范围内随机绘制1个像素×1个像素的正方形:
for (var i = 0; i < stars; i++) {
x = Math.random() * canvas.offsetWidth;
y = Math.random() * canvas.offsetHeight;
context.fillStyle = "white";
context.fillRect(x,y,1,1);
}
The result:
结果:
A simple star field, with small square white stars 一个简单的星空,上面有白色的小方形星星That’s not a bad start, but there are a few problems: the stars are fairly obviously square when viewed closely, all the same brightness, and quite small. Let’s address all of those issues at the same time by drawing circles for the stars; each circle will have a random radius.
这不是一个不好的开始,但是有一些问题:当仔细观察时,星星显然是正方形的,亮度都一样,而且很小。 让我们同时为星星画圆,以解决所有这些问题。 每个圆都有一个随机半径。
for (var i = 0; i < stars; i++) {
var x = Math.random() * canvas.offsetWidth;
y = Math.random() * canvas.offsetHeight,
radius = Math.random() * 1.2;
context.beginPath();
context.arc(x, y, radius, 0, 360);
context.fillStyle = "hsla(200,100%,50%,0.8)";
context.fill();
}
Somewhat oddly, canvas does not have a fillCirc
method; rather, it draws arcs. Drawing a circle is therefore a task of determining the center and radius of the circle, the starting angle (0) and the ending angle (360).
有点奇怪的是,canvas没有fillCirc
方法。 相反,它绘制弧线 。 因此,绘制圆是确定圆的中心和半径,起始角度(0)和终止角度(360)的任务。
The starfield now looks like this:
现在,星空看起来像这样:
An improved star field, with small blue circles for stars 改进的星场,带有蓝色小圆圈That’s better, but all our stars are blue-shifted due to the hsla color. We want a range of color.
更好,但是由于hsla颜色,我们所有的星星都发生了蓝移。 我们想要一个颜色范围 。
The perceived color of a star depends on its mass and temperature, both of which are functions of its age. Young stars in new galaxies gulp in gas, and shine a bright blue; an older galaxy will be darker, with aged stars appearing as red embers. The color distribution of main sequence stars in our galaxy is fairly typical: three-quarters of them are red and 20% yellow or orange, with the remainder scattered between white and blue.
恒星的感知颜色取决于其质量和温度,这两者都是其年龄的函数。 新星系中的年轻恒星吞噬着气体,并发出明亮的蓝色。 年龄较大的星系会更暗,年龄较大的恒星会显示为红色余烬。 我们银河系中主要序列恒星的颜色分布相当典型:四分之三是红色,而20%是黄色或橙色,其余分布在白色和蓝色之间。
Our perception of star color distribution is skewed by the fact that cool red stars are much harder to see against the black background of space. For similar reasons, humans do not see green stars: any star emitting green light will also emit red and blue, making it look white.
我们对恒星颜色分布的认识因以下事实而歪曲:在太空黑色背景下,很难看到冷的红色恒星。 出于类似的原因,人类看不到绿色的恒星:任何发出绿光的恒星也将发出红色和蓝色,使其看上去呈白色。
If you’re familiar with HSL color, you should know that anything with a luminosity of 100% will appear white, no matter what the hue and saturation. So if we randomize hue and saturation but keep luminosity fairly high, we’ll get hints of color, but the stars will be predominantly white.
如果您熟悉HSL颜色 ,则应该知道任何亮度和100%亮度的东西都会显示为白色。 因此,如果我们将色相和饱和度随机化,但保持较高的光度,则将获得颜色提示,但星星将主要为白色。
Our JavaScript becomes:
我们JavaScript变为:
function getRandom(min, max) {
return Math.floor(Math.random() * (max - min + 1)) + min;
}
var canvas = document.getElementById("starfield"),
context = canvas.getContext("2d"),
stars = 500,
colorrange = [0,60,240];
for (var i = 0; i < stars; i++) {
var x = Math.random() * canvas.offsetWidth;
y = Math.random() * canvas.offsetHeight,
radius = Math.random() * 1.2,
hue = colorrange[getRandom(0,colorrange.length - 1)],
sat = getRandom(50,100);
context.beginPath();
context.arc(x, y, radius, 0, 360);
context.fillStyle = "hsl(" + hue + ", " + sat + "%, 88%)";
context.fill();
}
The getRandom
function creates a random integer between two numbers (inclusive): with the hue
variable, it randomly selects a value of 0, 60, or 240 (avoiding green), and for saturation, a number from 50 to 100.
getRandom
函数在两个数字(包括两个数字)之间创建一个随机整数:使用hue
变量,它将随机选择一个0、60或240(避免绿色)的值,并为饱和度选择一个50到100的数字。
To quickly make the responsive, add a percentage width in CSS:
要快速使响应,请在CSS中添加一个百分比宽度:
canvas {
width: 100%;
height: auto;
background: #111;
}
The final result, shown at the top of this article, is pretty good, but does lack a few features:
最终结果显示在本文的顶部,效果不错,但是缺少一些功能:
Finally, it would be good to have the script draw stars appropriate for the current viewport*: when the is small, it tends to be overcrowded with 200 stars, while it looks a little large and scattered on larger screens. The
will be redrawn on viewport resize: that’s just its nature when it’s made responsive in this way - but it could still be improved.
最后,最好让脚本绘制适合当前视口的星星*: 较小时,它往往拥挤了200颗星星,而它看上去又大又散在较大的屏幕上。
将在视口调整大小时重绘:这就是它以这种方式进行响应时的本质,但是它仍可以改进。
As written, the starfield could make an excellent random background for a page: you’d just have to use absolute positioning, to ensure that it was always at the “back” of subsequent elements.
如所写,星空可以为页面提供出色的随机背景:您只需要使用绝对定位即可确保它始终位于后续元素的“背面”。
翻译自: https://thenewcode.com/81/Make-A-Starfield-Background-with-HTML5-Canvas
css画布星空