cocos creator屏幕適配的一些知識點(2.0之后的版本)


一. cocos creator 提供的幾種適配策略

  • EXACT_FIT

   整個應用程序在指定區域可見,無需嘗試保留原始縱橫比。可能會出現失真,應用程序會被拉伸或壓縮。也就是說設計分辨率的長和寬不會等比縮放,它們會各自進行縮放,設計分辨率的寬會用 “屏幕寬/設計分辨率寬” 作為縮放因子,設計分辨率的高會用 “屏幕高/設計分辨率高” 作為縮放因子。(2.0版本這個策略有問題,等修復)

  • NO_BORDER

   整個應用程序填充指定區域,沒有失真,但可能會有一些裁剪,同時保持原樣應用程序的縱橫比。這個是等比進行縮放設計分辨率,取 “屏幕寬/設計分辨率寬” “屏幕高/設計分辨率高” 中較大的一個作為縮放因子,比如:“屏幕寬/設計分辨率寬”是2,“屏幕高/設計分辨率高”是1,那么取2作為縮放因子,這個時候高放大兩倍,自然超出屏幕之外看不見了。

  • SHOW_ALL

   整個應用程序在指定區域可見而不失真,同時保持原樣應用程序的縱橫比。邊界可以出現在應用程序的兩側。這個是等比進行縮放設計分辨率,取 “屏幕寬/設計分辨率寬” “屏幕高/設計分辨率高” 中較小的一個作為縮放因子,比如上述的那個例子,取1作為縮放因子,寬只放大一倍,明顯不夠,雖然整個應用程序都能看到,但會有黑邊。

  • FIXED_HEIGHT

   應用程序采用設計分辨率大小的高度並修改內部的寬度畫布使其適合設備的縱橫比,不會發生失真。這個是等比進行縮放設計分辨率,保持設計分辨率的高度不變,根據屏幕分辨率改變設計分辨率的寬度,這個時候設計分辨率和屏幕分辨率一樣了,再進行等比縮放。

  • FIXED_WIDTH

   這個和 FIXED_HEIGHT 類似,唯一不同的是它是保持的寬度不變。

  是否等比縮放 寬的縮放比例 高的縮放比例 是否改變設計分辨率
EXACT_FIT 屏幕寬/設計寬 屏幕高/設計高
NO_BORDER 較大的比 較大的比
SHOW_ALL 較小的比 較小的比
FIXED_HEIGHT 隨便取,因為兩個比一樣 隨便取,因為兩個比一樣
FIXED_WIDTH 隨便取,因為兩個比一樣 隨便取,因為兩個比一樣

 

 

 

 

 

 

 

 

 

 

 

二. cocos提供的幾個獲取View的函數

  • cc.view.getDesignResolutionSize()

   獲取的是你在編輯器中設計的分辨率,也就是canvas 組件下設置的設計分辨率。

  • cc.view.getFrameSize()

   獲取各種手機、pad上的屏幕分辨率,也就是硬件分辨率。

  • cc.view.getVisibleSizeInPixel()

   獲取的是 visibleSize 的基礎上乘以各種適配策略下的縮放比例后的分辨率。

  • cc.view.getVisibleSize()

   官方文檔上說返回視圖窗口可見區域尺寸,經過輸出對比發現,這個可見區域尺寸實際上是指設計分辨率,不過它返回的是經過各種適配策略后的設計分辨率,在EXACT_FIT,NO_BORDER,SHOW_ALL中因為不改變設計分辨率,所以和cc.view.getDesignResolutionSize()返回的結果一樣。但在FIXED_HEIGHT,FIXED_WIDTH中改變了設計分辨率,所以返回的是修改后的設計分辨率。

后續通過查看creator源碼也證實了這一點,以下是源碼解釋:

 1 /**
 2      * !#en
 3      * Returns the visible area size of the view port.
 4      * !#zh 返回視圖窗口可見區域尺寸。
 5      * @method getVisibleSize
 6      * @return {Size}
 7      */
 8     getVisibleSize: function () {
 9         return cc.size(this._visibleRect.width,this._visibleRect.height);
10     },
getVisibleSize()返回的是this._visbleRect的值,我們來找找this._visbleRect在哪進行賦值

 1 cc.js.mixin(View.prototype, {
 2     init () {
 3         .........
 4 
 5         var w = cc.game.canvas.width, h = cc.game.canvas.height;
 6         this._designResolutionSize.width = w;
 7         this._designResolutionSize.height = h;
 8         this._originalDesignResolutionSize.width = w;
 9         this._originalDesignResolutionSize.height = h;
10         this._viewportRect.width = w;
11         this._viewportRect.height = h;
12         this._visibleRect.width = w;
13         this._visibleRect.height = h;
14 
15         cc.winSize.width = this._visibleRect.width;
16         cc.winSize.height = this._visibleRect.height;
17         ......
18     },
19 ........
20 }

可以看到在這里給一些保持分辨率的對象賦了同一個值,那就是cc.game.canvas里面的值,這個值代表的是屏幕分辨率,因為后續進行適配策略是用的也是這個值,這就奇怪了,都一樣了還怎么比較,每個函數返回的值也應該一樣呀,所以一定有一個地方改變了它們,繼續找。

 

 1 setDesignResolutionSize: function (width, height, resolutionPolicy) {
 2         .........
 8         this.setResolutionPolicy(resolutionPolicy);
 9         var policy = this._resolutionPolicy;
10         if (policy) {
11             policy.preApply(this);
12         }
13 
14        ..........28 
29         this._originalDesignResolutionSize.width = this._designResolutionSize.width = width;
30         this._originalDesignResolutionSize.height = this._designResolutionSize.height = height;
31 
32         var result = policy.apply(this, this._designResolutionSize);
33 
34         if(result.scale && result.scale.length === 2){
35             this._scaleX = result.scale[0];
36             this._scaleY = result.scale[1];
37         }
38 
39         if(result.viewport){
40             var vp = this._viewportRect,
41                 vb = this._visibleRect,
42                 rv = result.viewport;
43 
44             vp.x = rv.x;
45             vp.y = rv.y;
46             vp.width = rv.width;
47             vp.height = rv.height;
48 
49             vb.x = 0;
50             vb.y = 0;
51             vb.width = rv.width / this._scaleX;
52             vb.height = rv.height / this._scaleY;
53         }
54 
55         policy.postApply(this);
56         cc.winSize.width = this._visibleRect.width;
57         cc.winSize.height = this._visibleRect.height;
58      ........64     },

我們直接來看setDesignResolutionSize()這個函數,它是通過設置設計分辨率和匹配模式來進行游戲畫面的屏幕適配。所以它必然會改變相應的值。可以看到第29,30行把我們傳進來的設計分辨率賦值給了this._originalDesignResolutionSize和this._designResolutionSize,改變了它們的值。那么什么時候改變this._visbleRect的值呢,我們看39行到52行,很明顯就是在這里改變的。vb.width = rv.width / this._scaleX; vb.height = rv.height / this._scaleY;

 

那么憑什么說this._visbleRect是適配策略后到設計分辨率呢,我們來看看result.viewport里面是什么東西,var result = policy.apply(this, this._designResolutionSize);policy是一個適配策略的實例,它根據你傳入的適配策略來決定調用哪個適配策略的方法,類似於c++中的多態。然后我們來看看每個適配策略做了什么,這里主要就拿SHOW_ALL和FIXED_HEIGHT來加以說明:

 1 var ShowAll = cc.Class({
 2         name: "ShowAll",
 3         extends: cc.ContentStrategy,
 4         apply: function (view, designedResolution) {
 5             var containerW = cc.game.canvas.width, containerH = cc.game.canvas.height,
 6                 designW = designedResolution.width, designH = designedResolution.height,
 7                 scaleX = containerW / designW, scaleY = containerH / designH, scale = 0,
 8                 contentW, contentH;
 9 
10             scaleX < scaleY ? (scale = scaleX, contentW = containerW, contentH = designH * scale)
11                 : (scale = scaleY, contentW = designW * scale, contentH = containerH);
12 
13             return this._buildResult(containerW, containerH, contentW, contentH, scale, scale);
14         }
15     });
16 
17 var FixedHeight = cc.Class({
18         name: "FixedHeight",
19         extends: cc.ContentStrategy,
20         apply: function (view, designedResolution) {
21             var containerW = cc.game.canvas.width, containerH = cc.game.canvas.height,
22                 designH = designedResolution.height, scale = containerH / designH,
23                 contentW = containerW, contentH = containerH;
24 
25             return this._buildResult(containerW, containerH, contentW, contentH, scale, scale);
26         }
27     });

可以看到它們都繼承於cc.ContentStrategy。在apply函數中返回值來自於this._buildResult()函數,我們來看這個函數:

 1 _buildResult: function (containerW, containerH, contentW, contentH, scaleX, scaleY) {
 2         // Makes content fit better the canvas
 3         Math.abs(containerW - contentW) < 2 && (contentW = containerW);
 4         Math.abs(containerH - contentH) < 2 && (contentH = containerH);
 5 
 6         var viewport = cc.rect((containerW - contentW) / 2, (containerH - contentH) / 2, contentW, contentH);
 7 
 8         // Translate the content
 9         if (cc.game.renderType === cc.game.RENDER_TYPE_CANVAS){
10             //TODO: modify something for setTransform
11             //cc.game._renderContext.translate(viewport.x, viewport.y + contentH);
12         }
13 
14         this._result.scale = [scaleX, scaleY];
15         this._result.viewport = viewport;
16         return this._result;
17     },

主要來看this._result中的viewport的值,它的width是contentW,height是contentH。到這里,一切都清楚了。我們假設屏幕分辨率的寬高是Pw和Ph,設計分辨率的寬高是Sw和Sh。

那么在SHOW_ALL中:假設Pw/Sw更小,contentW=Pw,contentH=Sh*(Pw/Sw),在進行this._visbleRect賦值時,width = Pw/(Pw/Sw) = Sw,height = (Sh*(Pw/Sw))/(Pw/Sw) = Sh,所以設計分辨率沒有改變。

在FIXED_HEIGHT中:contentW=Pw,contentH=Ph,scale = Ph/Sh,在進行this._visbleRect賦值時,width = Pw/(Ph/Sh) = Sh*(Pw/Ph),height = Ph/(Ph/Sh) = Sh,所以設計分辨率是改變的。

從上述代碼還發現cc.winSize和cc.view.getVisibleSize()的返回值是一樣的,二者可以通用。

 

在進行屏幕適配時主要用到cc.view.getDesignResolutionSize()和cc.view.getFrameSize()兩個函數。


免責聲明!

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



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