changed 9 months ago
Linked with GitHub

アイマスハッカソン2024成果

再現シリーズ


自己紹介

Image Not Showing Possible Reasons
  • The image file may be corrupted
  • The server hosting the image is unavailable
  • The image path is incorrect
  • The image format is not supported
Learn More →

.ごっち(フリーランスエンジニア)

X: @gggooottto
Bluesky: @yougoto.dev


自己紹介続き

Image Not Showing Possible Reasons
  • The image file may be corrupted
  • The server hosting the image is unavailable
  • The image path is incorrect
  • The image format is not supported
Learn More →

#imas_mokumoku 会の主催してます。

  • 学園アイドルマスター 6DBPWQP6
  • シンデレラガールズスターライトステージ 584226133
  • シャイニーカラーズ SONG for PRISM W8XF4Q2VX
Image Not Showing Possible Reasons
  • The image file may be corrupted
  • The server hosting the image is unavailable
  • The image path is incorrect
  • The image format is not supported
Learn More →

アイマスハッカソン2019成果

https://spamltheater-yougoto510.vercel.app/

Image Not Showing Possible Reasons
  • The image file may be corrupted
  • The server hosting the image is unavailable
  • The image path is incorrect
  • The image format is not supported
Learn More →

(当時の)ミリシタUI

Image Not Showing Possible Reasons
  • The image file may be corrupted
  • The server hosting the image is unavailable
  • The image path is incorrect
  • The image format is not supported
Learn More →

全然メンテしていない。。


今回の成果物

https://hatsuboshi-logo.pages.dev/

Image Not Showing Possible Reasons
  • The image file may be corrupted
  • The server hosting the image is unavailable
  • The image path is incorrect
  • The image format is not supported
Learn More →

Image Not Showing Possible Reasons
  • The image file may be corrupted
  • The server hosting the image is unavailable
  • The image path is incorrect
  • The image format is not supported
Learn More →

学園アイドルマスター: 初星学園のロゴ


ぎじゅつ

  • Rust + wasm
  • Cloudflare Pages

Rust言語でWASMするためのテンプレートがあります。ありがたや。
wasm-pack rust で検索すると見つかるはず。

https://rustwasm.github.io/docs/wasm-pack/tutorials/hybrid-applications-with-webpack/index.html


下準備

もくもく会を使って仕込んでいました。

Image Not Showing Possible Reasons
  • The image was uploaded to a note which you don't have access to
  • The note which the image was originally uploaded to has been deleted
Learn More →

https://x.com/gggooottto/status/1836752572008558756


// browser.rs
use anyhow::{anyhow, Result};
use wasm_bindgen::JsCast;
use web_sys::{Document, HtmlCanvasElement, Window};

pub fn window() -> Result<Window> {
    web_sys::window().ok_or_else(|| anyhow!("no window found"))
}

pub fn document() -> Result<Document> {
    window()?
        .document()
        .ok_or_else(|| anyhow!("no document found"))
}

pub fn canvas() -> Result<HtmlCanvasElement> {
    document()?
        .get_element_by_id("canvas")
        .ok_or_else(|| anyhow!("no canvas found"))?
        .dyn_into::<HtmlCanvasElement>()
        .map_err(|_| anyhow!("failed to cast to HtmlCanvasElement"))
}

pub fn context() -> Result<web_sys::CanvasRenderingContext2d> {
    canvas()?
        .get_context("2d")
        .map_err(|_| anyhow!("Error getting 2d context"))?
        .ok_or_else(|| anyhow!("No 2d context found"))?
        .dyn_into::<web_sys::CanvasRenderingContext2d>()
        .map_err(|element| {
            anyhow!(
                "Error converting {:#?} to CanvasRenderingContext2d",
                element
            )
        })
}

// draw.rs
use crate::browser;

pub struct Draw;
pub struct DrawLogo;

impl Draw {
    pub fn draw() {
        let context = browser::context().unwrap();

        DrawLogo::draw_diamond(&context);
        DrawLogo::draw_middle_line(&context);
        DrawLogo::draw_circle(&context);
        DrawLogo::draw_h_in_circle(&context);
        DrawLogo::draw_6lines(&context);
        DrawLogo::curved_sparkle(&context);
        DrawLogo::draw_arc(&context);
        DrawLogo::draw_5lines_between_arc(&context);
    }
}

impl DrawLogo {
    const LINE_WIDTH: f64 = 10.0;

    pub fn draw_diamond(context: &web_sys::CanvasRenderingContext2d) {
        context.set_line_width(Self::LINE_WIDTH);
        context.begin_path();
        context.move_to(300.0, 50.0);
        context.line_to(50.0, 300.0);
        context.line_to(300.0, 550.0);
        context.line_to(550.0, 300.0);
        context.line_to(300.0, 50.0);
        context.close_path();
        context.stroke();
    }

    pub fn draw_middle_line(context: &web_sys::CanvasRenderingContext2d) {
        context.set_line_width(Self::LINE_WIDTH);
        context.begin_path();
        context.move_to(175.0, 175.0);
        context.line_to(425.0, 425.0);
        context.stroke();
    }

    pub fn draw_circle(context: &web_sys::CanvasRenderingContext2d) {
        context.set_line_width(Self::LINE_WIDTH);
        context.begin_path();
        context
            .arc(168.0, 300.0, 78.0, 0.0, std::f64::consts::PI * 2.0)
            .unwrap();
        context.stroke();
    }

    pub fn draw_h_in_circle(context: &web_sys::CanvasRenderingContext2d) {
        context.set_line_width(Self::LINE_WIDTH);
        context.begin_path();
        context.move_to(125.0, 365.0);
        context.line_to(125.0, 235.0);
        context.move_to(125.0, 300.0);
        context.line_to(205.0, 300.0);
        context.move_to(205.0, 235.0);
        context.line_to(205.0, 365.0);
        context.stroke();
    }

    pub fn draw_6lines(context: &web_sys::CanvasRenderingContext2d) {
        let adjust = 127.0;
        let gap = 23.0;

        context.set_line_width(Self::LINE_WIDTH);
        context.begin_path();
        context.move_to(405.0, 405.0);
        context.line_to(405.0 - adjust, 405.0 + adjust);

        context.move_to(405.0 - 1.0 * gap, 405.0 - 1.0 * gap);
        context.line_to(405.0 - 1.0 * gap - adjust, 405.0 - 1.0 * gap + adjust);

        context.move_to(405.0 - 2.0 * gap, 405.0 - 2.0 * gap);
        context.line_to(405.0 - 2.0 * gap - adjust, 405.0 - 2.0 * gap + adjust);

        context.move_to(405.0 - 3.0 * gap, 405.0 - 3.0 * gap);
        context.line_to(405.0 - 3.0 * gap - adjust, 405.0 - 3.0 * gap + adjust);

        context.move_to(405.0 - 4.0 * gap, 405.0 - 4.0 * gap);
        context.line_to(405.0 - 4.0 * gap - adjust, 405.0 - 4.0 * gap + adjust);

        context.move_to(405.0 - 5.0 * gap, 405.0 - 5.0 * gap);
        context.line_to(405.0 - 5.0 * gap - adjust, 405.0 - 5.0 * gap + adjust);

        context.stroke();
    }

    pub fn curved_sparkle(context: &web_sys::CanvasRenderingContext2d) {
        context.set_line_width(Self::LINE_WIDTH);
        context.set_line_join("bevel");

        context.begin_path();
        context
            .arc(
                174.0,
                48.5,
                125.5,
                std::f64::consts::PI * 0.0,
                std::f64::consts::PI * 0.5,
            )
            .unwrap();
        context
            .arc(
                174.0,
                300.5,
                125.5,
                std::f64::consts::PI * 1.5,
                std::f64::consts::PI * 2.0,
            )
            .unwrap();
        context
            .arc(
                425.5,
                300.5,
                125.5,
                std::f64::consts::PI * 1.0,
                std::f64::consts::PI * 1.5,
            )
            .unwrap();
        context
            .arc(
                425.5,
                48.5,
                125.5,
                std::f64::consts::PI * 0.5,
                std::f64::consts::PI * 1.0,
            )
            .unwrap();

        context.stroke();
    }

    pub fn draw_arc(context: &web_sys::CanvasRenderingContext2d) {
        context.set_line_width(Self::LINE_WIDTH);
        context.begin_path();
        context
            .arc(
                492.0,
                365.0,
                85.0,
                std::f64::consts::PI * 0.75,
                std::f64::consts::PI * 1.75,
            )
            .unwrap();
        context.stroke();
    }

    pub fn draw_5lines_between_arc(context: &web_sys::CanvasRenderingContext2d) {
        context.set_line_width(Self::LINE_WIDTH);
        context.begin_path();

        context.move_to(390.0, 180.0);
        context.line_to(390.0 + 100.0, 180.0 + 100.0);

        context.move_to(360.0, 190.0);
        context.line_to(360.0 + 100.0, 190.0 + 100.0);

        context.move_to(337.0, 207.0);
        context.line_to(337.0 + 100.0, 207.0 + 100.0);

        context.move_to(320.0, 230.0);
        context.line_to(320.0 + 98.0, 230.0 + 98.0);

        context.move_to(308.0, 262.0);
        context.line_to(308.0 + 100.0, 262.0 + 100.0);

        context.stroke();
    }
}

// lib.rs
#[macro_use]
mod browser;
mod draw;
use draw::Draw;

use wasm_bindgen::prelude::*;
use web_sys::console;

#[wasm_bindgen(start)]
pub fn main_js() -> Result<(), JsValue> {
    // This provides better error messages in debug mode.
    // It's disabled in release mode so it doesn't bloat up the file size.
    #[cfg(debug_assertions)]
    console_error_panic_hook::set_once();

    // Your code goes here!
    console::log_1(&JsValue::from_str("Hello world!"));

    Draw::draw();

    Ok(())
}

苦労した点


見よう見まねで再現した!

以上!

Rustっぽい難しさは無かった。



本物

https://gakuen.idolmaster-official.jp/assets/img/common/logo_text.svg

Image Not Showing Possible Reasons
  • The image file may be corrupted
  • The server hosting the image is unavailable
  • The image path is incorrect
  • The image format is not supported
Learn More →

Image Not Showing Possible Reasons
  • The image file may be corrupted
  • The server hosting the image is unavailable
  • The image path is incorrect
  • The image format is not supported
Learn More →
Image Not Showing Possible Reasons
  • The image file may be corrupted
  • The server hosting the image is unavailable
  • The image path is incorrect
  • The image format is not supported
Learn More →

Image Not Showing Possible Reasons
  • The image file may be corrupted
  • The server hosting the image is unavailable
  • The image path is incorrect
  • The image format is not supported
Learn More →
  • 黒色が今回つくったもの
  • 灰色が重なったもの(本物に不透明度50%重ねたもの)
  • 白色が本物

うーん

Image Not Showing Possible Reasons
  • The image file may be corrupted
  • The server hosting the image is unavailable
  • The image path is incorrect
  • The image format is not supported
Learn More →

中らずと雖も遠からず

見よう見まねで作ったわりにはよかったのでは。


ちゃんとやるなら

本物のSVGを解析するべし

https://gakuen.idolmaster-official.jp/assets/img/common/logo_text.svg

<svg xmlns="http://www.w3.org/2000/svg" width="300" height="300">
  <path fill-rule="evenodd" fill="#FFF" d="
    M299.1 141.522l-7.472 8.373-1.412-1.411 1.838-9.967-5.902 5.902-1.412-1.412 8.372-8.372 1.558 1.558-1.862 9.699 5.78-5.781.512 1.411z
    m-13.604-12.069l-2.202 2.202 3.005 3.006-1.217 1.217-3.006-3.006-2.518 2.519 3.723 3.724-1.217 1.217-5.305-5.306 8.372-8.372 5.123 5.123-1.217 1.217-3.541-3.541z
    m-11.681.951c-1.193.096-2.434-.439-3.638-1.643-1.132-1.133-1.74-2.374-1.631-3.627.122-1.46 1.119-2.458 1.825-3.164l5.038-5.038 1.607 1.606-5.294 5.294c-1.18 1.18-1.704 2.385-.243 3.845 1.46 1.461 2.665.937 3.845-.243l5.294-5.294 1.399 1.4-5.038 5.038c-.706.706-1.704 1.703-3.164 1.826z
    m-9.027-7.349l-1.984-1.984.901-7.812-4.357 4.356-1.606-1.606 8.372-8.372 1.606 1.606-3.809 3.809 7.289-.328 1.717 1.715-7.253.195-.876 8.421z
    m-10.963-10.962l1.363-2.702-3.164-3.164-2.726 1.339-1.46-1.461 11.39-5.354 1.716 1.716-5.403 11.341-1.716-1.715z
    m4.515-8.969l-4.722 2.312 2.361 2.36 2.361-4.672z
    m-5.925-6.29s-.548-1.229-1.655-2.337c-1.85-1.849-3.906-1.983-6 .11-2.105 2.105-2.044 4.235-.45 5.828a5.28 5.28 0 001.192.901l2.045-2.045-1.46-1.459 1.192-1.193 3.03 3.03-4.125 4.125s-1.557-.681-3.067-2.19c-2.603-3.504-3.054-5.707-.158-8.604 2.969-2.969 6.207-2.482 8.944.256 1.23 1.229 1.863 2.422 1.863 2.422l-1.254 1.253-.097-.097z
    m-22.11-8.261l8.372-8.372 1.607 1.606-8.373 8.372-1.606-1.606z
    m-4.72-4.72l3.736-3.736-3.602-3.602-3.736 3.736-1.606-1.606 8.372-8.373 1.606 1.607-3.419 3.419 3.602 3.602 3.419-3.42 1.607 1.607-8.372 8.372-1.607-1.606z
    m-1.459-15.332s-.645-1.399-1.557-2.312c-.913-.912-1.728-.973-2.288-.413-1.631 1.63 2.568 5.001-.219 7.787-1.655 1.656-3.797 1.12-5.695-.778-1.302-1.302-1.825-2.58-1.825-2.58l1.253-1.253.085.085s.669 1.643 1.68 2.653c.949.949 1.934 1.083 2.616.401 1.752-1.752-2.434-5.135.207-7.776 1.448-1.448 3.419-1.181 5.293.694a10.18 10.18 0 011.752 2.385l-1.205 1.205-.097-.098z
    m-18.361-4.172c-2.556-2.556-2.252-5.61.389-8.251 2.689-2.689 5.792-2.945 8.348-.389 2.555 2.555 2.251 5.61-.39 8.25-2.689 2.689-5.792 2.945-8.347.39z
    m7.52-7.472c-1.46-1.46-3.298-1.205-5.403.901-2.105 2.105-2.361 3.942-.901 5.403 1.461 1.46 3.299 1.204 5.404-.901s2.36-3.943.9-5.403z
    m-10.914-5.194s1.911 2.056-.085 4.051c-.961.962-2.02 1.12-3.005.889-1.205-.28-2.057-1.131-2.775-1.849l-2.824-2.824 8.373-8.372 2.799 2.799c.754.754 1.375 1.399 1.63 2.361.232.888.037 1.763-.779 2.579-1.691 1.692-3.334.366-3.334.366z
    m-3.383-1.899l-2.604 2.604 1.205 1.205c.292.292.779.779 1.448.961.608.17 1.144 0 1.63-.486.548-.548.646-1.084.487-1.656-.182-.644-.596-1.058-.986-1.447l-1.18-1.181z
    m5.294-1.351c-.134-.475-.463-.827-.779-1.143l-1.01-1.01-2.288 2.287 1.01 1.01c.341.341.645.645 1.132.791.474.134.998.049 1.484-.438.487-.487.584-1.022.451-1.497z
    m-13.543-1.105c-1.193.096-2.434-.439-3.638-1.643-1.132-1.132-1.74-2.373-1.631-3.627.122-1.46 1.119-2.458 1.825-3.164l5.038-5.038 1.607 1.607-5.294 5.293c-1.18 1.181-1.704 2.385-.244 3.845 1.461 1.461 2.666.937 3.846-.243l5.293-5.293 1.4 1.399-5.038 5.038c-.706.706-1.704 1.704-3.164 1.826z
    m-3.029-15.222s-.645-1.4-1.557-2.313c-.913-.912-1.728-.973-2.288-.413-1.631 1.63 2.568 5.001-.219 7.788-1.655 1.655-3.797 1.119-5.695-.779-1.302-1.302-1.825-2.579-1.825-2.579l1.253-1.254.085.085s.669 1.643 1.679 2.653c.95.949 1.935 1.083 2.617.401 1.752-1.752-2.434-5.135.207-7.776 1.448-1.448 3.419-1.18 5.293.694a10.202 10.202 0 011.753 2.385l-1.205 1.205-.098-.097z
    m-9.088-9.479l-7.131 7.131-1.607-1.606 7.131-7.131-2.324-2.325 1.241-1.241 6.243 6.243-1.242 1.241-2.311-2.312z
    m-13.519.744l1.363-2.702-3.164-3.164-2.726 1.339-1.46-1.46 11.39-5.355 1.716 1.716-5.403 11.342-1.716-1.716z
    m4.515-8.969l-4.722 2.312 2.361 2.361 2.361-4.673z
    m-14.31-.826l3.736-3.735-3.601-3.602-3.736 3.736-1.607-1.607 8.373-8.372 1.606 1.606-3.419 3.419 3.601 3.602 3.42-3.419 1.606 1.607-8.372 8.372-1.607-1.607z
    m125.374 142.527l2.369 2.37L141.524 299.1 32.181 190.657l-.02-.018-.018-.019-32.147-32.147 32.158-32.158.007-.008a.057.057 0 00.008-.007L141.524 16.946l139.157 139.157h.001zM141.524 291.422l64.33-64.33-8.577-8.577-64.331 64.33 8.578 8.577z
    m32.522-187.658a65.68 65.68 0 00-8.052 6.272l43.999 43.999a50.982 50.982 0 018.319-6.005l-44.266-44.266z
    m49.996 41.417a51.783 51.783 0 0111.022-3.301l-45.612-45.613a65.548 65.548 0 00-10.015 4.309l44.605 44.605z
    m-62.337-30.857a66.063 66.063 0 00-6.263 8.06l44.232 44.232a51.796 51.796 0 016.023-8.3l-43.992-43.992z
    m33.167 93.208a51.718 51.718 0 01-2.198-14.974c0-.477.023-.951.035-1.426l-46.611-46.611a65.284 65.284 0 00-1.511 12.727l50.285 50.284z
    m-1.364-24.178a51.156 51.156 0 013.287-11.038l-44.556-44.556a65.43 65.43 0 00-4.299 10.026l45.568 45.568z
    m-.52 30.872l-8.577-8.577-64.331 64.33 8.577 8.577 64.331-64.33z
    m-77.197 51.464l64.33-64.33-8.576-8.577-64.331 64.33 8.577 8.577z
    m-12.866-12.866l64.33-64.33-8.576-8.577-64.331 64.33 8.577 8.577z
    m-12.867-12.867l64.331-64.329-8.577-8.577-64.33 64.33 8.576 8.576z
    m-12.866-12.866l64.331-64.329-8.577-8.577-64.33 64.33 8.576 8.576z
    m15.011-96.494a39.946 39.946 0 00-3.616-3.191v62.134a40.002 40.002 0 003.606-3.181l.01-.01c15.371-15.371 15.371-40.382 0-55.752z
    m-27.877 83.628l11.819-11.818a45.713 45.713 0 01-23.637 0l11.818 11.818z
    m-18.195-20.766c5.552 2.896 11.754 4.437 18.195 4.437 6.442 0 12.644-1.541 18.196-4.437v-31.954H46.131v31.954zM8.573 158.473l11.861 11.86a45.803 45.803 0 010-23.721L8.573 158.473z
    m31.493-31.067a39.793 39.793 0 00-3.616 3.191c-15.371 15.37-15.371 40.379-.002 55.75l.004.004a40.036 40.036 0 003.614 3.189v-62.134z
    m6.065 28.034h36.391v-31.953c-5.552-2.896-11.754-4.438-18.196-4.438-6.441 0-12.643 1.542-18.195 4.438v31.953z
    m6.376-40.901a45.724 45.724 0 0111.819-1.554c12.151 0 23.574 4.731 32.166 13.323 11.907 11.907 15.807 28.824 11.727 44.026l20.438-20.438-55.753-55.753-20.397 20.396z
    m85.504 36.133c-3.566-29.938-27.367-53.739-57.305-57.305l57.305 57.305zM80.706 86.341c29.938-3.567 53.739-27.367 57.305-57.305L80.706 86.341z
    m12.848 3.513c22.932 6.914 41.055 25.037 47.97 47.968 6.914-22.931 25.037-41.054 47.968-47.968-22.931-6.914-41.054-25.038-47.968-47.969-6.915 22.931-25.038 41.055-47.97 47.969z
    m51.482-60.818c3.567 29.938 27.367 53.738 57.305 57.305l-57.305-57.305z
    m63.882 63.882a65.45 65.45 0 00-12.741 1.498l46.651 46.651a51.78 51.78 0 0116.433 2.193l-50.343-50.342z
    m3.144 67.475c-17.091 17.09-17.706 44.506-1.857 62.348l64.206-64.206c-17.841-15.847-45.257-15.233-62.349 1.858z
  " />
</svg>
Image Not Showing Possible Reasons
  • The image file may be corrupted
  • The server hosting the image is unavailable
  • The image path is incorrect
  • The image format is not supported
Learn More →

時間が余ってたら

親愛度10のアイドルコミュのあとに流れる特別な演出のあれを作る予定だった。


これ


時間が余ってたら。。。?


もくもく会やります!!

Image Not Showing Possible Reasons
  • The image file may be corrupted
  • The server hosting the image is unavailable
  • The image path is incorrect
  • The image format is not supported
Learn More →

https://imastudy-mokumoku.connpass.com/event/334074/

Image Not Showing Possible Reasons
  • The image file may be corrupted
  • The server hosting the image is unavailable
  • The image path is incorrect
  • The image format is not supported
Learn More →

ありがとー

Image Not Showing Possible Reasons
  • The image file may be corrupted
  • The server hosting the image is unavailable
  • The image path is incorrect
  • The image format is not supported
Learn More →
Select a repo