国产xxxx99真实实拍_久久不雅视频_高清韩国a级特黄毛片_嗯老师别我我受不了了小说

資訊專欄INFORMATION COLUMN

fc-whiteboard,支持鏡像、錄播、回放的 Web 電子白板

paulquei / 3204人閱讀

摘要:而關(guān)鍵幀事件,則會(huì)在每一次界面變動(dòng)時(shí)觸發(fā)該事件內(nèi)建了,但仍然會(huì)有比較多的數(shù)目。關(guān)鍵幀事件的定義如下當(dāng)前事件觸發(fā)者的譬如當(dāng)某個(gè)發(fā)生移動(dòng)時(shí)候,其會(huì)觸發(fā)如下的事件僅在與級(jí)別提供了事件的響應(yīng),而在與級(jí)別提供了事件的觸發(fā)。

fc-whiteboard,支持鏡像、錄播、回放的 Web 電子白板

在很多培訓(xùn)、協(xié)作、在線演講的場景下,我們需要有電子白板的功能,能夠方便地在演講者與聽眾之間共享屏幕、繪制等信息。fc-whiteboard https://parg.co/NiK 是 Web 在線白板組件庫,支持實(shí)時(shí)直播(一對(duì)多)與回放兩種模式,其繪制版也能夠獨(dú)立使用。fc-whiteboard 內(nèi)置了 EventHub,只需要像 Mushi-Chat 這樣提供簡單的 WebSocket 服務(wù)端,即可快速構(gòu)建實(shí)時(shí)在線共享電子白板。

Usage | 使用 Whiteboard live mode | 直播模式

直播模式的效果如下圖所示:

示例代碼請(qǐng)參考 Code Sandbox,或者直接查看 Demo;

import { EventHub, Whiteboard, MirrorWhiteboard } from "fc-whiteboard";

// 構(gòu)建消息中間件
const eventHub = new EventHub();

eventHub.on("sync", (changeEv: SyncEvent) => {
  console.log(changeEv);
});

const images = [
  "https://upload-images.jianshu.io/upload_images/1647496-6bede989c09af527.jpg?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240",
  "http://upload-images.jianshu.io/upload_images/1647496-d281090a702045e5.jpg?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240",
  "http://upload-images.jianshu.io/upload_images/1647496-611a416be07d7ca3.jpg?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240"
];

// 初始化演講者端
const whiteboard = new Whiteboard(
  document.getElementById("root") as HTMLDivElement,
  {
    sources: images,
    eventHub,
    // Enable this option to disable incremental sync, just use full sync
    onlyEmitSnap: false
  }
);

whiteboard.open();

// 初始化鏡像端,即觀眾端
const mirrorWhiteboard = new MirrorWhiteboard(
  document.getElementById("root-mirror") as HTMLDivElement,
  {
    sources: images,
    eventHub
  }
);

mirrorWhiteboard.open();
WebSocket 集成

WebSocket 天然就是以事件驅(qū)動(dòng)的消息通信,fc-whiteboard 內(nèi)部對(duì)于消息有比較好的封裝,我們建議使用者直接將消息透傳即可:

const wsEventHub = new EventEmitter();

if (isPresenter) {
  wsEventHub.on("sync", data => {
    if (data.event === "finish") {
      // 多帶帶處理結(jié)束事件
      if (typeof callback === "function") {
        callback();
      }
    }
    const msg = {
      from: `${currentUser.id}`,
      type: "room",
      to: `${chatroom.room_id}`,
      msg: {
        type: "cmd",
        action: "whiteboard/sync",
        message: JSON.stringify(data)
      }
    };
    socket.sendMessage(msg);
  });
} else {
  socket.onMessage(([data]) => {
    const {
      msg: { type, message }
    } = data;

    if (type === "whiteboard/sync") {
      wsEventHub.emit("sync", JSON.parse(message));
    }
  });
}
Whiteboard replay mode | 回放模式

fc-whiteboard 還支持回訪模式,即我們可以將某次白板操作錄制下來,可以一次性或者分批將事件傳遞給 ReplayWhiteboard,它就會(huì)按序播放:

import { ReplayWhiteboard } from "fc-whiteboard";
import * as events from "./events.json";

let hasSend = false;

const whiteboard = new ReplayWhiteboard(document.getElementById(
  "root"
) as HTMLDivElement);

whiteboard.setContext(events[0].timestamp, async (t1, t2) => {
  if (!hasSend) {
    hasSend = true;
    return events as any;
  }

  return [];
});

whiteboard.open();

The persistent events are listed as follow:

事件的基本結(jié)構(gòu)如下所示,具體的事件類別我們會(huì)在下文介紹:

[
  {
    "event": "borderSnap",
    "id": "08e65660-6064-11e9-be21-fb33250b411f",
    "target": "whiteboard",
    "border": {
      "id": "08e65660-6064-11e9-be21-fb33250b411f",
      "sources": [
        "https://upload-images.jianshu.io/upload_images/1647496-6bede989c09af527.jpg?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240",
        "http://upload-images.jianshu.io/upload_images/1647496-d281090a702045e5.jpg?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240",
        "http://upload-images.jianshu.io/upload_images/1647496-611a416be07d7ca3.jpg?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240"
      ],
      "pageIds": [
        "08e65661-6064-11e9-be21-fb33250b411f",
        "08e6a480-6064-11e9-be21-fb33250b411f",
        "08e6cb91-6064-11e9-be21-fb33250b411f"
      ],
      "visiblePageIndex": 0,
      "pages": [
        { "id": "08e65661-6064-11e9-be21-fb33250b411f", "markers": [] },
        { "id": "08e6a480-6064-11e9-be21-fb33250b411f", "markers": [] },
        { "id": "08e6cb91-6064-11e9-be21-fb33250b411f", "markers": [] }
      ]
    },
    "timestamp": 1555431837
  }
  ...
]
Use drawboard alone | 多帶帶使用 Drawboard

Drawboard 也可以多帶帶使用作為畫板,整體可以被導(dǎo)出為圖片:

import { Drawboard } from "fc-whiteboard/src";

const d = new Drawboard({
  imgEle: document.getElementById("root") as HTMLImageElement
});

d.open();
內(nèi)部設(shè)計(jì)

fc-whiteboard 的內(nèi)部組件級(jí)別,依次是 WhiteBoard, WhitePage, Drawboard 與 Marker,本節(jié)即介紹內(nèi)部設(shè)計(jì)與實(shí)現(xiàn)。

Draw System | 繪制系統(tǒng)

繪制能力最初改造自 markerjs,在 Drawboard 中提供了基礎(chǔ)的畫板,即 boardCanvas 與 boardHolder,后續(xù)的所有 Marker 即掛載于 boardCanvas 中,并相對(duì)于其進(jìn)行絕對(duì)定位。當(dāng)我們添加某個(gè) Marker,即執(zhí)行以下步驟:

const marker = markerType.createMarker(this.page);

this.markers.push(marker);
this.selectMarker(marker);
this.boardCanvas.appendChild(marker.visual);

// 定位
marker.moveTo(x, y);

目前 fc-whiteboard 中內(nèi)置了 ArrowMarker, CoverMarker, HighlightMarker, LineMarker, TextMarker 等多種 Marker:

export class BaseMarker extends DomEventAware {
  id: string = uuid();
  type: MarkerType = "base";
  // 歸屬的 WhitePage
  page?: WhitePage;
  // 歸屬的 Drawboard
  drawboard?: Drawboard;
  // Marker 的屬性發(fā)生變化后的回調(diào)
  onChange: onSyncFunc = () => {};

  // 其他屬性
  // ...

  public static createMarker = (page?: WhitePage): BaseMarker => {
    const marker = new BaseMarker();
    marker.page = page;
    marker.init();
    return marker;
  };

  // 響應(yīng)事件變化
  public reactToManipulation(
    type: EventType,
    { dx, dy, pos }: { dx?: number; dy?: number; pos?: PositionType } = {}
  ) {
    //  ...
  }

  /** 響應(yīng)元素視圖狀態(tài)變化 */
  public manipulate = (ev: MouseEvent) => {
    // ...
  };

  public endManipulation() {
    // ...
  }

  public select() {
    // ...
  }

  public deselect() {
    // ...
  }

  /** 生成某個(gè)快照 */
  public captureSnap(): MarkerSnap {
    // ...
  }

  /** 應(yīng)用某個(gè)快照 */
  public applySnap(snap: MarkerSnap): void {
    // ...
  }

  /** 移除該 Marker */
  public destroy() {
    this.visual.style.display = "none";
  }

  protected resize(x: number, y: number, cb?: Function) {
    return;
  }
  protected resizeByEvent(x: number, y: number, pos?: PositionType) {
    return;
  }

  public move = (dx: number, dy: number) => {
    // ...
  };

  /** Move to relative position */
  public moveTo = (x: number, y: number) => {
    // ...
  };

  /** Init base marker */
  protected init() {
    // ...
  }

  protected addToVisual = (el: SVGElement) => {
    this.visual.appendChild(el);
  };

  protected addToRenderVisual = (el: SVGElement) => {
    this.renderVisual.appendChild(el);
  };

  protected onMouseDown = (ev: MouseEvent) => {
    // ...
  };

  protected onMouseUp = (ev: MouseEvent) => {
    // ...
  };

  protected onMouseMove = (ev: MouseEvent) => {
    // ...
  };
}

這里關(guān)于 Marker 的內(nèi)部實(shí)現(xiàn)可以參考具體的 Marker,另外值得一提的是,想 LinearMarker, 或者 RectangleMarker 中,其需要響應(yīng)對(duì)關(guān)鍵點(diǎn)拖拽引發(fā)的伸縮事件,這里的拖拽點(diǎn)是自定義的 Grip 組件。

Event System | 事件系統(tǒng)

事件系統(tǒng),最基礎(chǔ)的理解就是用戶的任何操作都會(huì)觸發(fā)事件,也可以通過外部傳入某個(gè)事件的方式來觸發(fā)白板的界面變化。事件類型分為 Snapshot(snap)與 Key Actions(ka)兩種。

首先是 Snapshot 事件,即快照事件;快照會(huì)記錄完整的狀態(tài),整個(gè)白板可以從快照中快速恢復(fù)。白板級(jí)別的快照如下:

{
  id: this.id,
  sources: this.sources,
  pageIds: this.pages.map(page => page.id),
  visiblePageIndex: this.visiblePageIndex,
  pages: this.pages.map(p => p.captureSnap())
}

如果是 Shallow 模式,則不會(huì)下鉆到具體的頁面的快照。頁面的快照即是 Marker 快照構(gòu)成,每個(gè) Marker 的快照則是樸素對(duì)象:

{
  id: this.id,
  type: this.type,
  isActive: this.isActive,
  x: this.x,
  y: this.y
}

一般來說,Whiteboard 會(huì)定期分發(fā)快照,可以通過 snapInterval 來控制間隔。而關(guān)鍵幀事件,則會(huì)在每一次界面變動(dòng)時(shí)觸發(fā);該事件內(nèi)建了 Debounce,但仍然會(huì)有比較多的數(shù)目。因此可以通過 onlyEmitSnap 來控制是否僅使用快照事件來同步。

關(guān)鍵幀事件的定義如下:

export interface SyncEvent {
  target: TargetType;

  // 當(dāng)前事件觸發(fā)者的 ID
  id?: string;
  parentId?: string;
  event: EventType;
  marker?: MarkerData;
  border?: WhiteboardSnap;
  timestamp?: number;
}

譬如當(dāng)某個(gè) Marker 發(fā)生移動(dòng)時(shí)候,其會(huì)觸發(fā)如下的事件:

this.onChange({
  target: "marker",
  id: this.id,
  event: "moveMarker",
  marker: { dx, dy }
});

僅在 WhiteBoard 與 WhitePage 級(jí)別提供了事件的響應(yīng),而在 Drawboard 與 Marker 級(jí)別提供了事件的觸發(fā)。

延伸閱讀

您可以通過以下任一方式閱讀筆者的系列文章,涵蓋了技術(shù)資料歸納、編程語言與理論、Web 與大前端、服務(wù)端開發(fā)與基礎(chǔ)架構(gòu)、云計(jì)算與大數(shù)據(jù)、數(shù)據(jù)科學(xué)與人工智能、產(chǎn)品設(shè)計(jì)等多個(gè)領(lǐng)域:

在 Gitbook 中在線瀏覽,每個(gè)系列對(duì)應(yīng)各自的 Gitbook 倉庫。

Awesome Lists Awesome CheatSheets Awesome Interviews Awesome RoadMaps Awesome-CS-Books-Warehouse
編程語言理論 Java 實(shí)戰(zhàn) JavaScript 實(shí)戰(zhàn) Go 實(shí)戰(zhàn) Python 實(shí)戰(zhàn) Rust 實(shí)戰(zhàn)
軟件工程、數(shù)據(jù)結(jié)構(gòu)與算法、設(shè)計(jì)模式、軟件架構(gòu) 現(xiàn)代 Web 開發(fā)基礎(chǔ)與工程實(shí)踐 大前端混合開發(fā)與數(shù)據(jù)可視化 服務(wù)端開發(fā)實(shí)踐與工程架構(gòu) 分布式基礎(chǔ)架構(gòu) 數(shù)據(jù)科學(xué),人工智能與深度學(xué)習(xí) 產(chǎn)品設(shè)計(jì)與用戶體驗(yàn)

文章版權(quán)歸作者所有,未經(jīng)允許請(qǐng)勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。

轉(zhuǎn)載請(qǐng)注明本文地址:http://specialneedsforspecialkids.com/yun/105664.html

相關(guān)文章

  • Radio Dream流媒體直播平臺(tái)基于Docker應(yīng)用

    摘要:支持等主流流媒體格式。控制中心會(huì)給直播服務(wù)器這些信息,直播服務(wù)器調(diào)用自身的直播流,分發(fā)到各個(gè)切片服務(wù)器。自動(dòng)化運(yùn)維故障恢復(fù)這部分主要是監(jiān)控推流,和切片,以及直播源是否正常。 本文整理自【時(shí)速云微信群線上分享】第十一期 首先介紹一下背景,Radio Dream項(xiàng)目是一個(gè)開源項(xiàng)目,前身為五雷轟頂網(wǎng)絡(luò)電臺(tái),這個(gè)項(xiàng)目是我個(gè)人逐漸打磨了將近兩年,最開始是因?yàn)樨垞渚W(wǎng)絡(luò)電臺(tái)停播,我個(gè)人是貓撲電臺(tái)的老...

    aboutU 評(píng)論0 收藏0
  • 全方面了解超寬帶信號(hào)高速采集記錄回放系統(tǒng)

    摘要:超寬帶信號(hào)高速采集記錄回放系統(tǒng)特點(diǎn)超寬帶信號(hào)采集記錄存儲(chǔ)與回放,用于實(shí)驗(yàn)數(shù)據(jù)事后分析及外場環(huán)境重建。超寬帶信號(hào)高速采集記錄存儲(chǔ)回放系統(tǒng)基于高性能及協(xié)議,實(shí)現(xiàn)標(biāo)準(zhǔn)化模塊化可擴(kuò)展可重構(gòu)的超寬帶信號(hào)高速連續(xù)采集記錄回放產(chǎn)生平臺(tái)。 超寬帶高速記錄回放系統(tǒng) 超寬帶信號(hào)高速采集記錄存儲(chǔ)回放系統(tǒng)主要用于對(duì)...

    nanchen2251 評(píng)論0 收藏0
  • 全方位了解超寬帶信號(hào)高速采集記錄回放系統(tǒng)

    摘要:超寬帶信號(hào)高速采集記錄回放系統(tǒng)特點(diǎn)超寬帶信號(hào)采集記錄存儲(chǔ)與回放,用于實(shí)驗(yàn)數(shù)據(jù)事后分析及外場環(huán)境重建。超寬帶信號(hào)高速采集記錄存儲(chǔ)回放系統(tǒng)基于高性能及協(xié)議,實(shí)現(xiàn)標(biāo)準(zhǔn)化模塊化可擴(kuò)展可重構(gòu)的超寬帶信號(hào)高速連續(xù)采集記錄回放產(chǎn)生平臺(tái)。 超寬帶高速記錄回放系統(tǒng) 超寬帶信號(hào)高速采集記錄存儲(chǔ)回放系統(tǒng)主要用于對(duì)...

    Jaden 評(píng)論0 收藏0
  • 新一代智能視頻云發(fā)展現(xiàn)狀分析:五大要素成關(guān)鍵

    摘要:遠(yuǎn)程醫(yī)療這一概念被提出后,已經(jīng)被廣泛應(yīng)用。但是,如何提高視頻傳輸性能,如何確保家庭基層醫(yī)療機(jī)構(gòu)和戶外應(yīng)急的遠(yuǎn)程醫(yī)療快速接入,是當(dāng)前的遠(yuǎn)程醫(yī)療業(yè)務(wù)系統(tǒng)面臨的主要挑戰(zhàn)。 編者按:近日,Gartner最新發(fā)布了一份《Five Key Essentials for the New Generation of Intelligent Video Cloud》白皮書報(bào)告,報(bào)告中針對(duì)各行業(yè)在視頻應(yīng)用...

    levy9527 評(píng)論0 收藏0
  • 在線教育開發(fā)實(shí)踐(一):實(shí)時(shí)視頻與白板教學(xué)

    摘要:本系列的第一篇文章,筆者分享了在瀏覽器端,結(jié)合聲網(wǎng)的實(shí)時(shí)音視頻互動(dòng)能力與的在線白板能力,來實(shí)現(xiàn)一個(gè)簡單但實(shí)用的在線教室。一引入音視頻音視頻方案選擇聲網(wǎng)作為本次的技術(shù)方案,先從下載聲網(wǎng)最新的備用。 作者:maverick、buhe,本文首發(fā)于 RTC 開發(fā)者社區(qū) 隨著技術(shù)和基礎(chǔ)設(shè)施的進(jìn)一步演進(jìn),線下的教育、會(huì)議已有很大比重演進(jìn)為線上的教育和會(huì)議,突破了空間的桎梏。需求的多樣性爆發(fā)增長和...

    Kahn 評(píng)論0 收藏0

發(fā)表評(píng)論

0條評(píng)論

最新活動(dòng)
閱讀需要支付1元查看
<