1

I think it's usual question, but I have some problems with displaying dots in canvas. The first thing I'd like to know is how to draw dot like this (please zoom it). The second thing is, how to draw a shadow to each element of the grid of this dots, with the light source in the center.

What I have at this moment right here:

the part of my code:

context.fillStyle = "#ccc";

context.shadowColor = '#e92772';
context.shadowOffsetX = 15;
context.shadowOffsetY = 15;

while (--e >= 1) {
    x -= z;
    if(x < 0) {
        x = z*w;
        y -= z;
    }
    context.moveTo(x, y);
    context.fillRect( x, y, 1, 1 );
    outs = a[e];
}

Also, I've tried to use "context.arc();", but I think "context.fillRect();" is more easier. And one else moment, when I use "while (--e >= 0)" instead of "while (--e >= 1)" I have two more dots, on the top. Why?

If you know some articles or tutorials, would you give me the link to them. Preferably without the use of the frameworks. Thanks.

4

1 回答 1

2

您可以使用一些三角函数来模拟带有光源的 3D 点。

这是一个在线演示

这是您可以做到的一种方式,当然还有其他方式(这是第一个想到的):

  • 在主画布上用一些点绘制网格
  • 将径向渐变渲染到屏幕外画布
  • 更改合成模式,以便在现有像素上绘制任何内容
  • 计算到光源的距离和角度,并将点绘制到每个网格点偏移角度/距离。

这是演示中的一些代码。

用点绘制网格

我们跳过一个网格点,因为稍后我们将用渐变点填充每个点,否则会在相邻点上绘制。

/// draw a grid of dots:
for (y = 0; y < ez.width; y += gridSize * 2) {
    for (x = 0; x < ez.height; x += gridSize * 2) {
        ctx.beginPath();
        ctx.arc(x + offset, y + offset, radius, 0, arcStop);
        ctx.closePath();
        ctx.fill();
    }
}

创造光“反射”

将渐变点准备到屏幕外的画布(dctx= dot-context)。我正在使用easyCanvas进行设置,并给我一个已经计算出中心点的屏幕外画布,但当然也可以手动设置:

grd = dctx.createRadialGradient(dot.centerX, dot.centerY, 0,
                                dot.centerX, dot.centerY, gridSize);
grd.addColorStop(0, '#fff');
grd.addColorStop(0.2, '#777'); // thighten up
grd.addColorStop(1, '#000');

dctx.fillStyle = grd;
dctx.fillRect(0, 0, gridSize, gridSize);

算一算

然后我们进行所有的计算和偏移:

/// change composition mode
ctx.globalCompositeOperation = 'source-atop';

/// calc angle and distance to light source and draw each
/// dot gradient offset in relation to this
for (y = 0; y < ez.width; y += gridSize) {
    for (x = 0; x < ez.height; x += gridSize) {

        /// angle
        angle = Math.atan2(lightY - y, lightX - x);
        //if (angle < 0) angle += 2;

        /// distance
        dx = lightX - x;
        dy = lightY - y;
        dist = Math.sqrt(dx * dx + dy * dy);

        /// map distance to our max offset
        od = dist / maxLength * maxOffset * 2;
        if (od > maxOffset * 2) od = maxOffset * 2;

        /// now get new x and y position based on angle and offset
        offsetX = x + od * Math.cos(angle) - maxOffset * 0.5;
        offsetY = y + od * Math.sin(angle) - maxOffset * 0.5;

        /// draw the gradient dot at offset
        ctx.drawImage(dot.canvas, x + offsetX, y + offsetY);
    }
}

阴影

destination-over对于阴影,您只需在使用将在已绘制像素之外绘制的合成模式时反转偏移量:

/// Shadow, same as offsetting light, but in opposite
/// direction and with a different composite mode
ctx.globalCompositeOperation = 'destination-over';

for (y = 0; y < ez.width; y += gridSize) {
    for (x = 0; x < ez.height; x += gridSize) {

        /// angle
        angle = Math.atan2(lightY - y, lightX - x);
        //if (angle < 0) angle += 2;

        /// distance
        dx = lightX - x;
        dy = lightY - y;
        dist = Math.sqrt(dx * dx + dy * dy);

        /// map distance to our max offset
        od = dist / maxLength * maxOffset * 2;
        if (od > maxOffset * 4) od = maxOffset * 4;

        /// now get new x and y position based on angle and offset
        offsetX = x - od * Math.cos(angle) + gridSize * 0.5;
        offsetY = y - od * Math.sin(angle) + gridSize * 0.5;

        ctx.beginPath();
        ctx.arc(x + offsetX, y + offsetY, radius, 0, arcStop);
        ctx.fill();

    }
}

当然,这都可以优化为单个循环对,但为了概述,代码是分开的。

额外的

在演示中,我添加了鼠标跟踪,因此鼠标成为光源,您可以在移动鼠标时看到点反射的变化。为了获得最佳性能,请使用 Chrome。

为了满足您的需要,只需缩小我正在使用的值 - 或 - 绘制到一个大的屏幕外画布并使用drawImage将其缩小到主画布。

于 2013-08-09T16:23:57.347 回答