Skip to main content

HTML5 Canvas Disable Perfect Drawing Tip

In some cases drawing on canvas has unexpected results. For example, let's draw a shape with fill, stroke and opacity. As strokes are drawn on top of fill, there's a line of half the size of the stroke inside the shape which is darker because it's the intersection of the fill and the stroke.

Probably that is not expected for you. So Konva fixes such behavior with using buffer canvas.

In this case Konva is doing these steps:

  1. Draw shape on buffer canvas
  2. Fill and stroke it WITHOUT opacity
  3. Apply opacity on layer's canvas
  4. Then draw on layer canvas result from buffer

Using a buffer canvas is extra work on every draw. Since Konva 10.7.0, built-in shapes use a buffer only as large as the shape, and Konva frees it when it is no longer used. A custom shape gets a buffer the size of the whole canvas, unless it describes its painted area with selfRectFunc.

If you draw many translucent shapes with fill and stroke, you can disable such fixing:

shape.perfectDrawEnabled(false);

See difference here:

import Konva from 'konva';

const stage = new Konva.Stage({
container: 'container',
width: window.innerWidth,
height: window.innerHeight,
});

const layer = new Konva.Layer();
stage.add(layer);

// With perfect drawing (default)
const perfectCircle = new Konva.Circle({
x: 100,
y: 100,
radius: 50,
fill: 'red',
stroke: 'black',
strokeWidth: 10,
opacity: 0.5,
});

// Without perfect drawing
const nonPerfectCircle = new Konva.Circle({
x: 250,
y: 100,
radius: 50,
fill: 'red',
stroke: 'black',
strokeWidth: 10,
opacity: 0.5,
perfectDrawEnabled: false,
});

// Add labels
const perfectLabel = new Konva.Text({
x: 50,
y: 170,
text: 'Perfect Drawing',
fontSize: 16,
});

const nonPerfectLabel = new Konva.Text({
x: 200,
y: 170,
text: 'Perfect Drawing Disabled',
fontSize: 16,
});

layer.add(perfectCircle);
layer.add(nonPerfectCircle);
layer.add(perfectLabel);
layer.add(nonPerfectLabel);