<ruby id="bdb3f"></ruby>

    <p id="bdb3f"><cite id="bdb3f"></cite></p>

      <p id="bdb3f"><cite id="bdb3f"><th id="bdb3f"></th></cite></p><p id="bdb3f"></p>
        <p id="bdb3f"><cite id="bdb3f"></cite></p>

          <pre id="bdb3f"></pre>
          <pre id="bdb3f"><del id="bdb3f"><thead id="bdb3f"></thead></del></pre>

          <ruby id="bdb3f"><mark id="bdb3f"></mark></ruby><ruby id="bdb3f"></ruby>
          <pre id="bdb3f"><pre id="bdb3f"><mark id="bdb3f"></mark></pre></pre><output id="bdb3f"></output><p id="bdb3f"></p><p id="bdb3f"></p>

          <pre id="bdb3f"><del id="bdb3f"><progress id="bdb3f"></progress></del></pre>

                <ruby id="bdb3f"></ruby>

                ThinkChat2.0新版上線,更智能更精彩,支持會話、畫圖、視頻、閱讀、搜索等,送10W Token,即刻開啟你的AI之旅 廣告
                :-: **介紹一** [TOC] ![來自http://fabricjs.com](https://github.com/kangax/fabric.js/raw/master/lib/screenshot.png =400x400) `Fabric.js`是一款可以更簡便的操作`HTML5 canvas`畫布的強大的`javascript`庫;`Fabric`提供了對象模型,`svg`解析器,交互層以及一整套完整的工具組件.基于`MIT`協議完全開源,每年都有很多開發者參與貢獻. ### Why? 首先,`Canvas`現在允許我們創造強大的圖形界面.但是`API`可能比較差強人意.我們很容易忘記它們,即便是要畫一些基本的形狀,更何況各種交互,更換圖片或者更復雜的形狀. `Fabric`的目的就是解決這些問題. 原生的`canvas`方法只允許我們觸發簡單的圖形命令,然后盲目地修改整個畫布; 取代了如此`low`的方法,`Fabric`在原生基礎上提供了簡單且強大的對象模型.它負責畫布的狀態和渲染,而我們直接面向對象. 下面是一些示例: > 使用canvas API ```js // reference canvas element (with id="c") var canvasEl = document.getElementById('c'); // get 2d context to draw on (the "bitmap" mentioned earlier) var ctx = canvasEl.getContext('2d'); // set fill color of context ctx.fillStyle = 'red'; // create rectangle at a 100,100 point, with 20x20 dimensions ctx.fillRect(100, 100, 20, 20); ``` > 使用`Fabric.js` ```js // create a wrapper around native canvas element (with id="c") var canvas = new fabric.Canvas('c'); // create a rectangle object var rect = new fabric.Rect({ left: 100, top: 100, fill: 'red', width: 20, height: 20 }); // "add" rectangle onto canvas canvas.add(rect); ``` > 效果圖 ![](http://fabricjs.com/article_assets/1.png =300x300) 在這點上,從代碼量上看幾乎沒有差別-上述兩個例子基本相同。但是你已經發現了在使用`canvas`上的差別了。原生方法中,我們操作代表整個`canvas`位圖的對象`context`,而在`fabric`中我們操作對象去實例化它們,改變它們的屬性,然后將它們添加到`canvas`中去。由此可見,`fabric`是面向對象的。 上述渲染一個紅色的矩形略顯無聊,下面我們來進行一些有趣的操作,比方說輕微的旋轉一下? > 先看原生的方法 ```js var canvasEl = document.getElementById('c'); var ctx = canvasEl.getContext('2d'); ctx.fillStyle = 'red'; ctx.translate(100, 100); ctx.rotate(Math.PI / 180 * 45); ctx.fillRect(-10, -10, 20, 20); ``` > 我們使用`fabric` ```js var canvas = new fabric.Canvas('c'); // create a rectangle with angle=45 var rect = new fabric.Rect({ left: 100, top: 100, fill: 'red', width: 20, height: 20, angle: 45 }); canvas.add(rect); ``` ![](http://fabricjs.com/article_assets/2.png =300x300) 我們在`fabric`中只需要改變`angle`到45度即可,使用原生的方法,事情反而不是那么有趣了。首先我們得記住不能直接操作對象,我們通過操作`canvas`的上下文對象來改變位置,調整角度以滿足我們的需求。接著我們畫矩形,記住偏移位置,讓其可以在準確的點渲染出來。額外地,我們還得將旋轉度數轉為弧度。 下面我們看下其他的例子,如何跟蹤記錄`canvas`的狀態。 如果現在我們要將熟悉的紅色矩形移動到`canvas`上的另外一個位置,該怎么辦呢?我們如何不操作對象來實現呢?我們是在畫布上再調用一個`fillRect`方法嗎? 不完全正確!重新調用另一個`fillRect`命令其實是在原先的矩形上再繪制一個矩形。就像畫畫一樣,為了移動它,我們需要先擦掉之前畫的矩形,再在一個新的位置畫一個矩形。 ```js var canvasEl = document.getElementById('c'); ... ctx.strokRect(100, 100, 20, 20); ... // erase entire canvas area ctx.clearRect(0, 0, canvasEl.width, canvasEl.height); ctx.fillRect(20, 50, 20, 20); ``` > `fabric`怎么做的呢? ```js var canvas = new fabric.Canvas('c'); ... canvas.add(rect); ... rect.set({ left: 20, top: 50 }); canvas.renderAll(); ``` 注意到這個變化,在使用`fabric`的時候我們不再需要在我們嘗試修改任何內容的時候,先擦拭掉內容。我們仍然只需要改變對象的屬性達到刷新視圖的目的。 ### Objects 我們已經知道了如何實例化`fabric.Rect`構造函數來畫矩形了。`fabric`自然也提供了其他基礎形狀的構造器了--圓,三角,橢圓等等。它們都是通過`fabric`下的命名空間導出的,例如`fabric.Circle`,`fabric.Triangle`,`fabric.Ellipse`。 `Fabric`提供了7種基本圖形的接口 * `farbic.Circle` * `fabric.Ellipse` * `fabric.Line` * `farbic.Polygon` * `fabric.Polyline` * `fabric.Rect` * `fabric.Triangle` 下面給些示例: ```js var circle = new fabric.Circle({ radius: 20, fill: 'green', left: 100, top: 100 }); var triangle = new fabric.Triangle({ width: 20, height: 30, fill: 'blue', left: 50, top: 50 }); canvas.add(circle, triangle); ``` ![](http://fabricjs.com/article_assets/4.png =300x300) #### 對象操作 以上還僅僅只是個開始,事實上,我們更希望能夠修改這些對象。可能是一些狀態改變的響應,或者是一些不同的動畫。或者我們想在某些鼠標事件下改變對象的屬性(顏色,透明度,尺寸,位置)。 `Fabric`幫助我們解決了畫布的繪制和狀態管理,我們僅僅需要操作這些對象即可。 在此之前,我們使用`set`方法證明了,如何通過方法`set({left:20,top:50})`來移動一個對象。類似的,我們還可以改變對象的其他屬性。那些屬性呢? 顯而易見,你也可以猜到,定位屬性——`top,left`,尺寸屬性——`width,height`,繪制屬性——`fill,opacity,stroke,strokeWidth`,縮放和旋轉屬性——`scaleX,scaleY,angle`,還有翻轉屬性`flipX,flipY`,彎曲屬性——`skewX,skewY`。 是的,創建翻轉元素在`Fabric`中就是如此容易,只需要設置`flip*`屬性為`true`。你可以通過`set`來設置這些屬性,通過`get`來獲取這些屬性。下面看個栗子: ```js var canvas = new fabric.Canvas('c'); ... canvas.add(rect); rect.set('fill', 'red'); rect.set({ strokeWidth: 5, stroke: 'rgba(100,200,200,0.5)' }); rect.set('angle', 15).set('flipY', true); ``` ![](http://fabricjs.com/article_assets/5.png) 分析下上面的代碼,首先我們通過設置`fill`的值為`red`,就是將對象填充為紅色。然后設置`strokeWidth和stroke`的值,得到了一個5px的綠色外邊框。最后我們改變了`angle`和`flipY`的值。 但請注意上面三行代碼之間細微的語法差別。 `set`方法是我們常用的方法,這樣定義是非常方便使用的。 與之對應,`get`方法也是獲取屬性值最方便的方法了。例如`get('width')或getWidth()`。 當然我們也可以之間定義個全量的對象,賦值為`set`方法 ```js var rect = new fabric.Rect({ width: 10, height: 20, fill: '#f55', opacity: 0.7 }); // or functionally identical var rect = new fabric.Rect(); rect.set({ width: 10, height: 20, fill: '#f55', opacity: 0.7 }); ``` #### 默認選項 也許你可能問了,加入我們不給對象設置任何構造參數,這些屬性還有嗎? 當然了。所有的`Fabric`對象都設有默認屬性。當創建對象過程中發生遺漏,就會有默認的屬性賦值給對象。我們自己可以嘗試一下: ```js var rect = new fabric.Rect(); // notice no options passed in rect.get('width'); // 0 rect.get('height'); // 0 rect.get('left'); // 0 rect.get('top'); // 0 rect.get('fill'); // rgb(0,0,0) rect.get('stroke'); // null rect.get('opacity'); // 1 ``` 我們的矩形獲得了一組默認的屬性。它的位置是0,0,是黑色,完全不透明,沒有邊框,沒有尺寸(寬度和高度為0)。由于沒有尺寸,我們無法在畫布上看到它。但是給它任何寬度/高度的正值,肯定會在畫布的左上角顯示一個黑色的矩形。 #### 層次和繼承 `Fabric`對象并不是互相獨立存在的。它們之間形成了非常明確的層次關系。 絕大多數對象都是繼承自根對象`fabricj.Object`。`fabirc.Object`代表一個二維的形狀,呈現在二維的`canvas`的畫布上。它是一個具有寬高,偏移還有一堆其他圖形屬性的實體。我們在上面見到的對象的這些屬性都是繼承來自`fabric.Object`。 這中繼承關系,允許我們在`fabirc.Object`上定義方法,共享與`fabric`所有的類。舉個栗子,假如你希望所有的對象都有一個`getAngleInRadians`方法,你只需要在`fabric.Object.prototype`的原型上創建即可。 ```js fabric.Object.prototype.getAngleInRadians = function() { return this.get('angle') / 180 * Math.PI; }; var rect = new fabric.Rect({ angle: 45 }); rect.getAngleInRadians(); // 0.785... var circle = new fabric.Circle({ angle: 30, radius: 10 }); circle.getAngleInRadians(); // 0.523... circle instanceof fabric.Circle; // true circle instanceof fabric.Object; // true ``` 如你所見,方法立刻就可以在所有實例上運行啦。 盡管子類繼承自`fabric.Object`,但他們也有自己的屬性和方法。舉例來說,`fabric.Circle`需要有半徑(`radius`)屬性,`fabric.Image`需要`setElement/getElement`方法來講設置源自`HTML img`標簽中的圖片。 使用原型獲取自定義渲染和行為對于牛逼項目是非常普遍的。 ### 畫布`Canvas` 我們已經了解了對象的詳細信息,現在讓我們回歸`canvas`. 在所有`fabric`的栗子中,創建對象之前你首先看到的是`new fabric.Canvas('...')`,`fabric.Canvas`給`canvas`元素提供一個包裹容器,它的主要職責就是管理指定畫布上的`fabric`對象.它需要元素的`id`返回`fabric.Canvas`的一個實例. 我們可以向里面添加對象,從中引用他們.甚至刪除他們: ```js var canvas = new fabric.Canvas('c'); var rect = new fabric.Rect(); canvas.add(rect); // add object canvas.item(0); // reference fabric.Rect added earlier (first object) canvas.getObjects(); // get all objects on canvas (rect will be first and only) canvas.remove(rect); // remove previously-added fabric.Rect ``` 盡管管理對象是`farbric.Canvas`的唯一宗旨,但是它還可以當作主要配置項.需要在整個`canvas`上設置一個背景色或圖片?將所有內容剪輯到指定區域?設置不同的寬高?指定畫布是不是可交互的?所有的這些選項(還有其余的)都可以設置在`fabric.Canvas`上,可以在創建對象時,也可以在此之后: ```js var canvas = new fabric.Canvas('c', { backgroundColor: 'rgb(100,100,200)', selectionColor: 'blue', selectionLineWidth: 2 // ... }); // or var canvas = new fabric.Canvas('c'); canvas.setBackgroundImage('http://...'); canvas.onFpsUpdate = function(){ /* ... */ }; ``` #### 交互 既然我們討論到了`canvas`元素了,那就讓我們講講交互吧.`Fabricj`中一個特性就是我們看到的,在對象模型上有一個互動層. 對象模型允許對畫布對象進行編程訪問和操作.在外面,在用戶級別上,可以通過鼠標(觸摸,觸摸設備)來操作對象.一旦你通過`new fabric.Canvas(..)`初始化畫布之后,你就可能選擇對象,來回拖拽,旋轉,縮放他們,設置將它們分到一個操作組. ![](http://fabricjs.com/article_assets/8.png) 如果我們想要允許用戶拖拽畫布上的東西,比如說圖片,我們需要做的僅僅是初始化畫布,然后將對象添加到畫布上.不許其他額外的配置和安裝. 但是如果我們不想要這樣的交互呢?那這樣的話,你可以使用`fabric.StaticCanvas`替代`fabric.Canvas`. 初始化語法完全相同,你只需要使用`StaticCanvas`替換`Cavnas`. ```js var staticCanvas = new fabric.StaticCanvas('c'); staticCanvas.add( new fabric.Rect({ width: 10, height: 20, left: 100, top: 100, fill: 'yellow', angle: 30 })); ``` 這樣就創建了一個輕量級的畫布,沒有任何多余的操作邏輯.需要注意的是你仍然擁有完成的對象模型,包括添加,刪除,修改對象和修改畫布的配置,這些仍然有效.僅僅只是事件操縱沒了. 稍后,當我們自定義構建選項時,您會看到,如果`StaticCanvas`是您所需要的,那么就可以創建一個較輕的`Fabric`版本。如果您需要諸如非交互式圖表之類的東西,或者在應用程序中使用濾鏡的非交互式圖像,這可能是一個不錯的選擇。 ### 圖片`Images` 說到圖片.......... 在畫布上添加矩形和圓很有趣,但為什么我們沒有用到一些圖片呢?如你所想,`Fabric`讓這變得比較簡單. 讓我們使用`fabric.Image`初始化圖片對象,然后添加到畫布中. ```html <canvas id="c"></canvas> <img src="my_image.png" id="my-image"> ``` ```js var canvas = new fabric.Canvas('c'); var imgElement = document.getElementById('my-image'); var imgInstance = new fabric.Image(imgElement, { left: 100, top: 100, angle: 30, opacity: 0.85 }); canvas.add(imgInstance); ``` 注意我們是如何將圖片元素傳遞給`fabric.Image`構造器.這個`fabric.Image`的實例看上去就像是文檔中的圖片.而且,我們立即設置了`left/top`值,角度值以及透明度值.一旦添加到畫布,圖片就被渲染在`(100,100)`的位置,順時針旋轉30度,輕微的透明度.不錯! ![](http://fabricjs.com/article_assets/9.png) 現在我們文檔中并沒有圖片,只有一個圖片的`url`鏈接,咋整?不是問題,讓我們看看`fabric.Image.fromURL`: ```js fabric.Image.fromURL('my_image.png', function(oImg) { canvas.add(oImg); }); ``` 看起來是不是很直接?僅僅是通過`fabric.Image.fromURL`加載圖片的`URL`,然后當圖片加載完成時,給一個回調函數.這個回調函數接收已經創建完成的`farbic.Image`對象當做第一個參數.在這里,你可以直接將它添加到畫布上,也可以對其做一些修改然后再添加到畫布上. ```js fabric.Image.fromURL('my_image.png', function(oImg) { // scale image down, and flip it, before adding it onto canvas oImg.scale(0.5).set('flipX, true); canvas.add(oImg); }); ``` ### 路徑`Paths` 我們已經了解了簡單的形狀和圖片.那么更復雜和豐富的形狀呢? 讓我們看看這強大的一對---`Path和Groups`. `Fabric`中的路徑表示可以通過其他方法填充修改的輪廓形狀.路徑是由一系列從一點到另一點的指令組成.通過這些指令,例如`move`,`line`,`curve`,`arc`等等,路徑可以繪制出令人難以想象的復雜形狀.再加上`PathGroup`的幫助,還可以有更多的擴展. `Fabric`中路徑類似`svg`元素.他們使用相同的一組命令,可以從`<path>`元素創建它們,并將它們序列化.稍后我們會更深入地觀察序列化和SVG解析,但是現在值得一提的是,您很可能很少手工創建`Path`實例.相反,您將使用`Fabric`的內置SVG解析器。但是為了理解什么是Path對象,讓我們嘗試手工創建一個簡單的對象: ```js var canvas = new fabric.Canvas('c'); var path = new fabric.Path('M 0 0 L 200 100 L 170 200 z'); path.set({ left: 120, top: 120 }); canvas.add(path); ``` ![](http://fabricjs.com/article_assets/10.png) 我們在實例化時,傳入了一個路徑參數的字符串.雖然看起來神兮兮的,但還是蠻好理解的.`M`是`move`命令,告訴那支無形的畫布移動到`0,0`的位置.`L`是`Line`命令,讓畫筆畫一條線到`200,100`,然后另一個`L`命令,是使畫筆畫到`170,200`,`z`命令是強制關閉當前的路徑,完成圖形的繪制.結果我們獲得是一個三角形. 既然`fabric.Path`跟其他`fabric`對象看起很像,所以我們可以改變一些它的屬性: ```js ... var path = new fabric.Path('M 0 0 L 300 100 L 200 300 z'); ... path.set({ fill: 'red', stroke: 'green', opacity: 0.5 }); canvas.add(path); ``` ![](http://fabricjs.com/article_assets/11.png) ```js ... var path = new fabric.Path('M121.32,0L44.58,0C36.67,0,29.5,3.22,24.31,8.41\ c-5.19,5.19-8.41,12.37-8.41,20.28c0,15.82,12.87,28.69,28.69,28.69c0,0,4.4,\ 0,7.48,0C36.66,72.78,8.4,101.04,8.4,101.04C2.98,106.45,0,113.66,0,121.32\ c0,7.66,2.98,14.87,8.4,20.29l0,0c5.42,5.42,12.62,8.4,20.28,8.4c7.66,0,14.87\ -2.98,20.29-8.4c0,0,28.26-28.25,43.66-43.66c0,3.08,0,7.48,0,7.48c0,15.82,\ 12.87,28.69,28.69,28.69c7.66,0,14.87-2.99,20.29-8.4c5.42-5.42,8.4-12.62,8.4\ -20.28l0-76.74c0-7.66-2.98-14.87-8.4-20.29C136.19,2.98,128.98,0,121.32,0z'); canvas.add(path.set({ left: 100, top: 200 })); ``` ![](http://fabricjs.com/article_assets/12.png) 好了,現在我們加載`SVG`元素可以使用`fabric.loadSVGFromString`or`fabric.loadSVGFromURL`. ### 后話
                  <ruby id="bdb3f"></ruby>

                  <p id="bdb3f"><cite id="bdb3f"></cite></p>

                    <p id="bdb3f"><cite id="bdb3f"><th id="bdb3f"></th></cite></p><p id="bdb3f"></p>
                      <p id="bdb3f"><cite id="bdb3f"></cite></p>

                        <pre id="bdb3f"></pre>
                        <pre id="bdb3f"><del id="bdb3f"><thead id="bdb3f"></thead></del></pre>

                        <ruby id="bdb3f"><mark id="bdb3f"></mark></ruby><ruby id="bdb3f"></ruby>
                        <pre id="bdb3f"><pre id="bdb3f"><mark id="bdb3f"></mark></pre></pre><output id="bdb3f"></output><p id="bdb3f"></p><p id="bdb3f"></p>

                        <pre id="bdb3f"><del id="bdb3f"><progress id="bdb3f"></progress></del></pre>

                              <ruby id="bdb3f"></ruby>

                              哎呀哎呀视频在线观看