Más contenido relacionado
Single Page Application における PreloadJS の活用事例
- 1. Single Page Application における
PreloadJS の活用事例
山田 直樹
株式会社リクルートマーケティングパートナーズ
2016.01.22
- Case study of PreloadJS -
CreateJS 勉強会 (第7回)
- 18. 1. ページを表示するのに必要な情報 ( JSON 形式 ) を API から取得し、
モデルクラスにパースする ( => ValueObject )
2. モデルから読み込みたいメディアファイルの URL を抽出して manifest
を生成する
3. 読み込み処理が完了したらキャッシュオブジェクトをモデルに追加し、
以降は任意のタイミングで参照・表示する
ページ (セクション) 毎に manifest を生成して loadManifrst() を呼び出す
- 19. {
"listening": {
"bgmSoundUrl": “http://example.com/bgm.m4a”,
"phrases": [
{
"id": 1,
"bgImageUrl": “http://example.com/bg_1.png",
"character" : {
"id": 1,
"name": "bobby",
"imageUrl": "http://example.com/bobby.png",
},
"normalVoiceSoundUrl": “http://example.com/voice_normal_l.m4a",
"fastVoiceSoundUrl" : “http://example.com/voice_fast_1.m4a",
"slowVoiceSoundUrl" : “http://example.com/voice_slow_1.m4a",
},
… 中略 …
]
}
}
var valueObject = new models.valueobjects.responses.Listening(jsonData);
- 20. var valueObject = new models.valueobjects.responses.Listening(jsonData);
var manifest = [
{id: ‘bgm.m4a', src: 'http://example.com/bgm.m4a'},
{id: 'bg_1.png', src: ‘http://example.com/bg_1.png'},
{id: 'bobby.png', src: 'http://example.com/bobby.png'},
{id: 'voice_normal_l.m4a', src: 'http://example.com/voice_normal_1.m4a'},
{id: 'voice_fast_1.m4a', src: 'http://example.com/voice_fast_1.m4a'},
{id: 'voice_slow_1.m4a', src: ‘http://example.com/voice_slow_1.m4a'},
// … 中略 …
];
モデルから manifest を生成
- 21. valueObject: {
cached: {
'bgm.m4a' : AudioBuffer,
'bg_1.png' : 'blob:http%3A//localhost/0beacb23-d698-4dda-9f59-61cfd2ed3b86',
'voice_norma_l.m4a': AudioBuffer,
'voice_slow_1.m4a' : AudioBuffer'
}
}
var queue = new createjs.LoadQueue(true);
queue.on('complete', () => {
valueObject.cached['bgm.m4a'] = queue.getResult('bgm.m4a');
valueObject.cached['bg_1.png'] = queue.getResult(‘bg_1.png').src;
});
queue.loadManifest(manifest);
画像は src 値から Blob オブジェクトのパスを取り出すと扱いやすくなる (※
- 22. valueObject: {
cached: {
'bgm.m4a' : AudioBuffer,
'bg_1.png' : 'blob:http%3A//localhost/0beacb23-d698-4dda-9f59-61cfd2ed3b86',
'voice_norma_l.m4a': AudioBuffer,
'voice_slow_1.m4a' : AudioBuffer'
}
}
var queue = new createjs.LoadQueue(true);
queue.on('complete', () => {
valueObject.cached['bgm.m4a'] = queue.getResult('bgm.m4a');
valueObject.cached['bg_1.png'] = queue.getResult(‘bg_1.png').src;
});
queue.loadManifest(manifest);
画像は src 値から Blob オブジェクトのパスを取り出すと扱いやすくなる
• v0.6.2 だとBlob オブジェクトパスを参照しても画像が読み込めな
かった …
• Complete イベントは発火しているので、リソースの読み込み自体
は成功していると想定
• 他の実装箇所に何らかの問題があるのか、現時点では不明
Blob オブジェクトの仕様を理解する
必要があるのでは… ( ごくり
悲報
- 25. {
"id": 123,
"bgmSoundUrl": “http://example.com/bgm.m4a",
"characters": [
{
"id": 1,
"name": "Bobby",
"imageUrl": "http://example.com/bobby.png",
}
],
"phrases": [
{
"id": 1,
"bgImageUrl": “http://example.com/bg_1.png",
"character": {
"id": 1,
"name": "Bobby",
"imageUrl": "http://example.com/bobby.png",
},
"normalVoiceSoundUrl": "http://example.com/voice_normal.m4a",
“fastVoiceSoundUrl" : "http://example.com/voice_fast.m4a",
“slowVoiceSoundUrl" : "http://example.com/voice_slow.m4a",
}
],
"commentary": "よく出来ましたね!この調子で頑張りましょう。",
"teacherImageUrl": "http://images/teacher.png"
}
- 26. var manifest = [
{id: 'm4a.m4a', src: 'http://example.com/fuga.m4a'},
{id: 'bobby.png', src: 'http://example.com/bobby.png'},
{id: 'bg_1.png', src: 'http://example.com/bg_1.png'},
{id: 'bobby.png', src: 'http://example.com/bobby.png'},
{id: 'voice_normal_l.m4a', src: 'http://example.com/voice_normal_1.m4a'},
{id: 'voice_fast_1.m4a', src: 'http://example.com/voice_fast_1.m4a'},
{id: 'voice_slow_1.m4a', src: 'http://example.com/voice_slow_1.m4a'},
];
このままだとメディアファイルを重複して読み込んでしまう
重複した 項目は削除するのと同時に
既に読み込み済みの項目も削除する
- 27. private removeStoredAssets(urls) => {
// … ゴニョゴニョ …
return result;
}
var urls = [
'http://example.com/bgm.m4a',
'http://example.com/bobby.png',
'http://example.com/bg_1.png',
'http://example.com/bobby.png'
];
[
'http://example.com/bgm.m4a',
'http://example.com/bobby.png',
'http://example.com/bg_1.png',
'http://example.com/voice_norma_l.m4a'
];
- 29. • メディアファイルは AWS S3 に配置しているため、そのままでは URL
直打ちでアクセスされて盗まれるリスクがある
• ログインユーザー毎に JWT トークンを発行し、全てのメディアファイ
ルはこのトークンで認証することで読み込み可能とする
• manifest の headers プロパティに JWT トークンを含め、src 値にも
query string として JWT トークンを含める
manifest の headers に JWT トークンパラメータを含める
画像か音声かを正確に判断するために
type プロパティも指定する必要があります
- 30. var manifest = [];
var fixedUrl = urls[i];
var isCrossdomain = fixedUrl.indexOf('http') == 0;
var type = 'image';
if (~fixedUrl.indexOf('.m4a')) {
type = 'sound';
fixedUrl = fixedUrl.replace('static_resources', 'static_resources.m4a')
}
if (this.Config.IS_IE && isCrossdomain) {
fixedUrl += this.getJWTTokenParameter();
}
var info = {
id: urls[i],
src: fixedUrl,
type: type,
headers: null
};
if (isCrossdomain) {
info.headers = {
'Authorization': this.SessionService.getJWTToken(),
'Content-Type': 'application/x-www-form-urlencoded'
};
}
manifest.push(new createjs.LoadItem().set(info));
- 31. まとめ
ページ (セクション) 毎に manifest を生成して
loadManifest() を呼び出し、メディアファイルを読
み込む
既にキャッシュ済みのメディアファイルは再読込み
せずに、既存のものを使い回すことでリソースを
節約する
manifest の header プロパティに JWT トークンパ
ラメータを含めて読み込むことで、セキュリティを
担保する