天天看點

JavaScript 之 canvas(五)-- 橢圓、橡皮

原文位址: https://www.jeremyjone.com/490/, 轉載請注明。

橢圓

通過前面的文章,我們已經可以繪制大部分圖形以及文字。但是,在

canvas

中,橢圓是一個複雜的存在,本身我們上學時學習橢圓本身也是一個複雜的結構。我看了很多畫橢圓的方案,大部分分為兩類:

  • 第一類是 使用

    arc()

    畫一個圓形,然後将其縮放變形,完成一個橢圓。
  • 第二類是 使用貝塞爾曲線,即使用多條貝塞爾曲線混合拼接為一個橢圓。

經過我的實際測試,采用我認為比較簡單并且顯示效果比較好的方式,使用貝塞爾曲線的方式繪制橢圓。

剛才說過,貝塞爾的方式是使用多條曲線拼接,一個橢圓可以是兩條曲線、三條曲線,或四條甚至更多曲線拼接。我這裡使用兩條就夠了,而且很大程度減少我們的計算量。

關于貝塞爾曲線

貝塞爾曲線(Bézier curve),又稱貝茲曲線或貝濟埃曲線,是應用于二維圖形應用程式的數學曲線。

canvas

中,使用

bezierCurveTo()

方法來繪制貝塞爾曲線,該方法通過使用表示三次貝塞爾曲線的指定控制點,向目前路徑添加一個點。

  • 提示:三次貝塞爾曲線需要三個點。前兩個點是用于三次貝塞爾計算中的控制點,第三個點是曲線的結束點。曲線的開始點是目前路徑中最後一個點。如果路徑不存在,那麼請使用 beginPath() 和 moveTo() 方法來定義開始點。
JavaScript 之 canvas(五)-- 橢圓、橡皮

** 以上摘自HTML5 canvas bezierCurveTo()方法說明

通過貝塞爾曲線繪制橢圓

通過上圖,我們可以清楚看到繪制一條貝塞爾曲線的基本要素。

是以,我們的橢圓應該大緻如下(純滑鼠繪制,别吐~ ~ ~):

JavaScript 之 canvas(五)-- 橢圓、橡皮

從圖中可以看到,橢圓可以被分成兩條貝塞爾曲線,我們隻需要找到對應的點即可。計算過程忽略,直接看代碼(代碼已經經過位置計算的優化,看上去更像使用滑鼠點選的起始點到結束點的橢圓):

let k = ((x2 - x1) / 0.55);
let w = (x2 - x1) / 2;
let h = (y2 - y1) / 2;

// bezier double ellipse algorithm
context.moveTo(x1, y1 + h);
context.bezierCurveTo(x1, y1 + h * 3, x1 + w * 11 / 5, y1 + h * 3, x1 + w * 11 / 5, y1 + h);
context.bezierCurveTo(x1 + w * 11 / 5, y1 - h, x1, y1 - h, x1, y1 + h);
context.stroke();
           

效果:

JavaScript 之 canvas(五)-- 橢圓、橡皮

這樣就繪制出了一個比較完美的橢圓。

橡皮擦

在canvas中,有三個繪制圖形函數,分别是

fillRect()

strokeRect()

clearRect()

,分别是填充圖形,空心矩形,和清除矩形,前面兩個函數我們已經使用過。最後的函數通常:

clearRect(0, 0, canvas.width, canvas.height)
           

可以完成清屏的功能。

我們如果想要達到橡皮擦的功能,該如何操作呢?

JavaScript 之 canvas(五)-- 橢圓、橡皮

其實原理是一樣的,隻不過,我們需要先固定住我們需要修改的圖檔。

context.arc(x1, y1, 10, 0, 2 * Math.PI);  // 畫一個圓形,位置即滑鼠目前位置,大小就是橡皮擦的半徑大小,當然,也可以不适用圓形,任意形狀的橡皮擦都可以。
context.clip();  // 這句很重要,它可以将上面一句定義的形狀,從目前畫布中剪切出來單獨操作,如果沒有這一句,那麼一會操作的仍然是整幅畫布。
context.clearRect(0, 0, canvas.width, canvas.height);  // 這句很簡單,和剛才的清空示例是一樣的。
self.X1 = self.X2;
self.Y1 = self.Y2;
           

是以,它的整體邏輯分三步:

定義橡皮擦的大小和形狀,通常我們定義為圓形。
固定畫闆,将橡皮擦的内容單獨剪切出來。
清空剪切出來的内容,就完成了橡皮功能。
           

是不是很簡單,當然,需要注意的是,随後不要忘記和随心畫一樣,實時修改傳入的坐标,達到連續擦出的效果。

這樣,簡單的橡皮功能也完成了。

完整的内容已經更新在了我的github - canvasPaint中,您也可以通過我的示例來測試一下功能。

前期目錄:

JavaScript 之 canvas(一)-- 認識canvas

JavaScript 之 canvas(二)-- 繪制基本圖形

JavaScript 之 canvas(三)-- 使用滑鼠實時繪制圖形

JavaScript 之 canvas(四)-- 繪制文字

繼續閱讀