這篇文章的標題真的很難下,因為主要是搭配以下兩種技術來實作
- socket.io (其實可以直接用 rxjs 的 interval 來跑,這個不是必要的技術)
- angular 6
大家一定都常常看到某些看股票的網頁,如果上升和下降都會閃爍一下,表示有變化
但今天這篇文章要再進階一點,如果數字上升,就會閃一下綠色,反之就會閃一下紅色
環境
- Windows 10 Pro
- Webstorm 2018.2
最近迷上了 Typescript,所以 socket.io 的部分將會使用 Typescript 來實作,並且使用 Webpack 來進行打包,這篇文章將會附上部分的程式碼,給各位參考
大概說明一下 socket.io 的部分主要是在定義 namespace 和使用 rxjs 的 interval 來不斷的產生隨機的數字,並且透過名為 random 的 event,來將數字送到前端去
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53
| import * as express from 'express'; import * as socketIo from 'socket.io'; import {createServer, Server} from "http"; import {interval} from 'rxjs'; import {tap} from "rxjs/operators";
export class WebSocketServer {
private app: express.Application; private server: Server; private io: socketIo.Server; private readonly SERVER_IP: string; private readonly SERVER_PORT: number;
constructor(ip?: string, port?: number) { this.SERVER_IP = ip || '127.0.0.1'; this.SERVER_PORT = port || 8080; this.initialize(); this.start(); }
private initialize() { this.app = express(); this.server = createServer(this.app); this.io = socketIo(this.server); }
start() { this.server.listen(this.SERVER_PORT, this.SERVER_IP, () => { console.log(`server is running on ip: ${this.SERVER_IP}, port: ${this.SERVER_PORT}`) });
this.io.of('/animation').on('connection', (socket: socketIo.Socket) => { console.log(`a client with id ${socket.client.id} connect on port ${this.SERVER_PORT}`); interval(500) .pipe( tap(() => { socket.emit('random', Math.floor(Math.random() * 100)); }) ).subscribe();
}); }
get expressApp(): express.Application { return this.app; }
}
|
這邊是 webpack 的打包定義檔
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26
| const path = require('path'); const nodeExternals = require('webpack-node-externals');
module.exports = { mode: 'development', target: "node", entry: path.resolve(__dirname, './src/index.ts'), module: { rules: [ { test: /\.tsx?$/, use: 'ts-loader' } ] }, resolve: { extensions: ['.tsx', '.ts', '.js'] }, output: { filename: "bundle.js", path: path.resolve(__dirname, 'dist') }, externals: [ nodeExternals() ] };
|
angular
來到前端的部分,如果要使用 socket.io 的 client 只要使用 yarn 或著 npm 照以下指令安裝相關 packages 即可
1 2 3 4 5 6 7
| # socket.io-client yarn add socket.io-client npm install --save socket.io-client
# @types/socket.io-client yarn add --dev @types/socket.io-client npm install --save-dev @types/socket.io-client
|
為了讓我們有點長的 animation 不要讓 component 的程式看起來太亂,所以我把它搬到另外一個 typescript 檔案。
基本上我們會預先定義兩個狀態,一個是 plus 另外一個是 minus 狀態,而 transition 裡面定義的就是從哪個狀態改變到另外一個狀態的時候,要撥放什麼動畫,為了營造那種閃爍的效果,所以我們定義 0.5 秒內要將畫面從透明變成紅色/綠色,再變回透明(看起來就是背景會閃一下)。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38
|
import { animate, keyframes, state, style, transition, trigger } from '@angular/animations';
export const valueChangeAnimation = trigger('state', [ state('plus', style({})), state('minus', style({})), transition( '* => plus', animate( '0.5s', keyframes([ style({ backgroundColor: 'transparent' }), style({ backgroundColor: 'green' }), style({ backgroundColor: 'transparent' }) ]) ) ), transition( '* => minus', animate( '0.5s', keyframes([ style({ backgroundColor: 'transparent' }), style({ backgroundColor: 'red' }), style({ backgroundColor: 'transparent' }) ]) ) ) ]);
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36
| import { AfterViewInit, Component } from '@angular/core'; import { valueChangeAnimation } from './models/animations'; import * as io from 'socket.io-client';
@Component({ selector: 'app-root', templateUrl: './app.component.html', styleUrls: ['./app.component.css'], animations: [valueChangeAnimation] }) export class AppComponent implements AfterViewInit { payload; state = '-'; nsp: SocketIOClient.Socket; constructor() { this.nsp = io.connect('http://localhost:8080/animation'); }
ngAfterViewInit() { this.nsp.on('random', data => { if (+this.payload > +data) { this.state = 'minus'; } else if (+this.payload < +data) { this.state = 'plus'; }
this.payload = data; }); }
handleDone(evt) { if (this.state !== '-' && this.state === evt.toState) { this.state = '-'; } } }
|
使用以上程式碼,將 angular 及 socket.io 分別執行,就可以看到自然的閃動了
參考連結