Company logo
  • Empleos
  • Bootcamp
  • Acerca de nosotros
  • Para profesionales
    • Inicio
    • Empleos
    • Cursos y retos
    • Preguntas
    • Profesores
    • Bootcamp
  • Para empresas
    • Inicio
    • Nuestro proceso
    • Planes
    • Pruebas
    • Nómina
    • Blog
    • Comercial
    • Calculadora

0

73
Vistas
How to create a common shadow for multiple strokes in a single canvas?

I'm trying to draw multiple strokes on a canvas and I'd like them to have a common shadow. Currently the cast shadows on one another which is not what I want.

Ideal result

ideal result

What I've tried

  • Creating shadow using ctx.shadowColor jsfiddle
  • Creating shadow using ctx.filter jsfiddle
  • Creating shadow using css box-shadow on the canvas -- draws shadow on the whole box
  • Creating shadow using css filter on the canvas -- draws shadow on the whole box
7 months ago · Juan Pablo Isaza
2 Respuestas
Responde la pregunta

0

If you need each stroke to be independent (i.e so that they have each their own strokeStyle or lineWidth), you will need to use a second detached canvas:

  • on this detached canvas you draw all your strokes without shadow
  • you drawImage that detached canvas on the visible one with the shadow:

const canvas = document.querySelector("canvas");
const ctx = canvas.getContext("2d");
const detached = canvas.cloneNode();
const detachedCtx = detached.getContext("2d");
const colors = ["green", "blue", "yellow", "orange", "aqua"];  

detachedCtx.lineWidth = 5;
for (let color of colors) {
  // draw on the detached canvas
  detachedCtx.beginPath();
  for (let i = 0; i<5; i++) {
    detachedCtx.lineTo(Math.random() * canvas.width, Math.random() * canvas.height);
  }
  detachedCtx.strokeStyle = color;
  detachedCtx.lineWidth = Math.random() * 8 + 2;
  detachedCtx.stroke();
}

// now draw all this with shadows on the visible canvas
ctx.shadowOffsetX = 3;
ctx.shadowOffsetY = 3;
ctx.shadowBlur    = 3;
ctx.shadowColor   = "red";
ctx.drawImage(detached, 0, 0);
<canvas></canvas>

But to produce the image you have all you need is to call stroke() only once after you did compose your full path:

const canvas = document.querySelector("canvas");
const ctx = canvas.getContext("2d");

ctx.fillStyle = "#0F0";
ctx.fillRect(0, 0, canvas.width, canvas.height);
ctx.lineWidth = 5;
ctx.shadowOffsetX = -3;
ctx.shadowOffsetY = -3;
ctx.shadowBlur    = 3;
ctx.shadowColor   = "red";
ctx.moveTo(10, 50);
ctx.lineTo(90, 50);
ctx.moveTo(50, 10);
ctx.lineTo(50, 90);
ctx.stroke(); // stroke only once, with the full path being traced
<canvas width=100 height=100></canvas>

7 months ago · Juan Pablo Isaza Denunciar

0

You can use Path2D and add all your segments to one path, then do the stroke to that path.

Here is your jsfiddle using ctx.filter with my recommendation.

const segments = [
 [{x: 10, y: 50}, {x: 50, y: 50}],
 [{x: 50, y: 10}, {x: 50, y: 50}],
 [{x: 90, y: 50}, {x: 50, y: 50}],
 [{x: 50, y: 90}, {x: 50, y: 50}],
]

let path = new Path2D()
segments.forEach(segment => {  
  path.moveTo(segment[0].x, segment[0].y)
  path.lineTo(segment[1].x, segment[1].y)  
})

const ctx = document.getElementById('my-canvas').getContext('2d')
ctx.lineWidth = 5
ctx.filter = 'drop-shadow(-3px -3px 3px #f00)';
ctx.strokeStyle = 'black'
ctx.stroke(path)
<canvas width="100" height="100" id="my-canvas" style="background: #00ff00"/>

You can read more about Path2D here:
https://developer.mozilla.org/en-US/docs/Web/API/Path2D/Path2D

7 months ago · Juan Pablo Isaza Denunciar
Responde la pregunta
Encuentra empleos remotos