diff --git a/examples/web/index.ts b/examples/web/index.ts
index 4bce785195942390dd8fed2f23321146381ca354..3261d7478f4e4214920e639c7e3d7b1716cde18a 100644
--- a/examples/web/index.ts
+++ b/examples/web/index.ts
@@ -524,6 +524,10 @@ class GameboyEmulator extends Observable implements Emulator {
         return this.fps;
     }
 
+    getTile(index: number): Uint8Array {
+        return this.gameBoy!.get_tile_buffer(index);
+    }
+
     toggleRunning() {
         if (this.paused) {
             this.resume();
diff --git a/examples/web/react/app.tsx b/examples/web/react/app.tsx
index 25c8ab4fc329c177f637e55795e2228fbf8c1d0d..dbdafd8857af56853448f4b53dec1784f0d79cc4 100644
--- a/examples/web/react/app.tsx
+++ b/examples/web/react/app.tsx
@@ -21,6 +21,7 @@ import {
     PanelSplit,
     Paragraph,
     Section,
+    Tiles,
     Title,
     Toast
 } from "./components";
@@ -159,6 +160,8 @@ export interface Emulator extends ObservableI {
      */
     getFramerate(): number;
 
+    getTile(index: number): Uint8Array;
+
     /**
      * Boot (or reboots) the emulator according to the provided
      * set of options.
@@ -443,6 +446,10 @@ export const App: FC<AppProps> = ({ emulator, backgrounds = ["264653"] }) => {
                             onClearHandler={onClearHandler}
                             onMinimize={onMinimize}
                         />
+                        <Tiles
+                            getTile={(index) => emulator.getTile(index)}
+                            tileCount={384}
+                        />
                         <KeyboardGB />
                     </div>
                 }
diff --git a/examples/web/react/components/canvas/canvas.css b/examples/web/react/components/canvas/canvas.css
new file mode 100644
index 0000000000000000000000000000000000000000..e69de29bb2d1d6434b8b29ae775ad8c2e48c5391
diff --git a/examples/web/react/components/canvas/canvas.tsx b/examples/web/react/components/canvas/canvas.tsx
new file mode 100644
index 0000000000000000000000000000000000000000..b3c4df8f58e82014ed30f0cf2bf254c0515eb8a2
--- /dev/null
+++ b/examples/web/react/components/canvas/canvas.tsx
@@ -0,0 +1,70 @@
+import React, { FC, useEffect, useRef } from "react";
+
+import "./canvas.css";
+
+export type CanvasStructure = {
+    canvas: HTMLCanvasElement;
+    canvasContext: CanvasRenderingContext2D;
+    canvasImage: ImageData;
+    canvasBuffer: DataView;
+};
+
+type CanvasProps = {
+    width: number;
+    height: number;
+    scale?: number;
+    style?: string[];
+    onCanvas?: (structure: CanvasStructure) => void;
+};
+
+export const Canvas: FC<CanvasProps> = ({
+    width,
+    height,
+    scale = 1,
+    style = [],
+    onCanvas
+}) => {
+    const classes = () => ["canvas", ...style].join(" ");
+    const canvasRef = useRef<HTMLCanvasElement>(null);
+    useEffect(() => {
+        if (canvasRef.current) {
+            const structure = initCanvas(
+                width,
+                width,
+                scale,
+                canvasRef.current
+            );
+            onCanvas && onCanvas(structure);
+        }
+    }, [canvasRef]);
+    return (
+        <canvas
+            ref={canvasRef}
+            className={classes()}
+            width={width}
+            height={height}
+        />
+    );
+};
+
+const initCanvas = (
+    width: number,
+    height: number,
+    scale: number,
+    canvas: HTMLCanvasElement
+): CanvasStructure => {
+    const canvasContext = canvas.getContext("2d")!;
+    canvasContext.imageSmoothingEnabled = false;
+
+    const canvasImage = canvasContext.createImageData(width, height);
+    const canvasBuffer = new DataView(canvasImage.data.buffer);
+
+    return {
+        canvas: canvas,
+        canvasContext: canvasContext,
+        canvasImage: canvasImage,
+        canvasBuffer: canvasBuffer
+    };
+};
+
+export default Canvas;
diff --git a/examples/web/react/components/index.ts b/examples/web/react/components/index.ts
index 1de0da2be5d18c6e7531c5ea8a79b3a91e1a22db..838636b94e5c09949d1234242e97bcdccf67ca09 100644
--- a/examples/web/react/components/index.ts
+++ b/examples/web/react/components/index.ts
@@ -2,6 +2,7 @@ export * from "./button/button";
 export * from "./button-container/button-container";
 export * from "./button-increment/button-increment";
 export * from "./button-switch/button-switch";
+export * from "./canvas/canvas";
 export * from "./display/display";
 export * from "./footer/footer";
 export * from "./info/info";
diff --git a/examples/web/react/components/tiles/tiles.tsx b/examples/web/react/components/tiles/tiles.tsx
index a6f522a4d54e7eb0f10bea0c3fa69e69305a2c0a..e9e3cc4bad6d46585f76a2333b0ded1f7878f1f3 100644
--- a/examples/web/react/components/tiles/tiles.tsx
+++ b/examples/web/react/components/tiles/tiles.tsx
@@ -1,17 +1,30 @@
 import React, { FC } from "react";
 import { PixelFormat } from "../../app";
+import Canvas, { CanvasStructure } from "../canvas/canvas";
 
 import "./tiles.css";
 
 type TilesProps = {
+    getTile: (index: number) => Uint8Array;
+    tileCount: number;
     style?: string[];
 };
 
-export const Tiles: FC<TilesProps> = ({ style = [] }) => {
+export const Tiles: FC<TilesProps> = ({ getTile, tileCount, style = [] }) => {
     const classes = () => ["title", ...style].join(" ");
+    const onCanvas = (structure: CanvasStructure) => {
+        console.info("On canvas");
+        setTimeout(() => {
+            for (let index = 0; index < 384; index++) {
+                const pixels = getTile(index);
+                console.info("VAI desenhar");
+                drawTile(index, pixels, structure);
+            }
+        }, 1000);
+    };
     return (
         <div className={classes()}>
-            <canvas className="canvas-tiles" width="128" height="192"></canvas>
+            <Canvas width={128} height={192} scale={2} onCanvas={onCanvas} />
         </div>
     );
 };
@@ -23,24 +36,20 @@ export const Tiles: FC<TilesProps> = ({ style = [] }) => {
  * @param index The index of the sprite to be drawn.
  * @param pixels Buffer of pixels that contains the RGB data
  * that is going to be drawn.
- * @param context The canvas context to which the tile is
+ * @param structure The canvas context to which the tile is
  * growing to be drawn.
- * @param buffer The data buffer to be used in the drawing
- * process, re-usage of it improves performance.
  * @param format The pixel format of the sprite.
  */
 const drawTile = (
     index: number,
     pixels: Uint8Array,
-    canvas: HTMLCanvasElement,
-    context: CanvasRenderingContext2D,
-    canvasImage: ImageData,
-    buffer: DataView,
+    structure: CanvasStructure,
     format: PixelFormat = PixelFormat.RGB
 ) => {
     const line = Math.floor(index / 16);
     const column = index % 16;
-    let offset = (line * canvas.width * 8 + column * 8) * PixelFormat.RGBA;
+    let offset =
+        (line * structure.canvas.width * 8 + column * 8) * PixelFormat.RGBA;
     let counter = 0;
     for (let i = 0; i < pixels.length; i += format) {
         const color =
@@ -48,17 +57,17 @@ const drawTile = (
             (pixels[i + 1] << 16) |
             (pixels[i + 2] << 8) |
             (format === PixelFormat.RGBA ? pixels[i + 3] : 0xff);
-        buffer.setUint32(offset, color);
+        structure.canvasBuffer.setUint32(offset, color);
 
         counter++;
         if (counter === 8) {
             counter = 0;
-            offset += (canvas.width - 7) * PixelFormat.RGBA;
+            offset += (structure.canvas.width - 7) * PixelFormat.RGBA;
         } else {
             offset += PixelFormat.RGBA;
         }
     }
-    context.putImageData(canvasImage, 0, 0);
+    structure.canvasContext.putImageData(structure.canvasImage, 0, 0);
 };
 
 export default Tiles;