做爲一個非專業遊戲和可視化開發方向的前端,我對canvas的使用經驗是頗有限的,可是在某些狀況又須要用到canvas,好比圖片合成。 這個時候咱們一般會藉助於已有的類庫來完成咱們的需求, 好比上面提到的圖片合成需求,可使用html2canvas
來完成。 可是html2canvas的原理是將整個渲染樹給解析一遍,所以會解析不少我不須要的東西。 另外,html2canvas的性能我是不能接受的,合成一個圖片要花費數秒的時間。html
一個很直觀的方式就是使用原生canvas去寫,可是這又有以下三個問題。前端
第一是canvas對我來講的寫起來不順手。 第二是爲了跨端的能力,canvas的語法寫出來必需要在支持canvas的容器中運行。 第三是對於咱們團隊來講,有不少人不熟悉canavs,強行推可能會不順利。git
所以我動手造了一個輪子,這個輪子不只很好地解決了上面三個問題, 而且因爲其是基於編譯時聲稱可執行的代碼, 所以它在性能上也有很大的優點。github
爲了你們可以更好地理解我說的,咱們先來複習一下簡單的canavs知識, 若是已經瞭解的能夠快速看一下或者跳過。canvas
canvas元素和普通的元素看起來沒有什麼不一樣,而且canvas更加簡單,只有兩個屬性width和height。 沒有設置寬度和高度的時候,canvas會初始化寬度爲300像素和高度爲150像素。async
和其餘元素不一樣的是,canvas元素會建立一個固定大小的畫布,它公開了一個或多個渲染上下文,其能夠用來繪製和處理要展現的內容。佈局
<canvas id="tutorial" width="150" height="150"></canvas>
複製代碼
var canvas = document.getElementById('tutorial');
var ctx = canvas.getContext('2d'); // 這個方法是用來得到渲染上下文和它的繪畫功能
複製代碼
有了畫筆, 咱們就能夠畫畫了。 你須要指揮畫筆,從哪開始,畫到哪,用什麼顏色的筆。性能
function draw(canvas) {
if (canvas.getContext) {
var ctx = canvas.getContext("2d");
ctx.fillStyle = "rgb(200,0,0)"; // 筆的顏色
ctx.fillRect (10, 10, 55, 50); // 畫一個矩形
ctx.fillStyle = "rgba(0, 0, 200, 0.5)";// 筆的顏色
ctx.fillRect (30, 30, 55, 50); // 畫一個矩形
}
}
var canvas = document.getElementById("canvas");
draw(canvas)
複製代碼
看起來就是這樣的:flex
對於使用jsx2canvas來講,有了這些知識就足夠了,是否是很簡單?動畫
剛纔咱們反覆提到了圖片合成,是所以這個項目的靈感來自這個需求。那麼咱們就拿圖片合成來舉例子。 個人需求是能夠將多行圖片按照某種形式組合起來。 傳統的方式咱們能夠直接使用canvas的API去一個個繪製圖片,並本身計算佈局。 所以canavs是 沒有相似盒模型或者flex佈局這種概念的,所以須要本身去計算佈局,固然你能夠本身封裝。 還有一個問題就是層級,若是 用canvas去作的話,須要控制繪製順序來控制層級。 若是合成的動畫能夠動呢? 咱們可能還要寫邏輯來控制每一幀的變化等等。
貌似上面有不少問題,或大或小,而且均可以解決。 可是,咱們可否跳出這個思惟,用別的方式來解決這個問題呢?若是使用JSX2Canavs
會是怎麼樣呢?
若是使用JSX2Canavs
可能會是這樣的:
import { Canvas, CImage, CText, jsx2canvas } from "@duiba/jsx2canvas";
function getCTX() {
const c = document.getElementById("canvas");
return c.getContext("2d");
}
function render(commands) {
const ctx = getCTX();
commands.map(command => {
return command.run(ctx);
});
}
async function canvas({ backgroundImage, text, QRCode }) {
const commands = await (
<Canvas>
<CImage zIndex={9} center middle src={backgroundImage} />
<CText fontSize={60} center middle text={text} />
<CImage center src={QRCode} />
</Canvas>
);
return render(commands);
}
canvas({
backgroundImage: "http://www.duiba.com.cn/_nuxt/img/huan.16841d6.png",
text: "我是動態生成的文本!",
QRCode: "http://www.duiba.com.cn/_nuxt/img/cainiao.f7032a9.png"
});
複製代碼
渲染結果是:
能夠看出它實際上是將兩個圖片和一個文本按照某種佈局方式組織起來。 若是你的合成更復雜,其簡潔性和直觀性會表現地更加明顯。
倉庫地址:github.com/azl39798585… 詳細文檔你們能夠去倉庫查看。
固然這個倉庫還在alpha版本,後續會考慮加入更多的功能, 好比border
, onClick
, 動畫
等。