Skip to content

Drawing "3D" box

In this example shown how you can draw "3D" boxes, using Perspective distortion.

Source images:

Box side:

Box side

Box front:

Box front

Code we will use to draw 3d box:

ts
import { Canvas, distort } from "@alxcube/lens";

// Load image adapters
const [sideImage, frontImage] = await Promise.all(
  ["merlot-side.png", "merlot-front.png"].map((url) =>
    Canvas.createFromUrl(url)
  )
);

// Map side image corners to their new locations at result canvas
// prettier-ignore
const sideControlPoints = [
  0, 0, 46, 57,
  sideImage.width - 1, 0, 119, 12,
  sideImage.width - 1, sideImage.height - 1, 119, 338,
  0, sideImage.height - 1, 46, 311,
];
// prettier-ignore
const frontControlPoints = [
  0, 0, 119, 12,
  frontImage.width - 1, 0, 287, 67,
  frontImage.width - 1, frontImage.height - 1, 287, 301,
  0, frontImage.height - 1, 119, 338,
];

// distort images
const results = await Promise.all(
  [
    [sideImage, sideControlPoints],
    [frontImage, frontControlPoints],
  ].map(([image, args]) =>
    distort(image, "Perspective", args, { viewport: true })
  )
);

// create canvas for displaying result
const resultCanvas = document.createElement("canvas");
resultCanvas.width = 336;
resultCanvas.height = 350;

// draw distorted images on canvas, considering virtual viewport offset
for (const { image } of results) {
  const vp = image.getViewport();
  resultCanvas.getContext("2d").drawImage(image.getResource(), vp.x1, vp.y1);
}

// display result
document.body.appendChild(resultCanvas);

And here's the final result:

Result