web技術分享|白板SDK之函式和方程式的運用

web技術分享|白板SDK之函式和方程式的運用

白板通常會提供多種工具型別,每種工具的用途也各不相同,例如下表:

web技術分享|白板SDK之函式和方程式的運用

正因此白板除了要判斷當前畫筆的工具型別的同時,還要對該工具型別在白板上的表現形式進行區分和處理,這個工作會面臨著許多的條件判斷,所以我們會藉助一些演算法來輔助我們判斷是否滿足條件,根據條件的不同執行不同的動作,從而在白板上呈現出不一樣的畫面。

比如:在白板中我們經常會用到

碰撞檢測

演算法來輔助判斷以下情況:

框選工具是否框中圖形,選中哪些圖形?

滑鼠是否選中圖形(空心形狀還是填充形狀)?

圖形是否相交/切?

等等

最終我們將這些

檢測演算法

一步步拆解下來後,會發現它們的實現會經常用到我們熟知的一些函式以及方程式:

三角函式

勾股定理

圓的標準方程式

等等,如果是動畫的話還包括

重力加速度

均速

拋物線

等等。

那麼今天我們就主要來聊聊,

函式以及方程式

在白板上的一些簡單的應用場景吧!

複習一下:什麼是直角座標系、三角函式、勾股定理、圓的標準方程式

這些函式以及方程式都應用在哪些場景?

實戰練習

直接座標系

通常我們所接觸的直角座標系的 Y 軸都是向上的,但是由於前端的渲染機制是從左上角開始,到右下角結束,因此前端座標系的 Y 軸都是向下的。

在平面內畫兩條互相垂直,並且有公共原點的數軸。其中橫軸為 X 軸,縱軸為 Y 軸。這樣我們就說在平面上建立了平面直角座標系,簡稱

直角座標系

。還分為

第一象限,第二象限,第三象限,第四象限

。從右上角開始(逆時針方向)算起。

web技術分享|白板SDK之函式和方程式的運用

勾股定理

勾股定理

,常用於數學和幾何學中,是一個基本的幾何定理,指

直角三角形的兩條直角邊的平方和等於斜邊的平方

web技術分享|白板SDK之函式和方程式的運用

公式

:a2 + b2 = c2

應用場景

在白板中我們經常使用勾股定理來:

計算兩個座標點之間的距離

計算兩形狀是否相交(切)

判斷座標是否在圓上

高階:計算物理移動的速度

三角函式

三角函式在數學這門學科中屬於

初等函式

,通常在平面直角座標系中定義。三角函式看似很複雜,也有很多公式,但都可以相互推導。在我們學習

圓的標準方程式

時,我們會發現

三角函式

結合

勾股定理

還可以推理得到

圓的標準方程式

首先,我們看一下幾個簡單又常用的三角函式在

幾何學

直角座標系

中的實現方式:

web技術分享|白板SDK之函式和方程式的運用

根據上圖,我們應該很快能浮想起:數學老師在講臺上第一次發出

sin

cos

讀法惹人發笑,復讀機式的

對邊比鄰邊,鄰邊比對邊

等一系列催眠口訣。

下面我們看一下

三角函式

的定義:任何角的集合與一個比值的集合的變數之間的對映。那麼換成我的話來講:

已知兩條邊,求兩條邊的夾角

已知一條邊和這條邊的夾角,求夾角的另一條邊

在上面的基礎上,我們要舉一反三、互相推導。

應用場景

在白板中我們經常使用三角函式來:

繪製箭頭

計算旋轉角度

圓的標準方程式

圓的兩個基本概念:

圓心

半徑

,其中圓心座標是圓的定位條件,半徑是圓的定形條件。當圓心座標和半徑確定之後,圓在直角座標系中的位置和大小也已經確定。

圓心座標為(a,b),r 為圓的半徑

公式

(x-a)²+(y-b)²=r²

應用場景

在白板中我們經常使用圓的標準方程式來

判斷座標是否在圓上

實戰練習

針對上面幾個函式以及表示式,為了避免過於幹,下面我舉了幾個例子,大家也可以舉一反三,慢慢推導:

計算兩個圖形是否相交(切)

繪製箭頭

筆鋒(簽字筆、鋼筆、毛筆)

通常我們會結合多個函式以及方程式相互配合去實現一個功能或者實現一個演算法。例如筆鋒,我們就需要結合物理學的速度計算公式以及數學的勾股定理計算兩點的(平面直接座標系中的)距離。

計算兩個圖形是否相交(切)

白板相交判斷通常有兩種:一種是

外接矩形判定法

,另一種是

外接圓形判定法

。為了保證真實性,我們通常會將近似圓的圖形使用

外接圓形判定法

,否則使用

外接矩形判定法

外接矩形判定法

外接圓形判定法

都可以使用

中心判定法

來實現,不同的是:

圓形只需要判斷

兩個圓心之間的距離是否小於兩圓半徑之和

web技術分享|白板SDK之函式和方程式的運用

矩形則需要判斷兩個矩形中心點的:x 軸的距離是否小於兩矩形寬度之和的 1 / 2y 軸的距離是否小於兩個矩形高度之和的 1 / 2

中心判定法

的本質是

計算兩點(中心)之間的距離

繪製箭頭

繪製箭頭,我們需要用到

勾股定理

三角函式

這裡我們以在直線末端繪製箭頭為例,下面是它的實現步驟:

第一步,我們需要繪製一條直線,從 A(x0, y0) 點到 B(x1, y1) 點

第二步,設定箭頭的長度

headlen

和箭頭與之前的夾角

θ

第三步,計算這條線與 X 軸正方向的夾角

web技術分享|白板SDK之函式和方程式的運用

這裡我們使用 atan2 (

https://developer。mozilla。org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Math/atan2

)函式,該函式可以計算出從原點 (0,0) 到 (x,y) 點的線段與 x 軸正方向之間的平面角度(弧度值)。

我們將 A(x0, y0) 看做是原點 (0, 0),也就是從原點 A(x0, y0) 到 B(x1, y1) 點的線段與 x 軸正方向之間的平面角度(弧度值),然後將其轉換成度數。

// 將弧度制轉換成度數

const angle = Math。atan2(y1 - y0, x1 - x0) * 180 / Math。PI;

第四步,推理出箭頭左右(上下)兩側斜線與 X 軸正方向的夾角

根據步驟三我們可以算出箭頭兩側的斜線與 x 軸正方向之間的平面角度(弧度值),已知箭頭與直線的夾角

θ

是固定的,另外已知直線與 X 軸正方向的夾角,只需要減去或者加上

θ

就是箭頭兩側的斜線與 x 軸正方向之間的平面角度。

大家可以在箭頭末端作出延伸線(如下圖),箭頭上邊(下圖左邊)的夾角為

π + α - θ

,箭頭下邊(圖右邊)的夾角為

π + α + θ

web技術分享|白板SDK之函式和方程式的運用

下面是程式碼示例:

// 箭頭的左側夾角

const angle1 = (angle - theta) * Math。PI / 180;

// 箭頭的右側夾角

const angle2 = (angle + theta) * Math。PI / 180;

// 計算出右側箭頭的座標點

const topX = headlen * Math。cos(angle1);

const topY = headlen * Math。sin(angle1);

// 計算出左側箭頭的座標點

const botX = headlen * Math。cos(angle2);

const botY = headlen * Math。sin(angle2);

最終,我們計算出了箭頭的 2 個關鍵座標:

(topx, topy)

(botx, boty)

。更詳細的介紹請移步這裡(

https://www。dbp-consulting。com/tutorials/canvas/CanvasArrow。html

)。

筆鋒

在開始介紹之前,我推薦一個第三方庫

points-on-curve

,它會將一系列的座標點轉換成很好看到筆鋒(svg 或者 canvas),還提供很多豐富的配置,詳情點選(

https://www。npmjs。com/package/points-on-curve

)。

下面我們講講筆鋒的實現方式,其中最常見的步驟大致為:

落點是個圓形

透過計算畫筆移動的距離和時間得到畫筆的速度,透過速度的快慢來設定畫筆的粗細

使用

二次貝塞爾曲線

或者

三次貝塞爾曲線

進行繪製

收筆畫筆粗細慢慢變細(可以根據筆的型別:鋼筆、毛筆、簽字筆等自由發揮)

這裡我們只闡述如果簡單的實現筆鋒效果,關於更多的實現方式在文末的參考文獻中也有提供。下面我們一起來看看如何實現從 A(x0, y0) 點到 B(x1, y1) 點來繪製筆鋒。

第一步,透過

勾股定理

計算出 AB 兩點之間的距離

// 計算兩點 X 軸上的距離

const x = x1 - x0;

// 計算兩點 Y 軸上的距離

const y = y1 - y0;

// 計算兩點的直線距離

const s = Math。sqrt(Math。pow(x, 2) + Math。pow(y, 2));

第二步,透過

速度計算公式

計算出兩點之前移動的速度

一般白板中我們會記錄每個座標繪製的時間,因此我們可以很輕易的計算出 A 到 B 的耗時

t

,套用速度計算公式,我們就可以計算出,A 到 B 繪製的速度

v

// 速度計算公式

速度 v = 距離 s / 時間 t

第三步,根據速度快慢來調整畫筆的粗細

最後我們根據速度的快慢,然後根據可變的速度比例,計算出速度在多少以下變粗,多少以下變細。

其他

除了以上我介紹的一些場景,白板還有其他的很多場景,例如:

圖形旋轉 - 使用

矩陣轉換

的公式

動畫 - 拋物線、勻速運動,加速運動,重力加速

等等

本文的目的只是一個入門的介紹,雖然大多都是講一些在 2D 平面上的運用,但是在 3D 緯度上有些知識也還是受用的,想必有些同學已經磨手擦掌準備躍躍欲試了 ,歡迎留言、轉發加評論。

參考文獻

直角座標系 - 百度百科(

https://baike。baidu。com/item/%E7%9B%B4%E8%A7%92%E5%9D%90%E6%A0%87%E7%B3%BB/1835293?fr=aladdin

三角函式 - 百度百科(

https://baike。baidu。com/item/%E4%B8%89%E8%A7%92%E5%87%BD%E6%95%B0%E5%85%AC%E5%BC%8F/4374733?fr=aladdin#ref_[4]_959840

勾股定理 - 百度百科(

https://baike。baidu。com/item/%E5%8B%BE%E8%82%A1%E5%AE%9A%E7%90%86/91499

圓的標準方程式 - 百度百科(

https://baike。baidu。com/item/%E5%9C%86%E7%9A%84%E6%A0%87%E5%87%86%E6%96%B9%E7%A8%8B/3723940

箭頭的繪製(

https://www。dbp-consulting。com/tutorials/canvas/CanvasArrow。html

筆鋒(https://www。cnblogs。com/zl03jsj/p/8048102。html)

web技術分享|白板SDK之函式和方程式的運用