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

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

  • EXACT_FIT

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

  • NO_BORDER

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

  • SHOW_ALL

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

  • FIXED_HEIGHT

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

  • FIXED_WIDTH

   這個和 FIXED_HEIGHT 相似,惟一不一樣的是它是保持的寬度不變。函數

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

 

 

 

 

 

 

 

 

 

 

 

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

  • cc.view.getDesignResolutionSize()

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

  • cc.view.getFrameSize()

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

  • cc.view.getVisibleSizeInPixel()

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

  • cc.view.getVisibleSize()

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

後續經過查看creator源碼也證明了這一點,如下是源碼解釋:prototype

 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()兩個函數。

相關文章
相關標籤/搜索