我认为这是一个常见的问题,但我在画布上显示点有一些问题。我想知道的第一件事是如何绘制像this这样的点(请缩放它)。 第二件事是,如何在这个点的网格的每个元素上绘制阴影,光源位于中心。
目前我所拥有的here:
我的代码部分:
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];
}
另外,我尝试使用“context.arc();”,但我认为“context.fillRect();”更容易。还有一个时刻,当我使用“while(--e&gt; = 0)”代替“while(--e&gt; = 1)”时,我还有两个点,在顶部。为什么呢?
如果你知道一些文章或教程,你会给我链接吗?优选地,不使用框架。感谢。
答案 0 :(得分:2)
您可以使用一些三角函数来模拟光源的3D点。
<强> HERE IS AN ONLINE DEMO 强>
这是你可以做到的一种方式,当然还有其他方式(这是第一个想到的):
以下是演示中的一些代码。
用点绘制网格
我们跳过一个网格点,因为我们稍后会用渐变点填充每个点,否则会在相邻点上绘制。
/// 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
将其缩小到主画布。