创建一个带阴影的圆锥体

Create a cone with shadows

我想创建一个具有特殊 阴影 效果的 。 喜欢这个:

.

它应该看起来像木头或金属制成的锥体。

我试图用 canvas 中的径向渐变做一些事情,但我无法创建那种特殊的效果。 我不知道如何创建这种阴影效果。

有人可以给我提示或帮助我吗?

这是我试过的:JSFiddle

var canvas = document.getElementById('canvas');
var ctx = canvas.getContext('2d');

var x = 100,
y = 75,
innerRadius = 1,
outerRadius = 70,
radius = 60;

ctx.arc(x, y, radius, 0, 2 * Math.PI);

var gradient = ctx.createRadialGradient(x, y, innerRadius, x, y, outerRadius);
gradient.addColorStop(0, '#FF9900');
gradient.addColorStop(1, '#FFFFFF');

ctx.fillStyle = gradient;
ctx.fill();

来自德国的问候 马祖曼

尝试使用

ctx.shadowBlur = 40;
ctx.shadowColor = "#FF9900";

画圆之前。 shadowBlur设置阴影的大小,如果你想禁用它可以设置为0。 shadowColor 不言自明。

不幸的是 canvas 中没有渐变类型允许您指定辐射渐变。您必须提供一种机制来手动执行此操作。

可以使用阴影方法在屏幕外绘制对象,同时偏移阴影,使其与圆锥体底部重叠。一个是亮的,一个是暗的。

通过绘制一个“light/dark 条纹”,根据角度以不同的不透明度级别围绕中心旋转,可以获得更好的效果。

“渲染”圆锥体的示例

此示例允许您调整参数,例如反射的可见度、颜色、锥体大小等。试验这些值以找到您想要的。

要偏移“光源”,只需在渲染重叠条纹之前以您需要的角度旋转一次。

var ctx = document.querySelector("canvas").getContext("2d"),
    cx = 75, cy = 75, radius = 70,     // for arc/cone
    maxOpacity = 1,                    // max opacity (will accumulate)
    angleStep = 0.01,                  // "resolution"
    angle = 0, t;                      // current angle and opacity

// draw base of cone
ctx.fillStyle = "rgb(139, 108, 33)";
ctx.arc(cx, cy, radius, 0, 2*Math.PI);
ctx.fill();

// now rotate around center drawing a white stripe at varying opacity
// depending on angle
ctx.fillStyle = "rgb(181, 159, 109)";
ctx.translate(cx, cy);                 // pivot for rotation = center of cone

// half of the cone is done with white overlay
for(angle = 0; angle < Math.PI; angle += angleStep) {
  // calculate t [0,1] based on angle. Multiply with max opacity
  t = (angle < Math.PI * 0.5 ? angle : Math.PI - angle) / Math.PI * maxOpacity;
  ctx.rotate(angleStep);               // increase angle by step
  ctx.globalAlpha = t;                 // set opacity to t
  drawStripe();                        // draw a small segment / "stripe"
}

// the other half of the cone is done with dark overlay
ctx.fillStyle = "rgb(95, 54, 5)";
for(angle = 0; angle < Math.PI; angle += angleStep) {
  t = (angle < Math.PI * 0.5 ? angle : Math.PI - angle) / Math.PI * maxOpacity;;
  ctx.rotate(angleStep);
  ctx.globalAlpha = t;
  drawStripe();
}

function drawStripe() {
  ctx.beginPath();
  ctx.lineTo(0, 0);
  ctx.arc(0, 0, radius, 0, angleStep*5);
  ctx.fill();
}

// top off by drawing a smaller circle on top
ctx.setTransform(1,0,0,1,0,0);          // reset transforms
ctx.globalAlpha = 1;                    // reset alpha
ctx.fillStyle = "rgb(130, 97, 32)";     // draw in a topping
ctx.beginPath();
ctx.arc(cx, cy, radius * 0.25, 0, 2*Math.PI);
ctx.fill();
<canvas></canvas>

使用阴影近似圆锥形状的示例

var ctx = document.querySelector("canvas").getContext("2d"),
    cx = 75, cy = 75, radius = 70, offset = radius * 2;

// draw base of cone
ctx.fillStyle = "rgb(139, 108, 33)";
ctx.arc(cx, cy, radius, 0, 2*Math.PI);
ctx.fill();

// offset next shape, couter-offset its shadow
ctx.translate(cx, offset*2);                    // make sure shape is drawn outside
ctx.scale(0.75, 1);                             // make shadow more narrow
ctx.globalCompositeOperation = "source-atop";   // comp. on top of existing pixels

ctx.shadowOffsetY = -offset * 1.1;              // counter-offset shadow
ctx.shadowBlur = 25;                            // some blur
ctx.shadowColor = "rgba(181, 159, 109, 1)";   // highlight color

ctx.beginPath();                                // draw new shape
ctx.arc(0, 0, radius * 0.6, 0, 2*Math.PI);      // reduce radius ~50%
ctx.fill();

ctx.shadowOffsetY = -offset * 1.8;              // counter-offset shadow
ctx.shadowColor = "rgba(95, 54, 5, 0.7)";       // shadow
ctx.beginPath();                                // draw new shape
ctx.arc(0, 0, radius * 0.6, 0, 2*Math.PI);      // reduce radius ~50%
ctx.fill();

// top off by drawing a smaller circle on top
ctx.setTransform(1,0,0,1,0,0);                  // reset transforms
ctx.globalCompositeOperation = "source-over";   // reset comp. mode
ctx.fillStyle = "rgb(130, 97, 32)";             // draw in a topping
ctx.beginPath();
ctx.arc(cx, cy, radius * 0.25, 0, 2*Math.PI);
ctx.fill();
<canvas></canvas>