View
710
Download
7
Category
Preview:
Citation preview
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
何かできないかな?
もしかして
• 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ベースのRendererclass 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 { }
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()); } }
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
Recommended