From 1b5489279fce39f93a3b7275783bfaa868cf9b45 Mon Sep 17 00:00:00 2001 From: Lucas Dino Nolte Date: Sat, 7 May 2022 17:07:10 +0200 Subject: [PATCH] chore: add function-templates using framebased animation --- packages/create-mechanic/CHANGELOG.md | 3 + .../canvas-video-framebased/dependencies.json | 5 + .../canvas-video-framebased/index.js | 105 +++++++++++++++++ .../function-templates/index.js | 15 +++ .../function-templates/p5-video/index.js | 2 + .../react-video-framebased/dependencies.json | 5 + .../react-video-framebased/index.js | 107 ++++++++++++++++++ .../svg-video-framebased/dependencies.json | 5 + .../svg-video-framebased/index.js | 101 +++++++++++++++++ 9 files changed, 348 insertions(+) create mode 100644 packages/create-mechanic/function-templates/canvas-video-framebased/dependencies.json create mode 100644 packages/create-mechanic/function-templates/canvas-video-framebased/index.js create mode 100644 packages/create-mechanic/function-templates/react-video-framebased/dependencies.json create mode 100644 packages/create-mechanic/function-templates/react-video-framebased/index.js create mode 100644 packages/create-mechanic/function-templates/svg-video-framebased/dependencies.json create mode 100644 packages/create-mechanic/function-templates/svg-video-framebased/index.js diff --git a/packages/create-mechanic/CHANGELOG.md b/packages/create-mechanic/CHANGELOG.md index 6978ee17..81626935 100644 --- a/packages/create-mechanic/CHANGELOG.md +++ b/packages/create-mechanic/CHANGELOG.md @@ -7,6 +7,9 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 ## Unreleased +### Added +- Added function templates for framebased animations + ## 1.2.0 - 2022-02-14 ### Fixed diff --git a/packages/create-mechanic/function-templates/canvas-video-framebased/dependencies.json b/packages/create-mechanic/function-templates/canvas-video-framebased/dependencies.json new file mode 100644 index 00000000..2715603f --- /dev/null +++ b/packages/create-mechanic/function-templates/canvas-video-framebased/dependencies.json @@ -0,0 +1,5 @@ +{ + "dependencies": { + "@mechanic-design/engine-canvas": "^2.0.0-beta.4" + } +} diff --git a/packages/create-mechanic/function-templates/canvas-video-framebased/index.js b/packages/create-mechanic/function-templates/canvas-video-framebased/index.js new file mode 100644 index 00000000..479c6119 --- /dev/null +++ b/packages/create-mechanic/function-templates/canvas-video-framebased/index.js @@ -0,0 +1,105 @@ +import { drawLoop } from "@mechanic-design/core"; + +export const handler = async ({ inputs, mechanic }) => { + const { width, height, text, color1, color2, radiusPercentage, turns } = + inputs; + + const center = [width / 2, height / 2]; + const radius = ((height / 2) * radiusPercentage) / 100; + let angle = 0; + + const canvas = document.createElement("canvas"); + canvas.width = width; + canvas.height = height; + + const ctx = canvas.getContext("2d"); + + drawLoop(({ frameCount, stop }) => { + ctx.fillStyle = "#F4F4F4"; + ctx.fillRect(0, 0, width, height); + + ctx.fillStyle = color1; + ctx.beginPath(); + ctx.arc( + center[0], + center[1], + radius, + Math.PI + angle, + 2 * Math.PI + angle, + false + ); + ctx.fill(); + + ctx.fillStyle = color2; + ctx.beginPath(); + ctx.arc(center[0], center[1], radius, 0 + angle, Math.PI + angle, false); + ctx.fill(); + + ctx.fillStyle = "#000000"; + ctx.font = `${height / 10}px sans-serif`; + ctx.textAlign = "center"; + ctx.strokeText(text, width / 2, height - height / 20); + ctx.fillText(text, width / 2, height - height / 20); + + if (angle < turns * 2 * Math.PI) { + mechanic.frame(canvas); + angle = frameCount; + } else { + stop(); + mechanic.done(canvas); + } + }, mechanic.frameRate); +}; + +export const inputs = { + width: { + type: "number", + default: 400, + }, + height: { + type: "number", + default: 300, + }, + text: { + type: "text", + default: "mechanic", + }, + color1: { + type: "color", + model: "hex", + default: "#E94225", + }, + color2: { + type: "color", + model: "hex", + default: "#002EBB", + }, + radiusPercentage: { + type: "number", + default: 40, + min: 0, + max: 100, + slider: true, + }, + turns: { + type: "number", + default: 3, + }, +}; + +export const presets = { + medium: { + width: 800, + height: 600, + }, + large: { + width: 1600, + height: 1200, + }, +}; + +export const settings = { + engine: require("@mechanic-design/engine-canvas"), + animated: true, + frameRate: 60, +}; diff --git a/packages/create-mechanic/function-templates/index.js b/packages/create-mechanic/function-templates/index.js index 85193753..1e3b94d9 100644 --- a/packages/create-mechanic/function-templates/index.js +++ b/packages/create-mechanic/function-templates/index.js @@ -9,6 +9,11 @@ const options = [ type: "Canvas", dir: "canvas-video", }, + { + name: "Vanilla JS Video (Framebased)", + type: "Canvas", + dir: "canvas-video-framebased", + }, { name: "Vanilla JS Image", type: "SVG", @@ -19,6 +24,11 @@ const options = [ type: "SVG", dir: "svg-video", }, + { + name: "Vanilla JS Video (Framebased)", + type: "Canvas", + dir: "svg-video-framebased", + }, { name: "p5.js Image", type: "Canvas", @@ -39,6 +49,11 @@ const options = [ type: "SVG", dir: "react-video", }, + { + name: "React Video (Framebased)", + type: "SVG", + dir: "react-video-framebased", + }, ]; module.exports = options.reduce((acc, cur) => { diff --git a/packages/create-mechanic/function-templates/p5-video/index.js b/packages/create-mechanic/function-templates/p5-video/index.js index 76ac279c..7f2c5c7e 100644 --- a/packages/create-mechanic/function-templates/p5-video/index.js +++ b/packages/create-mechanic/function-templates/p5-video/index.js @@ -8,6 +8,7 @@ export const handler = ({ inputs, mechanic, sketch }) => { sketch.setup = () => { sketch.createCanvas(width, height); + sketch.frameRate(mechanic.frameRate); }; sketch.draw = () => { @@ -89,4 +90,5 @@ export const presets = { export const settings = { engine: require("@mechanic-design/engine-p5"), animated: true, + frameRate: 60, }; diff --git a/packages/create-mechanic/function-templates/react-video-framebased/dependencies.json b/packages/create-mechanic/function-templates/react-video-framebased/dependencies.json new file mode 100644 index 00000000..988ca32f --- /dev/null +++ b/packages/create-mechanic/function-templates/react-video-framebased/dependencies.json @@ -0,0 +1,5 @@ +{ + "dependencies": { + "@mechanic-design/engine-react": "^2.0.0-beta.4" + } +} diff --git a/packages/create-mechanic/function-templates/react-video-framebased/index.js b/packages/create-mechanic/function-templates/react-video-framebased/index.js new file mode 100644 index 00000000..ea07ed58 --- /dev/null +++ b/packages/create-mechanic/function-templates/react-video-framebased/index.js @@ -0,0 +1,107 @@ +import React, { useEffect, useRef } from "react"; +import { useDrawLoop } from "@mechanic-design/engine-react"; + +export const handler = ({ inputs, mechanic }) => { + const { width, height, text, color1, color2, radiusPercentage, turns } = + inputs; + + const center = [width / 2, height / 2]; + const radius = ((height / 2) * radiusPercentage) / 100; + const angle = useRef(0); + + const isPlaying = useRef(true); + const frameCount = useDrawLoop(isPlaying.current, mechanic.frameRate); + + useEffect(() => { + if (angle.current < turns * 360) { + mechanic.frame(); + angle.current = frameCount; + } else if (isPlaying.current) { + isPlaying.current = false; + mechanic.done(); + } + }, [frameCount]); + + return ( + + + + + + + + + {text} + + + + ); +}; + +export const inputs = { + width: { + type: "number", + default: 400, + }, + height: { + type: "number", + default: 300, + }, + text: { + type: "text", + default: "mechanic", + }, + color1: { + type: "color", + model: "hex", + default: "#E94225", + }, + color2: { + type: "color", + model: "hex", + default: "#002EBB", + }, + radiusPercentage: { + type: "number", + default: 40, + min: 0, + max: 100, + slider: true, + }, + turns: { + type: "number", + default: 3, + }, +}; + +export const presets = { + medium: { + width: 800, + height: 600, + }, + large: { + width: 1600, + height: 1200, + }, +}; + +export const settings = { + engine: require("@mechanic-design/engine-react"), + animated: true, + frameRate: 60, +}; diff --git a/packages/create-mechanic/function-templates/svg-video-framebased/dependencies.json b/packages/create-mechanic/function-templates/svg-video-framebased/dependencies.json new file mode 100644 index 00000000..ee1fd618 --- /dev/null +++ b/packages/create-mechanic/function-templates/svg-video-framebased/dependencies.json @@ -0,0 +1,5 @@ +{ + "dependencies": { + "@mechanic-design/engine-svg": "^2.0.0-beta.4" + } +} diff --git a/packages/create-mechanic/function-templates/svg-video-framebased/index.js b/packages/create-mechanic/function-templates/svg-video-framebased/index.js new file mode 100644 index 00000000..50bda286 --- /dev/null +++ b/packages/create-mechanic/function-templates/svg-video-framebased/index.js @@ -0,0 +1,101 @@ +import { drawLoop } from "@mechanic-design/core"; + +export const handler = ({ inputs, mechanic }) => { + const { width, height, text, color1, color2, radiusPercentage, turns } = + inputs; + + const center = [width / 2, height / 2]; + const radius = ((height / 2) * radiusPercentage) / 100; + + let angle = 0; + drawLoop(({ frameCount, stop }) => { + const svg = ` + + + + + + + + ${text} + + + `; + + if (angle < turns * 360) { + mechanic.frame(svg); + angle = frameCount; + } else { + stop(); + mechanic.done(svg); + } + }, mechanic.frameRate); +}; + +export const inputs = { + width: { + type: "number", + default: 400, + }, + height: { + type: "number", + default: 300, + }, + text: { + type: "text", + default: "mechanic", + }, + color1: { + type: "color", + model: "hex", + default: "#E94225", + }, + color2: { + type: "color", + model: "hex", + default: "#002EBB", + }, + radiusPercentage: { + type: "number", + default: 40, + min: 0, + max: 100, + slider: true, + }, + turns: { + type: "number", + default: 3, + }, +}; + +export const presets = { + medium: { + width: 800, + height: 600, + }, + large: { + width: 1600, + height: 1200, + }, +}; + +export const settings = { + engine: require("@mechanic-design/engine-svg"), + animated: true, + frameRate: 60, +};