Posted on Leave a comment

[新手教程-6] 使用Routing來切換頁面

什麼是Routing?

Routing意指路由器,也就是由一個路由器來決定現在要顯示的頁面是什麼
在套用Routing時,會有下列的實踐流程
1. 套用轉址設定(讓伺服器不去真正網址所在的位置去讀取資料,而改由Routing來決定現在要顯示什麼畫面)
2. 由url分析要顯示的狀態是什麼
3. 由狀態去獲得真正要取得那些資訊
4. 從這些資訊組成實體
5. 套用導覽動作,由這個畫面切換至另一個畫面

在Angular裡,最佳做法是將載入和設定Routing放在一個top-level的模組內,並於AppModule內來import所有的路由資訊。
按照慣例,模組AppRoutingModuleapp-routing.module.ts會放在src/app

Angular的Routing 產生的虛擬 URL,並不是真的存在於檔案系統裡,因此需要伺服器能夠支援,否則重新整理時會出現404 not found。

新增AppRoutingModule

透過下列CLI的指令來新增一個Routing

ng generate module app-routing --flat --module=app

--flat 的意思是將產出文件放在src/app裡,而非自己一個資料夾
--module=app 則是告知CLI註冊這個Routing在AppModule的imports裡

新產生的src/app/app-routing.module.ts檔案內容如下:

import { NgModule } from '@angular/core';
import { CommonModule } from '@angular/common';

@NgModule({
  imports: [
    CommonModule
  ],
  declarations: []
})
export class AppRoutingModule { }

一般我們不會在Routing裡宣告元件,因此可以將@NgModule.declarations及CommonModule的宣告刪除
通常我們會使用Routes與RouterModule來實做Routing,修改後的檔案如下:

import { NgModule }             from '@angular/core';
import { RouterModule, Routes } from '@angular/router';

@NgModule({
  exports: [ RouterModule ]
})
export class AppRoutingModule {}

增加Routes

此時我們來設定不同路徑要導向的位置,如下面的程式碼

import { HeroesComponent }      from './heroes/heroes.component';

const routes: Routes = [
  { path: '', redirectTo: '/dashboard', pathMatch: 'full' },
  { path: 'heroes', component: HeroesComponent },
  { path: 'detail/:id', component: HeroDetailComponent }
];

上述程式碼代表在網址為http://localhost/heroes時,會在標籤內顯示HeroesComponent這元件的內容。
另外,也要設定當伺服器剛運行時(http://localhost/),要顯示的模組。

設定完Router的map後,將之設定進RouterModule.forRoot()裡
然後再將這整個Router功能設定為可以被export,之後便可以在app.module裡import這個Router

import { NgModule }             from '@angular/core';
import { RouterModule, Routes } from '@angular/router';

import { DashboardComponent }   from './dashboard/dashboard.component';
import { HeroesComponent }      from './heroes/heroes.component';
import { HeroDetailComponent }  from './hero-detail/hero-detail.component';

const routes: Routes = [
  { path: '', redirectTo: '/dashboard', pathMatch: 'full' },
  { path: 'dashboard', component: DashboardComponent },
  { path: 'detail/:id', component: HeroDetailComponent },
  { path: 'heroes', component: HeroesComponent }
];

@NgModule({
  imports: [ RouterModule.forRoot(routes) ],
  exports: [ RouterModule ]
})
export class AppRoutingModule {}

而detail/:id裡的:id可於HeroDetailComponent裡去取得,來做進一步更詳細的資料顯示
取得方法如下:

ngOnInit(): void {
  this.getHero();
}

getHero(): void {
  const id = +this.route.snapshot.paramMap.get('id');//用route.snapshot.paramMap.get取得Routing時傳入的變數
  this.heroService.getHero(id)
    .subscribe(hero => this.hero = hero);
}

我們可以發現,例子中不同的path為所傳入的參數不同,它們代表不同的意義,可以更多元化的設定Routing的功能。Routes可傳入的參數有下面這些

interface Route {
  path?: string //瀏覽器上方的網址列的字串
  pathMatch?: string //當導航至此網址時要顯示的元件
  matcher?: UrlMatcher //網址列過濾器
  component?: Type<any>
  redirectTo?: string //要轉址到那邊
  outlet?: string
  canActivate?: any[]
  canActivateChild?: any[]
  canDeactivate?: any[]
  canLoad?: any[]
  data?: Data //要傳入元件裡的資料
  resolve?: ResolveData
  children?: Routes
  loadChildren?: LoadChildren
  runGuardsAndResolvers?: RunGuardsAndResolvers
}

在這邊可看一下APP_BASE_HREF的設定方式
如果沒有設定,會跑出錯誤訊息如下:

另一個簡單的方式則是在index.html增加下面這行,也可以解決這個錯誤

<base href="/">

在src/app/app.component.html中增加這個導航功能

<h1>{{title}}</h1>

<router-outlet></router-outlet>

利用routerLink來增加導航用超連結

修改src/app/app.component.html如下:

<h1>{{title}}</h1>


<nav>
  <a routerLink="/heroes">Heroes</a>
</nav>

<router-outlet></router-outlet>

如果要回上一頁則使用

goBack(): void {
  this.location.back();
}

這篇文章的範例檔案可由此觀看: live example / download example

參考資料

Posted on Leave a comment

[新手教程-5] 建立Service

這邊是上一篇Angular的主從元件開發的範例檔案:按此下載

創建 HeroService

使用Angular CLI創建一個名為hero的服務

ng generate service hero

我們會看到在src/app下多出了兩個檔案:hero.service.spec.ts和hero.service.ts

打開src/app/hero.service.ts可以看到下面內容

import { Injectable } from '@angular/core';

@Injectable()
export class HeroService {

  constructor() { }

}

注意到我們用@Injectable() 來宣告HeroService這個類別,代表這個類別可能本身有依賴注入,對Service來說是強烈建議要加上這個宣告

將HeroService提供給app使用

Service可以供appModule、或任何Component使用,如果要給appModule使用,
則需在src/app/app.module.ts的@NgModule裡加入

providers: [ HeroService ],

這邊有更多NgModule的說明:NgModule

另外,若要使用CLI來自動完成providers的設定,則可以用下面的指令

ng generate service hero --module=app

修改HeroesComponent去使用HeroService裡的資料

打開src/app/heroes/heroes.component.ts,修改成以下的內容

import { Component, OnInit } from ‘@angular/core’;
import { HeroService } from ‘../hero.service’;//1. 增加HeroService並移除HEROES
import { Hero } from ‘../hero’;

@Component({
selector: ‘app-heroes’,
templateUrl: ‘./heroes.component.html’,
styleUrls: [‘./heroes.component.css’]
})
export class HeroesComponent implements OnInit {

heroes: Hero[];//2. 在這邊先不設定內容

selectedHero: Hero;

constructor(private heroService: HeroService) { }//3. 宣告注入的service

getHeroes(): void {
this.heroes = this.heroService.getHeroes();//4. 取service內的資料放進變數內
}

ngOnInit() {
this.getHeroes();//5. ngOnInit會在初始化元件時被呼叫,在此時去取得heroes的值
}

onSelect(hero: Hero): void {
this.selectedHero = hero;
}
}

讓getHeroes被更動時能夠被通知

Observable是RxJS library中很重要的一個功能。

當我們在src/app/hero.service.ts的getHeroes方法回傳值前面加上Observable宣告,當service內的資料變動時,其他注入的內容也會同步被異動

首先要先import下面兩個檔案

import { Observable } from 'rxjs/Rx';
import { of } from 'rxjs/observable/of';

然後在getHeroes的回傳直類型前加上Observable宣告

getHeroes(): Observable<hero&#91;&#93;> {
  return of(HEROES);
}

注:若使用HttpClient.get<Hero[]>()亦會傳回Observable<Hero[]>,只是內容是由http傳來

在接收Observable物件時的方法也與非Observable物件的方式不同,過去若非Observable物件時,在hero.component.ts裡的getHeroes函數如下

getHeroes(): void {
  this.heroes = this.heroService.getHeroes();
}

若要使用Observable宣告則須改為:

getHeroes(): void {
  this.heroService.getHeroes()
      .subscribe(heroes => this.heroes = heroes);
}

Observable.subscribe()是最關鍵的相異之處
最大的差異在於我們送出修改到伺服器傳回回應之間,未使用Observable.subscribe()方法時,它不會先凍結UI不讓使用者修改,而有可能會造成資料的不一致。而使用Observable.subscribe()可以避免這個問題。

本日範例下載: live example / download example

Posted on Leave a comment

[新手教程-4] Angular的主從元件開發

創立hero-detail元件

在前一篇新手教程3-使用angular的迴圈及判斷式等功能裡,我們在顯示selectedHero的資訊時是與列表寫在同一個頁面
但如果顯示詳細資訊的地方有需要額外拆分出來,可以在創立一個元件,並將selectedHero傳入元件

ng generate component hero-detail

寫入hero-detail的內容

開啟檔案src/app/hero-detail/hero-detail.component.html,這邊會將selectedHero的名稱改為hero


<div *ngIf="hero">

<h2>{{ hero.name | uppercase }} Details</h2>


<div><span>id: </span>{{hero.id}}</div>


<div>
    <label>name:
      <input &#91;(ngModel)&#93;="hero.name" placeholder="name"/>
    </label>
  </div>

</div>

讓元件能接受外部傳送物件進來

開啟src/app/hero-detail/hero-detail.component.ts

import { Hero } from '../hero';

在hero-detail.component.ts裡面,hero一定要以@Input來宣告這個物件

@Input() hero: Hero;

而在HeroesComponent裡,則會以下面的宣告來將hero的值傳入

<app-hero-detail &#91;hero&#93;="selectedHero"></app-hero-detail>

現在我們打開heroes.component.html,修改後的網頁內容會如下

<h2>My Heroes</h2>



<ul class="heroes">

<li *ngFor="let hero of heroes" &#91;class.selected&#93;="hero === selectedHero" (click)="onSelect(hero)">
    <span class="badge">{{hero.id}}</span> {{hero.name}}
  </li>

</ul>


<app-hero-detail &#91;hero&#93;="selectedHero"></app-hero-detail>

今日練習的範例連結:live example / download example

Posted on Leave a comment

[新手教程-3] 使用Angular的迴圈及判斷式等功能

延續上一篇的範例: 請按此下載.

利用*ngFor來做迴圈顯示完整列表

首先開啟src/app/heroes/heroes.component.ts
設定一個變數heroes

    heroes: Hero[] = [
    { id: 11, name: 'Mr. Nice' },
    { id: 12, name: 'Narco' },
    { id: 13, name: 'Bombasto' },
    { id: 14, name: 'Celeritas' },
    { id: 15, name: 'Magneta' },
    { id: 16, name: 'RubberMan' },
    { id: 17, name: 'Dynama' },
    { id: 18, name: 'Dr IQ' },
    { id: 19, name: 'Magma' },
    { id: 20, name: 'Tornado' }
  ];

接著開啟app.component.html,利用*ngFor來迴圈式的顯示列表內容

<ul class="heroes">
  <li *ngFor="let hero of heroes">
    <span class="badge">{{hero.id}}</span> {{hero.name}}
  </li>
</ul>

這時網頁上就可以看到成果如下圖:

更多資訊有關於ngFor

使用(click)來設定觸發事件

開啟src/app/heroes/heroes.component.ts,在li裡面增加click的事件

  <li *ngFor="let hero of heroes" (click)="onSelect(hero)">

在src/app/heroes/heroes.component.ts增加處理的函數

selectedHero: Hero;

onSelect(hero: Hero): void {
  this.selectedHero = hero;
}

更多資訊有關於event-binding

以條件式去增加元件的類別

打開heroes.component.html,在li內增加 [class.要增加的類別名稱]=”條件式為true時增加”

<li *ngFor="let hero of heroes"
  &#91;class.selected&#93;="hero === selectedHero"
  (click)="onSelect(hero)">
  <span class="badge">{{hero.id}}</span> {{hero.name}}
</li>

這樣當hero === selectedHero為真時,這個li就會被加上selected這個類別
接下來再到src/app/heroes/heroes.component.css設定該類別的CSS,就能突顯現在所選擇的是那一個了
.selected{
color:red;
}

Posted on Leave a comment

[新手教程-2] 創立Angular的元件

使用CLI來為專案建立一個元件

ng generate component heroes

用這個指令,CLI會為我們初始化一個新的元件樣版
這時我們開啟app/heroes/heroes.component.ts

import { Component, OnInit } from '@angular/core';

@Component({
  selector: 'app-heroes',
  templateUrl: './heroes.component.html',
  styleUrls: ['./heroes.component.css']
})
export class HeroesComponent implements OnInit {

  constructor() { }

  ngOnInit() {
  }

}

只要創建元件,都必需從Angular去import Component。
而@Component則是用來定義這一個元件的相關資訊,有三個metadata

  1. selector: the components CSS element selector以及在HTML裡要宣告的TAG名稱
  2. templateUrl: 要使用的HTML樣版位置
  3. styleUrls: 專為這個元件設定的CSS

要注意的是,我們通常會使用export class,以方便在其他的模組裡可以import來使用

修改元件內容

打開heroes.component.ts

import { Component, OnInit, ViewEncapsulation } from '@angular/core';

@Component({
  selector: 'app-heroes',
  templateUrl: './heroes.component.html',
  styleUrls: ['./heroes.component.css'],
  encapsulation: ViewEncapsulation.None
})
export class HeroesComponent implements OnInit {
  hero = 'heroes works!';//增加一個變數
  constructor() { }

  ngOnInit() {
  }

}

修改heroes.component.html,使用{{hero}}來顯示剛剛在TS檔裡定義的變數

<h1>{{hero}}</h1>

將元件放進頁面裡

打開src/app/app.component.html

<app-heroes></app-heroes>

這時候就可以在頁面中看到剛剛我們所增加的內容

使用物件

創建一個Hero物件
src/app/hero.ts

export class Hero {
   id: number;
   name: string;
}

打開src/app/heroes/heroes.component.ts,給予物件正確的值

import { Component, OnInit } from '@angular/core';
import { Hero } from '../hero';

@Component({
selector: 'app-heroes',
templateUrl: './heroes.component.html',
styleUrls: ['./heroes.component.css']
})
export class HeroesComponent implements OnInit
{
//在這邊設定物件內容
hero: Hero = {
id: 1,
name: 'Windstorm'
};

constructor() { }

ngOnInit() {
}

}

顯示在heroes.component.ts所設定的值



<h2>{{ hero.name }} Details</h2>




<div><span>id: </span>{{hero.id}}</div>




<div><span>name: </span>{{hero.name}}</div>


如果希望將變數格式化
則可以使用


<h2>{{ hero.name | uppercase }} Details</h2>


這個格式化的功能叫做Pipes,更多的說明請見Pipes說明

雙向繫結

Angular一個很方便的功能就是可以支持雙向繫結,使用[(ngModel)]能做到當欄位的值改變時,TS裡變數的值也同時被更改。
這個功能在做表單驗證時非常方便
詳細使用說明請見:NgModules
使用方法: 在src/app/heroes/heroes.component.html加上下面這段

<div>
    <label>name:
      <input &#91;(ngModel)&#93;="hero.name" placeholder="name">
    </label>
</div>

接著要去app.module.ts去加上import資訊讓專案能夠使用ngModel標籤
要注意是在app.module.ts裡喔!
先import並且將FormsModule加進@ngModule的imports列表內,讓下面所有的元件都可以使用FormsModule的功能
import { FormsModule } from ‘@angular/forms’; // <-- NgModel lives here[/code] [code lang="js"]imports: [ BrowserModule, FormsModule ],[/code] 接著,要把剛剛我們所建立的元件HeroesComponent放進@NgModule.declarations裡 [code lang="js"]import { HeroesComponent } from './heroes/heroes.component';[/code] 在app.module.ts的@NgModule增加 [code lang="js"] declarations: [ AppComponent, HeroesComponent ], [/code] 這時,我們會發現我們更動input裡的文字時,model的值也會被更改 今日練習成果下載:live example / download example.

Posted on Leave a comment

[新手教程-1] 建立一個Angular5的專案

這系列的文章為我在官網學習Angular 5時所紀錄下來的學習筆記。
原文的原始教程都可在Angular的Docs看到。

這三十天的筆記大綱預計分為新手教程、功能介紹、技術支援三個部份:

  • 新手教程:一個最簡單的專案,用step by step的方式引導大家去做
  • 功能介紹:一個個介紹Angular裡面各別的功能和特性
  • 技術支援:涵蓋如何佈署、設定以及angular所使用的npm、typescript等的設定

建立專案

確認電腦已有安裝NodeJS(6.9.x以上版本)以及NPM(3.x.x以上版本)

創建專案

ng new my-app

開啟專案

cd my-app
ng serve --open

編輯第一個自己的頁面

打開src/app/app.component.ts,改為

import { Component } from '@angular/core';

@Component({
    selector: 'app-root',
    templateUrl: './app.component.html',
    styleUrls: ['./app.component.css']
})
export class AppComponent {
    title = '我的第一個網頁';
}

打開src/app/app.component.html,將內容改為

這是 {{title}}!

src資料夾內的檔案架構

檔案 目的
app/app.component. {ts,html,css,spec.ts} 所有的 Componet、Service、Pipe、Unit test 等等..程式碼都是放在這個資料夾,而 app.component 則是 Angular CLI 預設建立的 root component
app/app.module.ts 預設的 root module , 告訴 Angular 有哪些 Components 、Modules、 Services,讓 Angular 知道如何 assemble the application
assets/* 放圖片或者是建立 application 需要用的到材料
environments/* 設定 Angular 程式碼會用到的參數,很像 Web.config 的東西。 預設為 environment.ts , 要產生不同的 environment 的話,參考命名規則為 environment.xxx.ts,在執行或者 build Angular application 的時候加入 xxx 的參數,則可以指定到該 environmnet ,例如 : ng build -xxx、 ng serve -xxx
favicon.ico 網頁頁籤的 icon
index.html 網頁進入點,當使用者拜訪網站的時候,是執行到這個頁面。 在大部分的情況,是不需用編輯的, Angular CLI 在 build application 的時候會自動加入 js 和 css
main.ts 若使用JIT,這個文件為JIT compiler和bootstraps的root module,也就是編譯的起始點。也可以用ng serve –aot,改為AOT編譯而不用修改任何的code
polyfills.ts 因為不同的瀏覽器會支援不同的 web standards, polyfills 就像補丁的概念,補足些沒有支援的部分。Browser Support guide for more information.
styles.css 放置 global styles 的 CSS
test.ts unit tests 的進入點,有些 unit tests 的設定也寫在這邊
tsconfig.{app|spec}.json TypeScript 編譯設定檔(tsconfig.app.json) and for the unit tests (tsconfig.spec.json).

 

根目錄資料夾檔案列表

檔案 目的
e2e/ 負責放 End-to-End 測試程式碼的資料夾
node_modules/ Node.js 建立的資料夾,負責放 third party modules 的資料夾,其 thrid party modules 清單則放在 package.json裡面
.angular-cli.json 放 Angular CLI 的設定檔 Angular CLI Config Schema
.editorconfig 幫助開發者使用不同的 IDEs 保持檔案格式一致性的設定檔。更多資訊請見此
.gitignore Git 的設定檔,讓指定檔案不會 commit 到 Source control
karma.conf.js Karma test 的 unit tests 設定
package.json npm 設定檔, third party 清單與版本資訊
protractor.conf.js Angular end-to-end test framework Protractor 設定檔
README.md 專案基本說明文件
tsconfig.json TypeScript 編譯器設定檔案
tslint.json Codelyzer(用以保持code style的一致性)和TSLint的設定檔。
Posted on

Starling簡報分享

Starling簡介

  1. 基於Stage3D技術來實作
  2. 在Flash Player 11之後的版本才能支援此技術
  3. 使用GPU做圖形的運算,讓Flash的效能能夠到之前的1000倍(官方說法)!
  4. 易學,使用跟Flash native API類似的類別,方法,架構等,讓原本熟悉Flash的開發者可以很快的上手可發布到多種平台(包括 iOS andAndroid及各種瀏覽器)
    image-712

 

3D畫面運作原理

  1. Flash原有的坐標系統:Global Point和Local Point
  2. 3D世界的坐標系統:世界坐標到相機坐標的轉換
    201212141827446597-349

3D透視變換方法

  1. 正交投影
    201212141827541985-383
  2. 透視投影
    201212141827559901-404
  3. 比較圖
    201212141827571132-411

Stage3D的渲染過程

VertexShader 主要作用就是3D流程中的前半段操作(對頂點進行一系列的矩陣變換)
FragmentShader:對這些變換後的頂點(及流程中的光柵化部分)進行渲染
螢幕快照-2014-01-30-下午1.03.21-494

過去主要的3D技術

  1. 使用GPU的3D引擎:硬件加速(hardware acceleration)
    1. DirectX
    2. OpenGL
  2. 其他Flash3D引擎:軟件模式(software mode)
    1. Papervision3D
    2. Away3D
    3. Alternativa3D

Starling的渲染方式

螢幕快照-2014-02-01-下午11.37.51-731

 

剩的請自行看投影片….

Posted on

UI進化論-行動裝置使用者介面設計

此文為閱讀此書的讀後心得:http://www.books.com.tw/products/0010471021

閱讀想法

這本書算是為專業的產品設計師所寫的,會講到許多有關於如何管理一個專業的設計團隊、制定開發流程、設計師頭銜討論,以及設計師如何訓練自己的藝術感等。並且也有說到一些相關電腦知識,例如掌上型行動設備的基礎知識之類。主要是以設計師的角度,去探討該如何去成為一個產品經理,然後開發一個產品。

也因為此書完全是以設計師角度去撰寫的,我是程式師,以想了解怎麼設計行動裝置的角度去看此書,很多地方會因身份角度不同而較無意義,不過或許對於設計師而言是一本很有意義的書。

重點筆記

使用者如何看待產品:這邊告訴我們使用者會怎樣看待我們的產品

  1. 合格的產品
    螢幕快照 2014-02-28 下午11.52.28
  2. 優秀的產品
    螢幕快照 2014-02-28 下午11.52.38
  3. 卓越的產品
    螢幕快照 2014-02-28 下午11.52.54

如何將設計商品化

  1. 做市場需求的觀察:包括人口特徵、使用行為、利潤潛力、價值觀、需求、動機、購買因素、態度、產品使用場合、地理位置
  2. 使用者研究:目標族群的身份、使用場合、怎樣會讓使用者感覺這是個好商品、為使用者和產品間建立感情的聯繫(例如遊戲打寶,因為有感情因素,使用者會願意花時間去練功)、觀察使用者想買這個APP的目的,要能符合他們想像中的目的。
  3. 研究目標市場的文化內涵

使用者分析與研究

分析方法

當我們想要做一個行動介面的產品設計圖,除了美術的畫面及色彩設計外,對使用者的分析及研究也非常重要,這一篇是這本書裡我覺得最喜歡的,它提供我們怎麼去設計一個行動介面的動線的方式。在此介紹如下:

  1. 任務分析法:把特定的任務分成好幾個階段,先想好自己的APP想要提供給使用者那些功能,然後把特定的功能分解成多個步驟。例如像穿襯衫,可以分解為:雙手抓住襯衫領子>把襯衫披在肩上>右手穿進袖子裡,從袖口伸出>左手穿進袖子裡,從袖口伸出>把後襟拉平>把左右門襟對齊
    這邊也列出一些心智模型工具:物理符號系統、諾爾曼模型、流程認知模型、SOAR模型、心智的社會模型、動力振盪理論模型、大腦協調學。
  2. 情境設定法:要包含角色和劇情。如在那邊、發生什麼事、怎樣的狀況下會想操作系統,不同情境下會需要不同的設計。例如會議中,靜音模式就很重要,或是在家裡,那就要有輕鬆、方便的感覺。
  3. 社會性研究法:研究一些社會的事件影響產品的事件。例如使用者的使用心得影響銷售的狀況、或是被影響等等。理解不同地域、文化背景、社會環境中的介面風格。

範例:MP3播放器

  1. 定義產品功能:明確定義出產品要有的功能有那些
    螢幕快照 2014-03-02 下午9.49.53
  2. 繪製互動設計流程圖:
    螢幕快照 2014-02-28 下午11.46.40
  3. 繪製介面原型:最簡單的版面元件位置配置
  4. 視覺設計:先設定APP主要要使用的色彩有那些(先配色),然後再繪製介面細節

如何讓圖型介面更有創意

  1. 更人性化
  2. 情感化因素不可忽視:應該要從美學本能和功能主義的瓶頸中跳脫,營造一種感覺,這種感覺能讓使用者把產品和品牌連繫在一起
  3. 互動特效的引入
  4. 產品=體驗=品牌
  5. 臨場的體驗決定購買意願

視覺設計的原則

  1. 介面清楚明瞭
  2. 讓機器幫助記憶,減少短期記憶的負擔
  3. 依賴認知而非記憶。例如列印圖示的記憶等
  4. 提供視覺線索
  5. 完善的視覺清晰度
  6. 介面的協調一致:如手機介面的按鈕排放、左鍵肯定右鍵否定或內容擺放位置
  7. 色彩與內容:整體設計不要超過五的色系,相近的色系表示相似的意思

制定設計流程

在本書的最後幾章一直在強調設計流程的重要性,其實這有點像程式開發的流程圖的設計師版本…XD

大概就是在強調一致的設計產出流程對設計師而言很重要,可以確保多個產品間的一致性,也可以提高產出效能。總而言之和程式的開發流程方法有點像。流程大概會劃分為十個步驟:

  1. 制定流程
  2. 確定工作內容
  3. 圖示風格:這本書前面有提到在設計圖示的風格上,可以分為兩個部份的會議去討論(也就是3與4)。
    第一次的會議採用Brainstorming的方式,Brainstorming的討論方式其實和這篇的原則類似,總之就是不要特別限定某種想法,讓點子越多越好,讓所有人發表所有他們所想的到的可能風格和idea,不去評斷idea的優劣,所有的討論內容越自由越好,隨意的讓點子發想。在會議之後,讓各個設計師去分別設計自己想要的圖示風格及理念想法
  4. 首次檢查:展開討論設計方向、設計師闡述設計概念、第一次設計評審會議。
    然後第二此的會議則和第一次完全相反,由某個人去引導會議,並且由每個人提出前一個會議中提出各個點子的優劣,並由主導者來決定以那個圖示為主。
  5. 介面風格:定義色彩、解析度、關鍵介面數量、介面元素、通用性等
  6. 互動特效:定義合適的互動效果、思考如何更好的表現互動模型、視覺化介面風格、並要考慮最終實現的難度
  7. 介面設計:設計師分別獨立完成
  8. 準備演練展示
  9. 互動模型:例如用flash去做一個demo檔案
  10. 最終提案:最後決定要用那一個介面
Posted on

Intro to Artificial Intelligence

課程網址:https://www.udacity.com/course/viewer#!/c-cs271

什麼是Intelligent Agent

人工智能代理(Agent)根據環境的感知器(下圖的Sensors)傳入的資料,經過一連串的映設函數(紅箭頭部份),藉由效應器對環境做影響(下圖Actuators)。在裡面紅色箭頭部份是最重要的課題,這稱為代理控制策略。
螢幕快照 2014-02-18 下午11.05.25
如上圖這樣的一個決策過程會重覆進行很多次,從環境將資訊透過Sensors傳給Agent,經過代理做出決定,然後用Actuators影響環境,這樣的一個周期稱為perception action cycle。

AI應用範疇

  1. 財務金融:應用環境可以在股票市場、債卷市場或期貨市場,感知到一些東西的資訊和相關新聞,決策則是買入和賣出。
  2. 機器人學:這個是研究時間最長的一門ai領域,他的Sensors及Actuators都是與物理環境交互,而更為特殊。
  3. 遊戲:分兩種,一種是與人類對戰,像是象棋對戰,對Agent來說玩家是環境,它必需觀察玩家的動作,目的是戰勝玩家。另一種是遊戲情境模擬,為了要讓遊戲更自然,讓玩家感覺遊戲世界像真實世界般。
  4. 醫藥學:可以用在終身醫療上,輸入過去病史,讓它可以幫助判斷未來可能出現的疾病。
  5. WEB應用:像智能搜索,對語意進行判定,然後幫助找出可能更符合使用者想要的搜尋結果。

術語介紹

  1. 完全可觀察的環境 vs 部份可觀察的環境(partially)
    完全可觀察:例如一些牌類遊戲,當所有牌都已被掀開在桌子上,我們可以看到所有的資訊,可以算出最佳解答。
    部份可觀察:像另一些紙牌遊戲,有些牌是掀開的,有些則是未被掀開的。這時就要去觀察並記憶過去曾有的牌型紀錄,和桌上現有的牌,來推算可能是最有利的出牌方式。越多的歷史紀錄可以幫助Agent去做出更正確的推斷。這個循環稱為馬爾可夫模型(Markov Model),我們會廣泛的討論要如何具有下面的這種結構:
    螢幕快照 2014-02-19 上午1.10.56拷貝
  2. 確定性環境 vs 隨機性環境(stochastic)
    確定性環境:Agent所做的結果會產生的影響是否確定。例如像在象棋遊戲中,移動一個棋子的效果是完全可預見的。
    隨機性環境:像是大富翁的擲骰子遊戲,雖然所做的決定會影響結果,但是我們無法預期骰子會擲出多少,因此無法完全預見所做決策會影響到的效果。
  3. 離散環境 vs 連續環境(continuous)
    離散環境:有有限多個選擇和可能性,例如象棋遊戲。
    環境:可做的行動或可能性是無限的,例如丟飛鏢會有無限種角度的可能性與加速方式
  4. 良性環境 vs 敵對環境(adversarial):環境因素的存在與影響是否剛好與我們所要達成的目標相反?

AI的不確定性

螢幕快照 2014-02-19 上午1.51.16

包括感知器的有限、很多時候會忽略掉某些不重要或無法判別的因素、敵對因素的影響、隨機性環境的不可預測因素、可計算的步數有限性等…。而AI的存在就是在處理並控制不確定性以供做出決策的規則。

定義問題

  1. 初始狀態:一開始的狀態
  2. 動作狀態:若當Agent處於該狀態時會有那幾種可能性(返回一組該狀態可做行動的序列)
  3. 結果狀態:一個狀態和一個動作為輸入,一個新的狀態為輸出
  4. 目標測試函數:是否這個狀態是可達成目標的。
  5. 路徑成本函數:計算從a狀態到b狀態要花的成本

幾個路徑計算方式

螢幕快照 2014-02-19 下午2.20.59
求從上圖的路徑中的A點到B點的最佳路徑的方式有下面這些工具:

  1. Graph Search vs Tree Search
  2. Graph
  3. Tree
  4. BFS
  5. DFS
  6. Best-first Search:在大部份的時後,找到最佳解是最困難的,因此這部份很難實作,有許多文章有在探討相關實作方式。

像上述的這些搜尋方式,是完全不考慮有什麼意外發生的狀態下才有效的。
要使用上面這種路徑搜尋方式,環境必須符合下面幾項條件:
螢幕快照 2014-02-19 下午2.12.33

  1. 搜索域必須是完全可觀察的,換句話說,我們必須具備觀察我們開始的初始狀態的能力
  2. 域必須是可知的,我們必需知道我們可採取的行動的集合
  3. 必須為離散域,可選擇的行動的數量必需是有限的
  4. 域必須是具有確定性的,必須知道採取某一行動所產生的結果
  5. 域必須是靜態的,除了我們自己的行動以外,域中不可以存在任何可以改變它的東西

在AI中以機率去找出最佳解

貝葉斯概率:http://wiki.mbalib.com/zh-tw/%E8%B4%9D%E5%8F%B6%E6%96%AF%E6%A6%82%E7%8E%87
聯合概率分布:http://zh.wikipedia.org/wiki/%E8%81%94%E5%90%88%E5%88%86%E5%B8%83
貝葉斯網絡可以簡潔地表示一個聯合概率分佈狀況,如下圖可表示一個汽車壞掉可能原因的貝葉斯網路圖,我們觀察一些面板數值,然後去推斷可能的原因的發生機率,再去做交叉比對,這樣就可以列出一個概率分布圖。
螢幕快照 2014-02-19 上午3.15.19

機率學相關概念:互補事件獨立性事件(任意兩個變量的聯合概率是兩個機率的乘積)、貝葉斯法則

貝葉斯公式

螢幕快照 2014-02-19 下午7.55.50
P(A|B) = P(B|A) P(A) / P(B)
P(A,B) = P(A|B) P(B)

經過如下的推導
未命名1
可得知P(A,B|C) = P(A|B,C) P(B|C)

這邊有相關的理論說明:條件機率與貝氏定理

範例題目
螢幕快照 2014-02-19 下午5.37.10

是在探討今天若心情很好P(H)可能原因有天氣好P(S)或是被加薪P(R)
假使天氣好P(S)的機率為0.7
被加薪P(R)的機率為0.01

P(H | S,R) = 1 >> 天氣好且被加薪,心情好機率為1
P(H | ^S,R) = 0.9 >> 天氣不好但被加薪,心情好的機率為0.9
P(H | S,^R) = 0.7 >> 天氣好但沒被加薪,心情好的機率為0.7
P(H | ^S,^R) = 0.1 >> 天氣不好又沒被加薪,心情好的機率為0.1

則求出P( R | H,S)  > 也就是求出在心情好且天氣好的狀況下,是被加薪的機率
下面是好心人在討論版所給的詳解方式

According to Bayes formula p(R|H,S) = p(H,S|R)p(R)/p(H,S) = p(H|S,R)p(S|R)p(R)/p(H,S) (1)
In the second equality we used the analog of formula p(H,S) = p(H|S)p(S) but under definite value of R: p(H,S|R) = p(H|S,R)p(S|R).
Further, p(S|R) = p(R|S)p(S)/p(R). Plugging it in the formula (1) and accounting that p(H,S) = p(H|S)p(S) we get the targeted expression:
p(R|H,S) = p(H|R,S)p(R|S)/p(H|S). It’s the strict formula and should be remembered. It’s easy if you note that this formula is the custom Bayes rule p(R|H) = p(H|R)p(R)/p(H) but under definite value of S of all probabilities in the formula.

Posted on 1 Comment

產生TextureAtlas素材的方式

方法一、使用TexturePacker

軟體官網:http://www.codeandweb.com/texturepacker
範例圖檔下載:woman
螢幕快照 2014-02-12 下午2.39.46
首先,要先把圖檔整理成多個png圖檔,若是連續的圖檔,則需要在後面加0001~~XXXX之類的數字,固定是四個數字。若是單一圖檔則可以不用加。到時在取圖檔時,例如本範例是woman0001~woman0028,則只需要用woman當前置詞就可以取出全部的動態圖檔了

var woman:MovieClip = new MovieClip(atlas.getTextures("woman"),30);

而在操作TexturePacker時,最重要的是Data Format要選擇Sparrow/Starling。

索取TexturePacker免費序號

免費序號申請單:http://www.codeandweb.com/request-free-license

首先要說一下這套軟體的開發者真的很用心,當時看到有Blog說如果是有部落格的開發者,可以寫信去申請免費序號。我寫了申請表後,他回信了這封信給我:

Hi Claire,

Here’s your license key for TexturePacker:
TP-xxxxxxxxxxxxxxxx
I’ve added a license for PhysicsEditor (see file attached) in case you might want to try it too 😉
Nice blog! I would be happy to get a (short) blog post in return.
In case you do a tutorial post about my tools I can link back to your blog from the tutorials section on my page. That might give you some more visitors on your page!

Kind regards
Kerstin on behalf of Andreas

因為還有我的名字,我就回信問他中文的部落格可以嗎?結果居然真的是人工回信的耶(本以為都是自動發信),而且回信速度很快,真的很用心在經營他的產品。

最酷的是,後來因為我在寫Starling前面的教程,所以遲遲未寫關於TexturePacker的介紹文,他居然隔了一段時間又寄了封信給我:

Dear Claire,

I sent you a blogger license for TexturePacker some time ago,
and I am curious how you like the program.
Did you get it running successfully? Or do you need some assistance?
I would be happy to get a (short) blog post in return.

Kind regards
Kerstin on behalf of Andreas

還會關心我們的使用狀況耶!真的是超用心的開發者~

方法二、使用Flash CC

Flash CC和之前的版本比起來,就是它終於支援可以把元件庫的東西匯出了。

只需要在元件庫按右鍵,就可以選擇是要將其匯出成連續png或者是直接匯出成Sprite Sheet,並可同時選擇多個圖檔然後一起匯在同一個Spite Sheet裡。相關操作教學請見此:Sprite Sheets in Flash Professional CS6
螢幕快照 2014-02-12 下午2.47.52
螢幕快照 2014-02-12 下午2.49.40