javascript - 阴影重叠多边形

标签 javascript canvas shadow

我正在尝试在我的三 Angular 形后面添加阴影,但阴影在实际图像应该位于其后面时与实际图像重叠。我已经尝试修复此问题,但添加临时 Canvas 或以某种方式将三边形向前移动都可以。 这是 jsfiddle 链接,因此您可以看到我在说什么:https://jsfiddle.net/r0dkeu1g/3/

这里是创建阴影的地方:

function drawHexagon(canvasContext, x, y, fill) {
    fill++;           
    var fill = fill || false;

    canvasContext.shadowColor = "rgb(45, 44, 44)"; //Here is the shadow
    canvasContext.shadowBlur = 5;
    canvasContext.shadowOffsetX = 5;
    canvasContext.shadowOffsetY = 5; //Shadow Ends

    canvasContext.beginPath(); //Start drawing hexagaon
    canvasContext.moveTo(x + hexRadius, y);
    canvasContext.lineTo(x + hexRectangleWidth, y + hexHeight);
    canvasContext.lineTo(x + hexRectangleWidth, y + hexHeight + sideLength);
    canvasContext.lineTo(x + hexRadius, y + hexRectangleHeight);
    canvasContext.lineTo(x, y + sideLength + hexHeight);
    canvasContext.lineTo(x, y + hexHeight);
    canvasContext.closePath(); // Stop drawing hexagon
    //Unrelated, this is just where some colors are set
    if(fill) {
        switch(fill){
            case 1:
                canvasContext.fillStyle = JUNGLECOLOR;
                break;
            case 2:                 
                canvasContext.fillStyle = GRASSCOLOR;
                break;
            case 3:
                canvasContext.fillStyle = DESERTCOLOR;
                break;
            case 4:
                canvasContext.fillStyle = QUARRYCOLOR;
                break;
            case 5:
                canvasContext.fillStyle = LAGOONCOLOR;
                break;
            default:
                break;
        }
    }
    else{
        canvasContext.fillStyle = VOLCANOCOLOR;
    }
        canvasContext.fill();
        canvasContext.strokeStyle = "white";
        canvasContext.stroke();
}

基本上,有一点阴影与三 Angular 形重叠。

最佳答案

通过分层产生阴影。

2D Canvas 上的阴影除了最简单的渲染之外没有任何意义。它们很慢,如果你有不止一种颜色,你最终会遇到各种分层和构图问题。

解决您问题的最快方法是分两次渲染(或图层)。第一层或所谓的阴影 channel 是在打开阴影的情况下绘制的。

然后,当绘制完所有阴影后,再进行下一层渲染顶层,以便没有阴影与上面的层重叠。

两个 channel 阴影的快速示例。

// the colours from your fiddle

const JUNGLECOLOR  = 'rgba(0, 100, 0, 255)'; 
const GRASSCOLOR   = 'rgba(0, 225, 0, 255)'; 
const DESERTCOLOR  = 'rgba(255, 201, 102, 255)';
const QUARRYCOLOR  = 'rgba(123, 123, 139, 255)';
const LAGOONCOLOR  = 'rgba(0, 191, 255, 255)';
const VOLCANOCOLOR = 'rgba(255, 48, 48, 255)';
var colors = [JUNGLECOLOR, GRASSCOLOR , DESERTCOLOR, QUARRYCOLOR, LAGOONCOLOR, VOLCANOCOLOR ];

// Get context and set settings
const ctx = canvas.getContext("2d");
const hexSize = 40;
const hexGridCenterX = 150;
const hexGridCenterY = 100;
ctx.lineWidth = 2;


// function only creates a hex path does not draw
function drawHex(x,y,size){
  ctx.moveTo(x ,       y - size);
  ctx.lineTo(x + size, y - size/2);
  ctx.lineTo(x + size, y + size/2);
  ctx.lineTo(x ,       y + size);  
  ctx.lineTo(x - size, y + size/2);
  ctx.lineTo(x - size, y - size/2);
  ctx.closePath();
}

// Draw a hex with colour and outline. Calls the function above.
function drawHexColor(x, y, size, col){
  ctx.beginPath();
  ctx.fillStyle = col;

  ctx.strokeStyle = "white";
  drawHex(x,y,size);
  ctx.fill();
  ctx.stroke()
}

// Draws all hexs at once so that the shadows are not
// overlapping each other, which is just as bad as over lapping stuff
// above.
function shadowPass(){
   const x = hexGridCenterX;
   const y = hexGridCenterY;
   ctx.save(); // save state 
   ctx.shadowColor = "rgb(45, 44, 44)";
   ctx.shadowBlur = 5;
   ctx.shadowOffsetX = 5;
   ctx.shadowOffsetY = 5;
   ctx.fillStyle = "black";
   ctx.beginPath(); // the colour does not mater at the moment
   drawHex(x - hexSize, y + hexSize, hexSize);
   drawHex(x + hexSize, y + hexSize, hexSize);
   drawHex(x          , y - hexSize + hexSize / 2, hexSize);
   ctx.fill(); // creates the shadows;
   ctx.restore(); // restore the state which turns off shadows
}

// Draws just the hexs with color and no shadow
function colorPass(){
   const x = hexGridCenterX;
   const y = hexGridCenterY;

   drawHexColor(x - hexSize, y + hexSize, hexSize, colors[2]);
   drawHexColor(x + hexSize, y + hexSize, hexSize, colors[1]);
   drawHexColor(x          , y - hexSize + hexSize / 2, hexSize, colors[5]);

}


// Draw shadows first
shadowPass(); // that puts the shadow under everything
// Then draw the colours without shadows ontop
colorPass();



  
<canvas id="canvas" width="300" height="300"></canvas> 

使用 Sprite 是另一种选择。

个人而言,这种类型的显示最适合预渲染内容。将十六进制和阴影绘制为位图 Sprite ,然后将它们分层。但这是很多工作。

关于javascript - 阴影重叠多边形,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/48453663/

相关文章:

javascript - 如何安全地存储服务器端使用的密码?

javascript - HTML5 Canvas - 在 Canvas 上拖动文本问题

css - html 在不拉伸(stretch) Canvas 的情况下在 div 中居中 Canvas

swift - SceneKit – 来自定向光的阴影取决于相机角度

javascript - 记录javascript错误

javascript - background.html 与 background.js - chrome 扩展

html - 文本阴影不适用于 Opera

css - Bootstrap Image Circle 内阴影

javascript - 如何合并 typescript 模块定义

java - 如何在启动时生成SWT绘制事件