Вам нужно смешать ваш шум с градиентом. Вы не можете напрямую смешивать ImageData, вам нужно сначала преобразовать его в растровое изображение (это можно сделать на холсте). Поэтому вместо оверлея , в котором говорилось о вашем уроке, вы можете предпочесть hard-light
, который изменит порядок наших слоев.
const w = 300;
const h = 300;
const canvas = document.getElementById( 'canvas' );
const ctx = canvas.getContext( '2d' );
// some colored noise
const data = Uint32Array.from( {length: w*h }, () => Math.random() * 0xFFFFFFFF );
const img = new ImageData( new Uint8ClampedArray( data.buffer ), w, h );
ctx.putImageData( img, 0, 0 );
// first pass to convert our noise to black and transparent
ctx.globalCompositeOperation = "color";
ctx.fillRect( 0, 0, w, h );
ctx.globalCompositeOperation = "hard-light";
ctx.fillStyle = ctx.createLinearGradient( 0, 0, 0, h );
ctx.fillStyle.addColorStop( 0.1, 'white' );
ctx.fillStyle.addColorStop( 0.9, 'black' );
ctx.fillRect( 0, 0, w, h );
canvas { background: lime; }
<canvas id="canvas" height="300"></canvas>
Но смешивание требует наличия непрозрачной сцены. Если вы хотите иметь прозрачность, вам также придется использовать композитинг:
const w = 300;
const h = 300;
const canvas = document.getElementById( 'canvas' );
const ctx = canvas.getContext( '2d' );
// some black and transparent noise
const data = Uint32Array.from( {length: w*h }, () => Math.random() > 0.5 ? 0xFF000000 : 0 );
const img = new ImageData( new Uint8ClampedArray( data.buffer ), w, h );
ctx.putImageData( img, 0, 0 );
ctx.fillStyle = ctx.createLinearGradient( 0, 0, 0, h );
ctx.fillStyle.addColorStop( 0.1, 'transparent' );
ctx.fillStyle.addColorStop( 0.9, 'black' );
// apply transparency gradient on noise (dim top)
ctx.globalCompositeOperation = "destination-in";
ctx.fillRect( 0, 0, w, h );
// apply black of the gradient on noise (darken bottom)
ctx.globalCompositeOperation = "multiply";
ctx.fillRect( 0, 0, w, h );
// optionally change the color of the noise
ctx.globalCompositeOperation = "source-atop";
ctx.fillStyle = "red";
ctx.fillRect( 0, 0, w, h );
canvas { background: lime; }
<canvas id="canvas" height="300"></canvas>