Skip to content

Drawing 3D Cube

Let's make 3d cube from these images and place text over it.

Butterfly by DreamyArt from Pixabay

Web by Kai Reschke from Pixabay

Boat by enriquelopezgarre from Pixabay

White text

Example code:

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

const butterfly = await Canvas.createFromUrl("butterfly.jpg");
const web = await Canvas.createFromUrl("web.jpg");
const boat = await Canvas.createFromUrl("boat.jpg");

// Output square image side size
const outputSize = 210;
// Cube edge size
const edgeSize = (outputSize - 10) / 2;
// Cube center coords
const center = [outputSize / 2, outputSize / 2];

// Create canvas for output image and append it to body
const resultCanvas = makeCanvas(outputSize, outputSize, true);
document.body.appendChild(resultCanvas);

// Calculate cube apexes destination coords.
const north = [center[0], center[1] - edgeSize];
const northWest = [
  Math.cos(degreesToRadians(30)) * -edgeSize + center[0],
  Math.sin(degreesToRadians(30)) * -edgeSize + center[1],
];
const northEast = [
  Math.cos(degreesToRadians(30)) * edgeSize + center[0],
  northWest[1],
];
const southWest = [northWest[0], northWest[1] + edgeSize];
const southEast = [northEast[0], southWest[1]];
const south = [center[0], center[1] + edgeSize];

// Map images to destination apexes coordinates
const argsMap = [
  [butterfly, [north, northEast, center, northWest]],
  [web, [northWest, center, south, southWest]],
  [boat, [northEast, southEast, south, center]],
];

for (const [
  sourceImage,
  [topLeft, topRight, bottomRight, bottomLeft],
] of argsMap) {
  // Map image corners to corresponding destination image points.
  // prettier-ignore
  const controlPoints = [
      0, 0, ...topLeft,
      sourceImage.width - 1, 0, ...topRight,
      sourceImage.width - 1, sourceImage.height - 1, ...bottomRight,
      0, sourceImage.height - 1, ...bottomLeft
  ];
  // Distort image
  const { image } = await distort(sourceImage, "Affine", controlPoints, {
    viewport: true,
  });
  // Get image virtual viewport
  const vp = image.getViewport();
  // Put distorted image on result canvas according to virtual viewport offset
  resultCanvas.getContext("2d").drawImage(image.getResource(), vp.x1, vp.y1);
}

// Load image with text
const text = await Canvas.createFromUrl("white-text.png");
// Distort text image
const { image: circleText } = await distort(text, "Arc", [
  360, // Arc angle — full circle
  0, // Rotation angle - 0 deg
  edgeSize * 0.8, // Outer radius of text circle,
  edgeSize * 0.4, // // Inner radius of text circle
]);
// Get offset of circle center
const { x1: textCenterOffsetX, y1: textCenterOffsetY } =
  circleText.getViewport();
// Draw circle so that circle center will be placed on destination canvas center
resultCanvas
  .getContext("2d")
  .drawImage(
    circleText.getResource(),
    center[0] + textCenterOffsetX,
    center[1] + textCenterOffsetX
  );

Drawing result: 3d cube