【個人開発】新年早々、今年の抱負をつぶやくWEBアプリをつくってみた

# 【個人開発】新年早々、今年の抱負をつぶやくWEBアプリをつくってみた

明けましておめでとうございます。  
本年もよろしくお願いいたします。  
早速ですが、新年早々アプリを作成しました。  

**[今年の抱負メーカー](https://ambition.nozomi.bike)**

アイデアを思いついて形にするまでに3日間という短い期間で作成したので、それまでの過程を記事にしようと思います。  

## アプリの内容
使い方は非常に簡単で、**名前**と**今年の抱負**を入力するだけで半紙に筆で書いた抱負画像を生成することができます。  
下の方にある「つぶやく」ボタンをクリックしてツイッターにアップロードするという流れです。  
他にはシェアした抱負が見られたランキング、PVランキングを搭載したぐらいですね（よくあるパターンです）  

こんな感じ

![FireShot Capture 4 - 今年の抱負メーカー I のんさんの抱負 - https___ambition.nozomi.bike_share_5.png](https://qiita-image-store.s3.amazonaws.com/0/192516/2e524a99-466a-89ff-0d1a-b4dce91396f4.png)

##　アプリ作成の流れ

開発期間は３日間なので特に目立ったことはしていません。  
アイデアを形にするまでにダッシュもダッシュ、猛ダッシュで作成しました。
**[https://ambition.nozomi.bike](https://ambition.nozomi.bike)**
この子のドメインも既に買ってあるやつから適当に追加しました。
では、開発の流れにいきます。

### １日目
アイデアを思いつき、それを形に使用と決意。  
それと同時に競合してそうなサービスがあるかなどを調査。これは同じようなサービスを作成されている先人がいる場合、できるだけ作りを参考にしたり、自分の個性を表現する機会を得るためです。
個人的には学ぶは真似ぶ、同じような物があれば積極的に参考にしていきます。  
**今回は１０分位調べて結果なさそうだったので、完全オリジナルです。**

ついでにこのあたりから頭の中で設計開始。「２画面くらいやな〜」と思いながら構想を練ってました。

### ２日目
コーディング開始  
ちなみに使用技術は

- Laravel
- Vue.js

この２つです。目立った技術は使用していません。
敷いてあげるのであれば、画像生成のところを苦労しました。
Laravelで画像生成処理が搭載されているものと踏んでいたのでサクサク進むかなぁと思っていたのですが、見つけられずに自作しました。（もしこういう便利機能あるよって知っている方おりましたらご教示いただきたい。）

#### 画像生成

大体こんな感じ

```php:image.php
/**
 * 抱負画像を作成します。
 *
 * @param string $ambition 抱負
 * @return string $toImage 保存先
 */
private function createAmbitionImage(string $ambition)
{
    // 元になる画像を取得
    $image = imagecreatefromjpeg('./dist/001.jpg');
    // ファイル名
    $fileName = str_random(32).'.jpg';
    // 保存先
    $toImage = Ambitions::AMBITION_FILE_PATH.$fileName;
    // 設定情報
    $size = 150;
    $x = imagesx($image) / 2 - 75;
    $y = 80;
    $color = imagecolorallocate($image, 0, 0, 0);
    $font = "../public/font/fude.ttf";
    $verticalString = $this->convertStringToVirtival($ambition);
    if (count($verticalString) > 1) {
        $x = imagesx($image) / count($verticalString) * (count($verticalString) - 1) - 75;
    }
    // 画像と文字を合成
    foreach ($verticalString as $string) {
        imagettftext($image, $size, 0, $x, $y, $color, $font, $string);
        $x -= 75 * 4;
    }
    imagejpeg($image, $toImage, 100);
    imagedestroy($image);
    $imagePath = asset(Ambitions::AMBITION_FILE_PATH. $fileName);
    return $imagePath;
}
/**
 * 文字列の文字と文字の間に改行コードを挿入し、縦書き対応にします。
 *
 * @param string $string 対象文字列
 * @return array $verticalString 変換後文字列
 */
private function convertStringToVirtival(string $string)
{
    $l = mb_strlen($string, 'UTF-8');
    $chunked = array();
    $col = 0;
    for ($i = 0; $i < $l; $i++) {
        if ($i % 7 == 0) {
            $col++;
            for ($j = 0; $j < $col; $j++) {
                $chunked[$col][] = '';
            }
        }
        $chunked[$col][] = mb_substr($string, $i, 1, 'UTF-8');
    }
    //配列を改行でjoin
    $verticalString = array();
    foreach ($chunked as &$colValue) {
        $verticalString[] = join("\n", $colValue);
    }
    return $verticalString;
}
```
**こう見るとマジックナンバー多いですね・・・**課題に挙げられます。
image~系のメソッドを駆使して画像を生成しています。
正直このあたりは初めてのことでしたので、手探りでした。ここの機能開発に少し時間を取られたくらいでしょうか。

#### DB周り
他の機能に関してはただのDB通信なのでサクッと作成。

#### フロント
![FireShot Capture 6 - 今年の抱負メーカー - https___ambition.nozomi.bike_home.png](https://qiita-image-store.s3.amazonaws.com/0/192516/5c0cc522-c8b2-38a0-7c2f-e777b415545c.png)

この部分は今後のことを考えてVueで作成しました。
本当は全部Vueに任せるつもりだったんですが、時間がなくて慣れてる開発手法でやってしまったのが原因です。
フロントは只今勉強中・・・他のアプリは全てVueで作成しているのですが、この子は例外です。

#### SNS

![FireShot Capture 7 - 今年の抱負メーカー - https___ambition.nozomi.bike_home.png](https://qiita-image-store.s3.amazonaws.com/0/192516/3c09438d-f6e6-7e6b-3d71-271921af6ae2.png)

この部分はよくあるやつですね。
「SNS ボタン 設置」とかで検索すると出てきますよ。

#### つぶやく / 画像ダウンロード

![FireShot Capture 8 - 今年の抱負メーカー I のんさんの抱負 - https___ambition.nozomi.bike_share_5.png](https://qiita-image-store.s3.amazonaws.com/0/192516/69202df1-b5ce-1b0f-2fbe-e93885d7a869.png)

機能として少し考え込んだのは左の「つぶやく」ボタン。
**ぶっちゃけこれだけのアプリのためにOAuth認証を作るのも、使わせるのも面倒くさい**
じゃあもうシェアボタンで良いや。となりこの子の招待はシェアボタンです。

ボタンの作り方は

```html:twitter.html
<a href="https://twitter.com/intent/tweet?url=URL&text=表示したいテキスト&hashtags='ハッシュタグ１',ハッシュタグ２"
onClick="window.open(encodeURI(decodeURI(this.href)), 'tweetwindow', 'width=650, height=1000, personalbar=0, toolbar=0, scrollbars=1, sizable=1'); return false;" rel="nofollow" class="btn btn-primary">
    <i class="fab fa-twitter-square"></i>つぶやく
</a>
```

画像ダウンロードは普通の画像ダウンロード処理です。

### ３日目
広告やCSSなどの最終調整とテスト

#### 広告
最終的に使用していませんが、[vue-google-adsense](https://www.npmjs.com/package/vue-google-adsense)というプラグイン便利でした。使用方法はリンク先に乗っていますので、見てください。

#### CSS
ほとんどBootstrapに頼っているので目立ったところはありません。
こういうのを凝ってしまうと時間かかるので、有り物で作成してしまうくせがあります。

#### テスト
自動テストするまでもないので、テストコードは書いていません。手動テストです。

## 作ってみて
**多分最速くらいに速いサービスです。**
こんなに早く完成できたのは初めてです。
もっと言えばこんなに適当に作ったもの初めてです。
クセでマージンは３倍取るのが僕のポリシーなので、普段なら１人日の作業ですね笑。
**競技プログラミングをしてるみたいでかなり面白かったです。**
タイムアタックみたいな感じでした。
[今年の抱負メーカー](https://ambition.nozomi.bike)

### 意識したこと
季節感でアプリを作成してみました。
いろんなアプリが世の中にある中で埋もれてしまいやすいものがたくさんあると思います。
**しかし日本人はイベントを重視する文化をもつので、季節やイベントに関するアプリは使用頻度は低いけど、廃れにくいのかなと思いました。**
今回は年末は近いのと、自分で抱負をつぶやこうと思っていたのでこれを選びました。

### スピード感
かなり焦りながら作りました。
なんてたって年末はすぐそこでしたから。
スピードを高めると技術獲得スピードが上がるというのは本当かもしれない。そう思えました。
~~これについては別記事にしようかなと思います。~~
記事にしました[【個人開発】勉強方法と開発手法、そのスピード感について【勉強方法】](https://qiita.com/Nozomi-Hosaka/items/ca06fd2212223c741041)

## 課題
- ３日間というのもあって機能不足が否めません。今後のアップデートにご期待ください。
- SNSボタンの使用方法に意外な使い方があるような気がしてしようがありません。
- 画像生成部分に違和感を感じるので、再作成するかも。

## 参考
[フォントフリー](http://fontfree.me/)
[和紙のフリー素材が無料](https://www.xn--0trq75g.pw/)

## 最後に
業務系というかビジネス関連で[トドTask](https://todo.nozomi.bike)というアプリも作成しました。
ただのタスク管理アプリなので、供給過多どころではありませんが、**API利用（予定）**や**ノート機能**も搭載しているので、良かったら使ってみてください。API利用については近々ドキュメント公開します。
**質問あれば回答できる範囲でするのでコメントお願いします**