SlideShare a Scribd company logo
1 of 29
Download to read offline
Angular 2のRenderer
おのうえ (@_likr)
ng-kyoto Angular Meetup #4
自己紹介
• おのうえ (@_likr)
• 京都大学 政策のための科学ユニット 特定助教 🆕
• ng-kyoto オーガナイザー

GDG神戸 スタッフ
• 可視化アプリケーションの

Webベース実装
Renderer ?
Renderer
• https://angular.io/docs/ts/latest/api/core/Renderer-class.html
• WHAT IT DOES
• Not yet documented
• HOW TO USE
• Not yet documented
Not yet documented
はじめに
• Angular 2のRendererで遊んでみる
• 明日使えなくなっても泣かない
Rendererの概要
• RootRenderer
• Rendererを返す
• Renderer
• レンダリングする
• DomRenderer (default)
• WorkerRenderer
• DebugDomRenderer
• RootRendererをDIする
RendererのInterface
• selectRootElement
• createElement
• createViewRoot
• createTemplateAnchor
• createText
• projectNodes
• attachViewAfter
• detachView
• destroyView
• listen
• listenGlobal
• setElementProperty
• setElementAttribute
• setBindingDebugInfo
• setElementClass
• setElementStyle
• invokeElementMethod
• setText
https://angular.io/docs/ts/latest/api/core/Renderer-class.html
簡単なRendererを作る
import {Injectable} from 'angular2/core';
import {
Renderer,
RootRenderer,
RenderComponentType,
RenderDebugInfo
} from 'angular2/src/core/render/api';
@Injectable()
export class MyRootRenderer implements RootRenderer {
renderComponent(componentProto: RenderComponentType): Renderer {
return new MyRenderer();
}
}
class MyRenderer implements Renderer {
selectRootElement(selectorOrNode: string | any, debugInfo: RenderDebugInfo) : any {
console.log('selectRootElement', selectorOrNode, debugInfo);
return {};
}
createElement(parentElement: any, name: string, debugInfo: RenderDebugInfo) : any {
console.log('createElement', parentElement, name, debugInfo);
return {};
}
// …
}
my-renderer.ts
自作Rendererを使う
import {Component} from 'angular2/core';
@Component({
selector: 'my-app',
template: '<h1>My First Angular 2 App</h1>'
})
export class AppComponent { }
import {provide, RootRenderer} from 'angular2/core';
import {bootstrap} from 'angular2/platform/browser';
import {AppComponent} from './app.component';
import {MyRootRenderer} from './my-renderer'
bootstrap(AppComponent, [
provide(RootRenderer, { useClass: MyRootRenderer }),
]);
app.component.ts
main.ts
動かす
https://plnkr.co/edit/ifMaZknans8yAAA8sSAV
何かできないかな?
もしかして
• Angularで3Dグラフィックスができるのでは!?
• Scene Graph
• 宣言的に3Dオブジェクトを作成
• Change Detectionの恩恵
• イベントハンドリングの抽象化
THREE.jsベースのRenderer
import {Injectable} from 'angular2/core';
import {
Renderer,
RootRenderer,
RenderComponentType,
RenderDebugInfo
} from 'angular2/src/core/render/api';
@Injectable()
export class MyRootRenderer implements RootRenderer {
scene: THREE.Scene; camera: THREE.Camera; renderer: THREE.WebGLRenderer;
constructor() {
this.scene = new THREE.Scene();
this.camera = new THREE.PerspectiveCamera(75, 1, 0.1, 1000);
this.camera.position.z = 5;
this.renderer = new THREE.WebGLRenderer();
}
renderComponent(componentProto: RenderComponentType): Renderer {
return new MyRenderer(this);
}
}
THREE.jsベースのRenderer
class MyRenderer implements Renderer {
constructor(private rootRenderer: MyRootRenderer) {
}
selectRootElement(selector: string, debugInfo: RenderDebugInfo) : any {
var element = document.querySelector(selector);
this.rootRenderer.renderer.setSize(600, 600);
element.innerHTML = ''; element.appendChild(this.rootRenderer.renderer.domElement);
var render = () => {
requestAnimationFrame(render);
this.rootRenderer.renderer.render(this.rootRenderer.scene, this.rootRenderer.camera);
};
render();
return this.rootRenderer.scene;
}
createElement(parentElement: any, name: string, debugInfo: RenderDebugInfo) : any {
switch (name) {
case 'three-box':
var geometry = new THREE.BoxGeometry(1, 1, 1);
var material = new THREE.MeshBasicMaterial();
var cube = new THREE.Mesh(geometry, material);
this.rootRenderer.scene.add(cube);
return cube;
// …
default:
throw 'unknown element';
}
}
setElementAttribute(renderElement: any, attributeName: string, attributeValue: string) : void {
switch (attributeName) {
case 'color':
renderElement.material.color = new THREE.Color(attributeValue);
break;
// …
}
}
}
描画してみる
https://plnkr.co/edit/yB0J8nVBK0KUiwkFO1VC
import {Component} from "angular2/core"
@Component({
selector: 'my-app',
template: '<three-box></three-box>',
})
export class AppComponent {
}
描画してみる
https://plnkr.co/edit/yB0J8nVBK0KUiwkFO1VC
Data Bindingできる
https://plnkr.co/edit/H4D1gmksKC0LH5AKHA3i
import {Component} from "angular2/core"
@Component({
selector: 'my-app',
template: `
<three-box
[attr.color]="boxColor">
</three-box>
`,
})
export class AppComponent {
boxColor = 'rgb(0, 255, 0)';
}
Data Bindingできる
https://plnkr.co/edit/H4D1gmksKC0LH5AKHA3i
import {Component, OnInit} from "angular2/core"
@Component({
selector: 'my-app',
template: `
<three-box [attr.color]="boxColor"
[attr.rotationX]="rotationX" [attr.rotationY]="rotationY">
</three-box>
`,
})
export class AppComponent implements OnInit {
boxColor = 'rgb(0, 255, 0)';
rotationX = 0; rotationY = 0;
ngOnInit() {
this.updateRotation();
}
updateRotation() {
this.rotationX += 0.1; this.rotationY += 0.1;
requestAnimationFrame(() => this.updateRotation());
}
}
ChangeDetectionが効く
https://plnkr.co/edit/EbqstFqCrsyVkZqLSWfY
ChangeDetectionが効く
https://plnkr.co/edit/EbqstFqCrsyVkZqLSWfY
ngForも使える
https://plnkr.co/edit/SAxskSugUVmBWFFcfiMC
import {Component, OnInit} from "angular2/core"
@Component({
selector: 'my-app',
template: `
<three-box *ngFor="let box of boxes"
[attr.color]="box.color" [attr.positionX]="box.x"
[attr.rotationX]="rotationX" [attr.rotationY]="rotationY">
</three-box>
`,
})
export class AppComponent implements OnInit {
boxes = [
{color: 'rgb(255, 0, 0)', x: -3},
{color: 'rgb(0, 255, 0)', x: 0},
{color: 'rgb(0, 0, 255)', x: 3},
];
rotationX = 0; rotationY = 0;
ngOnInit() {
this.updateRotation();
}
updateRotation() {
this.rotationX += 0.1; this.rotationY += 0.1;
requestAnimationFrame(() => this.updateRotation());
}
}
ngForも使える
https://plnkr.co/edit/SAxskSugUVmBWFFcfiMC
import {Component, OnInit} from "angular2/core"
var rotateColor = (box) => {
switch (box.color) {
case 'rgb(255, 0, 0)': box.color = 'rgb(0, 255, 0)'; break;
case 'rgb(0, 255, 0)': box.color = 'rgb(0, 0, 255)'; break;
case 'rgb(0, 0, 255)': default: box.color = 'rgb(255, 0, 0)';
}
};
@Component({
selector: 'my-app',
template: `
<three-box *ngFor="let box of boxes"
[attr.color]="box.color" [attr.positionX]="box.x"
[attr.rotationX]="rotationX" [attr.rotationY]="rotationY"
(click)="handleClick(box)">
</three-box>
`,
})
export class AppComponent implements OnInit{
boxes = [
{color: 'rgb(255, 0, 0)', x: -3}, {color: 'rgb(0, 255, 0)', x: 0}, {color: 'rgb(0, 0, 255)', x: 3},
];
rotationX = 0; rotationY = 0;
ngOnInit() {
this.updateRotation();
}
updateRotation() {
this.rotationX += 0.1; this.rotationY += 0.1;
requestAnimationFrame(() => this.updateRotation());
}
handleClick(box) {
rotateColor(box);
}
}
EventHandlingもできる
https://plnkr.co/edit/uy6oUMVoUc1DQ0YSvG8V
嬉しい!
でも、
こんなことやる
APIじゃないと思う
まとめ
• Renderer APIでHTMLのレンダリングをカスタマイズ
• One Framework
• Angular 2は、Component指向で構築された

XMLっぽい文書を解釈して

UIっぽい何かを開発するフレームワーク!?
• 多分違う
• ご利用は計画的に
Discussion

More Related Content

More from Yosuke Onoue

アニメーション(のためのパフォーマンス)の基礎知識
アニメーション(のためのパフォーマンス)の基礎知識アニメーション(のためのパフォーマンス)の基礎知識
アニメーション(のためのパフォーマンス)の基礎知識Yosuke Onoue
 
AngularJSでデータビジュアライゼーションがしたい
AngularJSでデータビジュアライゼーションがしたいAngularJSでデータビジュアライゼーションがしたい
AngularJSでデータビジュアライゼーションがしたいYosuke Onoue
 
GDG DevFest Kobe Firebaseハンズオン勉強会
GDG DevFest Kobe Firebaseハンズオン勉強会GDG DevFest Kobe Firebaseハンズオン勉強会
GDG DevFest Kobe Firebaseハンズオン勉強会Yosuke Onoue
 
Polymerやってみた
PolymerやってみたPolymerやってみた
PolymerやってみたYosuke Onoue
 
asm.jsとWebAssemblyって実際なんなの?
asm.jsとWebAssemblyって実際なんなの?asm.jsとWebAssemblyって実際なんなの?
asm.jsとWebAssemblyって実際なんなの?Yosuke Onoue
 
AngularFireで楽々バックエンド
AngularFireで楽々バックエンドAngularFireで楽々バックエンド
AngularFireで楽々バックエンドYosuke Onoue
 
AngularJSとD3.jsによるインタラクティブデータビジュアライゼーション
AngularJSとD3.jsによるインタラクティブデータビジュアライゼーションAngularJSとD3.jsによるインタラクティブデータビジュアライゼーション
AngularJSとD3.jsによるインタラクティブデータビジュアライゼーションYosuke Onoue
 
AngularJSでの非同期処理の話
AngularJSでの非同期処理の話AngularJSでの非同期処理の話
AngularJSでの非同期処理の話Yosuke Onoue
 
社会的決定とAHP
社会的決定とAHP社会的決定とAHP
社会的決定とAHPYosuke Onoue
 
CUDA 6の話@関西GPGPU勉強会#5
CUDA 6の話@関西GPGPU勉強会#5CUDA 6の話@関西GPGPU勉強会#5
CUDA 6の話@関西GPGPU勉強会#5Yosuke Onoue
 
Anaconda & NumbaPro 使ってみた
Anaconda & NumbaPro 使ってみたAnaconda & NumbaPro 使ってみた
Anaconda & NumbaPro 使ってみたYosuke Onoue
 
PythonistaがOCamlを実用する方法
PythonistaがOCamlを実用する方法PythonistaがOCamlを実用する方法
PythonistaがOCamlを実用する方法Yosuke Onoue
 
What's New In Python 3.3をざっと眺める
What's New In Python 3.3をざっと眺めるWhat's New In Python 3.3をざっと眺める
What's New In Python 3.3をざっと眺めるYosuke Onoue
 
PyOpenCLによるGPGPU入門 Tokyo.SciPy#4 編
PyOpenCLによるGPGPU入門 Tokyo.SciPy#4 編PyOpenCLによるGPGPU入門 Tokyo.SciPy#4 編
PyOpenCLによるGPGPU入門 Tokyo.SciPy#4 編Yosuke Onoue
 
PyOpenCLによるGPGPU入門
PyOpenCLによるGPGPU入門PyOpenCLによるGPGPU入門
PyOpenCLによるGPGPU入門Yosuke Onoue
 
数理最適化とPython
数理最適化とPython数理最適化とPython
数理最適化とPythonYosuke Onoue
 
Rsa暗号で彼女が出来るらしい
Rsa暗号で彼女が出来るらしいRsa暗号で彼女が出来るらしい
Rsa暗号で彼女が出来るらしいYosuke Onoue
 

More from Yosuke Onoue (19)

アニメーション(のためのパフォーマンス)の基礎知識
アニメーション(のためのパフォーマンス)の基礎知識アニメーション(のためのパフォーマンス)の基礎知識
アニメーション(のためのパフォーマンス)の基礎知識
 
AngularJSでデータビジュアライゼーションがしたい
AngularJSでデータビジュアライゼーションがしたいAngularJSでデータビジュアライゼーションがしたい
AngularJSでデータビジュアライゼーションがしたい
 
GDG DevFest Kobe Firebaseハンズオン勉強会
GDG DevFest Kobe Firebaseハンズオン勉強会GDG DevFest Kobe Firebaseハンズオン勉強会
GDG DevFest Kobe Firebaseハンズオン勉強会
 
Polymerやってみた
PolymerやってみたPolymerやってみた
Polymerやってみた
 
asm.jsとWebAssemblyって実際なんなの?
asm.jsとWebAssemblyって実際なんなの?asm.jsとWebAssemblyって実際なんなの?
asm.jsとWebAssemblyって実際なんなの?
 
AngularFireで楽々バックエンド
AngularFireで楽々バックエンドAngularFireで楽々バックエンド
AngularFireで楽々バックエンド
 
AngularJSとD3.jsによるインタラクティブデータビジュアライゼーション
AngularJSとD3.jsによるインタラクティブデータビジュアライゼーションAngularJSとD3.jsによるインタラクティブデータビジュアライゼーション
AngularJSとD3.jsによるインタラクティブデータビジュアライゼーション
 
AngularJSでの非同期処理の話
AngularJSでの非同期処理の話AngularJSでの非同期処理の話
AngularJSでの非同期処理の話
 
社会的決定とAHP
社会的決定とAHP社会的決定とAHP
社会的決定とAHP
 
CUDA 6の話@関西GPGPU勉強会#5
CUDA 6の話@関西GPGPU勉強会#5CUDA 6の話@関西GPGPU勉強会#5
CUDA 6の話@関西GPGPU勉強会#5
 
Anaconda & NumbaPro 使ってみた
Anaconda & NumbaPro 使ってみたAnaconda & NumbaPro 使ってみた
Anaconda & NumbaPro 使ってみた
 
PythonistaがOCamlを実用する方法
PythonistaがOCamlを実用する方法PythonistaがOCamlを実用する方法
PythonistaがOCamlを実用する方法
 
What's New In Python 3.3をざっと眺める
What's New In Python 3.3をざっと眺めるWhat's New In Python 3.3をざっと眺める
What's New In Python 3.3をざっと眺める
 
PyOpenCLによるGPGPU入門 Tokyo.SciPy#4 編
PyOpenCLによるGPGPU入門 Tokyo.SciPy#4 編PyOpenCLによるGPGPU入門 Tokyo.SciPy#4 編
PyOpenCLによるGPGPU入門 Tokyo.SciPy#4 編
 
PyOpenCLによるGPGPU入門
PyOpenCLによるGPGPU入門PyOpenCLによるGPGPU入門
PyOpenCLによるGPGPU入門
 
数理最適化とPython
数理最適化とPython数理最適化とPython
数理最適化とPython
 
201010ksmap
201010ksmap201010ksmap
201010ksmap
 
PyCUDAの紹介
PyCUDAの紹介PyCUDAの紹介
PyCUDAの紹介
 
Rsa暗号で彼女が出来るらしい
Rsa暗号で彼女が出来るらしいRsa暗号で彼女が出来るらしい
Rsa暗号で彼女が出来るらしい
 

Angular 2のRenderer

  • 2. 自己紹介 • おのうえ (@_likr) • 京都大学 政策のための科学ユニット 特定助教 🆕 • ng-kyoto オーガナイザー
 GDG神戸 スタッフ • 可視化アプリケーションの
 Webベース実装
  • 4. Renderer • https://angular.io/docs/ts/latest/api/core/Renderer-class.html • WHAT IT DOES • Not yet documented • HOW TO USE • Not yet documented
  • 6. はじめに • Angular 2のRendererで遊んでみる • 明日使えなくなっても泣かない
  • 7. Rendererの概要 • RootRenderer • Rendererを返す • Renderer • レンダリングする • DomRenderer (default) • WorkerRenderer • DebugDomRenderer • RootRendererをDIする
  • 8. RendererのInterface • selectRootElement • createElement • createViewRoot • createTemplateAnchor • createText • projectNodes • attachViewAfter • detachView • destroyView • listen • listenGlobal • setElementProperty • setElementAttribute • setBindingDebugInfo • setElementClass • setElementStyle • invokeElementMethod • setText https://angular.io/docs/ts/latest/api/core/Renderer-class.html
  • 9. 簡単なRendererを作る import {Injectable} from 'angular2/core'; import { Renderer, RootRenderer, RenderComponentType, RenderDebugInfo } from 'angular2/src/core/render/api'; @Injectable() export class MyRootRenderer implements RootRenderer { renderComponent(componentProto: RenderComponentType): Renderer { return new MyRenderer(); } } class MyRenderer implements Renderer { selectRootElement(selectorOrNode: string | any, debugInfo: RenderDebugInfo) : any { console.log('selectRootElement', selectorOrNode, debugInfo); return {}; } createElement(parentElement: any, name: string, debugInfo: RenderDebugInfo) : any { console.log('createElement', parentElement, name, debugInfo); return {}; } // … } my-renderer.ts
  • 10. 自作Rendererを使う import {Component} from 'angular2/core'; @Component({ selector: 'my-app', template: '<h1>My First Angular 2 App</h1>' }) export class AppComponent { } import {provide, RootRenderer} from 'angular2/core'; import {bootstrap} from 'angular2/platform/browser'; import {AppComponent} from './app.component'; import {MyRootRenderer} from './my-renderer' bootstrap(AppComponent, [ provide(RootRenderer, { useClass: MyRootRenderer }), ]); app.component.ts main.ts
  • 13. もしかして • Angularで3Dグラフィックスができるのでは!? • Scene Graph • 宣言的に3Dオブジェクトを作成 • Change Detectionの恩恵 • イベントハンドリングの抽象化
  • 14. THREE.jsベースのRenderer import {Injectable} from 'angular2/core'; import { Renderer, RootRenderer, RenderComponentType, RenderDebugInfo } from 'angular2/src/core/render/api'; @Injectable() export class MyRootRenderer implements RootRenderer { scene: THREE.Scene; camera: THREE.Camera; renderer: THREE.WebGLRenderer; constructor() { this.scene = new THREE.Scene(); this.camera = new THREE.PerspectiveCamera(75, 1, 0.1, 1000); this.camera.position.z = 5; this.renderer = new THREE.WebGLRenderer(); } renderComponent(componentProto: RenderComponentType): Renderer { return new MyRenderer(this); } }
  • 15. THREE.jsベースのRenderer class MyRenderer implements Renderer { constructor(private rootRenderer: MyRootRenderer) { } selectRootElement(selector: string, debugInfo: RenderDebugInfo) : any { var element = document.querySelector(selector); this.rootRenderer.renderer.setSize(600, 600); element.innerHTML = ''; element.appendChild(this.rootRenderer.renderer.domElement); var render = () => { requestAnimationFrame(render); this.rootRenderer.renderer.render(this.rootRenderer.scene, this.rootRenderer.camera); }; render(); return this.rootRenderer.scene; } createElement(parentElement: any, name: string, debugInfo: RenderDebugInfo) : any { switch (name) { case 'three-box': var geometry = new THREE.BoxGeometry(1, 1, 1); var material = new THREE.MeshBasicMaterial(); var cube = new THREE.Mesh(geometry, material); this.rootRenderer.scene.add(cube); return cube; // … default: throw 'unknown element'; } } setElementAttribute(renderElement: any, attributeName: string, attributeValue: string) : void { switch (attributeName) { case 'color': renderElement.material.color = new THREE.Color(attributeValue); break; // … } } }
  • 16. 描画してみる https://plnkr.co/edit/yB0J8nVBK0KUiwkFO1VC import {Component} from "angular2/core" @Component({ selector: 'my-app', template: '<three-box></three-box>', }) export class AppComponent { }
  • 18. Data Bindingできる https://plnkr.co/edit/H4D1gmksKC0LH5AKHA3i import {Component} from "angular2/core" @Component({ selector: 'my-app', template: ` <three-box [attr.color]="boxColor"> </three-box> `, }) export class AppComponent { boxColor = 'rgb(0, 255, 0)'; }
  • 20. import {Component, OnInit} from "angular2/core" @Component({ selector: 'my-app', template: ` <three-box [attr.color]="boxColor" [attr.rotationX]="rotationX" [attr.rotationY]="rotationY"> </three-box> `, }) export class AppComponent implements OnInit { boxColor = 'rgb(0, 255, 0)'; rotationX = 0; rotationY = 0; ngOnInit() { this.updateRotation(); } updateRotation() { this.rotationX += 0.1; this.rotationY += 0.1; requestAnimationFrame(() => this.updateRotation()); } } ChangeDetectionが効く https://plnkr.co/edit/EbqstFqCrsyVkZqLSWfY
  • 22. ngForも使える https://plnkr.co/edit/SAxskSugUVmBWFFcfiMC import {Component, OnInit} from "angular2/core" @Component({ selector: 'my-app', template: ` <three-box *ngFor="let box of boxes" [attr.color]="box.color" [attr.positionX]="box.x" [attr.rotationX]="rotationX" [attr.rotationY]="rotationY"> </three-box> `, }) export class AppComponent implements OnInit { boxes = [ {color: 'rgb(255, 0, 0)', x: -3}, {color: 'rgb(0, 255, 0)', x: 0}, {color: 'rgb(0, 0, 255)', x: 3}, ]; rotationX = 0; rotationY = 0; ngOnInit() { this.updateRotation(); } updateRotation() { this.rotationX += 0.1; this.rotationY += 0.1; requestAnimationFrame(() => this.updateRotation()); } }
  • 24. import {Component, OnInit} from "angular2/core" var rotateColor = (box) => { switch (box.color) { case 'rgb(255, 0, 0)': box.color = 'rgb(0, 255, 0)'; break; case 'rgb(0, 255, 0)': box.color = 'rgb(0, 0, 255)'; break; case 'rgb(0, 0, 255)': default: box.color = 'rgb(255, 0, 0)'; } }; @Component({ selector: 'my-app', template: ` <three-box *ngFor="let box of boxes" [attr.color]="box.color" [attr.positionX]="box.x" [attr.rotationX]="rotationX" [attr.rotationY]="rotationY" (click)="handleClick(box)"> </three-box> `, }) export class AppComponent implements OnInit{ boxes = [ {color: 'rgb(255, 0, 0)', x: -3}, {color: 'rgb(0, 255, 0)', x: 0}, {color: 'rgb(0, 0, 255)', x: 3}, ]; rotationX = 0; rotationY = 0; ngOnInit() { this.updateRotation(); } updateRotation() { this.rotationX += 0.1; this.rotationY += 0.1; requestAnimationFrame(() => this.updateRotation()); } handleClick(box) { rotateColor(box); } } EventHandlingもできる https://plnkr.co/edit/uy6oUMVoUc1DQ0YSvG8V
  • 28. まとめ • Renderer APIでHTMLのレンダリングをカスタマイズ • One Framework • Angular 2は、Component指向で構築された
 XMLっぽい文書を解釈して
 UIっぽい何かを開発するフレームワーク!? • 多分違う • ご利用は計画的に