【问题标题】:Shadow Overlapping Polygon阴影重叠多边形
【发布时间】:2018-01-25 23:36:58
【问题描述】:

我正在尝试在我的 trihex 后面添加一个阴影,但阴影在实际图像应该位于它后面时却与实际图像重叠。我已经尝试过解决这个问题,但是添加临时画布或以某种方式将 trihex 向前移动都可以。 这是 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();
}

基本上,有一点阴影与三进制重叠。

【问题讨论】:

  • 描边也会产生阴影。所以你有两个影子。一个用于填充,另一个在顶部绘制的是描边的阴影。在绘制描边之前,您需要关闭阴影,否则您将需要一些更复杂的代码才能使阴影正确。
  • 当你说在描边之前关闭阴影,这是什么意思?我应该将阴影移到函数之外吗?
  • 我从函数中取出描边并将其更改为之后调用,但由于某种原因,只有左六边形获得了白色描边样式,看起来它在图像的其余部分之上.
  • 我刚刚看了你的小提琴,它需要一些更复杂的工作才能获得阴影,因为你也会从一个十六进制中获得阴影。您需要分两遍绘制六角形。首先绘制所有打开阴影的六角形。这将创建基础阴影。但有过圈。然后重新绘制所有的六边形,但没有阴影。或者将十六进制绘制到屏幕外的画布上,然后将带有阴影的画布绘制到显示画布上。
  • 我只是尝试实现重绘并没有产生结果,阴影似乎仍然出现。也许我做错了?如果不是太麻烦的话,你可以用那个 jsfiddle 演示一下。

标签: javascript canvas shadow


【解决方案1】:

通过分层的阴影。

2D 画布上的阴影仅用于最简单的渲染。它们很慢,如果你有不止一种颜色,你最终会遇到各种分层和构图问题。

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

然后,当所有的阴影都被绘制出来后,你再进行下一层渲染顶层,这样阴影就不会与上面的层重叠。

两个通道阴影的快速示例。

// 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> 

使用精灵是另一种选择。

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

【讨论】:

    猜你喜欢
    • 2017-09-22
    • 2018-08-29
    • 2018-01-01
    • 2015-11-15
    • 1970-01-01
    • 2020-12-29
    • 1970-01-01
    • 1970-01-01
    • 2017-03-24
    相关资源
    最近更新 更多