I am trying to add a drop shadow behind my trihex, but the shadow overlaps the actual image when it should be behind it. I've tried fixing this, but either adding a temporary canvas or somehow bringing the trihex forward just does work. Here's the jsfiddle link so you can see what I'm talking about: https://jsfiddle.net/r0dkeu1g/3/
Here is where the shadow is being created:
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();
}
Basically, there's a bit of the shadow overlapping the trihex.
The shadows on 2D canvas are not mean for anything but the simplest of rendering. They are slow and if you have more than one color you end up with all sorts of layering and composition problems.
The quickest solution for your problem is to render in two passes (or layers). First layer or so called shadow pass is when you draw with the shadows turned on.
Then when all the shadows are drawn you then do the next layer rendering the top layer so that no shadows overlap the layer above.
// 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>
Personally this type of display is best suited to pre rendered content. Draw the hexs and shadows as bitmap sprites and then layer them. But that is a lot of work.