9
3

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 5 years have passed since last update.

iOS #2Advent Calendar 2019

Day 5

あり物のSF Symbolsからカスタムシンボルをつくる

Posted at
この記事は
Xcode 11.2.1, iOS 13.2, Swift 5.1, SF Symbols 1.1
で書かれています

SF Symbols

以前、SF Symbolsを取り上げた記事を書きました。あれから数ヶ月、Symbols関連で検索すると結構上位に結果表示されたりする(ライバルが少ない)ので、気分をよくしてまた書きたいと思います。

内製App

「ヘイSiri、焼きそばひとつ」で焼きそばが注文できればいいな、と思ってAppをつくりはじめてはやn年。設計やバックエンドの変更を繰り返し、いまだ完成の目処すら立ちませんが、また転がり落ちるとわかっている大岩を山頂へと押し上げるが如く、こつこつと焼きそばの合間をみては開発をつづけています。

そんなわけで先日はショッピングAppには必須の「購入履歴」機能の実装に取り組んでいました。時すでに2019年も終わろうかという折、SF Symbolsにも当然アダプトするべく、「購入履歴」にあうシンボルを探していました。

購入履歴

SF Symbolsはイニシャルリリースのベータから数度バージョンアップされ、現在は1.1が最新です。風の噂でリリースのたびにシンボルの種類が増えているということですが、残念ながら今回の目的にあうものはざっと見たところ見当たりません。

でも、だからといって一からつくるのは避けたい(その理由は過去のSF Symbolsへの取り組みでご覧ください)。

なにかいい手はないものか・・・

カスタマイズ、という手

SF Symbolsはこの種のApple謹製リソースとしてはかなり珍しいと思うのですが、提供されたシンボルの<カスタマイズ>が積極的に推奨されています(※Appleが特に指定する一部シンボルを除く)。

ではお言葉に甘えて、あり物を使ってみてはどうでしょうか。

そこで今度は視点を「そのもののピックアップ」から「元ネタ探し」へと変えて、もう一度リストを開きます。まず買い物といえばカートかショッピングバッグ、あるいはお金がシンボルとして定番だろうと、その辺から当たりました。

「購入した(会計済み)」ことの履歴なのだからカートじゃないだろうということで、ここはバッグをえらびます。

bag.fill.png

次に、履歴といえば時間の経過を表す・・・時計? リストっぽいのとか帳簿的なものとかもありなのかしれませんが、まあここは時計で。

clockwise.png

この二つを組み合わせてはどうだろうと思い、ベクターを編集するソフトであるAffinity Designerで開くべくsvg形式でエクスポートすべくもう一度bagに戻ったら、周辺になにかがチラチラと見えるような見えないような・・・

なんだろう?
😐 じーっと見る。
customizing-sf-symbols.png
😳 見えた!!

bagについたplusサインとclock.fillは、ある点(2点)を除いてほとんど一緒。加工もすごく簡単そう。ということでカスタマイズすることにしました。使ったソフトは前述の通りAffinity Designer。まだうまく使えないし、不安な部分もありますが、作業そのものはごくシンプルなものなので、これでいきます。

実際の作業の様子

簡単ですね。これをウェイトとスケール全27の組み合わせで行います。

customizing-sf-symbols-04.png 手間ではあります。たしかに。 時間がないという方には、Apple推奨の優先順位として、
  • まずはMedium-Regular(青い線で挟まれたもの)から。これは必須。
  • つぎにSmall-RegularとLarge-Regularを
  • その次にMedium-Semibold・・・

といった順番で埋めていくといいそうです。

カスタマイズのための基礎的知識

ここでいったい何をしているのかを、実際にUIBezierPathを使って描画した下図(仮に“レオパルドン”と呼びます)をつかって説明します。

customizing-sf-symbols-05.png

UIBezierPathではまず最初に描画をはじめたい場所までポイントを移動させます。

LeopardonViewController.swift
let path = UIBezierPath()		
let initialPoint = CGPoint(.zero)
path.move(to: initialPoint)

ここではまだ描画はされていません。ポイントが移動しただけです。
描画するにはaddLine(to:)します。

LeopardonViewController.swift
path.addLine(to: secondPoint)
path.addLine(to: thirdPoint)

Point、Node、Vertex

ここで注目したいのは、addLine(to:)の引数がCGPointであることです。線(line)はあくまでもポイントとポイントをつなぐもので、Sketch.appやAffinity Designerといったドロー系ソフトやBlenderなどの3Dモデリングソフトでは、ポイントを動かせばその間に引かれた線もそれにともなって移動します。

※ポイントはSketchではPoint、Affinity DesignerではNode、BlenderではVertexと呼ばれる描画の最小単位で、xy、あるいはzといった座標の値をもっているのですが、Appによって呼び方がちがうこととドメインによっても意味がちがっていたりとかなりややこしいので注意が必要です。

もしある形から似た別の形をつくろうと思えば、いくつかポイントを消したり足したりしてつくることが可能なのです。

レオパルドンの真ん中の十字型には赤字で書かれた12のポイントがありますが、6、7、10、9の四つを消す(コメントアウトする)ことで、時計っぽい形にすることが簡単にできます(図では必要のない5、11も消しています)。

LeopardonViewController.swift
path.addLine(to: fifthPoint)
// path.addLine(to: sixthPoint)
// path.addLine(to: seventhPoint)
path.addLine(to: eighthPoint)
customizing-sf-symbols-06.png

この作業を視覚的にしたのが上の動画、というわけです。

結果

customizing-sf-symbols-09.png

イメージとフォントのバランスがおかしいような気がしないでもないですが、なににしろ誇らしいです。
参考にコードを

let symbolWeights: [UIImage.SymbolWeight] = [.ultraLight, .medium, .black]
let symbolScales: [UIImage.SymbolScale] = [.small, .medium, .large]
let fontWeights: [UIFont.Weight] = [.ultraLight, .medium, .black]
let fontStyles: [UIFont.TextStyle] = [.title3, .title2, .title1]

func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
    let cell = UITableViewCell(style: .default, reuseIdentifier: "staticCell")
    let idx = indexPath.row
    let titleFont = UIFont.preferredFont(forTextStyle: fontStyles[idx])

    let config = UIImage.SymbolConfiguration(pointSize: titleFont.pointSize, weight: symbolWeights[idx], scale: symbolScales[idx])
    let image = UIImage(named: "purchase.history", in: nil, with: config)!
    cell.imageView?.image = image.withRenderingMode(.alwaysTemplate)

    cell.textLabel?.text = "Purchase Hisotry"
    cell.textLabel?.textColor = UIColor.link
    cell.textLabel?.font = UIFont.systemFont(ofSize: titleFont.pointSize, weight: fontWeights[idx])
    
    return cell
}

最後に

近年MLやAR絡みでもとても便利なツールが次々とリリースされていて、より高機能なAppの作成がより容易になっています。自分のような趣味グラマーにとっての「自分はプロのデベロッパーではないからこの程度いいだろう」の「この程度」のレベルがどんどん上がって来ているのを感じます。

これまでであれば、無くてもよかっただろうもの(例:ボタンのアイコン)が、すでに素材(SF Symbols)が有るから付けないといけなくなった。と思ったら、なんとイメージに合うものが無い! でももう付けないわけにはいかないから結局自分で作らないといけない、という、ともするとありがた迷惑なことにもなりかねない状況だったりもします。

でもそこはそれ、より手間を省いて、よりよいAppをつくるためにアイデアと工夫をこらして、今後もひるむことなく内製を続けていきたいと思います。

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

9
3
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
9
3

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?