The question is ambiguous as there are many ways to "fillRect with an image".
First off images in the browser are downloaded asynchronously so you need to wait for an image to load before you can use it. For canvas situations the most common way to get an image is to create a new Image
and set an onload
listener
const img = new Image();
img.onload = someFunctionToCallWhenTheImageHasLoaded
img.src = 'http://url/to/image';
Then the question is what do mean by "fillRect"
Using this 256x256 image

For example to draw the image at the size it was downloaded you can use drawImage
with 3 arguments
ctx.drawImage(img, x, y);

const img = new Image();
img.onload = draw;
img.src = 'https://i.stack.imgur.com/CbEMh.png';
function draw() {
const ctx = document.querySelector('canvas').getContext('2d');
ctx.drawImage(img, 0, 0);
}
canvas { border: 1px solid black; }
<canvas></canvas>
To draw the image at a different size you can use
ctx.drawImage(img, x, y, width, height);

const img = new Image();
img.onload = draw;
img.src = 'https://i.stack.imgur.com/CbEMh.png';
function draw() {
const ctx = document.querySelector('canvas').getContext('2d');
const destX = 10;
const destY = 20;
const destWidth = 30;
const destHeight = 40;
ctx.drawImage(img, destX, destY, destWidth, destHeight);
}
canvas { border: 1px solid black; }
<canvas></canvas>
To draw part of the image you can use
// part of image to draw
const srcX = 10;
const srcY = 20;
const srcWidth = 130;
const srcHeight = 140;
// where to draw it
const dstX = 60;
const dstY = 70;
const dstWidth = 160;
const dstHeight = 40;
ctx.drawImage(img, srcX, srcY, srcWidth, srcHeight,
dstX, dstY, dstWidth, dstHeight);

const img = new Image();
img.onload = draw;
img.src = 'https://i.stack.imgur.com/CbEMh.png';
function draw() {
const ctx = document.querySelector('canvas').getContext('2d');
// part of image to draw
const srcX = 10;
const srcY = 20;
const srcWidth = 130;
const srcHeight = 140;
// where to draw it
const dstX = 60;
const dstY = 70;
const dstWidth = 160;
const dstHeight = 40;
ctx.drawImage(img, srcX, srcY, srcWidth, srcHeight,
dstX, dstY, dstWidth, dstHeight);
}
canvas { border: 1px solid black; }
<canvas></canvas>
That said, "fillRect" being ambiguous maybe you wanted to use the image as a pattern in which case you need to make a pattern out of it using createPattern
const pattern = ctx.createPatttern(img, 'repeat');
For these let's use this 16x16 pixel image

You can then use the pattern as your fillStyle as in
ctx.fillStyle = pattern;
ctx.fillRect(10, 20, 30, 40);

const img = new Image();
img.onload = draw;
img.src = 'https://i.stack.imgur.com/HlmSe.png';
function draw() {
const ctx = document.querySelector('canvas').getContext('2d');
const pattern = ctx.createPattern(img, 'repeat');
ctx.fillStyle = pattern;
ctx.fillRect(10, 20, 30, 40);
}
canvas { border: 1px solid black; }
<canvas></canvas>
Patterns are relative to the origin of the canvas which means if you just use ctx.fillRect
(or any other fill) the pattern will match across fills.
ctx.fillRect(10, 20, 30, 40);
ctx.beginPath();
ctx.arc(50, 60, 25, 0, Math.PI * 2);
ctx.fill();

const img = new Image();
img.onload = draw;
img.src = 'https://i.stack.imgur.com/HlmSe.png';
function draw() {
const ctx = document.querySelector('canvas').getContext('2d');
const pattern = ctx.createPattern(img, 'repeat');
ctx.fillStyle = pattern;
ctx.fillRect(10, 20, 30, 40);
ctx.beginPath();
ctx.arc(50, 60, 25, 0, Math.PI * 2);
ctx.fill();
}
canvas { border: 1px solid black; }
<canvas></canvas>
Because patterns are anchored at the origin if you are animating without changing the origin you'll notice the pattern doesn't move
const img = new Image();
img.onload = start;
img.src = 'https://i.stack.imgur.com/HlmSe.png';
function start() {
const ctx = document.querySelector('canvas').getContext('2d');
const pattern = ctx.createPattern(img, 'repeat');
function render(time) {
time *= 0.001; // seconds;
ctx.clearRect(0, 0, ctx.canvas.width, ctx.canvas.height);
const x = Math.sin(time * 1.1) * 150 + 150;
const y = Math.sin(time * 1.2) * 50 + 50;
ctx.fillStyle = pattern;
ctx.fillRect(x, y, 30, 40);
ctx.beginPath();
ctx.arc(x, y, 25, 0, Math.PI * 2);
ctx.fill();
requestAnimationFrame(render);
}
requestAnimationFrame(render);
}
canvas { border: 1px solid black; }
<canvas></canvas>
In order to move the pattern you need to move the origin of the canvas using ctx.translate
(as well as ctx.rotate
, ctx.scale
, ctx.setTransform
)
const img = new Image();
img.onload = start;
img.src = 'https://i.stack.imgur.com/HlmSe.png';
function start() {
const ctx = document.querySelector('canvas').getContext('2d');
const pattern = ctx.createPattern(img, 'repeat');
function render(time) {
time *= 0.001; // seconds;
ctx.clearRect(0, 0, ctx.canvas.width, ctx.canvas.height);
const x = Math.sin(time * 1.1) * 150 + 150;
const y = Math.sin(time * 1.2) * 50 + 50;
ctx.translate(x, y);
ctx.fillStyle = pattern;
ctx.fillRect(0, 0, 30, 40);
ctx.beginPath();
ctx.arc(0, 0, 25, 0, Math.PI * 2);
ctx.fill();
ctx.setTransform(1, 0, 0, 1, 0, 0); // set it back to the default
requestAnimationFrame(render);
}
requestAnimationFrame(render);
}
canvas { border: 1px solid black; }
<canvas></canvas>