pixi.js教程中文版--基礎篇


前言

Pixi.js使用WebGL,是一個超快的HTML5 2D渲染引擎。作為一個Javascript的2D渲染器,Pixi.js的目標是提供一個快速的、輕量級而且是兼任所有設備的2D庫。提供無縫 Canvas 回退,支持主流瀏覽器,包括桌面和移動。 Pixi渲染器可以開發者享受到硬件加速,但並不需要了解WebGL。 網上暫時沒有找到關於

pixi.js的中文說明文檔,我這里僅是記錄項目中使用的經驗,即記錄利用pixi在制作精靈動畫時的一些方法。

=========================================================================

概述

需要說明的是,有些示例需要使用http://方式才能有效果,也就是說file://的方式有些示例是無法顯示的。

下面我們來看一下,用pixi創建一個精靈要經歷哪些步驟:

創建一個PIXI的實例,並展示出來,通常需要以下幾步:

  1. 創建一個舞台 (stage)
  2. 創建一個畫布 (render)
  3. 把畫布插入DOM中
  4. 創建一個精靈 (sprite)
  5. 把精靈加入畫布 
  6. 把畫布加入舞台
  7. 刷新舞台

概念解釋: 

 舞台(stage):

// A Stage represents the root of the display tree. Everything connected to the stage is rendered
所有要渲染的對象都必須連接到舞台中才能被顯示出來,舞台處於整個樹形展示結構的最底層,可以理解為背景
 
 demo :

 var stage = new PIXI.Stage(0xFFFFFF); //接收一個16進制的值,用於背景的顏色

 

  畫布(renderer):
 選用canvas或webGL進行渲染的一個區域
 demo:

 var renderer = PIXI.autoDetectRenderer(400, 300); 


它的后面還有兩個可選參數,分別 用來指定現有的canvas元素作為容器,canvas背景是否透明,

 

材質(texture):

可以理解成一種承載圖片的結構,它本身不能直接用於顯示,需要通過精靈(sprite)才能顯示,有點類似於dom中的臨時碎片(DocumentFragment)

demo:

  var texture = PIXI.Texture.fromImage("bunny.png");

精靈(sprite):

可以直接用於舞台顯示的對象,可以理解為DOM中的element.
精靈可以直接用圖片創建,也可以先創建材質,再用材質創建精靈

  demo :

 

var sprite = new PIXI.Sprite.fromImage('assets/image.png');//直接由圖片創建
//...
var texture = PIXI.Texture.fromImage("bunny.png"); var sprite = new PIXI.Sprite(texture);//由材質創建

 

//  sprite.position.x = 30; //沒有單位

//  sprite.position.y = 20; // 這就和給element設置樣式是一樣的道理。


 事件(event):
PIXI庫在精靈和舞台上提供了事件,用於交互.
 demo:

 stage.click = function(data){ var event = data.originalEvent } sprite.click = function(data){ var event = data.originalEvent var target = event.target //阻止默認行為,sprite.buttonMode = false;
 event.preventDefault(); }

 此外,還有.mousedown,.mouseover,.mouseout,.mousemove,.mouseup ,.mouseupoutside , .touchstart,.touchend,.tap


注意事項:

  1.  對於有事件的精靈,通常需要設置sprite.interactive = true , 對於作按鈕用的精靈,需要設置sprite.buttonMode = true;
  2.  與DOM的事件不同的是,精靈中的事件,是進行了二次封裝的,
  3.  通常需要用var event = data.originalEvent來與普通dom中的event對象保持一至

 不過又不完全相同,如data.originalEvent.stopPropagation()就不起作用.

 關於stopPropagation的問題,我問過pixijs的開發者,他答復說stopPropagation是dom中的概念,在canvas/webGL中是沒有的,所以不能說是pixi的問題。


  下面使用PIXI庫顯示一張圖片,簡單的演示下pixi的用法:
 

var stage = new PIXI.Stage(); var renderer = PIXI.autoDetectRenderer(400, 300); document.body.appendChild(renderer.view); var sprite = new PIXI.Sprite.fromImage('bunny.png'); stage.addChild(sprite);

 直接貼出上面的代碼,在網頁上只能看到漆黑的背景, 這是因為精靈的創建是異步的,必須等加載完圖片之后才能把精靈加入舞台中
 
我在這里給出兩種解決方式:


 1:不斷的去刷新舞台:

requestAnimFrame(animate); function animate(){ renderer.render(stage); requestAnimFrame(animate); }


2. 在圖片加載完成的回調中執行。這僅限於不需要刷新的精靈、
 

 sprite.texture.baseTexture.on('loaded',function(){ renderer.render(stage); })

 

在項目中實踐的時候發現用基於baseTexture的loaded事件有兩個問題
1:如果圖片加載失敗怎么辦?
2:同時加載多張圖片的時候,有些沒有觸發圖片的loaded回調

經過實踐,找到一個更加穩妥的辦法:

 

 var img = new Image(); 
  img.src = 'bunny.png'; 
  img.onload = function(){   
    var baseTexture = new PIXI.BaseTexture(this);
   var texture = new PIXI.Texture(baseTexture);   
    var sprite = new PIXI.Sprite(texture);   
    stage.addChild(sprite);   
    renderer.render(stage);
 }

 

此方案對於批量加載圖片也是適用的。最后再重復一遍,請用localhost://xxxxxx的方式進瀏覽

細心的比較也許你會發現,我和官方的示例不相同,官方使用了requestAnimFrame( animate ),而然我這里沒有用,為什么?因為我只是要顯示一張圖片而已,沒有必要不斷的去刷新舞台。requestAnimFrame( animate );這個是在精靈有變化的時候才需要用到。當然,如果不考慮性能,對一張靜態的圖不斷的刷新也沒有什么問題。

完整的示例:

 

        var stage = new PIXI.Stage(0xFFFFFF);
        var renderer = PIXI.autoDetectRenderer(400, 300);

        document.body.appendChild(renderer.view);

        var sprite = new PIXI.Sprite.fromImage('bunny.png');
        stage.addChild(sprite);

        sprite.texture.baseTexture.on('loaded',function(){
            renderer.render(stage);
        })

        sprite.interactive = true

        stage.click = stage.tap = function(data){
            console.log(data.originalEvent.target);
            //alert('you hit the stage')
        }

        sprite.mousedown = sprite.touchstart =function(data){
            // stop the default event...
            data.originalEvent.preventDefault();
            this.data = data;
            this.alpha = 0.9;
            this.dragging = true;
            console.log('mousedown');
        }

        sprite.mouseup = sprite.mouseupoutside = sprite.touchend = function(data){
            this.alpha = 1
            this.dragging = false;
            // set the interaction data to null
            this.data = null;
            console.log('mouseup');
        };

        sprite.mousemove = sprite.touchmove = function(data){
            if(this.dragging){
                var newPosition = this.data.getLocalPosition(this.parent);
                this.position.x = newPosition.x;
                this.position.y = newPosition.y;
                console.log('mousemove')
                renderer.render(stage);
            }
        }

        //requestAnimFrame(animate);
        function animate(){
               renderer.render(stage);
               requestAnimFrame(animate);
           }

精靈放大2倍

 var sprite = new PIXI.Sprite.fromImage('bunny.png');
 var sx = sprite.scale.x;
 var px = sprite.position.x;

 sprite.scale.x += 1;
 sprite.position.x -= px;
//Y方向同理
...
//刷新一下
requestAnimFrame(animate);

精靈的層級問題

在canvas中,由於不能用css的層級樣式表來控制層級關系,所以只能另想辦法進行模擬。pixi.js中沒有提供現成的方法,不過我們研究發現,只要控制精靈加入畫布的順序就可以實現類似的層級效果。它的規則是這樣的,先加入畫布的,出現在最下面,后加入的,出現在最上面。於是自然的就想到了先用一個數組收集這些精靈,排好序之后再循環加入畫布。可是問題就來了,有時候,我們事先往往不能確定層級,或者有時候是用戶觸發某一個動作之后才改變層級的,這怎么實現呢?這個我想到了給精靈人為的加一個zindex屬性。然后遍歷這個屬性,進行排序,最后再刷新一下舞台。

 

    /**
         * 對象按指定的屬性排序
         * @param  {array} arr    對象集合
         * @return null
         */
         function pixiSort(arr){
             var ln = arr.length;
             var tmp;
             for(var i = 0;i<ln-1;i++){
                 for(var j=i+1;j<ln;j++){
                     tmp = arr[i];
                     if(arr[i].sortIndex > arr[j].sortIndex){
                         arr[i] = arr[j];
                         arr[j] = tmp;
                     }
                 }
             }
         }

 

受html dom操作的影響,有時候我們需要精靈按照指定的層級進行排列顯示,比如給精靈指定index屬性。要做到對zindex的控制,可以用到如下方法

function updateZindex(ob,stage){ Object.defineProperty(ob,'zIndex',{ set : function(value){ if(this.sortIndex !== value){ this.sortIndex = value; pixiSort(stage.children); } }, get : function(){ return this.sortIndex; } }); }

 說白了,就是控制精靈的先后順序來達到顯示層級的效果。

最后是如何銷毀:

//移除全部精靈
stage.removeChildren() //移除整個舞台的引用
stage.removeStageReference()

 

以上創建的是建靜止的精靈,及在精靈上邦定事件。這個在官方沒有找到示例,特補充一下。(或許pixi就是為動畫而生的,所以沒有考慮這種簡單的需求了)

如果需要動畫效果的精靈,官方提供了多種方法。這里就不再細述了。我目前正在研究這一塊,有興趣的可以和我(@frog)一起交流!

 

在線資源

 

Pixi.js的GitHub主頁上,列舉了很多在線Demo。

 

GitHub:https://github.com/GoodBoyDigital/pixi.js/

 

官網: http://www.pixijs.com/

 

API :http://pixijs.download/release/docs/index.html

 

官方教程:https://github.com/kittykatattack/learningPixi

 

https://github.com/GoodBoyDigital/pixi.js  

 

 

 本篇為原創博文,轉載請注明出處.  278500368@qq.com


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM