JSFiddle - React, Tailwind, and code Playground

HTML

<h1>Draw stroke on HTML canvas with different levels of opacity</h1>
<h2>Desired result</h2>
<img src="http://goo.gl/SJjL5U" />
<h2>Non-solution 1, 'darken' blend mode, opaque pixels</h2>
<canvas id="cv-darken-opaque" width="280" height="80"></canvas>
<h2>Non-solution 1, 'darken' blend mode, transparent pixels</h2>
<canvas id="cv-darken-transparent" width="280" height="80"></canvas>
<h2>Non-solution 2, 'destination-out' compositing operator</h2>
<canvas id="cv-destination-out" width="280" height="80"></canvas>

CSS

canvas {
    display: block;
}
h1 {
    font-family: Arial, sans-serif;
    font-size: 14px;
}
h2 {
    font-family: Arial, sans-serif;
    font-size: 12px;
}

JavaScript

var lineDarkenOpaque = function (cx, x0, y0, x1, y1, a) {
	var r, g, b;
	r = Math.round(a * 0 + 1 * 255 * (1 - a));
	g = Math.round(a * 0 + 1 * 255 * (1 - a));
	b = Math.round(a * 255 + 1 * 255 * (1 - a));
	cx.strokeStyle = 'rgb(' + r + ',' + g + ',' + b + ')';
	cx.globalCompositeOperation = 'darken';
	console.log(cx.strokeStyle);
	cx.beginPath();
	cx.moveTo(x0, y0);
	cx.lineTo(x1, y1);
	cx.stroke();
};

var lineDarkenTransparent = function (cx, x0, y0, x1, y1, a) {
	cx.strokeStyle = 'rgba(0,0,255,' + a + ')';
	cx.globalCompositeOperation = 'darken';
	console.log(cx.strokeStyle);
	cx.beginPath();
	cx.moveTo(x0, y0);
	cx.lineTo(x1, y1);
	cx.stroke();
};

var lineDestinationOut = function (cx, x0, y0, x1, y1, a) {
	cx.strokeStyle = 'rgba(0,0,255,' + a + ')';
	cx.globalCompositeOperation = 'destination-out';
	console.log(cx.strokeStyle);
	cx.beginPath();
	cx.moveTo(x0, y0);
	cx.lineTo(x1, y1);
	cx.stroke();
	cx.strokeStyle = 'rgba(0,0,255,' + a + ')';
	cx.globalCompositeOperation = 'source-over';
	console.log(cx.strokeStyle);
	cx.beginPath();
	cx.moveTo(x0, y0);
	cx.lineTo(x1, y1);
	cx.stroke();
};

var runTest = function (canvasId, lineFn) {
	var cv, cx;
	cv = document.getElementById(canvasId);
	cx = cv.getContext('2d');
	cx.lineCap = 'round';
	cx.lineJoin = 'round';
	cx.lineWidth = 40;
	lineFn(cx, 20, 20, 100, 20, 0.4);
	lineFn(cx, 100, 20, 180, 20, 0.1);
	lineFn(cx, 180, 20, 260, 20, 0.4);
	lineFn(cx, 260, 20, 220, 60, 0.1);
};

runTest('cv-darken-opaque', lineDarkenOpaque);
runTest('cv-darken-transparent', lineDarkenTransparent);
runTest('cv-destination-out', lineDestinationOut);