✖
なんか知らないけど、100mm で撮った写真の Exif 見てると 13.2m のところにピントあわせてることが多い。
✖
✖
ものの正面に立つのがうまくなった気がする
✖
✖
✖
意外と空の写真を撮ってるなぁ。空ほど、写真にしてあとで見てがっかりするするものはない。
✖
Fotolife for Android リリース
Fotolife for Androidがリリースされました。
期間的にはだいたい1ヶ月で、そんなに短かいわけではないのですが、割と大変でした。Android ケータイはもちろん持っていて、使っていたわけですが、開発は Scala で rake 使って Hello, World! を動かす程度しかやっておらず (いろいろ間違ってる)、Java 自体、Rhino、Scala で間接的に一部 API を使ったことがあるだけで、ちゃんと Java のコードを書いたのは開発が決まってからでした。
「Java の文法・API」と「Android の API・バッドノウハウ」の二重でハマるので、特に最初の2週間は、アプリケーションも形にならず (アップロードもできず、表示もろくにできなかった)、たいへんしんどかったです。ちゃんとしたマルチスレッドも、普段 Perl, JavaScript ばかりなので同期方に慣れずに苦労しました (Ruby も割とシングルスレッド脳で書いてるし)、というか、いまもしてます。
スレッドまわりに関しては「Java 言語で学ぶデザインパターン入門 マルチスレッド編」を借りて読んだり、「Java 並行処理プログラミング」を買ってもらって読んだりしてみました。どちらも解りやすく、後者は特に何を使うべきかが明確で実践に即応用できたので良かったです。java.util.concurrent スゲー! ってことで使いまくってます。ソースコードは Future だらけです。new Thread() を全然書いてないです。
基本的に、Android の開発は Google のオフィシャルのドキュメントをちゃんと熟読するのが近道だと思いました。あと、それだけだと、僕みたいなのは頭に入ってこないので、android のレポジトリを全部落としてきてデフォルトで入っているアプリのソースを読むのがいいと思いました。SDK のサンプルは最小限で、それはそれでいいのですが、もっと具体的にどうするのかがよくわからなかったりするので、やっぱちゃんと動いてるコードは偉大です。
Java は食わず嫌いでしたが、やってみると案外楽しくて、思ったより書いていてイライラしない言語だなぁと思いました。基本部分のAPI (特に Stream 系) は死ぬほど冗長で意味がわからないのですが、Android 関係の API は割と普通に使える印象でした。(そのうち書きますが Eclipse と Vim を連携させて書いてます) 匿名クラス萌えです。
id:secondlife さんディレクションのもと開発し、id:nagayama さんに各種アイコンのデザイン、id:aaron さんに英語リソースのチェックをしてもらい、id:tikeda さん、id:hakobe932 さんに直前にフィードバックを貰いました。
しばらく社内用に書いたノウハウを公開していこうと思います。Fotolife for Android のAPI (インテント) も公開するので少々お待ちください。
Android の組込みアプリ以外のパーミッションの取り扱い
はてなアカウント管理を作るにあたり、最初は Android のパーミッションの仕組みにのっかろうと考えていましたが、調べていくうちにセキュリティリスクがあることがわかったので、別途自力でユーザにオプトインする仕組みを入れました。(はてな以外からリリースされるアプリケーションでは、アカウント管理に情報を渡す際に本当に渡すかをユーザに同意を求めるようになっています)
Android のパーミッションの仕組みは「先に定義したもん勝ち」という感じのようなので、端末デフォルトでインストールされていて、アンインストールが不可能になっているアプリケーションでのみ、安全に働くようでした。なんかやりかたがあるのかよくわかりませんが、そんな感じでしたので、今のところ一番確実な方法を選んでいます。
手元の実機 (Android 1.6) での検証では
- <permission android:name="com.example.permission.FOOBAR" android:protectionLevel="dangerous".../> というパーミッションを定義する、アプリケーションA
- それを uses-permission で定義する、アプリケーションB
- <permission android:name="com.example.permission.FOOBAR" android:protectionLevel="normal".../> というパーミッションを定義する、悪意あるアプリケーションC
A の signature と B, C の signature は別
A → B とインストール
- A インストール
- permission が定義される
- B インストール
- uses-permission の内容が表示される
- B で該当パーミッションAに対し使おうとする
- 成功する
→ 正常
B → A とインストール
- B インストール
- uses-permission は表示されない (Unknown permission)
- A インストール
- permission が定義される
- B で該当パーミッションAに対し使おうとする
- 該当パーミッションは定義されていないためセキュリティエラー Permission Denial
→ 正常 (この場合 B をインストールしなおすしかないのでユーザビリティ的に問題があるため採用できない)
C → A → B とインストール
- C インストール
- permission が定義される (protectionLevel="normal" == ユーザに確認がでないパーミッション)
- A インストール
- permission は定義されない (既に存在するので無視される)
- B インストール
- uses-permission の内容が表示されないが C で定義された permission が grant される
- B で該当パーミッションAに対し使おうとする
- 成功する
Bがユーザへの確認なしに、不正にパーミッションを行使していることになる。
インストール関係のインテントとかをコマンドラインから発行する
パーミッションのテストみたいなのは死ぬほどめんどいです。コマンドラインからやってもめんどい。
adb install は PackageManager を使わないのでダメです。もちろんちゃんと sign した apk じゃないとダメです。
adb push Foo.apk /sdcard adb shell am start -a android.intent.action.VIEW -t application/vnd.android.package-archive -d file:///sdcard/Foo.apk
でインストール
adb uninstall com.example.foo
でアンインストール (パッケージ名を指定するみたいです)
ちまたの sdcard からアプリをインストールするやつは、上記 Intent を投げているだけなので、特別パーミッションがいらないはずですが、なんかやたらパーミッションを要求するのが多くて、開発者以外にテストしてもらう際に困ります。
全くパーミッションを要求しないやつには com.mmg.appin というものがあるっぽいです。
ウェブアプリとAndroidアプリの対応
- ページ表示 (View, Controller) → Activity
- モデル → ContentProvider
- ワーカー → Service
- cron バッチ → AlarmManager
Eclipse + Vim 開発環境構築
Android SDK は Eclipse 前提でだいたい話が進むので、かたくなに Eclipse を使わないようにしているといらない苦労を負いすぎます (リソース管理とか)。ので、これを期に Eclipse と連携させて Vim を使う環境をつくりました。
Eclipse をコンパイル、実行環境にし、編集を Vim にするために
- Eclim をいれる http://eclim.org/
- Installing Guide 読めばすぐ入る http://eclim.org/guides/install.html
- eclimd を起動 (Window -> Show View -> eclimd or /Application/Eclipse/eclimd) して :PingEclim :EclimValidate がうまくいくか確かめる。ぼくは大丈夫だった。ダメなら FAQ
- ワークスペースの設定をする
- Eclipse デフォルトなら変えなくてもいいっぽいけど、僕の場合 ~/project なので
- eclimd はメモリ増やして起動する
- :ProjectInfo がうまくいくかを確認する。できなければ FAQ を見る
AutoComplPop の設定
.vimrc に追記
let g:AutoComplPop_Behavior = {
\ 'java' : [
\ {
\ 'command' : "\<C-n>",
\ 'pattern' : '\k\k$',
\ 'excluded' : '^$',
\ 'repeat' : 0,
\ },
\ {
\ 'command' : "\<C-x>\<C-u>",
\ 'pattern' : '\k\k$',
\ 'excluded' : '^$',
\ 'repeat' : 0,
\ },
\ {
\ 'command' : "\<C-x>\<C-f>",
\ 'pattern' : (has('win32') || has('win64') ? '\f[/\\]\f*$' : '\f[/]\f*$'),
\ 'excluded' : '[*/\\][/\\]\f*$\|[^[:print:]]\f*$',
\ 'repeat' : 1,
\ }
\ ]
\ }キーワードマッチしなければ eclipse に投げる (めっちゃ重い)。
デバッグ
保存すると自動で :Validate が走る。:lope で確認できる。+sign つきで vim がコンパイルされているならいい感じにでてくる!
:Validate が走るタイミングが保存よりも早いときがあってちょっと変
import 分関係
http://eclim.org/vim/java/import.html
- :JavaImportMissing
- :JavaImportClean
override しまくる
:JavaImpl すると override できるメソッド一覧がでてくるので、適当に RET おすと テンプレートが挿入される。便利なんだけど、Vim の undo が効かなくなってしまうのであんまり使ってない (表示させてコピペ、っていう使いかたをしてる)
データクラス
ハッシュを自由に作れないのが LL に比べて極めて不便なので、つどデータクラスを作るわけですが、getter setter 作るのが死ぬほどめんどい。
- :JavaGetSet
Android アプリケーションのヒープメモリを観察する
メモリが限られていると頻繁に OOM エラーがでますが、OOM エラーは出さないことが大前提なので、頑張って何が容量食ってるか調べないといけません。まぁ、コード的に勘が効く部分は良いのですが、ライブラリに隠蔽されていたり、普段 LL 使ってると見落したりする部分があるのでちゃんと計測したいもんです。
http://www.eclipse.org/mat/ をいれる。
エミュレータでアプリケーションを起動して、ある程度動かしてから
↑ のボタンを押す
メモリーリークしているっぽいものまで解析してくれる。すごい
Histogram -> ソート -> 右クリック -> List objects でどんなオブジェクトがみれるっぽい。List objects の outgoing incoming はよくわからない。
開発中これを使ったら、画像のURLを保持する的な部分で随分メモリを食っていることが分ったので、はてな記法のみを保持してURLとかは必要なときだけ更めて生成 (パフォーマンスは劣化しますがOOMでるよりはマシです) するようにしたらだいぶ改善しました。
あと、スレッドの一覧を見ながら動かして想定通りのスレッド数かを観察するのも大事だと思いました。HttpClient はインスタンスごとにプールスレッドを持つので注意が必要でした (若干反則な気がしますが static に確保するようにしました)
✖
✖
雪が猛烈に降ったり、止んで太陽が出たりと、安定しない日だった。おかげで、雪の中を自転車で走りまわることになり、風邪をひきそうだなぁという感じだった。どうなるかな。
滅多に使わない、シャッタースピード優先で撮ったりしたけど、慣れてないと難しいですね。ストロボを持っていないので、太陽がでてるときうまいこと光を使う必要がありめんどかった。
関連エントリー
- ストロボを購入 Canon スピードライト 430EX II cho45 キヤノン ★ 3.0 / 5.0 cho45 長らく必要性を感じていなかったので興...
- ✖ 自分で撮った古い写真を4K画面でだらだら眺めてると面白くて、歴史を感じる。 HT-03A の写真が1枚だけあって、解像度低すぎてビビる。でも...
- ✖ 部屋の掃除とかをした。 でかけようと思ったら、自転車がパンクしていたので、ひっぱって自転車屋までいった。割と遠くて疲れた。たてこんでいて時間...
- αのEVF は焦げるか 晴れている日に外にでると直射日光を浴びるわけですが、そういえば EVF にはレンズが入ってるのだから、条件が重なるとEVFに集光されて焦げる...
- ✖ 次の子どもの誕生日は自転車かなあと漠然と考えて、とりあえず昭和記念公園のレンタサイクルの乗せて様子を見た結果、本人の希望によりまた今度となっ...
✖
✖
Good Dog Happy Men の新譜 The Light が先日でたので聴いているけど、慰霊堂清掃奉仕 (Happy Birthday!) が本当にとてもいい…… こういうちょっと皮肉まじりのファンタジー世界観はいいなぁ。
アルバム全体として GDHM はあんまりキャッチーなの作らないなーという感覚が強くなってきた。しばらく聴いてないとよくわからない。
関連エントリー
- ✖ GDHM っぽいんだよな
- 最近のプレイリスト ミナソコ / BURGER NUDS カナリア / BURGER NUDS エコー / BURGER NUDS 鋼鉄の朝 / BURGER ...
- ✖ GDHM の「陽だまりを越えて」を買ってきた。これからも楽しみだなぁ。発売日を意識して買うアーティストは唯一 GDHM だけです。
- BURGER NUDS / Good Dog Happy Men の動画 ちょいちょいオフィシャルでアップロードされてるのがあって良い世の中になっていると感じる。しばらくアニソンばっかり聞いてる時期があったけど、最...
- ✖ 箱船に乗って助かったと思った世界は努力が報われない美しきファンタジー世界でした。\( こんにちは世界 )/
✖
Android リファレンスを Chemr で検索
✖
Android Emulator で DNS がひけない場合
エミュレータを
emulator -dns-server 8.8.8.8 -avd android1.6
みたいに起動。プライベート IP を指定するとアクセスできなかったりするので Google DNS をつかうのが楽
さらに、自作のアプリケーションの場合、
<uses-permission android:name="android.permission.INTERNET" />が入っていることを確認する。
Android でアプリケーションが強制終了したとき、エラーレポートを送るようにする
フォトライフアプリは例外発生時にバグレポを送れるようになってます。
バグレポの仕組みは、http://www.adamrocker.com/blog/288/bug-report-system-for-android.html で述べられているようなやり方で、フォトライフアプリではサーバサイドなしにしたりとか簡略化して実装をしています。
開発中やらデバッグ中も、ケーブルレスでエラースタックトレースが見れるようになるのでとても便利です。
100行程度なので、めんどくさいのでコード貼っておくと
import java.io.BufferedReader;
import java.io.File;
import java.io.FileReader;
import java.io.PrintWriter;
import java.lang.Thread.UncaughtExceptionHandler;
import android.app.Activity;
import android.app.ActivityManager;
import android.app.AlertDialog;
import android.content.Context;
import android.content.DialogInterface;
import android.content.Intent;
import android.content.pm.PackageInfo;
import android.content.pm.PackageManager.NameNotFoundException;
import android.net.Uri;
import android.os.Build;
class ErrorReporter implements UncaughtExceptionHandler {
private static Context sContext = null;
private static PackageInfo sPackageInfo = null;
private static ActivityManager.MemoryInfo sMemoryInfo = new ActivityManager.MemoryInfo();
private static final String BUG_FILE = "BUG";
private static final String MAIL_TO = "mailto:cho45@lowreal.net";
private static final UncaughtExceptionHandler sDefaultHandler = Thread.getDefaultUncaughtExceptionHandler();
public static void setup(Context context) {
context = context.getApplicationContext();
try {
sPackageInfo = context.getPackageManager().getPackageInfo(context.getPackageName(), 0);
} catch (NameNotFoundException e) {
e.printStackTrace();
}
sContext = context;
Thread.setDefaultUncaughtExceptionHandler(new ErrorReporter());
}
public static void bugreport(final Activity activity) {
File bugfile = activity.getFileStreamPath(BUG_FILE);
if (!bugfile.exists()) return;
File dstfile = activity.getFileStreamPath(BUG_FILE + ".txt");
bugfile.renameTo(dstfile);
final StringBuilder body = new StringBuilder();
String firstLine = null;
try {
BufferedReader br = new BufferedReader(new FileReader(dstfile));
String line;
while ((line = br.readLine()) != null) {
if (firstLine == null) {
firstLine = line;
} else {
body.append(line).append("\n");
}
}
} catch (Exception e) {
e.printStackTrace();
}
final String subject = firstLine;
new AlertDialog.Builder(activity)
.setIcon(R.drawable.icon)
.setTitle(R.string.bug_report)
.setMessage(R.string.bug_report_message)
.setPositiveButton(R.string.bug_report_positive_button, new DialogInterface.OnClickListener() {
public void onClick(DialogInterface dialog, int which) {
activity.startActivity(
new Intent(Intent.ACTION_SENDTO, Uri.parse(MAIL_TO))
.putExtra(Intent.EXTRA_SUBJECT, subject)
.putExtra(Intent.EXTRA_TEXT, body.toString())
);
}
})
.setNegativeButton(R.string.bug_report_negative_button, new DialogInterface.OnClickListener() {
public void onClick(DialogInterface dialog, int which) {
}
})
.show();
}
public void uncaughtException(Thread thread, Throwable error) {
error.printStackTrace();
try {
PrintWriter writer = new PrintWriter(sContext.openFileOutput(BUG_FILE, Context.MODE_WORLD_READABLE));
if (sPackageInfo != null) {
writer.printf("[BUG][%s] versionName:%s, versionCode:%d\n", sPackageInfo.packageName, sPackageInfo.versionName, sPackageInfo.versionCode);
} else {
writer.printf("[BUG][Unkown]\n");
}
try {
writer.printf("Runtime Memory: total: %dKB, free: %dKB, used: %dKB\n",
Runtime.getRuntime().totalMemory() / 1024,
Runtime.getRuntime().freeMemory() / 1024,
(Runtime.getRuntime().totalMemory() - Runtime.getRuntime().freeMemory()) / 1024
);
} catch (Exception e) {
e.printStackTrace();
}
try {
((ActivityManager)sContext.getSystemService(Context.ACTIVITY_SERVICE)).getMemoryInfo(sMemoryInfo);
writer.printf("availMem: %dKB, lowMemory: %b\n", sMemoryInfo.availMem / 1024, sMemoryInfo.lowMemory);
} catch (Exception e) {
e.printStackTrace();
}
writer.printf("DEVICE: %s\n", Build.DEVICE);
writer.printf("MODEL: %s\n", Build.MODEL);
writer.printf("VERSION.SDK: %s\n", Build.VERSION.SDK);
writer.println("");
error.printStackTrace(writer);
writer.close();
} catch (Exception e) {
e.printStackTrace();
}
sDefaultHandler.uncaughtException(thread, error);
}
}てな感じで
- R.drawable.icon
- R.string.bug_report
- R.string.bug_report_message
- R.string.bug_report_positive_button
- R.string.bug_report_negative_button
あたりをリソースに使いつつ、各 Activity の onCreate で
ErrorReporter.setup(this);を早い段階で呼び、
if (mPref.getBoolean(Setting.SEND_BUG, true)) ErrorReporter.bugreport(FooActivity.this);を適当に、ダイアログを表示する準備ができたときに呼んでやっています。
ErrorReporter.bugreport は前回アプリケーションが強制終了した痕跡があるなら、ダイアログを表示してユーザにレポートの送信を求めます。やってることは単にメール Intent を投げてるだけなので、特にパーミッションもいりません。
✖
✖
斜め上から目線ってのが流行ってるんですかね?
✖
インターネットにも結局、賑やかな孤独があるだけだった。無意味だ。
✖
何書いてもバカにされるだけ。↑ みたいなのを見て笑ってるやつばっかりってこと
✖
✖
✖
✖
ほんと晴れないなぁ… せめて雪が降ってくれると……
✖
修学旅行ぶりに金閣寺に行った。財布に1000円入っていなかったので入場できるか不安だったけれど、400円だった。御札が入場券の変わりになっていた。御札をもらっても (宗教的な理由で) いらない人はどうするのかと思ったけど回収箱が設置されてるっぽかった。
意外と記憶の中の金閣寺と違っており、派手だった。金色だなーと思って地味に感動した。眺めながらよくよく考えてみると、金閣寺のリアルな記憶よりも、プラモデルで金閣寺を作ったときの記憶のほうが強いことに気付いた。
修学旅行のときは「金閣寺で外国人観光客とコミュニケーションをとれ」という課題がでていてテンパった覚えがある。この課題、よく考えるとどうなんだって感じもする……
関連エントリー
- ✖ 日曜日は、二条城にいったことがないと思ったのでいってきた。「あんまり面白くなさそうだなー」と思っていたので行かなかったのだけれど、行ってみた...
- ✖ 昨日は伏見稲荷大社へ。前にいったときは、何もない平日の、何もない夕方で人が殆どいなかったけれど、今回はそれなりに人がいた。今日、明日と祭らし...
- ✖ 土曜日は歯医者のあと、奈良へ。春日大社に行ってみたかったから。奈良は、結構近い気がするし、実際1時間ぐらいで着くのだけれど、片道で800円ぐ...
- ✖ 土曜日は、というか金曜日はいつのまにか寝てしまっていて、次の日7時ぐらいに起きてしまった。起きてすぐ、なんとなく書きたいコードが受かんだので...
- 日光 なんか急に日光に行くことに。 東照宮 二荒山神社 滝尾神社 今回いって一番よかった。東照宮からは20~30分程度徒歩でまぁまぁ遠い。二荒山神...
✖
[[foursquare]] というサービスを使ってみているけど、なんともいえないなぁ。バッジ集めるのは楽しいんだけど、それ以上が特にない…… というのも京都内の Venue も TODO もサッパリ登録されていないせいな気がする。人口密集地とか派手な観光地じゃないと面白くないのかもしれない…… 位置情報ゲームで終わってないところは好きなので少し継続してやってみる。
神社も全然登録されてないので現地で登録するんだけど、なんかGPS情報をちゃんと使わないっぽく、ウェブ上で見るとよくずれていて自力で修正するハメになる。意味がない…… 僕は写真にGPS情報付与して撮っているので (GPS 情報を保存するためだけに写真撮ったりする)、それ上げれば済むとかになってればいいのになぁ。
バックエンドが Scala で再構築されたらしいので、そっちのほうでの興味もあります。
関連エントリー
- ✖ 今年写真を撮ってわかったことで、一番重要なのは、モノの正面をちゃんと見よということだと思った。写真撮るときにひねくれて撮ってもしょうがない。...
- ✖ 久しぶりに写真撮ったけど、感覚をすごい忘れていると実感した…… あとやっぱ人が多いところだとうまく被写体を発見できない…… ちなみに今年の写...
- トランジスタ技術 2016年 2月号 の GPS 特集 トランジスタ技術 2016年 2月号 cho45 トランジスタ技術編集部 ★ 3.0 / 5.0 cho45 ここ1ヶ月ぐらい GPSDO ...
- ゲームのFPSを制限して消費電力を下げる プレイはしないけど起動していなければならないというゲームがちょいちょいある。こういうときに全力でGPUを使われても電気代の無駄なので、FPS...
- ✖ 初個展やります:祈りの原風景 - 神と仏の混じりあう国 - 会場:Gallery・DOT(ギャラリー・ドット) 住所:〒606-0817 京...
✖
✖
一方的に、高台から発砲して人を殺すことを自覚してるのかしてないのか
✖
[tabelog:896885:detail]
割とよく行きます。
[tabelog:900921:detail]
この前 nanto_vi さんと motemen さんと一緒に行きました。パフェうまかったです (京大学食)
[[たべぞうさん、お楽しみ袋欲しい!]]
関連エントリー
- 『いなり、こんこん、恋いろは。』よしだもろへ いなり、こんこん、恋いろは。 (1) (角川コミックス・エース 326-1) cho45 よしだ もろへ ★ 3.0 / 5.0 cho45...
- YONGNUO YN600Air 5500K モデルを買ってみた YONGNUO YN600Air LED ビデオライト 5500K SMD LED搭載 超薄 カメラ ビデオカメラ用 補助照明 撮影用 Ca...
- Raspberry Pi がきたのでセットアップして I2C デバイスを読むところまで Raspberry Pi だ! ππだ!! Raspberry Pi は約5000円ぐらいで買うことができるカードサイズの Linux パソ...
- アンテナアナライザの回路 - ブリッジの三つの電位差を測るタイプ http://www.rigexpert.com/index?s=articles&f=aas ブリッジの50Ω/50Ωで分圧したほうの電位...
- Klipper 用の raspiberry pi のカスタマイズ Raspberry Pi の負荷が高くなると mcu との通信に支障がおこり、最悪プリンタが止まる。なので cron をできるだけ止める a...
✖
5つ以上スターを連打するとグリーンスターつけるように変える Greasemonkey script
5つ以上連打しようとすると勝手にグリーンスターを消費するようになるグリモンです。
グリーンスターに切り替わるとつく速度が落ちますが、連打したぶんはちゃんとつくので待っていてください (色つきスターはリクエストが増えるみたいなので純粋につけるのに時間がかかってます)
最近 Java の Executors にラブなので SingleThreadExecutor みたいなやつをつくってやってます。
✖
✖
最近 www.lowreal.net のページの作り直しをしている。もともと、1ページだけ好き勝手いろいろやってみるためのものだったので大分適当だったのを、もうちょいちゃんと自己紹介用のページに使えるようにするという狙いと、あとまぁやっぱ好き勝手またやってみたくなったという感じで、久しぶりに HTML のマークアップから CSS、 JS までいろいろと使った。
今回は、普通に内容情報を変更をするとともに、ページ単体でのスマートフォン (Mobile Webkit = iPhone, Android) 対応と、実験的に巨大スクリーン対応を入れている。
スマートフォン対応は大抵のまともなサイトは最近入れはじめているし、小さいスクリーン用に別の情報コントロールを入れるのはまぁ正しいと思うので、適度にそうやった。このページは twitter からの流入が一番多いし意味もある程度はありそう。
巨大スクリーン対応は、デカイ画面に全画面にすると余白があきすぎで滑稽になるのがあまりにもあれなので (かつてはまぁリキッドレイアウトならば、利用者が適時ウィンドウサイズを変えればいいだろうと思っていたけれども、そうはいっても、という感じなので)、特定サイズ以上のウィンドウサイズになったら、ページ全体を拡大するように (1240 を基準として、拡大率が 1.4 倍以上になるなら適用 = 1920程度から拡大される) してみた。(WebKit, Gecko のみ) この対応が正しい対応かどうかはちゃんと考えきれてはいない。フォントサイズが固定ではなく、エラスティックレイアウトなので、ピクセル基準ではなくフォントサイズ基準にすべきだけどとりあえず。
PC で開いたとき、一番上の画像を切り替わるようにしてみたけど、なんとなく実装したらおもいのほか簡単にできてびっくりした。簡単に管理したいなーと思ったので、切り替わる画像は fotolife の特定 ID の RSS からとっていて、あとは fotolife にアップロードしていくだけで切り替わる写真が変化していくので、管理も楽な感じになった。fotolife のフィードなら何でもいけるのでブログパーツみたいにできそう。
関連エントリー
- モールスコードを再生できるだけのページ をつくった。 http://play-morse.lowreal.net/ だいたい、符号って長点短点を可視化して見せてしまっていることが多...
- サイトの画像サイズを再びアップグレード 昨年の4月にデザインの調整ということで、写真の最大サイズを 1024px まで上げていたのですが、これは Google Photos の無料...
- ✖ Chrome やら Firefox やら、requestFullscreen に対応しつつあるブラウザでは写真をクリックしたときにそれを使う...
- Adsense の新しい広告ユニット 最近になって「関連コンテンツ」と「ページ単位の広告」というのが beta になって登場した。サイト最適化と同時にこれらも有効にしてみたりして...
- Gist に置いた JavaScript のベンチマークをとる デモ textContent innerText $().text() の比較ベンチ for of と単純な for の比較ベンチ ある要素...
✖
JavaScript、仮引数で宣言した変数へ代入したあとの arguments の挙動
さて問題です。以下のコードで alert されるのは何でしょう!!
(function (x) {
x = 2;
alert(arguments[0]);
})(1);
答えはやってみてください。ビビりました。どうやら arguments オブジェクトは、変数の参照 (値の参照ではなく) を持っています。
ECMAScript 3rd Edition 日本語訳から根拠を探すと、ちゃんと書いてありました。
- 0 以上 length プロパティの値未満の整数 arg それぞれについて、属性 { DontEnum } のプロパティ ToString(arg) が作成される。このプロパティの初期値は対応するパラメータの呼出側に供給される実際の値である。最初の実際のパラメータ値が arg = 0、2 番目は arg = 1, 以下同様である。arg が Function オブジェクトの仮引数の数より小さい場合、このプロパティは Activation オブジェクトの対応するプロパティとその値を共有する。このことは、このプロパティの変更が Activation オブジェクトの対応するプロパティを変更すること、そしてその逆を意味する。
ちゃんと説明しとくと、この動作の奇妙さは
var obj = new Object();
obj[0] = 1;
obj.foo = obj[0];
obj[0] = 2;
alert(obj.foo); //=> 1
var baz = new Object();
baz.foo = obj[0];
obj[0] = 3;
alert(baz.foo); //=> 2というあたり前 (に感じる) 挙動崩れるところです。普通、オブジェクトの別プロパティに代入したら、他のプロパティの値も同時に変わることなんてことはありえないし、別オブジェクトのプロパティが変わるなんてもってのほかですが、Activation オブジェクトの引数関係のプロパティだけは違う、ということです。
Activation オブジェクトはそもそも何かというと、変数を保持するオブジェクトです。この、隠れたオブジェクトを見えるようにしたコードを書くと、冒頭のコードは
(function (x) {
// // Variable Instantiation
// var a = new Activation();
// a.arguments = { };
// a.arguments[0] = 1;
// a["x"] = a.arguments[0];
// // End
// a["x"] = 2;
x = 2;
// alert(a.arguments[0]);
alert(arguments[0]);
})(1);のように (実際は Activation オブジェクトにはアクセスできない) なり、そもそも仮引数 x が保持されているオブジェクトと、渡された引数第一番目の arguments[0] は別々のオブジェクトなのにも関わらず、値が共有されて相互作用をします。
これは「変数」を保持している「オブジェクト」が存在するという仕様上の説明からすると、一貫性がない不可解な動作です。
✖
✖
土曜日は清水寺にいった。金閣寺が良かったので清水寺もいいかもしれないと行ってみた。けど、どうも、人が多すぎて全くおもしろくなかった。まぁもう行かなくていいかなという感じだった。あと、地主神社 (清水寺境内にある) もいったけど、そんなに面白くなかった。
近くの豊国神社にいったら、思ったよりも立派ですごかった。スカっとする厳格さがある神社だった。
関連エントリー
- ✖ 金曜日、休んで時代祭をスルーしつつ銀閣寺に行った。平日なのですいてるといいなあと思ったけどそうでもなかった。人がいるだけで、あんまり……とい...
- ✖ 松尾大社 月読神社 天龍寺・宝厳院 松尾大社には何度もいっているのに、月読神社には行ったことがなかった。行ってみたらとても趣きがあって良かっ...
- ✖ 土曜日は、大麻止乃豆乃神社と青渭神社に行った。大麻止乃豆乃神社は長い階段の両隣にお墓があってなんかすごい感じだった。社殿が囲われていて様式は...
- ✖ 土曜日は伏見稲荷へ。なんとなく疲れていたのですぐ帰ってきて寝てた。 日曜日は石清水八幡宮、飛行神社へ。 石清水八幡宮は山にうえにあってケーブ...
- ✖ 土曜日は京都御苑、上賀茂神社、大田神社、今宮大社にいって、ユニクロで適当なジャケットを買って帰った。大田神社はすごく雰囲気がいい神社なのだけ...
✖
日曜日は前々から行こうと思って、なかなかタイミングがあわなかった[[愛宕神社]]にいった。朝8時ぐらいに目が覚めて、大阪のほうの別の神社と悩んだ末に愛宕神社へ。奇跡的に晴れたのもあって、ものすごく良かった。
前もって想像していた感じでは、大山阿夫利神社本社みたいに社殿はこじんまりした感じで、あとは社務所というか休憩所だけデカいのかなーと思っていたのだけれど、そんなことなくて、社殿もものすごく立派だったし、厳格で美しかった。
愛宕神社、でかい神社では珍しく本殿も割と近くまで普通に入っていける。いくつか社殿はあったけど本当に良かったとしか言いようがない。
冬の愛宕山の山頂付近ということで、そもそも人も少なくて (それなりにはいるけど)、晴れていて、雪が残っている、というとてもいい状態だった。
神社まで最寄りバス亭から2時間山登りで、結構キツいかなぁと思って上っていったけど、それほどでもなかった。とはいえそれなりにはキツかった。雪が残っている山頂付近は滑って転びそうで怖かった。大山ほど登山道がひどいことになっていないし、落ちついていて、少し軽めの登山にもいいなぁと思った。また暖くなったら行きたい。
あと、登山靴ほしい (雪が残りすぎていて山頂までいけそうにないならひきかえそうと思ってた)
関連エントリー
- ✖ 今日は大山登山をしてきた。午前中から行って、山頂までいって、おにぎり食って下山。下山時に足がガクガクいって非常に危険だった…… 3回ぐらい手...
- ✖ 5/2 は横浜→浜松町→芝大神宮→東京タワー→愛宕神社→烏森神社→新宿→新宿タワレコ 芝大神宮はいかにも都会の神社という感じだった。本殿が木...
- ✖ 元旦初詣 比々多神社 箱根神社 伊勢原大神宮 比々多神社は三宮。箱根は、標高が高いせいなのか、湖の近くだからなのか、めちゃくちゃ寒かった。風...
- ✖ 土曜日は、大麻止乃豆乃神社と青渭神社に行った。大麻止乃豆乃神社は長い階段の両隣にお墓があってなんかすごい感じだった。社殿が囲われていて様式は...
- ✖ 自分で撮った古い写真を4K画面でだらだら眺めてると面白くて、歴史を感じる。 HT-03A の写真が1枚だけあって、解像度低すぎてビビる。でも...
✖
鐸比古鐸比賣神社はヲタク的聖地巡礼の類です。文乃さん関係です。
JSDeferred Deferred.chain
http://lab.hisasann.com/addCommand/index.html を見ていて、next().next() 以外に、こういう風に書けても別にいいよなぁと思ったので実装を書いてみた。next().next() はめんどい割とめんどいし
git master HEAD には今のところ Deferred.chain() として入ってる。これと Deferred.connect() の変数バインドを組み合せて、addCommand.js のデモ相当をしてみた。
それっぽいとこを抜きだすと
Deferred.define();
var img1 = $("#img1"),
img2 = $("#img2"),
img3 = $("#img3");
(function() {
var callee = arguments.callee;
var animate = function (target, prop, speed, easing) {
return Deferred.connect(target, "animate", { args: [ prop, speed, easing ] });
};
Deferred.chain(
animate(img1, {
opacity: 0, top: 90 + "px", left: 260 + "px"
}, 1000, "easeInOutCirc"),
animate(img2, {
opacity: 0, top: 170 + "px", left: 450 + "px"
}, 1000, "easeInOutCirc"),
animate(img3, {
opacity: 0, top: 260 + "px", left: 620 + "px"
}, 1000, "easeInOutCirc"),
[
animate(img1, {
opacity: 1, top: 0 + "px", left: 0 + "px"
}, 1000, "easeInBack"),
animate(img2, {
opacity: 1, top: 0 + "px", left: 0 + "px"
}, 1000, "easeInBack"),
animate(img3, {
opacity: 1, top: 0 + "px", left: 0 + "px"
}, 1000, "easeInBack")
],
function () {
return wait(0.5).next(callee);
},
function error (e) {
alert(e);
}
);
})();となっていて、デモのコードとほぼ同じになる。エラーをキャッチする関数には function error() としておくルールがある。
キモは animate() を実行した時点ではアニメーションは実行されず、アニメーションを実行する関数を返すだけのところです。(Deferred.connect は関数を返す関数です)
便利なので入れたい気もするけど、うまく書かないと混乱するのでむずかしい。
✖
デバッグの基本は問題の切り分けなのだから、下手にあんまりいじってはいけないのだけれども、人生はみじかく試行錯誤ができないために、どうしようもないことは多々ある
✖
todo
jsdeferred の recipe をかく












































































































