diff --git a/detail.html b/detail.html index 80487e6..6f0737f 100644 --- a/detail.html +++ b/detail.html @@ -19,6 +19,9 @@

+
+

Animations

+

States

@@ -50,6 +53,7 @@ if (prop.error) { showError(prop.error, filename) } else { + showAnimations(prop, document.getElementById("animations")) showStates(prop, document.getElementById("states")) showCels(prop, document.getElementById("cels")) } diff --git a/index.js b/index.js index a6e4c9b..d5377c0 100644 --- a/index.js +++ b/index.js @@ -468,7 +468,7 @@ const compositeCels = (cels) => { xRel += cel.xRel yRel += cel.yRel } - return { canvas: canvas, xOffset: minX * 8, yOffset: minY } + return { canvas: canvas, xOffset: minX * 8, yOffset: minY, w: w, h: h } } const imageFromCanvas = (canvas) => { @@ -493,6 +493,50 @@ const linkDetail = (element, filename) => { return detailLink } +const createAnimation = (prop, animation) => { + const frames = [] + for (let istate = animation.startState; istate <= animation.endState; istate ++) { + frames.push(compositeCels(celsFromMask(prop, prop.celmasks[istate]))) + } + if (frames.length == 1) { + return imageFromCanvas(frames[0].canvas) + } + let minX = Number.POSITIVE_INFINITY + let minY = Number.POSITIVE_INFINITY + let maxX = Number.NEGATIVE_INFINITY + let maxY = Number.NEGATIVE_INFINITY + for (const frame of frames) { + minX = Math.min(minX, frame.xOffset) + minY = Math.min(minY, frame.yOffset) + maxX = Math.max(maxX, frame.xOffset + frame.w) + maxY = Math.max(maxY, frame.yOffset + frame.h) + } + + const w = maxX - minX + const h = maxY - minY + const canvas = makeCanvas(w, h) + canvas.style.imageRendering = "pixelated" + canvas.style.width = `${w * 3}px` + canvas.style.height = `${h * 3}px` + let iframe = 0 + const ctx = canvas.getContext("2d") + const nextFrame = () => { + const frame = frames[iframe] + ctx.clearRect(0, 0, w, h) + ctx.drawImage(frame.canvas, frame.xOffset - minX, frame.yOffset - minY) + iframe = (iframe + 1) % frames.length + } + nextFrame() + setInterval(nextFrame, 250) + return canvas +} + +const showAnimations = (prop, container) => { + for (const animation of prop.animations) { + container.appendChild(linkDetail(createAnimation(prop, animation), prop.filename)) + } +} + const showStates = (prop, container) => { for (const celmask of prop.celmasks) { const state = compositeCels(celsFromMask(prop, celmask)) @@ -541,7 +585,11 @@ const displayFile = async (filename, container) => { showError(prop.error, prop.filename) } else { try { - showStates(prop, container) + if (prop.animations.length > 0) { + showAnimations(prop, container) + } else { + showStates(prop, container) + } } catch (e) { container.parentNode.removeChild(container) showError(e, prop.filename)