comic-bubbles
Version:
Animated comic bubbles - what else?
132 lines (108 loc) • 4.01 kB
JavaScript
import { getResourceUrl } from './helperFunctions.mjs'
export let fontDescs = new Map()
export let fontImages = new Map()
async function loadImage(url) {
const response = await fetch(url)
const blob = await response.blob()
const objectUrl = URL.createObjectURL(blob)
return new Promise((resolve, reject) => {
const image = new Image()
image.addEventListener('load', () => resolve(image))
image.addEventListener('error', reject)
image.src = objectUrl
})
}
export async function cacheFontDesc(fontName) {
try {
for (let bold = 0; bold <= 1; bold++) {
for (let italic = 0; italic <= 1; italic++) {
let fullFontName = getFullFontName(fontName, bold, italic)
if (fontDescs.has(fullFontName)) continue
const jsonPath = getResourceUrl('font JSON path', `/resources/fonts/${fontName}/${fullFontName}.json`)
const response = await fetch(jsonPath)
const data = await response.json()
fontDescs.set(fullFontName, data.font)
await cacheFontImage(fontName, data.font.image)
}
}
} catch (error) {
console.error(error)
}
}
export async function cacheFontImage(fontName, imageName) {
try {
if (fontImages.has(imageName)) return
const fontPath = getResourceUrl('font image path', `/resources/fonts/${fontName}/${imageName}`)
let fontImage = await loadImage(fontPath)
fontImages.set(imageName, fontImage)
} catch (error) {
console.error(error)
}
}
export function drawChar(sceneId, charName, fontName, bold, italic, x, y) {
const canvas = document.getElementById(sceneId)
const ctx = canvas.getContext('2d')
const char = getCharDesc(charName, fontName, bold, italic)
ctx.globalCompositeOperation = 'multiply'
let fontImageName = fontDescs.get(getFullFontName(fontName, bold, italic)).image
let fontImage = fontImages.get(fontImageName)
ctx.drawImage(
fontImage,
char.bounds.x,
char.bounds.y,
char.bounds.width,
char.bounds.height,
x + char.margin.left,
y + char.margin.top,
char.bounds.width,
char.bounds.height
)
ctx.globalCompositeOperation = 'source-over'
}
export function getFullFontName(fontName, bold, italic) {
let boldTxt = bold ? '-bold' : ''
let italicTxt = italic ? '-italic' : ''
let regularTxt = !italic && !bold ? '-regular' : ''
let fullFontName = fontName + boldTxt + regularTxt + italicTxt
return fullFontName
}
export function getCharDesc(charName, fontName, bold, italic) {
let char
try {
let fontDesc = fontDescs.get(getFullFontName(fontName, bold, italic))
char = fontDesc.chars.find((element) => element.char.name === charName).char
} catch (exc) {
console.log("Character missing in font map: '" + charName + "'")
}
return char
}
export function drawWord(sceneId, word, fontName, bold, italic, x, y) {
for (let i = 0; i < word.length; i++) {
const charName = word[i]
drawChar(sceneId, charName, fontName, bold, italic, x, y)
const charObj = getCharDesc(charName, fontName, bold, italic)
let fontDesc = fontDescs.get(getFullFontName(fontName, bold, italic))
x += charObj.bounds.width + charObj.margin.left + charObj.margin.right
if (i != word.length - 1) {
x += fontDesc.letterSpacing
}
}
}
export function drawRow(sceneId, row) {
let x = row.getX()
let y = row.getY()
for (let h = 0; h < row.getWordCount(); h++) {
let word = row.word(h)
for (let i = 0; i < word.getCharCount(); i++) {
let char = word.char(i)
drawChar(sceneId, char.name, char.font.name, char.font.bold, char.font.italic, x, y)
let fontDesc = fontDescs.get(getFullFontName(char.font.name, char.font.bold, char.font.italic))
const charObj = getCharDesc(char.name, char.font.name, char.font.bold, char.font.italic)
x += charObj.bounds.width + charObj.margin.left + charObj.margin.right
if (i != word.getCharCount() - 1) {
x += fontDesc.letterSpacing
}
}
x += word.spaceWidth
}
}