【AI活用】VRoid Studio・copainter・CLIP STUDIOを使ってコミック制作してみた

はじめに

こんにちは、エキサイト株式会社デザイナーの山﨑です。

エキサイトホールディングス Advent Calendar 2024 18日目は、山﨑が担当させていただきます。

qiita.com

今回は、VRoid Studio・copainter・CLIP STUDIO PAINTを用いてのコミック制作ついて、記して行きたいと思います。

AIを用いたコミック制作にチャレンジするまでの経緯

エキサイトでは、ウーマンエキサイトをはじめ、多くのコミックコンテンツを発信しています。

しかし、コミック制作には手作業が多く、時間やコストがかかるという課題がありました。

そこで、「AIツールを活用すれば、よりコミック制作の効率化が図れるのではないか?」という発想から、この挑戦がスタートしました。

今回の検証ポイントはこのようになります:

  1. 手作業の削減はどの程度可能か?
  2. 制作時間はどのくらい短縮できるか?
  3. 商業レベルのクオリティに達するか?

自分で絵を描かずにVRoid Studio、copainter、CLIP STUDIO PAINTを組み合わせて、どれほどスムーズにコミックが作れるか実際にやってみました!

ツールの説明

コミック制作に使用した主なツールを簡単に紹介します:

VRoid Studio:3Dキャラクターを簡単に作成できるソフトウェア。

vroid.com

copainter:ラフから線画を起こし、下塗り・着彩を行うAIイラスト制作支援ツール。

www.copainter.ai

CLIP STUDIO PAINT:プロ仕様のイラスト、漫画制作ソフトウェア。

www.clipstudio.net

今回の流れ:

  1. VRoid Studioでモデル制作
  2. copainterでモデルをコミック風イラストに変換
  3. CLIP STUDIO PAINTでセリフ入れや最終調整

セリフ入れ

まずは、CLIP STUDIO PAINTでコマ割りを作成し、セリフを入れていきます。(プロット〜ネーム部分は割愛させてください。)

モデル制作

登場人物は以下の3人です:

主人公(女性・黒髪ショート) 主人公の友達(女性・茶髪ロング) 主人公の彼氏(男性・茶髪ショート)

髪型・服装を見分けやすいデザインにしました。(似たような顔になることが多いので、髪色・髪型・洋服で差別化します。)

VRoid Studioでは、顔、髪型、衣装のセットが用意されており、簡単にモデルを作成できます。また、細かいカスタマイズも可能です。

さらに、VRoid用素材はBOOTH(pixivが運営するマーケットプレイス)からダウンロードして利用できます。

モデルにポーズを取らせる

VRoid Studioの強みは、モデルに表情やポーズを取らせた状態で写真を撮影できることです。 テンプレートモーションを使えば、自然な動きの瞬間をキャプチャすることができます。

このように、漫画のコマに沿ったポーズをモデルに取らせて写真を撮影していきます。

コミックイラスト化

撮影した画像をcopainterでコミックイラストに変換します。

copainterの「ペン入れ」から撮影した画像を入れ…

忠実度やその他の数値を調整すると…

コミックイラスト化できました。

このようにどんどんコミックイラスト変換して行きます。

泣き顔、頬を赤らめさせた表情にしたい場合は、画像の上に涙や頬に車線を加えるだけで、AIが自動で処理してくれます。

また、小物や背景は以下の方法で準備しました:

小物(財布など):CLIP STUDIO ASSETSから3Dモデルをダウンロード→スクショを撮影→copainterで出力。

背景:Adobe Stockから写真をダウンロード→copainterでコミックイラスト化。

イラストを合成

最終的に、作成したイラストをCLIP STUDIO PAINTでコマに組み込みます。 効果や文字入れを追加し、完成したのが以下の作品です:

検証結果

①手作業の削減はどの程度可能か? → 手作業の大部分である絵を描く必要がなくなるので大幅に削減できた。

ただし、セリフ入れや演出、モデルにポーズを取らせるスキルが必要になるため、完全な自動化は難しい。

②制作時間はどのくらい短縮できるか? → 約2~3時間で制作完了。従来なら8~10時間以上かかる作業を大幅に短縮できた。

③商業レベルのクオリティに達するか? → 出来上がりはかなり自然で、3Dモデルだと気付かれないほどのクオリティに仕上がった。

最後に

今回はモデルのポーズの取らせ方などは割愛してしまいましたが、今回の制作で、VRoid Studioやcopainterの可能性を実感しました!

最後に、エキサイトではデザイナー、フロントエンジニア、バックエンドエンジニア、アプリエンジニアを絶賛募集しております!

興味があればぜひ連絡よろしくお願いいたします!🙇

www.wantedly.com

Spring Bootにおいて、Controllerで全てのリクエストを受け取る方法

はじめに

こんにちは、新卒2年目の岡崎です。

エキサイトホールディングス Advent Calendar 2024の20日目を担当します。

他の記事はこちらから!

qiita.com

今回はSpring Bootにおいて、Controllerで全てのリクエストを受け取る方法を紹介します。

環境

  • gradle
------------------------------------------------------------
Gradle 8.11.1
------------------------------------------------------------

Build time:    2024-11-20 16:56:46 UTC
Revision:      481cb05a490e0ef9f8620f7873b83bd8a72e7c39

Kotlin:        2.0.20
Groovy:        3.0.22
Ant:           Apache Ant(TM) version 1.10.14 compiled on August 16 2023
Launcher JVM:  21.0.5 (Amazon.com Inc. 21.0.5+11-LTS)
Daemon JVM:    /Users/hiromi.okazaki/.sdkman/candidates/java/21.0.5-amzn (no JDK specified, using current Java home)
OS:            Mac OS X 14.7.1 aarch64
openjdk version "21.0.5" 2024-10-15 LTS
OpenJDK Runtime Environment Corretto-21.0.5.11.1 (build 21.0.5+11-LTS)
OpenJDK 64-Bit Server VM Corretto-21.0.5.11.1 (build 21.0.5+11-LTS, mixed mode, sharing)
  • Spring Boot
  .   ____          _            __ _ _
 /\\ / ___'_ __ _ _(_)_ __  __ _ \ \ \ \
( ( )\___ | '_ | '_| | '_ \/ _` | \ \ \ \
 \\/  ___)| |_)| | | | | || (_| |  ) ) ) )
  '  |____| .__|_| |_|_| |_\__, | / / / /
 =========|_|==============|___/=/_/_/_/

 :: Spring Boot ::                (v3.3.0)

実装

Spring Bootで全てのリクエストをControllerで受けとる場合、パスを/**とすれば実現できます。

    @RequestMapping("/**")
    public String getAllRequest() {
        return "hello world";
    }

@RequestMappingを使用すると、GETとPOSTの区別をつけず、リクエストを受け取ることができます。

また、GETのみ全てのリクエストを受け取りたい場合は、@GetMapping("/**")、POSTのみ全てのリクエストを受け取りたい場合は@PostMapping("/**")とすればそれぞれのリクエストを受け取ることができます。

特定のエンドポイントが存在する場合

特定のエンドポイントが存在する場合は、/**(ワイルドカード指定)よりも優先されます。

例えば、/sampleというエンドポイントが定義されている場合、リクエストは/**ではなく /sampleにルーティングされます。

最後に

本日はSpring Bootにおいて、Controllerで全てのリクエストを受け取る方法を紹介しました。どなたかの助けになれば幸いです。

小さなデザイナーチームで実践!レビュー依頼のワークフローを設計した話

こんにちは!SaaS・DX事業部デザイナーの鍜治本です。
前回、ブランチ機能を駆使してUIファイル管理している記事を書きました。

tech.excite.co.jp

事業部デザインチームでのUI更新方法が型化され、日々の作業が少し楽になった一方で、新たな課題が見えてきました。
それはレビュー依頼のやりとりです。この記事では、スラックのワークフロー機能を活用し、レビュー依頼を効率化した方法をご紹介します。

背景:レビュー依頼の課題

チームでUI更新の作業が分担できるようになった中、作業内容をレビューしてもらうにあたり課題が浮かび上がりました。

メンバーそれぞれのレビュー依頼

アナウンス手段が統一されていない

各メンバーがUI作成後にSlackで都度レビュー依頼を出しており、チャンネルは決まっているものの明確なルールは定義していませんでした。
「レビューの依頼はこのチャンネルでいいんでしたっけ…?」とメンバーに聞き、口頭で確認をとっている状態に…

依頼内容を作成するの負担が大きい

「修正なのか新規なのか」「どの箇所を見てほしいのか」など、依頼内容を毎回手書きで詳細に書くのが手間に感じる場面が多かったです。
また、プロトタイプを作成するとそれについても説明が必要に。レビュー依頼するたびに「依頼内容を説明」する必要があり、地味な負債となっていました。

これらの課題は特に、経験が浅いメンバーにとって心理的ハードルが高く、依頼が滞る原因にもなってしまいます。

解決策:ワークフロー機能を活用

この課題を解消するために、Slackのワークフロー機能を活用することに。
ワークフロー自体はデザイナー組織でも活用事例があるので、よければこちらもご覧ください。 tech.excite.co.jp

ワークフローを使えば、自己流になりがちなレビュー依頼も型化できます。
仕組み自体は簡単ですが、レビュー依頼は次のような流れにしました。

ワークフローの流れ

ワークフローの概要図
①ワークフローを立ち上げる
レビューを依頼したいメンバーがワークフローを起動。

②レビュー内容の入力
モーダルの内容に沿って、「レビューしてほしいリンク」「確認箇所」「その他備考」をフォームに記述して送信。

③該当チャンネルで通知
フォーム内容がレビュー担当者に通知され、次のアクションを促します。通知内容にはレビュー内容で記述されたリンクや、確認箇所が記載されています。

④レビュー担当者によるレビュー
レビュー担当者がボタンを押して、②レビュー内容の入力と同じくモーダルが立ち上げる。モーダルにはフォーム形式で「レビュー内容」「打合せ緊急度」を入力できるので、レビュー内容に合わせて記述&送信。

⑤レビュー依頼者への通知と共有
フォームが送信されると、レビュー依頼時のスレッドに④の内容が投稿される。

レビュー依頼者とレビュー担当者それぞれのフォーム

複数人がレビュー担当者としてレビューをする場合も、④のステップから開始でき、全て同じスレッドにまとめられます。

実際に使ってみて感じたこと

仕組み自体はシンプルですが、フォーム形式で入力できる点が大きなポイント。毎回のテキスト作成にかかる負担が軽減され、実際に自分以外のメンバーにも導入してもらっています。

ワークフローなので内容が統一され、担当者が確認しやすくなりました
元々、メンバーからも「レビューを投げる時に何を書けばいいか…?」という疑問があがっていたので、改めてレビューの流れを整頓できました。
特に、次の様なメリットがあったと感じています。

心理的ハードルを軽減できる

レビュー依頼やフィードバックのやりとり自体が簡単になり、依頼を投げるための準備といった仕込み作業を減らせました。これによって、本来のレビューに集中できるようになりますね。

必要な情報を押さえられる

依頼時に重要な要素となる「レビューで伝えるべき前情報」も必ず入力できます。新卒メンバーなど、レビュー依頼に慣れていない人もスムーズに依頼できるようになりました。

今後の展望

現在はSlack上で通知・内容確認し、具体的な修正などはミーティングをセットする流れとなっています。
ただ、これではレビュー内容と実タスクとの紐付きが弱く、後から見返した時の関連が分かりにい状態です。また、別タスクでも活かせる情報源でもあることから、レビューした内容自体にも価値がある考えています。

今後は、タスク管理をしているNotionと連携させて、もらったレビュー内容やフィードバックを関連づけたり、レビュー内容をチームのナレッジベースとして活用できないか調整してみます。

まとめ

今回の取り組みを通じて、チーム全体のレビュー依頼プロセスが出来上がったことで、メンバー同士でレビューする際の負担を減らせました。
小さな工夫でしたが、チームのコミュニケーションを円滑にできる環境作りになれたと思います。
皆さんも、ぜひワークフロー機能を試してみてください〜!

見逃さないために今からチェック!行きたい展示会2025

こんにちは!SaaS事業部デザイナーの澤田です! エキサイトホールディングス Advent Calendar 2024 の22日目を担当します。

エキサイトホールディングスの各社に所属するエンジニア・デザイナーが力を合わせてブログのバトンを回しているので、ぜひ他の記事も覗いてみてください😊

qiita.com

今回は来年見逃さないために絶対に行きたい展示会をご紹介します...!

デザインあ展neo

累計116万人を動員した「デザインあ展」が、装いも新たに「デザインあ展neo」として虎ノ門ヒルズ TOKYO NODEに登場します! 2025年4月18日から9月23日まで、歴代最長の会期で開催され、「みる」「かんがえる」「つくる・あそぶ」をテーマに、パーフェクトロン、プラプラックス、岡崎智弘らによる新作約35点を含む展示を通して、デザインの魅力を体感できる展示会となっているそうです。 360度スクリーンでの映像体験や、NHK『デザインあneo』でおなじみのコーナーも登場するそうで今からワクワク....!!

デザインあ展neo
デザインあ展neo

展示概要

会期:2025年4月18日 (金) ~ 9月23日 (火・祝) 入場料:未定 会場:TOKYO NODE GALLERY A/B/C (虎ノ門ヒルズ ステーションタワー 45F) 主催:TOKYO NODE、NHK、NHKエデュケーショナル、NHKプロモーション 総合ディレクター:佐藤 卓 映像ディレクター:中村 勇吾 音楽ディレクター:蓮沼 執太 展示構成作家:パーフェクトロン、プラプラックス、岡崎 智弘 exhibition-ah-neo.jp

ラーメンどんぶり展

展覧会を中心に、トークやワークショップなど、デザインの楽しさを体験できる多彩なプログラムを展開する21_21 DESIGN SIGHTでは、2025年3月7日から6月15日まで、企画展「ラーメンどんぶり展」を開催されます。日本のラーメン丼の90%を占める美濃焼に焦点を当て、その1300年の歴史や背景、職人たちの技、そしてラーメンと器の関係性を紐解く内容になっているそうです。 アーティストによるオリジナル丼の展示に加え、ラーメン屋台の紹介、「デザインの解剖」の手法を用いた考察など、多角的な視点からラーメンの魅力を探りラーメンの奥深さを発見する展覧会となっているそうです...!!

 ラーメンどんぶり展
ラーメンどんぶり展

展示概要

会期:2025年3月7日(金) - 6月15日(日) 会場:21_21 DESIGN SIGHTギャラリー1&2 開館時間:10:00 - 19:00(入場は18:30まで) 休館日:火曜日(4月29日、5月6日は開館) 入場料: 一般1,600 円、大学生800 円、高校生 500 円、中学生以下無料 ディレクター:佐藤 卓、橋本麻里

www.2121designsight.jp

美を疑え-資生堂クリエイティブ展-

化粧品メーカーである資生堂のクリエイティブ部門が独立して2022年1月に設立された資生堂クリエイティブ株式会社初の展覧会が開催されます。 コンテンツ内容はまだ公開されていませんが、どのような展示がされるのかプロダクト開発の裏側が知れるのでは...?と今からとても楽しみです...!

美を疑え-資生堂クリエイティブ展-
美を疑え-資生堂クリエイティブ展-

展示概要

会期:2025年1月11日(土) - 2025年1月26日(日) 会場:資生堂ギャラリー 開館時間:11:00 - 19:00(日曜日・祝日は18:00まで) 休館日:月曜日 入場料:無料

www.shiseidocreative.com

さいごに

いかがだったでしょうか!? 来年も見逃せない展示会がたくさんありいまからワクワクしています💓 もしおすすめの展示会があれば教えてください! 最後までお読みいただき、ありがとうございました

TerraformでECSコンテナとBedrockの間のPrivateLinkを確立する

こんにちは、エキサイト株式会社の平石です。

エキサイトホールディングス Advent Calendar 2024のシリーズ2, 19日目を担当いたします。

今回はAWS上のECSコンテナとBedrockの間のPrivateLinkを確立する方法をご紹介します。

AWSリソースの作成にはTerraformを使います。

はじめに

Amazon Bedrockとは

Amazon Bedrockは、AWS上で生成AIを利用できるようにするフルマネージドサービスです。
既存のモデルを容易に利用することもできますし、用途やデータに合わせてカスタマイズすることも可能です。

aws.amazon.com

PrivateLinkとは

Amazon BedrockはVPC上になく、ECSコンテナ環境で動作しているアプリケーションからBedrcokを利用する際にはNAT Gatewayを利用するなどしてインターネットを経由する必要があります。
しかし、インターネットを経由するとセキュリティの問題が生じます。

PrivateLinkは利用するAWSサービスがVPC上にあるかのように接続するための方法で、インターネットを経由しないプライベートな接続が可能になります。

PrivateLinkはVPCにアタッチするVPCエンドポイントというコンポーネントと接続先のAWSサービスを結びつけることで構築します。

環境

Terraform 1.10.3で動作確認をしています。

前提条件

AWSアカウントの作成、Terraformの環境構築、ECSコンテナのデプロイ、Bedrockのモデルへのアクセス許可は完了していることを前提としています。

実装

Security GroupとIAMポリシーを作成する

まずは、VPC エンドポイントにアタッチするSecurity Groupを作成します。

./vpc_endpoint/bedrock/main.tf

variable "vpc" {
  type = object({
    vpc_id             = string
    private_subnet_ids = list(string)
  })
}

variable "trusted_security_group_id" {
  type = string
}

module "security_group" {
  source      = "terraform-aws-modules/security-group/aws"
  version     = "5.1.0"
  name        = "bedrock-vpce-sg"
  description = "Security group for bedrock-vpce"
  vpc_id      = var.vpc.vpc_id
  ingress_with_source_security_group_id = [
    {
      from_port                = 443
      to_port                  = 443
      protocol                 = "tcp"
      source_security_group_id = var.trusted_security_group_id
    }
  ]
}

設定したSecurity GroupからのTCPプロトコルによる443ポートへの通信のみ許可します。 変数trusted_security_group_idには、ECSにアタッチしたSecurity GroupのIDを渡します。

次に、VPCエンドポイントにアタッチするポリシードキュメントを作成します。

./vpc_endpoint/bedrock/main.tf

variable "trusted_role_arns" {
  type = list(string)
}

........

data "aws_iam_policy_document" "bedrock_access_policy" {
  statement {
    actions = [
      "bedrock:InvokeModel",
      "bedrock:InvokeModelWithResponseStream",
    ]
    effect = "Allow"
    resources = [
      "arn:aws:bedrock:ap-northeast-1::foundation-model/anthropic.claude-*"
    ]
    principals {
      identifiers = var.trusted_role_arns
      type        = "AWS"
    }
  }
}

このポリシードキュメントでは、VPC エンドポイントにBedrockのInvokeModelとInvokeModelWithResponseStreamを許可します。
Bedrockのモデルにアクセスして、生成AIからのレスポンスを得るためにはこのポリシーを設定すれば十分でしょう。
今回は、AnthropicのClaudeというモデルにアクセスできるようにしています。

VPC エンドポイントを作成する

これまでに作成したSecurity Groupやポリシーを利用してVPCエンドポイントを作成します。

./vpc_endpoint/bedrock/main.tf

resource "aws_vpc_endpoint" "bedrock_vpc_endpoint" {
  service_name        = "com.amazonaws.ap-northeast-1.bedrock-runtime"  // â‘ 
  vpc_id              = var.vpc.vpc_id
  vpc_endpoint_type   = "Interface"  // â‘¡
  subnet_ids          = var.vpc.private_subnet_ids  
  policy              = data.aws_iam_policy_document.bedrock_claude_policy.json  // â‘¢
  security_group_ids  = [module.security_group.security_group_id]  // â‘£
  private_dns_enabled = true  // ⑤

  tags = {
    Name = "bedrock-vpce"
  }
}

output "bedrock_vpc_endpoint_id" {
  value = aws_vpc_endpoint.bedrock_vpc_endpoint.id
}

①では、VPC エンドポイントでVPCとPrivateLinkを確立するサービスを設定します。今回は東京リージョン(ap-northeast-1)のBedrockを設定しています。

②では、VPC エンドポイントのタイプを設定します。VPC エンドポイントのタイプには主にGatewayとInterfaceがあります。
Gateway エンドポイントは無料で利用できますが、現在のところAmazon S3またはDynamoDBとの接続しかサポートされていません。 今回は、Bedrockとの接続を確立するためInterface エンドポイントに設定しています。

③, ④では、上で作成したSecurity Groupとポリシーをアタッチしています。

⑤では、指定したVPCにプライベートホストゾーンを関連付けるかどうかを設定します。
VPC内のサービスが自動でVPC エンドポイントを利用するために必要なため、trueに設定しましょう。

ECSタスクのロールを変更

次にECSタスクのロールにアタッチされているポリシーを変更します。

./ecs/xxxxx/main.tf

variable "bedrock_vpc_endpoint_id" {
  type = string
}


data "aws_iam_policy_document" "iam_policy_document" {
  statement {
    actions = [
      〜〜 略 〜〜
      "ec2:CreateNetworkInterface",
      "ec2:DescribeNetworkInterfaces",
      "ec2:DeleteNetworkInterface",
      "ec2:*VpcEndpoint*"
    ]
    resources = ["*"]
  }

  // BedrockへのアクセスをVPC エンドポイント経由のみに制限
  statement {
    effect = "Allow"
    actions = [
      "bedrock:InvokeModel",
      "bedrock:InvokeModelWithResponseStream"
    ]
    sid       = "AllowTask"
    resources = ["*"]
    condition {
      test     = "ForAnyValue:StringEquals"
      values   = [var.bedrock_vpc_endpoint_id]
      variable = "aws:SourceVpce"
    }
  }
}

前半部分では、ECSタスクからVPCエンドポイントを利用できるようなstatementを追加しています。

また、後半部分ではECSタスクからBedrockへのアクセスをVPC エンドポイント経由のみに制限し、意図せぬインターネットへのアクセスが発生しないようにしています。
ただし、このstatementはあくまでVPCエンドポイントからBedrockにアクセスできるようにしているだけなので、他に無条件でBedrockにアクセスを許可するようなstatementを記述している場合には削除しておきましょう。

作成した部品を組み合わせる

最後にこれまで記述したVPC エンドポイントを実際に作成します。

./main.tf

// Bedrockに接続するためのVPCエンドポイント
module "bedrock_vpc_endpoint" {
  source = "./vpc_endpoint/bedrock"
  vpc = {
    vpc_id             = <使用するVPCのIDを指定>
    name               = <使用するVPCの名前を指定>
    private_subnet_ids = <使用するVPC内のサブネットを指定(基本的にはECSが存在するサブネット)>
  }
  trusted_role_arns = [
    <ECS タスクロールのarn>
  ]
  trusted_security_group_id = <ECSに設定したSecurity GroupのID>
}

終わりに

今回はECSコンテナとBedrockの間のPrivateLinkを確立する方法をご紹介しました。

インターネットを経由しないことでセキュリティ強化につながるため、Bedrockを利用する場合には設定すると良いでしょう。

参考文献

【保存版】デザイナーのインプット場所まとめ〜インスピレーションを求めて〜

こんにちは!SaaS事業部デザイナーの澤田です! エキサイトホールディングス Advent Calendar 2024 の最終日、25日目を担当します!

ここまでエキサイトホールディングスの各社に所属するエンジニア・デザイナーが力を合わせてブログのバトンを回してきたので、ぜひ他の記事も覗いてみてください😊

qiita.com

デザイナーにとって、新しいデザインに触れ、知識をアップデートしていくことは、表現の幅を広げる上で非常に大切です。そこで今回は、今後の情報収集に役立つ、おすすめのデザインインプット場所をまとめました!

デザイン全般

Pinterest

Pinterest(ピンタレスト)は、画像や動画を収集・共有するサービスです。まるで自分の好きな写真や画像をコルクボードにピンで留めるように、気になる画像や動画を「ピン」として保存し、それをカテゴリーごとに整理して「ボード」にまとめ、他のユーザーと共有することができます。

Pinterestの画面
Pinterest

https://jp.pinterest.com/

Behance

Adobe(アドビ)社が運営する、クリエイターのためのオンラインプラットフォームです。世界中のクリエイターの作品を見ることができます。

Behanceのサービス画面
Behance

https://www.behance.net/

Design Inspiration

Pinterestと同じく様々なジャンルのデザインが掲載されています。カラーを指定して画像検索することができます!

Design Inspirationのサービス画面
Design Inspiration

https://www.designspiration.com/

Dribbble

デザイナーのためのオンラインコミュニティプラットフォームです。世界中のデザイナーの作品を閲覧することができます。

dribbbleのサービス画面
dribbble

https://dribbble.com/

UIデザイン

mobbin

iOSとAndroidのモバイルアプリのUI/UXデザインパターンを豊富に集めたライブラリサイトです。様々なアプリのスクリーンショットをカテゴリー別に見ることができます。

mobbinのサービスサイト
mobbin

https://mobbin.com/

UIポケット

こちらもmobbinと同様にウェブデザインやアプリデザインの参考になる、アプリのUIデザインギャラリーサイトです。

UI Pocketのサービス画面
UI Pocket

https://www.ui-pocket.com/web/apps

ABTEST

mobbinによって提供されてるUIのABテスト結果が一覧で見られるサイトです。

ABTESTのサービス画面
ABTEST

https://abtest.design/

Webデザイン

SANKOU!

Webデザイン制作の参考になる日本のWebサイト・LPを集めたギャラリー・リンク集です。

SANKOU!のサービス画面
SANKOU!

https://sankoudesign.com/

URAGAWA

国内トップクラスの制作プロダクション、事業会社のクリエイティブが「どの企業が作ったのか」も含めてわかるWEBデザインギャラリー、参考サイト集です。

URAGAWAのサービス画面
URAGAWA

https://mirai-works.co.jp/uragawa/

1GUU

クオリティの高いWebデザインを集めたWebデザイナーのためのギャラリー・サイトリンク集です。一覧のサムネで動きもわかるためアニメーションから探すことも可能です!

1GUUのサービス画面
1GUU

https://1guu.jp/

MUUUUU.ORG

同じくWebデザインのインスピレーションを得るためのギャラリーサイトです。

MUUUUU.ORGのサービス画面
MUUUUU.ORG

https://muuuuu.org/

Studio Showcase

STUDIOで制作されたWebサイトが集められたギャラリーサイトです。カテゴリー別で検索して探すこともできます。

Studio Showcaseのサービス画面
Studio Showcase

https://showcase.studio.design/ja

グラフィックデザイン

バナーデザインの参考になる、おしゃれで良質なバナーデザインをまとめたギャラリーサイトです。バナー広告から特集バナーまで、幅広いジャンルから収集できます!

BANNER LIBRARYのサービス画面
BANNER LIBRARY

https://design-library.jp/

Facebook広告集めました。

Facebook広告運用者、これから広告運用をする方のためのFacebook広告を集めたサイトです。

Facebook広告集めました。のサービス画面
Facebook広告集めました。

https://facebook.adsquare.jp/

その他

GOOD PORTFOLIO / ポートフォリオサイト

世界中のクリエイターデザインポートフォリオ集です。Web、UI/UX、グラフィック、イラストなど多ジャンルのポートフォリオが掲載されています。

GOOD PORTFOLIOのサービス画面
GOOD PORTFOLIO

https://goodportfol.io/

COCODA / デザイン

デザインの裏側をまとめた事例集です。日本を代表するデザイン組織から、200以上の事例が公開されています!

COCODAのサービス画面
COCODA

https://cocoda.design/teams

終わりに

今回は、私が日頃から参考にしているデザインインプットの場所をご紹介しました。 少しでも皆さんのデザインワークのお役に立てれば幸いです!今回ご紹介したサイト以外にも、おすすめのインプット場所があれば、ぜひ教えてください!😊 最後までお読みいただき、ありがとうございました

【Flutter】go_routerの基本とOSごとにテーマを分ける方法

こんにちは、エキサイトでアプリエンジニアをしている岡島です。エキサイトホールディングス Advent Calendar 2024の21日目を担当させていただきます。

今回はgo_routerを触ってみたので、go_routerについて共有していこうと思います。

環境

dependencies:
go_router: ^14.6.2

go_routerの特徴

go_routerは、ルーティングのライブラリであり、URLに基づいたナビゲーションのため、ディープリンクを扱いやすいなどの特徴があります。

pub.devのReadmeには次のような特徴があると書かれています。

  • テンプレート構文を使用したパス パラメーターとクエリ パラメーターの解析
  • 目的地(サブルート)の複数画面の表示
  • リダイレクトのサポート
  • ShellRouterによる複数のナビゲーターのサポート
  • MaterialとCupertinoアプリのサポート
  • Navigator APIの後方互換性

go_routerの基本

準備

基本的に必要となることは以下のとおりです。

  1. GoRouterの構成を宣言する
  2. MaterialApp.routerやCupertinoApp.routerを使用して準備をする

GoRouterの構成を宣言する

以下の例のようにそれぞれの画面を宣言していきます。

最低限必要なものはpathとbuilderです。

final router = GoRouter(
  routes: [
    GoRoute(
      path: '/',
      builder: (BuildContext context, GoRouterState state) {
        return const HomeScreen();
      },
    ),
    GoRoute(
      path: 'screen1',
      builder: (BuildContext context, GoRouterState state) {
        return const Screen1();
      },
    ),
  ],
);

はじめに開く画面を指定する場合はinitialLocationでパスを指定します。

final router = GoRouter(
  initialLocation: '/',
  routes: [
    // GoRoute()の宣言
  ],
);

他にもdebugLogDiagnostics: true, とするとログが出力されるようになります。

MaterialApp.routerやCupertinoApp.routerを使用して準備をする

アプリでgo_routerを利用するには、MaterialApp.routerやCupertinoApp.router 使用し、routerConfig に宣言したGoRouterの構成オブジェクトを設定します。

void main() {
  runApp(const MyApp());
}

class MyApp extends StatelessWidget {
  const MyApp({super.key});

  @override
  Widget build(BuildContext context) {
    return MaterialApp.router(
      routerConfig: router,
    );
  }
}

以上で準備が完了です。

画面遷移の方法

ここまでの準備で、go_routerを利用すると、画面遷移の時にcontext.go()を用いて遷移することができます。下のように書くと、TextButtonをタップしてScreen1に遷移することができます。

  return TextButton(
    child: const Text('Screen1'),
    onPressed: () => context.go('/screen1'),
  );

他にもNavigator.of(context).push()やNavigator.of(context).pop()の代わりにcontext.push()やcontext.pop()が利用できます。

go_routerではBuildContextのナビゲーションに拡張関数を定義しています。

extension GoRouterHelper on BuildContext 

この拡張関数のおかげで、context.go()やcontext.pop()というようにcontext.〇〇で遷移することができるようになっています。

名前付きルートを使用する

GoRouteに一意の名前をつけることができます。設定するには宣言時にnameのパラメータを追加するだけです。

GoRoute(
   name: 'myPage',
   path: /* ... */,
   builder: /* ... */,
 ),

遷移する時はgoNamedを用います。

TextButton(
  onPressed: () {
    context.goNamed('myPage');
  },
  child: const Text('myPageへ遷移'),
),

こうすることで以下のメリットがあります。

  • パスの変更に柔軟になる
    • nameを用いて遷移するので、パスの変更があっても一括で変更できます。複数の画面でパスを指定して遷移していた場合は、それぞれの箇所でパスを変更する必要があります。

OSごとにテーマを設定する方法

準備の段階で、MaterialApp.routerやCupertinoApp.routerを使用していましたが、PlatformApp.routerを用いるとMaterialやCupertinoデザインを区別することができます。

PlatformApp.routerを用いるにはflutter_platform_widgetsをインストールする必要があるのでご注意下さい。 https://pub.dev/packages/flutter_platform_widgets

AndroidはMaterial系のデザインに寄せてテーマを設定するなどということができます。

    return PlatformApp.router(
      routerConfig: router,
      material: (_, __) => MaterialAppRouterData(
        theme: ThemeData(
          primaryColor: Colors.red,
        ),
      ),
      cupertino: (_, __) => CupertinoAppRouterData(
        theme: const CupertinoThemeData(
          primaryColor: Colors.blue,
        ),
      ),
    );

最後に

go_routerを用いることで、URLベースのナビゲーションが可能とwebに似た操作ができるようになりました。またディープリンクに対応しやすくなるのも利点の一つかと思いました。

最後まで読んでいただきありがとうございました!

【AI着彩】copainterを用いてコミック着彩にチャレンジしてみた

はじめに

こんにちは、エキサイト株式会社デザイナーの山﨑です。

エキサイトホールディングス Advent Calendar 2024の24日目を担当します。

qiita.com

この記事では、「copainterを用いたコミック着彩」について取り組んだ内容をご紹介します。

copainterって何?

copainterは、ラフから線画の作成や下塗り・着彩を行うイラスト制作支援ツールです。
詳細はこちらからご確認ください:
公式サイト - copainter

また、copainterはイラストの絵柄をAIで再現・量産するツール「mimic」を提供しているRADIUS 5によって運営されています。
RADIUS 5

目的

今回は、女性向けWebメディア「ウーマンエキサイト」で公開しているコミックの着彩工程を、AIツールを活用して効率化できるか検証しました。

現状では、ウーマンエキサイトのコミック制作では以下の工程をイラストレーターに依頼しています:

  • ラフ作成
  • 線画作成
  • 着彩
  • セリフ入れ

もし、ラフと線画だけをイラストレーターに依頼し、着彩とセリフ入れを内製化できれば、コミックのリリーススピードを向上させ、より多くの作品を公開できると考えました。

着彩準備

線画と下塗り

copainterでの着彩には、通常、線画と下塗りを事前に用意する必要があります。

下塗りは、AIに着彩のベースとなる色を正確に指示する、いわば設計図のような役割を果たしています。

実験していた時には実装されていませんでしたが、最近copainterに下塗りを自動で行う機能が追加されました。 下塗りの作業が煩わしいと感じる方は、この新機能を活用することをお勧めします。

今回は以下の手順を取りました:

  1. 線画の準備

    • 完成済みの線画を用意。
  2. 下塗り

    • CLIP STUDIO PAINTを使用し、人物の肌・髪・服などに任意の色を塗り、下塗りを作成。(登場人物ごとにカラーパレットを作成しておくと便利です。)

下塗りはシンプルな操作で済むため、1枚あたり1~2分程度で作業が完了します。

着彩手順

準備が整ったら、いよいよ着彩に移ります。以下はcopainterでの着彩手順です:

  1. ログイン
    copainterの公式サイトにアクセスし、アカウントを作成またはログイン。右メニューから「着彩」へ

  1. 線画と下塗りのアップロード
    対象の画像をアップロード。

  1. 塗りモードを選択
    「AIの変化の強さ」「書き込み量」「モデル」選択し、「送信」ボタンをクリック。 (最初はデフォルトで出力することをオススメします。)

  1. 結果の確認と出力
    着彩が完了した画像を確認し、ダウンロード。

以下が実際の出力例です:

[出力結果]

この絵にセリフを足して、完成です。

使用感と課題

使用感

  • 簡単な操作
    線画と下塗りさえ用意すれば、誰でも出力できる。
  • 迅速な処理
    1〜3分程度で処理が完了。
  • 塗り精度の限界
    部分的な指定がうまく反映されない場合があり、手直しが必要なケースも。

実用性の検討

copainterを使用した場合、以下の作業時間が必要になります:

  • 下塗り:1分〜2分
  • AI着彩:3〜4分
  • 背景設定・セリフ入れなどの追加作業:6〜7分

これにより、1枚の仕上げに約15分かかる計算となり、1連載分(約120枚)の着彩・セリフ入れに必要な時間は30時間以上を要します。

さらに、登場人物の感情表現に合わせた背景設定(例:悲しい感情にブルーのグラデーション背景、喜びの感情にピンクや黄色の背景など)は、物語の文脈を理解しながら作業する必要があり、これは専門的なスキルを伴う作業といえます。

以上の理由から、効率化には課題が多く、現段階での実用化は見送るという結論に至りました。

おわりに

copainterは簡単な操作で高品質な着彩ができる優れたツールですが、現状では運用に課題が残る結果となりました。

今後も効率化の可能性を模索していきたいと思います。

エキサイトではデザイナーやエンジニアを積極採用中です!

興味のある方はぜひご連絡ください。

www.wantedly.com

Tailwind CSSで要素間の境界線をスタイリングするときはdivide-*が便利

こんにちは。エキサイトでデザイナーをしている齋藤です。

エキサイトホールディングス Advent Calendar 2024 シリーズ1の23日目を担当します。

qiita.com

今回は、TailwindCSSで要素間の境界線をスタイリングするときはdivide-*が便利というお話をします。

実現したいこと

今回実現したいUIは、以下のように行内セル間の垂直な境界線が破線になっているテーブルです。

行内セル間の垂直な境界線が破線になっているテーブル

HTML・CSS的に言い換えると、2つ目以降のtd要素の左側に破線の境界線を設けるということになります。

<table>
    ...
    <tbody>
        <tr>
            <!-- 2つ目以降の`td`要素の左側に破線の境界線を設ける -->
            <td></td>
            <td></td>
            <td></td>
        </tr>
        ...
    </tbody>
</table>

どうやってスタイリングするか

Tailwind CSSでスタイリングする場合、行内2つ目以降のtdタグに対してborder-leftを付与する力技もありますが、コードの見通しが悪くなってしまいます。

そこで有用なのが、divide-*シリーズです。

divide-*は子要素間に境界線を設けるユーティリティクラスです。

例えば、先にお示ししたテーブルの条件である「各行内のセル間に破線で黒色の垂直な境界線を設ける」を、divide-*を使用してスタイリングすると以下のようになります。(※行間の水平な境界線は割愛します)

<table>
    ...
    <tbody>
        <tr class="divide-x divide-dashed divide-black">
            <td></td>
            <td></td>
            <td></td>
        </tr>
        ...
    </tbody>
</table>
  1. divide-xで水平要素間に境界線を追加
  2. divide-dashedで境界線を破線に設定
  3. divide-blackで境界線色を黒色に設定

何が起きているか

divide-*の中身を見てみると何が起きているかが理解できます。

例えば、devide-xの場合、以下のようなCSSになっています。

.divide-x > * + * {
    border-right-width: 0px;
    border-left-width: 1px;
}
  • 親が .divide-x であること
  • .divide-x の直接の子要素であること
  • その要素の直前に、同じ .divide-x の直接の子要素があること

これらの条件に合致する要素に、border-right-width: 0px; border-left-width: 1px;が付与されるといった仕組みになっています。

まとめ

今回は、Tailwind CSSで要素間の境界線をスタイリングするときに便利なdivide-*をご紹介しました。

divide-*を使用すると、対象の要素それぞれにユーティリティクラスを付与する必要がなくなり、見通しのよいコードになる上、要素の追加もしやすくなると考えます。

Tailwind CSSを使用される方の一助となれば幸いです。

ご精読ありがとうございました。

第10回テクデザBeer Bashを開催しました

こんにちは、エキサイトでエンジニアをしている吉川です。エキサイトホールディングス Advent Calendar2024 の23日目の記事になります!

先日12/20(金)に社内イベントの「テクデザBeer Bash」を開催したので、運営視点でレポートを書いていきます。

テクデザBeer Bashとは

Beer Bashとはbeer(ビール)+ bash(にぎやかなパーティー)を合わせた造語で、真面目な部分を残しつつ、カジュアルな雰囲気で交流を行うイベントです。 年に3、4回社内カフェスペースで開催しており、同じチーム内の人はもちろん、業務ではあまり関わることがない他部署の人たちとも繋がる場になっています。

当日のコンテンツ

今回は以下の2つをメインコンテンツとし、後半はフリートークの時間にしました。 - 作って理解する動画配信の仕組み - Studioを使ったサイトづくり

作って理解する動画配信の仕組み

弊社が提供しているウェビナーPDCAクラウド「FanGrowth」では、録画した過去のウェビナーをアーカイブとして配信する機能があります。 www.fangrowth.biz

今回は動画のストリーミング配信機能の開発方法やデプロイ方法などを、担当エンジニアの方からデモを交えて発表いただきました。ストリーミングの概要は知っていても、具体的な実装は詳しくない社員も多く、勉強になったとの反響が多く寄せられました。

Studioを使ったサイトづくり

弊社が提供している予実管理クラウド「KUROTEN」の一部ページは、ノーコードのWeb制作プラットフォームであるStudioを使って開発・公開しています。 kuroten.biz

今回は担当デザイナーの方からStudioの良いところや、ページ公開にあたりどんな作業をされたのかを発表いただきました。 デザインツール連携のようなデザイナーならではの視点や、エンジニアを介さないことでよりスピーディな実装になった話をいただき、参加者からもStudioが便利そうだというお声をいただきました。

運営視点の振り返り

前回 実施した座席+バイキング形式が好評だったので、今回はよりレベルをあげて立食+バイキング形式で実施しました。 移動しやすい分多くの方と交流しやすくなり、より会を盛り上げることができました。また途中から参加する社員も入りやすい雰囲気にできたのも良かった点です。

また今までは夜19時ごろから開始していましたが、時間を早めて夕方17時ごろから開始したところ、ご家庭事情で夜参加が難しい方や遠方から出社されている方も参加しやすくなりました。こうした裾野を増やす施策は今後も積極的に行っていきたいです。

まとめ

最後まで読んでいただき、ありがとうございました。 テクデザBeer Bashは社内イベントではありますが、少しでもイベントの雰囲気が伝わっていたら幸いです。

今回も内定者の学生さんをご招待しており、参加後のアンケートでは大変満足したとご回答いただけました。今後も社員同士、社員と学生の交流を深めるイベントとしてBeerBashを盛り上げていきます!

UI管理の効率化:Figmaのブランチ機能を活用する

こんにちは!SaaS・DX事業部デザイナーの鍜治本です。
エキサイトHDアドベントカレンダー シリーズ1の20日目を担当させていただきます!

qiita.com

この記事では、Figmaのブランチ機能を活用して、UI管理をどのように効率化したかについて詳しくお話しします。

これまでほぼ一人でFigmaを運用されていた方や、これからチームメンバーが増える組織、そして「ブランチ機能って実際どうなの?」と気になっている方にぜひ見ていただきたいです…!
何かしらの運用方法を見つけるヒントになれば幸いです!

ブランチ機能導入前に抱えていた課題

昨年度までは事業部デザイナーに私しかおらず、UI制作においてもエンジニアと直接やりとりすれば運用はできる状態でした。
今年から優秀な後輩が配属され、複数人で同じプロダクトのUIを修正することが増えました。分担できるのでアウトプットのスピードは向上したものの、運用部分で下記のような課題が積み上がってしまうことに。

ドラフトファイル管理の煩雑さ

これまでは、機能ごとにドラフトファイルを作成し、Fix後にマスターファイルに反映していました。

管理しているFigmaファイルの一部。 件数の積み重なり・更新の手間が課題に
しかし、複数ページにまたがるUI変更や他リリースとの競合で、更新漏れが頻発。最新状態の管理が難しく、実装されているものが正解という本末転倒な状態に。

UIの一貫性の欠如

同じページのUIなのに、ファイルが異なるとUIも異なる状態
ページをまたいだデザインのズレが生じやすく、結果としてユーザー体験を損なうことに。
また、機能同士で新しいUIと古いUIが入り混じりやすく、開発効率にも悪影響を及ぼしていました。

ブランチ機能とは?

これらを改善すべく、取り入れたのがブランチ機能です。
ブランチ機能をざっくり説明すると、メインとなるファイルを枝分かれさせて、同時に複数ファイル上で更新できるようになる機能です。

機能リリースが3年も前なので見え方は異なりますが、公式の動画やQiita株式会社の綿貫さんの記事がとてもわかりやすいです。

youtu.be

qiita.com

ブランチ機能を導入するために実施したこと

ブランチ機能導入するにあたり、ただ機能を取り入れるだけではうまく運用できないことも判明。
これまでのファイル管理方法などもテコ入れして、「ファイル管理方法の変更」と「ブランチ管理の手順策定」の2つを実施しました。

ファイル管理方法の再構築

これまでUIの修正や更新があるたびに、課題ごとにナンバリングしたファイルを作成して、一通り合意形成できたら「マスターファイル」へ更新させる方法をとっていました。
この方法、作成している間は1ファイル内で完結するため便利な反面、過去の履歴を探したり最新状況を確認するのに不向きで、一人での管理も中々面倒に。

新しいファイル管理方法では、ページを軸にマスターファイルを作成
ブランチ導入にあたり、機能ごとにファイルを分ける構造に変更。
複数ページにわたる改修でも、ファイルごとにブランチを切ります。 一つの修正・作成の間に関与するファイルは増えてしまいますが、過去のファイルを掘り出したいときには便利なため許容しています。
またファイルの切り分け方として、プロダクトのナビゲーションを軸にした「マスターファイル」を作成しました。

ブランチ運用の導入

ファイルの管理方法を変更し、いざブランチの導入へ。
運用として下記の流れを取るルールを設けました。

ファイル更新の方法。ブランチ(枝分かれ)を作成して修正します。

  1. 変更が生じたUIのマスターファイルからブランチを作成
  2. 修正/作成作業の実施
  3. 作成後はレビューを投げて問題ないか確認
  4. 問題がなければマージ

ブランチ機能を取り入れたことで、複数デザイナーが同時に編集する場合であっても、各自が独立して作業できる環境になっています。

同じページを別のデザイナーが編集(オレンジ線)しても内容の反映が可能
修正したUIはマージ操作で確実に反映されるため、これまでのような更新漏れの防止に繋がります。

ブランチ機能のメリットとデメリット

ブランチ機能導入にあたり、私が感じたメリット・デメリットはそれぞれこんな感じ。

メリット
  • 複数デザイナーが同一ページを編集可能。
  • マージ操作で反映漏れを防止。
  • 属人化せず、UI変更が誰にでも把握可能。
デメリット
  • すでにある仕組みに取り入れられるかの下調べが必要。
  • チーム全員で運用の統一するため、ルール整備が必要。

デメリット面はそこまで大きなハードルではなかったので、今回のように実現に振り切れました。
また、フェーズによって使う/使わないの切り分けをしてもいいと思います。

こんなチームにおすすめ!

  • デザイナー間の並行作業が増えている
  • UI変更に伴うファイル管理が煩雑化している
  • チーム全体で最新状態を共有できていない

自分たちは丁度このような課題を感じたために乗り換えた経緯があります。
もし同じような課題感があれば、ブランチ機能の導入を検討してみてもいいかもしれません。

最後に

ブランチ機能を取り入れたことで、チームのデザイン管理が大きく改善されました。
運用にはチームごとに使いやすい形があると思うので、今後も様子を見ながらより良い状態を維持していきたいです。
この記事が、皆さんのチーム運用を見直すきっかけになれば嬉しいです!
ご覧いただき、ありがとうございました🍣

FigmaでLottieアニメーションを作ってみた!

こんにちは!SaaS事業部デザイナーの澤田です! エキサイトホールディングス Advent Calendar 2024 の19日目を担当します。

エキサイトホールディングスの各社に所属するエンジニア・デザイナーが力を合わせてブログのバトンを回しているので、ぜひ他の記事も覗いてみてください😊

qiita.com

本日はもうすぐクリスマス🎄...ということで、Lottie(ロッティ)というサービスを利用してクリスマスにちなんだアニメーションを作成してみました!

この記事では、Lottie初心者向けに、同じくLottie初心者が実践したことの共有となります🔰 ぜひ「こんなこともできるよ...!」などがありましたら教えていただけると嬉しいです..!!

Lottieとは?

『Lottie(ロッティ)』とは、Airbnbが開発したJSONベースのアニメーションファイル形式です。GIFと比較してファイルサイズが小さく、どんなデバイスでもピクセル化を起こさずに拡大縮小できるのが特徴です。

FigmaやAfter Effectsなどのデザインツールで作成したアニメーションを、Webサイトやアプリに簡単に取り込むことができます。

参考:Lottieアニメーションとは?- LottieFiles

Lottieアニメーションの作り方

今回は普段よく使用するFigmaで作成しました。 そのほかAfter effectやLottie Creatorを利用してアニメーションを作ることもできます!

0.事前準備

Lottieのアカウントを作成する

アカウントを作成

1.Figmaのプロトタイプ機能でアニメーションイメージを作成

①フレームを作成し、アニメーションに必要なオブジェクトを配置する

Figmaでオブジェクトを配置

②プロトタイプ機能を使ってアニメーションを作る

プロトタイプ作成
【作成のポイント】

  • 最終形態から遡って作成し、不要なパーツは不透明度を0%にする(削除してしまうとうまくいきませんでした💦)

  • トリガーはアフターディレイにする(ユーザーが特定のフレームで一定の時間を費やすと、自動で次のアクションへと進むことができる設定です)

  • アニメーションはスマートアニメートにする(フレーム間で同し要素がある場合、変化前と変化後の要素の差分を埋め合わせてアニメーションをつける機能です)

  • フローの開始地点をつける(地点名がファイル名になります)

まだ自由になんでも再現できる...というわけではないみたいです。詳しくはサポートサイトをご参照ください。

2.プラグイン「LottieFiles」をインストール

Figmaプラグイン「LottieFiles」

3.ログインし、LottieFilesへ書き出す

①書き出したいフレームをすべて選択し、「Export to Lottie」ボタンをクリックする・または「Select prototype flow」から書き出したいフローを選択する

Flowの選択

② 「Save to workspace」をクリックする>アップロード先のフォルダーを選択し、「Save」ボタンをクリックする

Save to workspace

4.LottieFilesで書き出したアニメーションを確認

再生スピードや配色などはここでも変更できます。 思った通りにアニメーションが出来たら、Enble Asset CDNのトグルスイッチをONにし、埋め込みコードをコピーします。

ウェブサイト上のアニメーションを表示したい箇所にこのコードを記述するだけで簡単にWEBアニメーションが実装可能です!

アニメーションを確認

今回作成したクリスマスツリーのアニメーション

  

  
<script src="https://unpkg.com/@dotlottie/[email protected]/dist/dotlottie-player.mjs" type="module"></script>
<dotlottie-player src="https://lottie.host/80f8339e-ec85-4c78-b03e-cee4d9f76c93/Ff5O64O6jE.json" background="transparent" speed="1" style="width: 300px; height: 300px" direction="1" playMode="normal" loop controls autoplay></dotlottie-player>

GIFで書き出したアニメーション
GIFで書き出したアニメーション

Lottieでは無料アニメーションもたくさん!

試しに「Christmas」と検索したらたくさん出てきました! ここからイメージと近いものをダウンロードして編集することもできるので、アニメーション初心者にはありがたいですね...!

クリスマスツリーの検索結果

まとめ

今回、初めてLottieを触ってみましたがとても簡単で便利...!!と感じました。 やはり静止画よりアニメーションがつくとワクワクしますね💓

普段のクリエイティブでもワクワクしたものが作れるように積極的に利用していきたいと思います。 最後まで読んでいただきありがとうございました!

明日は私のメンターを務めてくださっているSaaS事業部デザイナーの鍜治本さんの記事です! お楽しみに..!!😊

AWSでSSL証明書を発行する方法

はじめに

こんにちは、新卒2年目の岡崎です。

まずは、次の画像を見てください。

ここから証明書の詳細をクリックすると、証明書に含まれていませんと出てきます。

この場合、SSL証明書を発行する必要があります。

今回はAWS上の環境で動いているサービスなので、AWSでSSL証明書を発行する方法を紹介します。

手順

AWSでSSL証明書を発行する手順を紹介します。

SSL証明書の作成

まず、AWSにログインをしたら、Private Certificate Authorityにアクセスします。

そこから、AWS Certificate Managerを選択します。

次に、リクエストをクリックします。

証明書のリクエストを行う画面で、次へをクリックします。

さらに、バプリック証明書をリクエストします。

完全修飾ドメイン名に、SSL証明書を発行したいドメイン名を追加してください。例えば、sample.test-excite.co.jpに対してSSL証明書を発行したい場合、*.test-excite.co.jpを追加します。

また、同じSSL証明書を複数のドメインで使用したい場合は、この証明書に別の名前を追加ボタンをクリックして、他のドメインを登録してください。

最後に検証方法・キーアルゴリズムは任意に選択します。今回はデフォルトの設定にしました。

リクエストをクリックすれば、SSL証明書が作成できます。

SSL証明書の作成後に証明書一覧にアクセスすると、作成したSSL証明書が追加できたことを確認できます。

SSL証明書の検証

SSL証明書の作成後、SSL証明書の検証を行います。

まずはSSL証明書IDをクリックします。

そこから、ドメインのRoute53でレコードを作成をクリックします。

以下の画面で、さらにレコードの作成をクリックします。

SSL証明書のステータスが発行済みになれば、SSL証明書の検証完了です。

SSL証明書の承認

ロードバランサーの中から、任意のロードバランサーを選択 します。 さらに、HTTPS:443から証明書のタブをクリックします。

今回はすでにデフォルトのSSL証明書の設定を行なっていたので、証明書の追加を行いました。

SNIのリスナー証明書から、証明書の追加をします。

作成した証明書にチェックを入れ、証明書のインポートをクリックします。

これでSSL証明書の承認ができました。

最後にサイトを確認します。

画像のようになっていたら、SSL証明書の発行完了です。

最後に

今回AWSでSSL証明書を発行する方法を紹介しました。誰かの助けになれば幸いです。

AWS Copilot CLIのScheduled JobとSpring Shellを組み合わせて一回限りのタスクを実行する

はじめに

エキサイト株式会社 バックエンドエンジニアの山縣(@zsp2088dev)です。 エキサイトホールディングス - Qiita Advent Calendar 2024 - Qiita の18日目を担当します。

エキサイトブログの開発では、新機能の開発や既存機能の改修時に、データベースに新たなテーブルを作成し既存のデータを移行することがあります。 データ移行を何度か経験していく中で、より快適なデータ移行環境を目指し、AWS Copilot CLIのScheduled JobとSpring Shellを組み合わせたデータ移行環境を構築しました。 本記事では、このような環境を用意した背景や、実際に取り組んでいることについて紹介します。

背景

一般に、あるテーブルから別のテーブルへデータを移行する場合、複雑な加工処理をしないのであればINSERT... SELECTで済むことが多いです。 一方で、スキーマ間のデータ移行や複雑な加工処理を必要とするデータ移行では、アプリケーション内でデータの加工をしたほうが柔軟性が高くなります。 例えば、データの正規化や結合、不要なデータのフィルタリングなどを必要とする場合、SQLだけでは記述が複雑になりがちです。 また、アプリケーションコードを書くことで、テストコードを書くことができたり、ログ出力ができたりなどの利点があります。

エキサイトブログの開発でも、昨年のブログテーマ機能の改修のときに以下のような取り組みをしていました。

tech.excite.co.jp

当時は、EC2上でgit cloneしてアプリケーションコードを手動実行していました。 データ移行は繰り返し行うものではなく一回限りの実行であるため、煩わしさを感じつつも「頻度が高くないからこのままでいいな」と考えていました。 しかし、今後も同様の操作をすることを考えたときに、より快適なデータ移行環境を目指したほうがよいと考え、新たなデータ移行環境を検討するようになりました。

環境

本記事で扱う環境は以下の通りです。 記事内では実際にデータ移行しているところまでは触れず、「データ移行を実行する環境」について触れていきます。

Spring Shellの設定

Spring Shell 3系では@Commandアノテーションを使用してコマンド登録ができます。 下記のコードに対して、./gradlew bootRun --args="hello"と実行したときに、test1と出力されることが確認できます。 同様に、./gradlew bootRun --args="world"と実行したときに、test2と出力されます。 このように、引数に応じて実行したいメソッドを切り替えることができます。

package com.example.command;

import lombok.RequiredArgsConstructor;
import org.springframework.shell.command.annotation.Command;

@Command
@RequiredArgsConstructor
public class SampleCommand {
    @Command(command = "hello")
    public String hello() {
        return "test1"
    }

    @Command(command = "world")
    public String hello() {
        return "test2"
    }
}

データ移行時は、本メソッド内にデータの読み込み、書き込み、加工処理を書いていました。

Spring Bootをコンテナ化する

jibを使用して、Spring Bootで作成したアプリケーションをコンテナ化しています。 argsプロパティに対して、@Commandアノテーションに定義したcommandの値を設定することで、コンテナ実行時に任意のメソッドを実行できるようになります。 これを利用して、./gradlew jibDockerBuild -Pargs=helloとコンテナ化することで、コンテナ実行時にtest1と出力するコンテナイメージを作成できます。

jib {
    container {
        if (project.hasProperty("args")) {
            args = [
                    project.property('args')
            ]
        }
    }
}

jibの詳細やその他オプションについては下記のドキュメントをご参照ください。

github.com

AWS Copilot CLIの設定

Amazon ECS内でコンテナ化されたアプリケーションを実行するために、AWS Copilot CLIのScheduled Jobを使用しています。 Scheduled Jobのマニフェストのscheduledフィールドにnoneを設定することで、タスクが定期実行されないように設定できます。

on:
  schedule: "none"

aws.github.io

上記の設定により、タスクは定期実行されません。 Scheduled Jobのドキュメント内には、noneを設定するのは一時的無効化したい場合と記載されているため、本来の用途とは違った使い方をしています。 copilot job runコマンドを実行すると、任意のタイミングでタスクを実行することができます。 これにより、タスクを実行したいときだけcopilot job runコマンドを実行すればよいです。

aws.github.io

GitHub Actionsから実行する

上記の内容までを実装することで、ローカル環境上でcopilot job runと実行するとタスクを実行できます。 これを、ローカル環境上にcopilotコマンドが無くても実行できるように、GitHub Actions上で実行できるようにしていきます。

ここでは、ワークフローを実行するのにGitHub Actionsのworkflow_dispatchイベントと、workflow_dispatch.inputsを使用します。 以下のようにworkflow_dispatch.inputsを定義すると、ワークフロー内で ${{ inputs.ARGS }}として扱えます。

on:
  workflow_dispatch:
    inputs:
      ARGS:
        description: ジョブ名を入力してください
        required: true
        type: string
      ENV:
        description: デプロイ先の環境を選択してください
        default: test
        required: true
        type: choice
        options:
          - test
          - prod

これにより、下記のようにhelloと入力し、ワークフロー内でコンテナをビルド、コンテナレジストリにプッシュ、copilot job run と実行することで、ECS上でtest1と出力できるようになります。

おわりに

本記事では、AWS Copilot CLIのScheduled JobとSpring Shellを組み合わせた一回限りのタスクを実行する方法について紹介しました。 サンプルでは標準出力をしただけですが、我々の開発ではデータベースからデータを読み取り、アプリケーション内で加工、データを書き込みといった操作をしています。 一度環境を整備してしまえば、いつでもすぐに利用できるのが非常に嬉しいです。

一方で、本記事では事業部内で知見のあるAWS Copilot CLIを使用していますが、以下のissueの通り、開発体制が不安定な状況にあるようです。 もし本記事と同様のことを実現したい場合は、以下の内容についてご留意いただけますと幸いです。

github.com

採用アナウンス

エキサイトではフロントエンジニア、バックエンドエンジニア、アプリエンジニアを随時募集しています。 また、長期インターンも歓迎しています。

カジュアル面談からもOKです。少しでもご興味がございましたら、お気軽にご連絡頂ければ幸いです。

▼ 募集職種一覧 ▼ recruit.jobcan.jp

Reactで良い感じのモーダルを作成する

こんにちは、エキサイト株式会社の奥川です。

エキサイトホールディングス・アドベントカレンダー2024シリーズ2の17日目を担当します。

qiita.com

今回は、Next.jsでいい感じのモーダルを作成する方法をご紹介します。

完成形

コンポーネントと呼び出し側のコードは下記になります。スタイルは適当です。

モーダルコンポーネント

// Modal.tsx
import { FC, ReactNode, useRef, useEffect } from 'react'
import { createPortal } from 'react-dom'

type ModalProps = {
  isOpen: boolean
  onClose: () => void
  children: ReactNode
}

const Modal: FC<ModalProps> = ({ isOpen, onClose, children }) => {
  const dialogRef = useRef<HTMLDialogElement>(null)

  useEffect(() => {
    if (isOpen) {
      // body要素にoverflow: hiddenを設定するとモーダル表示時に背景がスクロールしなくなる
      document.body.style.overflow = 'hidden'
      dialogRef.current?.showModal()
    } else {
      dialogRef.current?.close()
    }
  }, [isOpen])

  if (!isOpen) return null

  const handleClose = () => {
    onClose()
    // body要素のoverflow: hiddenを戻す
    document.body.style.overflow = ''
    // ボタンのフォーカスを外す
    document.activeElement instanceof HTMLElement && document.activeElement.blur()
  }

  return (
    <>
      {createPortal(
        <dialog>
            {children}
            <button 
              onClick={handleClose} 
              style={{ marginTop: '1rem', padding: '0.5rem 1rem', cursor: 'pointer' }}
            >
              閉じる
            </button>
        </dialog>,
        document.body,
      )}
    </>
  )
}
export default Modal

呼び出し部分の例

import { useState } from 'react'
import Modal from './Modal'

const ModalExample = () => {
  const [isOpen, setIsOpen] = useState(false)

  return (
    <div>
      <h1>Modal表示の例</h1>
      <button
        onClick={() => seIsOpen(true)}
        style={{ padding: '0.5rem 1rem', cursor: 'pointer' }}
      >
        モーダルを開く
      </button>

      <Modal isOpen={isOpen} onClose={() => setIsOpen(false)}>
        <h2>モーダルの中身</h2>
        <p>ここに任意のコンテンツを入れることができます。</p>
      </Modal>
    </div>
  )
}

モーダル作成時に意識した点

DOM上ではbody要素末尾だが、コード上ではコンポーネント内に書きたい

モーダルは次の観点からDOM上ではbody要素直下の末尾に記載されることが多いです。

  • 全ての要素より優先して表示させたい
  • 他の場所とスタイルを独立させたい

しかし、画面全体を複数コンポーネントで分けて実装している場合、コンポーネントの中でモーダルを書こうとするとbody要素の途中でモーダルを書くことになります。ReactではcreatPortalを利用することで、DOM上の別の場所にコードを移動させられるため、コンポーネントの中でモーダルを実装してもbodyの直下に配置させることができます。

ja.react.dev

dialog要素を活用する

モーダルはdialog要素を用いて実装します。

developer.mozilla.org

dialog要素を利用すると、backdropで背景のCSSを設定できたり、アクセシビリティ周りの設定をしなくてもブラウザがモーダルと認識してくれるため、非常に便利です。dialog要素を利用する場合、モーダルの開閉作業はHTMLDialogElement.showModal()/close()をそれぞれ利用します。ただ、Reactではコンポーネントを純粋に保つことが推奨されます。そのため、モーダルの開閉状態はpropsで管理し、実際の開閉処理はHTMLDialogElement.showModal()/close()を利用しています。

おわりに

今回はReactでモーダル用のコンポーネントを作成する方法を紹介しました。開閉ロジックをカスタムフックにしたり、まだ改善の余地はあるかと思います。まだ、dialog要素を利用する場合はcreatePortalでbody直下に飛ばさなくても問題なかったります。今回の記事が実装の助けになれば幸いです。