63
39

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 1 year has passed since last update.

【fabric.js】『化物語』の閑話休題演出をサクッと作れる「化物語「風」扉絵メーカー」を1.5時間で作ってみた

Last updated at Posted at 2022-06-07

はじめに

最近、Youtube動画の演出で「化物語でよく見る閑話休題や黒駒演出取りいれるのはどうだろう」と思い、動画編集ソフト上で実現してみた。
スクリーンショット 2022-06-07 201114.png
場面転換としてなかなか優秀だなと思い、これからこの演出を使っていこうかなと思ったが...

「都度色を考えたり、カラーコードコピーしたりが面倒だ...!!」

というわけで、自分が楽するためにサクッと閑話休題演出を作ってくれる簡単なWebアプリを作ってみた。

なお、1時間ちょっとで作ったver0.5版なので、簡単な操作しかできないが、気が向いたらもう少しブラッシュアップする予定。

作った(作っている)モノ

(PC画面しか対応してなくてスマン)
化物語「風」扉絵メーカー

こんな感じのモノが出来る。下部のボタンでダウンロードできる。(ブラウザはChromeでしか動作確認していない)
image.png

UIはクソでスマン。後でもう少しマシにする。

出来ること

  • 画面上のメインテキスト/サブテキストの編集(「化物語 桃駒」の部分とその下の英字)ができる(テキスト中身編集/位置移動回転)
  • Select Themeの色アイコンをクリックで、簡単に色テーマを切り替えできる
  • FontColor, BackgroundColor 欄に色コード(#333333やwhite など)を指定することで、好きなカラーに変更可能
  • Toggle Frameで周辺の白枠表示/非表示コントロールが可能
  • Downloadボタンで編集結果の画像をダウンロード可能

ソース

Git

ソース本体

index.html
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <script
    src="https://code.jquery.com/jquery-3.6.0.js"
    integrity="sha256-H+K7U5CnXl1h5ywQfKtSj8PCmoN9aaq30gDh27Xc0jk="
    crossorigin="anonymous"></script>
    <script type="text/javascript" src="js/lib/fabric.min.js"></script>
    <script type="text/javascript"  src="js/lib/FileSaver.js"></script>
    <script type="text/javascript"  src="js/lib/canvas-toBlob.js"></script>
    <link rel="preconnect" href="https://fonts.googleapis.com">
    <link rel="preconnect" href="https://fonts.gstatic.com" crossorigin>
    <link href="https://fonts.googleapis.com/css2?family=Noto+Serif+JP:wght@500&display=swap" rel="stylesheet">
    <link href="https://fonts.googleapis.com/css2?family=Kotta+One&family=Noto+Serif+JP:wght@500&family=Quintessential&display=swap" rel="stylesheet">
    <style>
        #canvas{
	        display: block;
        }
        #meta-wrapper {
            margin-left: auto;
            margin-right: auto;
        }
        #wrapper {
            width: 100%;
            height: 100%;
        }
        .color-preset-changer {
            width: 32px;
            height: 32px;
            border-radius: 16px;
            margin: 8px;
            display: inline-block;
        }
    </style>
    <title>化物語扉絵メーカー v0.5(プロトタイプ)</title>
</head>
<body>
    <div style="display: block">
        <div id="meta-wrapper">
            <div id="wrapper">
                <canvas id="canvas" width="" height=""></canvas>
            </div>
        </div>

        <div id="current-color-wrapper">
            <span class='setting-label'>FontColor: </span>
            <input type="text" id="current-color-fontColor">
            <span class='setting-label'>BackgroundColor: </span>
            <input type="text" id="current-color-bgColor">

            <button id="current-color-change-button">Change Color</button>
        </div>

        <div id="color-preset-wrapper"></div>

        <div id="frame-toggle-wrapper">
            <div class='setting-label'>Toggle Frame: </div>
            <input type="checkbox" id="frame-toggle-check">
        </div>

        <div id="download-image-wrapper">
            <button id="download-image">Download</button>
        </div>

        <input type="hidden" id="current-theme-holder">
    </div>

    <script>
        const COLOR_PRISETS = ["#1f2a3b/#ffffff", "#443830/#ffffff", "#9b459b/#ffffff", "#e0684b/#ffffff", "#dd931b/#ffffff", "#c40c09/#ffffff", "#bfbdbe/#ffffff", "#7d002f/#ffffff", "#e16369/#ffffff", "#e2601b/#ffffff", "#d2bd6b/#ffffff", "#90b932/#ffffff", "#8190ab/#1a1212", "#eaeae8/#8190ab"]

        const elCanvas = document.getElementById("canvas")
        const elWrapper = document.getElementById("wrapper")

        const baseWidth = elWrapper.offsetWidth * 0.8
        const canvasWidth = baseWidth
        const canvasHeight = baseWidth * 9 / 16
        elCanvas.width = canvasWidth
        elCanvas.height =  canvasHeight

        const canvas = new fabric.Canvas("canvas")

        const [defaultBgColor, defaultFontColor] = COLOR_PRISETS[0].split("/")
        const defaultFontFamily = "HGP明朝B, 'HGP明朝B', Noto Serif JP, 'Noto Serif JP', serif"

        $("#current-theme-holder").attr("data-attr-bgcolor", defaultBgColor).attr("data-attr-fontcolor", defaultFontColor)

        const bg = new fabric.Rect({
            left: 0,
            top: 0,
            fill: defaultBgColor,
            width: canvasWidth,
            height: canvasHeight,
            selectable: false,
        })

        const mainText = new fabric.IText("化物語 黒齣", {
            fontWeight: 'normal',
            left: canvasWidth / 2,
            top: canvasHeight / 2 - 48,
            fontFamily: defaultFontFamily,
            charSpacing: 1000,
            fill: defaultFontColor,
            fontSize: 64,
            originX: "center",
            originY: "center",
            selectable: true,
        })

        const subText = new fabric.IText("bakemonogatari                                            kuro", {
            fontWeight: 'normal',
            left: canvasWidth / 2,
            top: canvasHeight / 2 + 24,
            fontFamily: "Kotta One, 'Kotta One', serif",
            fontStyle: 'italic',
            charSpacing: 10,
            fill: defaultFontColor,
            fontSize: 24,
            originX: "center",
            originY: "center",
            selectable: true,
        })

        const rectangleWrap = new fabric.Rect({
            left: 64,
            top: 48,
            fill: "transparent",
            width: canvasWidth - 128,
            height: canvasHeight - 96,
            selectable: false,
            stroke: "transparent",
            strokeWidth: 4,
        })

        const calcFrameColor = color=> $("#frame-toggle-check").prop('checked') ? color : "transparent"

        const changeTheme = (bgColor, fontColor)=> {
            $("#current-theme-holder").attr("data-attr-bgcolor", bgColor).attr("data-attr-fontcolor", fontColor)

            bg.set("fill", bgColor)
            mainText.set("fill", fontColor)
            subText.set("fill", fontColor)
            rectangleWrap.set("stroke", calcFrameColor(fontColor))

            canvas.renderAll()
        }

        $("#color-preset-wrapper").append("<div class='setting-label'>Select Theme: </div>")
        const elColorPresetWrapper = COLOR_PRISETS.forEach(v=> {
            const [bgColor, fontColor] = v.split("/")
            const el = 
                $(`<div id='${v}' class='color-preset-changer' style='background-color: ${bgColor}' data-attr-bgcolor='${bgColor}' data-attr-fontcolor='${fontColor}'></div>`)
                    .on("click", event=> {
                        const bgColor = $(event.target).attr("data-attr-bgcolor")
                        const fontColor = $(event.target).attr("data-attr-fontcolor")

                        changeTheme(bgColor, fontColor)
                    })
            $("#color-preset-wrapper").append(el)
        })
        
        $("#frame-toggle-check").on("click", event=> {
            const fontColor = $("#current-theme-holder").attr("data-attr-fontcolor")
            rectangleWrap.set("stroke", calcFrameColor(fontColor))

            canvas.renderAll()
        })

        $("#current-color-change-button").on("click", event=> {
            const fontColor = $("#current-color-fontColor").val()
            const bgColor = $("#current-color-bgColor").val()

            changeTheme(bgColor, fontColor)
        })

        $("#download-image").on("click", ()=> {
            $("#canvas").get(0).toBlob(function(blob){
		        saveAs(blob, "monogatari-like-cut.png");
            })
        })

        canvas.add(bg)
        canvas.add(rectangleWrap)
        canvas.add(mainText)
        canvas.add(subText)
    </script>
</body>
</html>

ソースざっくり説明

  • Webフォントでそれっぽいフォントを使うことにしているよ
  • 生Canvasではなくて、fabric.jsを使ってるよ
  • ダウンロード処理にはFileSaver.jsとcanvas-toBlob.jsを使ってるよ

後は特記事項無しですね...

参考リンク

fabric.js
eligrey FileSaver(Git)
eligrey canvas-toBlob(Git)

63
39
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
63
39

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?