作者別: 7gano

iOS 11 Programming 著者さん紹介

「iOS 11 Programming」 のクラウドファンディングを開始して、3日でなんと360人以上の方々に購入いただきました。目標達成まで残り140名さまを切りましたのでもう少しです。ぜひ応援お願いします。

今回、僕が企画して声をかけたので「なぜこの人にお願いしたのか」という点を含めて著者さんを紹介させていただきます。

まず、人選ですがパパッと思いついた方々に声をかけさせてもらって、なんとなくこういう分担でやっていただけたらiOS 11をいい感じに網羅できそうだなとふんわり考えて、あとで目次を作ったらバッチリだったという感じでして、目次を作って声をかけた訳ではありません。が、まずは人ありきで、面白い方々が集まれば良い内容になるはず、と思っていました。結果、最強のiOS 11の本になります、きっと!

前置きが長くなりましたけど早速。

 

堤 修一 さん(@shu223) 第2章 ARKit 第13章 Metal 2

実はイベントでお見かけしたことはあるのですが、面識はありませんでしたが、なんといっても iOS Samplerシリーズが秀逸すぎるので、iOS 11の本をやるなら全体のバランスの監修をお願いしたいと最初に思い浮かんだ方です。Blogを見るとARKitをやっていらっしゃる!これは!とARKitをお願いしたらご快諾いただき、Metal 2もできるよーとのこと。こういうトピック読みたいっていうのあります?と伺ったら「永野さんのオーディオ」とのことで僕も書くことにしました。ウケる。
ARKit, Metal 2を開発者ってこういう内容を期待しているんじゃない?という観点から書いてくださるそうでプロフェッショナル。やばい。

 

吉田 悠一 さん(@sonson_twit) 第3章 Core ML

実は10年以上前から知っているけど、初めて会ったのは3年ぐらい前で最近ポッドキャストを一緒にやっているので二週に一回会っているソンソンさん。
ポッドキャストを聴いていただけると分かるのですが、数学に詳しいウルトラ研究者でしかもiOSアプリをもりもり作って、iOS SDK Hacksというぶっちぎりの名著も書いてて、なんだ超人かということで、Core MLはソンソンさん以外ないし、ソンソンさんが書いてくれなかったら本出せないなという感じでした。

 

池田 翔 さん(@ikesyo第4章 Swift 4の新機能とアップデート

実は面識はないのですが、そのオープンソース活動たるや、という人でSwift 4 = かつみさんかikesyoさんとパッと浮かんですぐ依頼。なんとまさかのご快諾!
Swift コミッターがSwiftの本って世界初かも?めちゃ楽しみ。

 

坂田 晃一 さん(@huin) 第5章 Xcode 9 の新機能

実は新卒前のインターンで入社されたばかりの時に横の席にいたんですけど、何を喋っても本当に20代かいな?という頭の切れっぷりで予想通りFrilに行っても大活躍されている、めちゃ注目している若手の方。WWDCまとめがいつも最高で、WWDC後の朝一はまず坂田さんのBlogを見るのですが、Xcode 9はいい機能ばっかりなんですぐ出してとツイートしていたのでXcode 9は坂田さんに書いてもらおうとすぐ依頼。最近書かれた本もいい内容で同期じゃなくてよかったよまったく。

 

加藤 尋樹 さん (@cockscomb第6章 Drag and Drop 第7章 Files と Document Based Application

UIKit、といえば所さんの名著があるのですが、いつも濃いめのUIKitの記事を書いていらっしゃる加藤さんが実は最初に浮かんですぐ依頼。新しいUIKitのポイントを早くも理解されていて

iOS 11で大きく強化されることになったファイルやドキュメントに関わる数々のAPIは、これまでのアプリ中心なiOSの世界に、ファイルを中心とした新しい軸をもたらします。

という一番どきっとした章説明をサクッと書いてもらって、おおマジかという感じです。UIKit In Depthみたいな本をお願いしようと思っていたのですが、まずはこの章をお願いしました。

 

川邉 雄介 さん(@jeffsuke第8章 UIKitのガイドラインの変更点とAutoLayoutの新機能、アップデート

UIKitですぐ浮かんだのが、名著「よくわかるAuto Layout」の著者の川邉さん。AutoLayout関連を依頼したところ「UIKitのLarge Titlesとかの変更が関連するのでそこも含めて書きます」と、先回りしてのお返事。「よくわかるAuto Layout」はここ3年ぐらいで一番読んだ本だったりしまして、やったね!という感じ。

 

岸川 克己 さん(@k_katsumi第9章 Core NFC 第10章 PDFKit 第11章 SiriKit

COOKPAD時代の同僚で、一緒にポッドキャストもやってるかつみさんに何か書きたいトピックあれば書いてくれないか聞いてみたら「今年のWWDCは近年になくいいですね。調べたいからなんでもいいですよ」とのことで、どれ入れたいいかな?と相談したところ3つ担当してくれるとのお返事。iOSといえばかつみさんなので紹介不要と思いますけど、iOSに詳しいだけではなくて、サービス理解やその他の知識も深くて困ったらかつみさんに聞いてみる、という感じでお世話になっています。

 

所 友太 さん(@tokorom第12章 HomeKit入門とiOS 11における新機能

名著「UIKit詳解リファレンス」が出たときから知り合いの所さんに何か書いてもらえないか聞いてみたらなんと「tvOSかHomeKit」という予想外の返事がきて、HomeKitをお願いしました。実はCOOKPAD時代にpotatotipsを一緒に始めたのですが、僕が退職した後も継続して開催されていてなんと42回もやっていらっしゃる。すごい。COOKPAD時代、iPadアプリの大改修を一緒にやったのですが、もちろん設計力・コーディング力も超一流の超人です。

という布陣で書きますので、応援お願いします。お知り合いの方にもお知らせくださいませー

広告

iOS 11の本を書きます!(8年ぶり4度目)

WWDC 2017 は周りの人と話してもよい内容の新機能、アップデートが多く、面白いセッションが多かったと思います。ですが近頃のiOSはかなり複雑で、もはや全てを把握している人はいないだろうし、何ができるか調べるのも大変です。

そこで、iOS 11 関連、全部サクッと分かってしかも応用が利くような本があればいいなーということで本を企画しました。

しかも、めちゃ豪華執筆陣に集まっていただきました。

https://peaks.cc/iOS11

クラウドファンディングなので、欲しい人が集まったら執筆開始です!

アーリーアクセスという特典があって、ベータ版から配信されるので最新の情報のしかも濃いやつが読めつつ、読んだ感想を返していただいて完成版に反映できるようになってます。普通に本を買うより楽しんでいただけるのではないかと思います。

僕は全体像とAudio系担当です。本を書くのは8年ぶりですがゴリっと書きますので応援お願いします。
https://peaks.cc/iOS11#author_profile_10

 

try! Swiftに参加して来ました(12年ぶり一度目)

2017年、何かしらアウトプットするかーということで、nextstep.fm というiOSを中心に話すポッドキャストをやっていまして、一緒にやっている かつみさん(@k_katsumi)が主催ということで、会社メンバーのもんもんと試しに行ってきました。ホワイト企業なのでチケットは会社負担です。

カンファンレンス参加はなんと2005年のIntel Macが発売されたWWDC以来12年ぶり、という浦島ぶり。

全体的な印象としては

  1. 運営がスムーズ
  2. そこそこ面白いセッションあるな
  3. 参加者若いな

でした。

1. 運営がスムーズ

運営に問題があってイライラするというようなことはないのでオススメします。初日にチケットを買った時に送られてくるPDF内のQRコードを何かしらで提示すればささっと入れて、名札がもらえますので、それで完了。

事前に知らなかったのですが、軽い朝ごはんもお昼ご飯には各種お弁当も用意されていて、最後の日は晩ご飯も用意されています。飲み物も潤沢なので持って行く必要はありません(その辺、事前に知りたかったというのはありますが)。

スケジュールは事前にアプリが配布されているので入れておきましょう。

メモするなら軽いMacは持って行ったほうがいいでしょうけど、僕は持って行かず聞くのに集中しました。詳しく調べるのは動画が公開されてからでもいいんじゃないでしょうか。あと今や動画公開が当たり前のカンファレンスで現場に行く理由は、仕事やらSNSやらから離れて集中して聴く時間を作るということじゃないでしょうか。

 

2. よくスピーカー集めたなぁ、そこそこ面白いセッションあるな

有名なiOS系エンジニア、と言われてもほとんど知らないのですが、kickstarterでやってますとか、fastlane作りました、みたいな人が来ます。だからと言って、めちゃすげぇなー理解できなーい、みたいなことはありませんし、さすがの突き詰めた人ならではの話が聞けるので貴重だと思います。QAセッションというのが並行して行われているので、本当はスピーカーに突撃して直接話すのが醍醐味だと思うのですが、そこまで関連することをやっていないのと、同時にセッションやってるというので行きませんでしたが、行けば確実に元は取れるでしょう。動画が公開される以上、QAセッションに突撃しなければ行く価値半減だと思います。カンファンレンス全てにおいて通訳完備なので英語がどうのこうのいうこともなく突撃可能だと思います。

セッション内容の詳細は色々記事が公開されているので、そちらを参照いただくとして、内容としては「こういうフィーチャーはこのAPIをこう使えばできる」みたいなセッションは少なくて(そういうのはWebでちゃちゃっと調べればいいかなと思います)どういう風に開発と向き合って行くか、という話が多いです。そういう話はAppleのドキュメントを調べても出てこないので、「こういうフィーチャーはこのAPIをこう使えばできる」というところはとっくに過ぎた人が実際どういうことを考えて何をやっているのか、という風に見て考え方を盗むのがいいんじゃないでしょうか。これはtry! Swiftに限った話じゃなさそうですが。

 

3. 参加者若いなぁ

12年ぶりだから歳とったということだと思いますが、若い人が目立ちました。一昔前のiOS系の集まりでも同年代が多かった印象なのですが、try! Swiftは明らかに次の世代が主役という感じでした。若い人にバリバリ作っていってもらいましょう。

 

まとめ

  1. よく練られたカンファレンスなのでオススメです。実際に行くならQAセッションに突撃すべきです。
  2. プログラミングの話はもうずいぶん前から次のステージに来ているんだろうなぁ。
  3.  try! Swiftまとめは nextstep.fm でもやるので音声コンテンツ好きな人は聴いてみてください。
  4.  来年も行くかというと、QAセッションに突撃して話したい人が来るなら行く、という感じでしょうか。

potatotipsというiOS/AndroidのTipsを話すイベントをはじめました

以前、所属していた会社でiOSアプリを作ったところ
「君が(いいもの)作れるのは分かったから、それ(iOSのノウハウ)を(部署にとどまらず)社内に広めてくれ!」
という指令がきて、僕はあまり人に教えるのは好きではないし(自分からやらなければ身に付かないと思っているので、特に外部がどうのこうのするのは反対)、そもそも自分が教える側に回れることも限られているし(Core Audioはセミナーとかやってます!)、僕もいろいろ知りたいですよ、ということで
「日々開発しているときに調べたことや、自分なりの工夫、アイディアを一人5分ぐらいで発表しあえばいいんじゃないか?」
ということで、毎週1時間、Tipsを発表しあう会をはじめました。

発表の資料のようなものは、Gistにコードと簡単な説明を張ることにしました。
コメントしあえるので便利でした。

これが毎回、非常に盛り上がりました。メンバーにもう一人iOSに詳しいエンジニアがいたので
「それはこれにも繋がる話だね」とか
「もっとこういうこともあるから、詳しく調べないと」
みたいな脱線も発生して、僕としては非常に有益な会でした。

また、集まったTipsを本にして出しちゃおう!という構想もありました。
本に書く、ということは嘘を書いてはいけないので、しっかり調べる必要があり、これまた技術向上に繋がると思っているからです。

potatotips

ときは流れ、現在所属しているCOOKPADでも同じような状況になってきました。
そこでまた同じ会をはじめたところ、これが毎回、非常に盛り上がりました(2)。
これはどこでも通用するメソッドだ!
ということで、社内ではなく社外の人にもこの会に参加してもらってはどうだろう?
と思い、はじめたのがpotatotipsというイベントです。

たとえば僕はこういう発表をしました。

クイズ形式なので、参加者のみなさんが
「まる!」
「バツ!」
「いやいや、これはこうじゃない?」
みたいに盛り上がってくれて、楽しくTips共有ができました。

まとめ記事

毎回、発表をまとめてくださる方々がいて、読みごたえのある記事になっています。

  1. クックパッドのLT会に参加してきたのでiOSのtipsをまとめる – Think Big Act Local
  2. 第2回 #potatotips に参加してきたのでiOSのtipsをまとめる – Think Big Act Local
  3. 第3回はヤフー開催! #potatotips で発表されたiOSのtipsまとめ – Think Big Act Local
  4. 第4回 #potatotips で発表されたiOSに関する9つのtips – Think Big Act Local

potatotipsで発表したもの以外でも

//platform.twitter.com/widgets.js

のような、ちょっとした工夫で開発が楽になるTipsはまだまだあると思っていて、もっとたくさんのTipsが集まればいいなと思っています。
ぜひご参加を!
参加には原則、1Tips持参していただく必要があります。

第五回は、3月第二週水曜日あたりに開催されると思います。

enchantMOON プログラミング入門 03 MOONBlock入門とグリッドシールの作成

前回は、簡単なJavaScriptのコードを実行する基礎的なシールを作り、実行してみました。
今回は、シールがタップされたときなど、特定のイベントに対応する仕組みを見ていきます。
最後にこの連載初の実用的なシールである「グリッドを引くシール」を作ります。

MOONBlock

導入の回で解説したように、enchantMOONにはMOONBlockというヴィジュアルプログラミング言語環境があります。MOONBlockを使わずにJavaScriptを書くとしても、何かと関係してきますので、基本的な部分をおさえておきます。
まずはMOONBlockを起動してシールのひな形となる形式の基礎を見ておきましょう。

横線を引いた画面で、図のようにシールと書いて指で丸で囲み、LINKで任意のページにリンクしたあと、再度シールを選択し、Hackを押してみましょう。

MOONBlockが起動します。

起動すると、次のような画面になっています。

見た目で

  • シールをタップしたときに、特定ページを開くこと
  • シールが貼られたときには何もしないこと
  • シールが剥がされたときには何もしないこと

が分かります。

Pageと書かれたところをタップし、Webに変更し、下の白いボックスをタップすると次のような画面が表示されるので
http://enchantmoon.com
と入力してOKを押します。

すると次の画面のようになります。

Doneを押して終了しましょう。

ページに戻り、シールをタップするとenchantmoon.comが表示されることを確認しましょう。

MOONBlockのパッチ化したシールのフォーマット

シールをMOONBlockのパッチにしたときに、フォーマットがどうなるのか確認しておきましょう。
enchantMOONをマウントしてみると、シールが増えたので、6BS0TI151376143029820というフォルダが一つ増えています。

6BS0TI151376143029820を見てみると

|-- hack.js
|-- images
|   |-- apad.png
|   |-- ..以下、画像がたくさん
|  
|-- info.json
|-- lib
|   |-- MOON.js
|   |-- color.enchant.js
|   |-- enchant.js
|   |-- moon.puppet.enchant.js
|   |-- puppet.enchant.js
|   |-- stylus.enchant.js
|   `-- ui.enchant.js
`-- manifest.json

のようになっています。

MOONBlockのパッチ化したシールは、前回のリンクのみのシールとは大幅に構成が異なります。
(おそらく)MOONBlockのパッチとして実行可能にするために必要なファイル群が一緒にコピーされます。

manifest.jsonの内容は”blocks”にMOONBlockにおけるBlockの配置情報を持つようになります。

{
  "version" : "1",
  "editor" : {
    "name" : "MOONBlock",
    "version" : "1"
  },
  "linked_pages" : [],
  "access_urls" : [
    "http://enchantmoon.com"
  ],
  "script" : "hack.js",
  "blocks" : [
    {
      "x" : 200,
      "y" : 280,
      "constructorName" : "StickerBlock",
      "variables" : {
        "name" : "シール",
        "fold" : "-",
        "ontap" : {
          "x" : 0,
          "y" : 0,
          "constructorName" : "LinkBlock",
          "variables" : {
            "type" : "Url",
            "link" : "http://enchantmoon.com"
          },
          "next" : null
        },
        "onattach" : {
          "x" : 0,
          "y" : 0,
          "constructorName" : "EndBlock",
          "variables" : {},
          "next" : null
        },
        "ondetach" : {
          "x" : 0,
          "y" : 0,
          "constructorName" : "EndBlock",
          "variables" : {},
          "next" : null
        }
      }
    }
  ],
  "block_images" : []
}

少々長いですが、”link” : “http://enchantmoon.com”が登場するまでが重要です。

"blocks" : [
{
  "x" : 200,
  "y" : 280,
  "constructorName" : "StickerBlock",
  "variables" : {
    "name" : "シール",
    "fold" : "-",
    "ontap" : {
      "x" : 0,
      "y" : 0,
      "constructorName" : "LinkBlock",
      "variables" : {
        "type" : "Url",
        "link" : "http://enchantmoon.com"
      }, 

StickerBlockがontapされたときに実行されるのは、typeに”Url”, “link”にhttp://enchantmoon.comが設定されたLinkBlock
という風に読めます。

hack.jsを見てみましょう。

importJS(["lib/MOON.js", 
"lib/enchant.js", 
"lib/ui.enchant.js", 
"lib/color.enchant.js", 
"lib/stylus.enchant.js", 
"lib/puppet.enchant.js", 
"lib/moon.puppet.enchant.js"], 
function() {
    enchant();
    enchant.puppet.prepareTheatre({
        assets: []
    });
    StickerPuppet.create("シール", {
        behavior: [{
            stickertap: function(event) {
                MOON.openUrl("http://enchantmoon.com");
                enchant.puppet.stopTheatre();
            },
            stickerattach: function(event) {
                enchant.puppet.stopTheatre();
            },
            stickerdetach: function(event) {
                enchant.puppet.stopTheatre();
            }
        }]
    });
});

importJSでは、lib以下のすべてのファイルが読み込まれるようになっています。

enchant();
enchant.puppet.prepareTheatre({
    assets: []
});

あたりはenchant.jsの基礎編に譲るとして

StickerPuppet.create("シール", {
        behavior: [{

以下を見ると、MOONBlockで表示された処理と同じように

  • シールをタップしたときに、http://enchantmoon.comを開くこと
  • シールが貼られたときには何もしないこと
  • シールが剥がされたときには何もしないこと

を表しています。

グリッドシールを作る

behavior: [{
            stickertap: function(event) {
                //任意のコード
                enchant.puppet.stopTheatre();
            },

を利用して、シールがタップされたときに処理を行ってみましょう。
ここでは、100ピクセルごとにグリッドを引くシールを作ってみます。

おおまかな仕様としては
– 現在の線の情報に追加で、縦横に100ピクセルごとの線を引く
– 何度実行されても同じ処理を行う(既に線が引かれているかどうかは判定しない)

とします。

hack.jsを次のように書き換えます。

importJS(
["lib/MOON.js",
"lib/enchant.js",
"lib/ui.enchant.js",
"lib/color.enchant.js",
"lib/stylus.enchant.js",
"lib/puppet.enchant.js",
"lib/moon.puppet.enchant.js"],
function() {
enchant();
enchant.puppet.prepareTheatre({
  assets: []
});
StickerPuppet.create("シール", {
  behavior: [{
    stickertap: function(event) {
      var page = MOON.getCurrentPage();
      var backing = page.backing;
      var paperJSON = MOON.getPaperJSON(backing);

      var paperWidth = paperJSON.width;
      var paperHeight = paperJSON.height;

      var lineStrokes = [];
      var lineSpacing = 100;
      var p = 1.0;
      var lineWidth = 1;

      //横線を引く
      for(var i = 1; i <= paperHeight / lineSpacing; i++){
        var y = i * lineSpacing;
        lineStrokes.push({width:lineWidth,
                          color: -1,
                          type:"pen",
                          data:[
                            0, y, p,
                            paperWidth, y, p
                          ]});
      }
      //縦線を引く
      for(var i = 1; i <= paperWidth / lineSpacing; i++){
        var x = i * lineSpacing;
        lineStrokes.push({width:lineWidth,
                          color: -1,
                          type:"pen",
                          data:[
                            x, 0, p,
                            x, paperHeight, p
                          ]});
      }
      //lineStrokesを追加
      paperJSON.strokes = paperJSON.strokes.concat(lineStrokes);
      //追加したlineStrokesを反映させる
      MOON.setPaperJSON(backing,paperJSON);

      enchant.puppet.stopTheatre();
    },
    stickerattach: function(event) {
      enchant.puppet.stopTheatre();
    },
    stickerdetach: function(event) {
      enchant.puppet.stopTheatre();
    }
  }]
});
});

実行すると次のようにグリッドが引かれます。

ソースコードを順番に見ていきましょう。

var page = MOON.getCurrentPage(); //1
var backing = page.backing; // 2
var paperJSON = MOON.getPaperJSON(backing); //3

1.ページを取得し
2.backing(ページID)を取得します。このbackingは第01回で見た

{
     "backing":"OdQ_svKy1375836774851",
     "stickers":[]
}

のbackingの値であるページIDです。
ページIDは実際にOdQ_svKy1375836774851です。

3.では、実際のJSONデータを取得しています。
ここで取得できるのは、同じく
OdQ_svKy1375836774851/info.json そのものです。以下のようなフォーマットでした。

{
    "version":"0.2",
    "x":0,
    "y":0,
    "width":768,
    "height":1024,
    "scale":1.0,
    "color":-16777216,
    "transparent":false,
    "strokes":[
        {
          "width":2.5,
          "color":-1,
          "type":"pen",
          "data":[
            180.84375
            ,432.85715
            ,0.6142651
         …

プロパティを見ていくと

"width":768,  
"height":1024, 

とあるので、

var paperWidth = paperJSON.width;
var paperHeight = paperJSON.height;

と書くと、それぞれ768と1024が取得できます。
この値を使って、縦横に何本、どれだけの長さの線を引けばよいかを計算しています。

lineStrokesという変数に

{
  "width":1,
  "color":-1,
  "type":"pen",
  "data":[ 開始点、終了点]
}

形式のオブジェクトを追加していき、すべてのデータが揃ったところでpaperJSON.strokesに追加しています。
追加しているので、既存のデータを消さずに追記することになります。
もし、追加ではなくpaperJSON.strokesを

paperJSON.strokes = lineStrokes;

のように新しく設定すると、既存のデータをすべて消して、グリッドのみになります。
以上からノートをクリアするシールが簡単に作れることが分かります。

最後に

MOON.setPaperJSON(backing,paperJSON);

で実際に反映させています。

以上のように、enchantMOONの線のデータはpaperJSONを変更することで、自由に操作できます。

今回新しく使ったAPIは

MOON.getCurrentPage()
MOON.getPaperJSON(backing)
MOON.setPaperJSON(backing, paperJSON)

の3つです。これらもMOON.jsに定義されています。
次回はこのシールを基本に、シール関連のAPIを見ていきます。

enchantMOON プログラミング入門 02 シールの基礎とHello World

前回は簡単にenchantMOONのデータ構造を見ていきました。
今回はシールの基礎を解説します。

シールとは何か?

enchantMOONで写真を撮ったり、書いたものに別のページへのリンクを張ったりすると、シールと呼ばれるものになります。
このシールの実態はページとプログラム(JavaScript)の組み合わせです。
実際にシールを作成して内容を確認してみます。

前回引いた直線を指で囲ってNEWページへリンクを張ります。

シールをタップするとリンクしたページに移動することを確認します。
その後enchantMOONをマウントして内容を確認してみましょう。次のようになっています。

前回と比べると
4q8JpI1V1375865464323
フォルダが増えています。

/info.json
の内容も、たしかに前回の

{
  "backing":"OdQ_svKy1375836774851",
  "stickers":[]
}

から

{
  "backing":"OdQ_svKy1375836774851",
  "stickers":["4q8JpI1V1375865464323"]
} 

に変わっています。
おそらく英語だとsealよりstickerの方が一般的なため、英語表記ではstickersという名前になっています。
4q8JpI1V1375865464323がシールの実態です。
中身を覗いてみましょう。

|-- hack.js
|-- info.json
`-- manifest.json

となっています。

info.jsonはシール化したstrokesです。
前回見たページのinfo.jsonと同じフォーマットです。
標準のページとは違い
“x”:95,”y”:37,”width”:496,”height”:219
のようになっており、これは(95, 37)からはじまり、横:496 縦:219の広さを持っていることを表します。つまり部分ページとでも言うべきものになっています。
そして、dataの内容がかなり増えています。実際一本の線だったのがシール化すると太い線に変わっています。

manifest.jsonを見ると以下のようになっています。
順番に見ていきましょう。

{
  "editor":{"name":"Columbia","version":"1"},
  "linked_pages":["Omvkn72h1375836777675"],
  "access_urls":[],
  "script":"hack.js"
}

editorのColumbiaは00回で見たアーキテクチャ図にありました。
linked_pagesはリンクしたNEWのページです。
access_urlsが何かは現時点では分かりません。
scriptにはhack.jsと書いてあり、同じディレクトリにhack.jsがあることから、対象スクリプトファイル名を書くようです。

hack.jsの内容を見てみましょう。

location.replace("page://Omvkn72h1375836777675");

location.replaceはJavaScriptの標準機能で、ブラウザの履歴に残さずに現在のドキュメントを書き換えます。

https://developer.mozilla.org/en-US/docs/Web/API/window.location

"linked_pages":["Omvkn72h1375836777675"],

と内容が重複していますが
page://対象ページのディレクトリ名 に移動する
となっています。

対象ページのディレクトリ名を以降、ページIDと呼ぶことにします。

シールがタップされると

location.replace("page://ページID");

が実行され、対象ページに移動します。
つまり、hack.jsが読み込まれ、実行されているのです。

まとめると
enchantMOONにおいては
page://というschemeはローカルのページを一意に表す表現であり

page://ページID 

というURLで他のページに移動できます。

Hello World

hack.jsに任意のJavaScriptを書けば実行されることが分かりましたので、Hello Worldをやってみます。

まず、4q8JpI1V1375865464323 フォルダをMacのデスクトップにコピーしておきます。

/ENCHANTMOON/App/MOONBlock/lib/MOON.js

をコピーしてきて4q8JpI1V1375865464323フォルダに置きます。

hack.jsを以下のように書き換えます。

importJS(
  ['MOON.js'],
  function(){
    MOON.alert('Hello, enchantMOON', function(){
      MOON.finish();
    });
  });

4q8JpI1V1375865464323フォルダをマウントしてある/ENCHANTMOONの同じ位置にコピーして上書きします。
enchantMOONをアンマウント、再起動して、シールを実行してみましょう。

最初にHello, enchantMOONというメッセージでAlertが表示され、OKを押すと元の画面に戻ります。

ソースコードを順番に見ていきましょう。

importJSは、与えられたファイルパス配列のJavaScriptファイルを順番に読み込み、読み込みが終わったらコールバック関数を呼びだす関数です。

importJS(filePaths, callback)

MOON.alertは、第1引数のmessageをアラート画面で表示し、OKがタップされたらコールバック関数を呼びだす関数です。

MOON.alert(message, callback)

MOON.finish()はシール実行モードを終了する関数です。
もし、この関数を実行しなければ、アラートでOKを押したあともシール実行モードのままで、ペンで書く操作はできません。
この場合、三本指のキャンセルでシール実行モードを終了することができます。

MOON.jsには上記以外にもenchantMOON独自の重要な関数が定義されています。

次回は、MOONBlockとシールのイベントを扱います。

enchantMOON プログラミング入門 01 環境構築とデータ構造

前回は導入としてenchantMOONのプログラミング環境について簡単に説明しました。今回はデータ転送関連の環境を整えつつ、enchantMOONのページのデータ構造を把握していきます。

注意事項

今までBlogの記事に苦情が来たことはないので大丈夫だと思いますが念のため。

連載全般における注意事項ですが、公式情報でもなく、動作を保証するものでもありません。また、正解が分からない状態での試行錯誤の結果であるため、ページデータが失われるなどの問題が発生する可能性があります。
事前にバックアップなどを行った上で実行してください。

データ構造

まずはデータ構造を簡単に把握しておきましょう。

ページが複数あると、どのフォルダが対象ページなのか、探すのが困難なため、以下の例では一度すべてのページデータを削除した状態から開始しています。
同じ環境で始めたい場合は、一度Dataフォルダ以下をバックアップした上でDataフォルダ以下を削除しておけば、おおよそ同じになります。

まずは新しいページを開き、横に短い線を引いてみます。

010

enchantMOONはMac/PCに繋ぐと、内蔵SDカードをマウントできます。

しかし、その前に一つ注意点を。
enchantMOONのプログラミングを行う場合、マウントしてデータの書き換え、アンマウントして実行結果を見る、という作業を繰り返すことになります。そのため、頻繁にUSBケーブルの抜き差しを行うことになり、しだいにケーブルが大変なことになってきます。
そこでそうなる前にスイッチ付きのUSBハブを購入しておくことをおすすめします。

僕が使っているのはこちら。

http://rcm-fe.amazon-adsystem.com/e/cm?t=monalisaauorg-22&o=9&p=8&l=as1&asins=B004FWEUPK&ref=tf_til&fc1=000000&IS2=1&lt1=_blank&m=amazon&lc1=0000FF&bc1=000000&bg1=FFFFFF&f=ifr

これでは開発が大変なため、転送の仕組みが用意されるとアナウンスがありました。続報を待ちましょう。

さて、enchantMOONをマウントして、先ほどのページを見てみましょう。

010

ディレクトリ構造は次のようになっています

  • /App
    • MOONBlockのすべてのソースコードとアセット、
  • /Data
    • 各ページのすべてのデータ
  • /DCIM
    • 各ページのプレビュー画像

となっています。

Dataを見てみましょう

Data以下は次のようになっているはずです。

010

MyNotebook1

以下に

|-- info.json
|
|-- 90PC2AlZ1375836774851(ランダムな文字列)
|   |-- OdQ_svKy1375836774851(ランダムな文字列)
|   |   `-- info.json
|   |-- info.json
|   `-- storage.json
|
|-- Omvkn72h1375836777675(ランダムな文字列)
|   |-- YnQBctau1375836777674(ランダムな文字列)
|   |   `-- info.json
|   |-- info.json
|   `-- storage.json
```

という構造(以下、ページフォルダ)が二つあるはずです。

ランダムな文字列のフォルダは環境によって変わりますので随時読み替えてください。

これは、先ほどの横線のページと自動で作られるNEWページがあるためです。
先ほどの横線のページは、更新日が一番新しいinfo.jsonがあるフォルダになります。

図では90PC2AlZ1375836774851以下になります。

トップのinfo.jsonを見てみましょう。

{"pages":["90PC2AlZ1375836774851","Omvkn72h1375836777675"]}

となっており、 ページフォルダが二つあることを表しています。
ページ一覧を表示する際にはこの順番で表示されます。

つまり、90PC2AlZ1375836774851が先頭のページになります。
enchantMOONではページ一覧ページでページを移動できるため、対象ページを分かりやすくするためには先頭に移動するとよいでしょう。
そして、トップのinfo.jsonを見て、pagesの最初のページフォルダを見つければよいでしょう。

次に90PC2AlZ1375836774851を見ていきましょう。

90PC2AlZ1375836774851/info.jsonを見ると

{
     "backing":"OdQ_svKy1375836774851",
     "stickers":[]
}

となっています。
backingは、ペンによる線の情報を持つフォルダ名
stickersはシールを貼っている場合にそのフォルダ名
が入ります。

先にbackingのみを見ていきます。

OdQ_svKy1375836774851フォルダを見てみましょう。
またinfo.jsonが入っています。

{
  "version":"0.2",
  "x":0,
  "y":0,
  "width":768,
  "height":1024,
  "scale":1.0,
  "color":-16777216,
  "transparent":false,
  "strokes":[
    {
      "width":2.5,
      "color":-1,
      "type":"pen",
      "data":[
        180.84375
        ,432.85715
        ,0.6142651
        ,181.59375
        ,433.2143
        ,0.62374014
        ,182.4375
        ,433.50003
        ,0.6276459
        ,183.375
        ,434.00003
        ,0.6292014
        ,184.125
        ,433.7143
        ,0.6307531
        …. 
      ]
    }
  ]
}

のようになっています。
これが実際の線の情報です。

dataをじっくり見てみると、パターンがあることが分かります。

180.84375
,432.85715
,0.6142651

,181.59375
,433.2143
,0.62374014

3つの要素で繰り返しているように見えます。

これは、座標x, 座標y, 筆圧の順番にデータが入っています。
横線を引いたので、xが徐々に増えていき、yはあまり変化がないことが分かります。

もし、横線を一気に一本だけ描いたなら、strokes配列の要素数は一つになっています。2回に分けて書いていたなら、二つあるはずです。

直線を引く

ためしにinfo.jsonを書き換えて直線に変更してみましょう。

strokesの”data”を以下のように変更します。

  "strokes":[
    {
      "width":2.5,
      "color":-1,
      "type":"pen",
      "data":[
        200, //start.x
        100, //start.y
        1,   //筆圧
        500, //end.x
        100, //end.y
        1    //筆圧
      ]
    }
  ]

(200, 100) から真横に300ピクセルの線が引かれることが期待されます。
変更を加えたあと、enchantMOONをアンマウントし、起動後ページを確認してみます。

010

できています。

これも立派なプログラミングですね。
つまり
“backing”:”backing_name”,
のbacking_name/info.jsonを編集するプログラムを書けば、enchantMOONで行えるすべての描画を操作できるでしょう。
実際、enchantMOON内でこの部分を動的に変更できます。

次回以降、シールを使って同じことをコードで実現していきます。