UNPKG

@someaspy/pet-pet-gif

Version:

Given an avatar, generate a petting gif (known as "petpet" or "pet the").

37 lines (36 loc) 1.76 kB
import { resolve } from "node:path"; import { buffer } from "node:stream/consumers"; import { GifEncoder } from "@skyra/gifenc"; import { createCanvas, loadImage } from "canvas"; const FRAMES = 10; const petGifCache = []; export default async function petPetGif(avatarURL, options = { resolution: 128, delay: 20, backgroundColor: null }) { const encoder = new GifEncoder(options.resolution, options.resolution); const outputStream = encoder.createReadStream(); encoder.start(); encoder.setRepeat(0); encoder.setDelay(options.delay); encoder.setTransparent(null); const canvas = createCanvas(options.resolution, options.resolution); const ctx = canvas.getContext("2d"); const avatar = await loadImage(avatarURL); for (let i = 0; i < FRAMES; i++) { ctx.clearRect(0, 0, canvas.width, canvas.height); if (options.backgroundColor) { ctx.fillStyle = options.backgroundColor; ctx.fillRect(0, 0, canvas.width, canvas.height); } const j = i < FRAMES / 2 ? i : FRAMES - i; const width = 0.8 + j * 0.02; const height = 0.8 - j * 0.05; const offsetX = (1 - width) * 0.5 + 0.1; const offsetY = 1 - height - 0.08; if (i === petGifCache.length) petGifCache.push(await loadImage(resolve(import.meta.dirname, `../img/pet${i.toString()}.gif`))); ctx.drawImage(avatar, options.resolution * offsetX, options.resolution * offsetY, options.resolution * width, options.resolution * height); ctx.drawImage(petGifCache[i], 0, 0, options.resolution, options.resolution); encoder.addFrame(ctx.getImageData(0, 0, canvas.width, canvas.height).data); } encoder.finish(); return await buffer(outputStream); }