【翻譯】在Ext JS和Sencha Touch中創建自己定義布局

原文:Creating Custom Layouts in Ext JS and Sencha Touch


布局系統是Sencha框架中最強大和最獨特的一部分。布局會處理應用程序中每個組件的大小和位置,因而,不須要手動去管理那些碎片。Ext JS與Sencha Touch的布局類有很多類似之處。近期在 Ivan Jouikov的這篇博文中對他們進行了具體的分析。



盡管是這樣。但非常多Ext JS和Sencha Touch開發者可能永遠都不會去了解布局系統的機制原理。Sencha框架已經提供了最經常使用的應用程序布局,因此非常少出現應用程序須要額外功能的需求,因而不大會有人愿意去了解布局系統的內部運作。



試想一下。你的公司須要在應用程序中使用3D Carousel來顯示界面元素。但沒有不論什么標準的Sencha布局能夠提供這樣的能力。哪怎么來解決問題呢?


選擇基類


在開發不論什么Ext JS或Sencha Touch自己定義組件的時候,第一步要考慮的總會是應該選擇哪一個基類來擴展。在眼下這樣的情況,就是須要使用哪種布局才干容納3D空間的項目。因為不須要不論什么特殊功能,僅僅是管理項目,因而,須要從布局繼承鏈最低這方面著手。在當前情況下,Ext.layout.container.Container (Ext JS)和Ext.layout.Default (Sencha Touch) 能夠說是最佳選擇。



在Ext JS中,因為須要支持舊版瀏覽器。而不能採用一些現代的CSS功能,如Flexbox,因而布局系統須要手動管理很多大小和定位的計算。這樣的后果就是,3D carousel布局須要重寫大多數的Ext.layout.container.Container方法,如calculate、getContainerSize和getPositionOffset。以便對它的子元素進行布局。


還有一個須要注意的問題是,Ext JS布局在執行“布局”時。每個“布局”的執行都要管理多個“周期”,比如。盒子布局配置為stretchmax就須要至少兩個周期,布局首先要檢測每個子組件的最大尺寸。并在第二周期將全部布局內的子組件擴展為同樣的大小。

布局的操作會產生大量的“布局”或“周期”(加入或移除多個條目),為了提供性能。可能會希望先暫停布局。在操作完畢后再恢復布局。



相比之下,Sencha Touch的Ext.layout.Default則同意瀏覽器通過CSS去處理布局中大多數項目的定位和尺寸(因為Sencha Touch僅僅支持現代瀏覽器,而全部這些都已實現CSS Flexbox)。

因此。Ext.layout.Default包括了與加入、移除和又一次定位子條目的相關的主要方法。

如今,已經了解將使用那些類來擴展新的3D Carousel布局。以下來逐步去實現它。


CSS3轉換和其它魔法

為了創建3D Carousel,須要使用一些高級CSS 3D轉換。如轉換、過渡、rotateX/rotateY和translateZ。CSS 3D轉換能夠非常復制。但總的來說,對于新的Sencha布局須要實現以下事情:


在父容器應用透視和轉換(讓它看上去是3D的)
在布局內的子組件應用轉換(環繞3D形狀從他們的邊界開始旋轉他們)
在父容器內部的DOM元素應用轉換(o physically rotate the 3D shape as the user interacts with it)

正如你所預期的,通過Ext JS和Sencha Touch生成的實際的DOM元素會有些許不同。因此。盡管在兩個框架中採取的方法是一樣的。但產生的CSS還是會有差別。新的3D Carousel布局所需的附加CSS例如以下(Sencha Touch):

.x-layout-carousel {-webkit-perspective : 1500px;-moz-perspective    : 1500px;-o-perspective      : 1500px;perspective         : 1500px;position            : relative !important;
}.x-layout-carousel .x-inner {-webkit-transform-style : preserve-3d;-moz-transform-style    : preserve-3d;-o-transform-style      : preserve-3d;transform-style         : preserve-3d;
}.x-layout-carousel.panels-backface-invisible .x-layout-carousel-item {-webkit-backface-visibility : hidden;-moz-backface-visibility    : hidden;-o-backface-visibility      : hidden;backface-visibility         : hidden;
}.x-layout-carousel-item {display  : inline-block;position : absolute !important;
}.x-layout-carousel-ready .x-layout-carousel-item {-webkit-transition : opacity 1s, -webkit-transform 1s;-moz-transition    : opacity 1s, -moz-transform 1s;-o-transition      : opacity 1s, -o-transform 1s;transition         : opacity 1s, transform 1s;
}.x-layout-carousel-ready .x-inner {-webkit-transition : -webkit-transform 1s;-moz-transition    : -moz-transform 1s;-o-transition      : -o-transform 1s;transition         : transform 1s;
}

為了讓Ext JS布局的CSS看上去基本一樣,還須要對CSS選擇器做點微調。


為了在Sencha Touch和Ext JS中讓3D Carousel能響應用戶交互,不得不在執行時對一些附加的CSS的進行改動。以下首先要做的是擴展布局的基類,然后研究怎樣加入交互功能。


擴展布局基類

首先來擴展Sencha Touch的Ext.layout.Default,主要目標是加入一些針對新的3D Carousel的觀感的配置項,以及一些布局內部用來正確定位子組件的功能。



初步的擴展例如以下:


Ext.define('Ext.ux.layout.Carousel', {extend : 'Ext.layout.Default',alias  : 'layout.carousel',config : {/*** @cfg {number} portalHeight* Height of the carousel, in pixels*/portalHeight : 0,/*** @cfg {number} portalWidth* Width of the carousel, in pixels*/portalWidth  : 0,/*** @cfg {string} direction* 'horizontal' or 'vertical'*/direction    : 'horizontal' //or 'vertical'},onItemAdd : function () {this.callParent(arguments);this.modifyItems();},onItemRemove : function () {this.callParent(arguments);this.modifyItems();},modifyItems : function () {//calculate child positions, etc}
});

代碼中除了config對象外,還定義了3個方法:onItemAdd、onItemRemove和modifyItems。

前啷個方法僅僅是簡單的重寫Ext.layout.Default的方法。以便在加入或刪除子組件后編輯子組件的位置,而modifyItems是一個新的方法。用來計算所需的CSS 3D轉換。



在布局指派給他們的容器時。布局系統內部的行為就會一直處于活動狀態:


setContainer: function(container) {var options = {delegate: '> component'};this.dockedItems = [];this.callSuper(arguments);container.on('centeredchange', 'onItemCenteredChange', this, options, 'before').on('floatingchange', 'onItemFloatingChange', this, options, 'before').on('dockedchange', 'onBeforeItemDockedChange', this, options, 'before').on('afterdockedchange', 'onAfterItemDockedChange', this, options);
},

對于我們的布局擴展來說。為了做進一步的初始化,還須要加上以下方法:


Ext.define('Ext.ux.layout.Carousel', {//...setContainer : function (container) {var me = this;me.callParent(arguments);me.rotation = 0;me.theta = 0;switch (Ext.browser.name) {case 'IE':me.transformProp = 'msTransform';break;case 'Firefox':me.transformProp = 'MozTransform';break;case 'Safari':case 'Chrome':me.transformProp = 'WebkitTransform';break;case 'Opera':me.transformProp = 'OTransform';break;default:me.transformProp = 'WebkitTransform';break;}me.container.addCls('x-layout-carousel');me.container.on('painted', me.onPaintHandler, me, { single : true });},onPaintHandler : function () {var me = this;//add the "ready" class to set the CSS transition stateme.container.addCls('x-layout-carousel-ready');//set the drag handler on the underlying DOMme.container.element.on({drag      : 'onDrag',dragstart : 'onDragStart',dragend   : 'onDragEnd',scope     : me});me.modifyItems();}});

在nebulous指派布局容器后,必須等到容器渲染之后才干將事件處理指定究竟層的DOM。

接下來,為了能讓布局管理子組件。還要填補功能之間的縫隙( fill in the functional gaps):


Ext.define('Ext.ux.layout.Carousel', {//...modifyItems : function () {var me = this,isHorizontal = (me.getDirection().toLowerCase() === 'horizontal'),ct = me.container,panelCount = ct.items.getCount(),panelSize = ct.element.dom[ isHorizontal ? 'offsetWidth' : 'offsetHeight' ],i = 0,panel, angle;me.theta = 360 / panelCount;me.rotateFn = isHorizontal ? 'rotateY' : 'rotateX';me.radius = Math.round(( panelSize / 2) / Math.tan(Math.PI / panelCount));//for each child item in the layout...for (i; i < panelCount; i++) {panel = ct.items.getAt(i);angle = me.theta * i;panel.addCls('x-layout-carousel-item');// rotate panel, then push it out in 3D spacepanel.element.dom.style[ me.transformProp ] = me.rotateFn + '(' + angle + 'deg) translateZ(' + me.radius + 'px)';}// adjust rotation so panels are always flatme.rotation = Math.round(me.rotation / me.theta) * me.theta;me.transform();},transform : function () {var me = this,el = me.container.element,h = el.dom.offsetHeight,style= el.dom.style;// push the carousel back in 3D space, and rotate itel.down('.x-inner').dom.style[ me.transformProp ] = 'translateZ(-' + me.radius + 'px) ' + me.rotateFn + '(' + me.rotation + 'deg)';style.margin = parseInt(h / 2, 10) + 'px auto';style.height = me.getPortalHeight() + 'px';style.width = me.getPortalWidth() + 'px';},rotate : function (increment) {var me = this;me.rotation += me.theta * increment * -1;me.transform();}
});

在演示樣例中,還栩雅大量的復雜運算來確定每個子組件的正確位置,以及須要在容器內手動更新CSS的轉換值。

最后,還須要加入用來捕獲用戶與3D Carousel之間交互的事件處理:


Ext.define('Ext.ux.layout.Carousel', {//...onDragStart : function () {this.container.element.dom.style.webkitTransitionDuration = "0s";},onDrag : function (e) {var me = this,isHorizontal = (me.getDirection().toLowerCase() === 'horizontal'),delta;if (isHorizontal) {delta = -(e.deltaX - e.previousDeltaX) / me.getPortalWidth();}else {delta = (e.deltaY - e.previousDeltaY) / me.getPortalHeight();}me.rotate((delta * 10).toFixed());},onDragEnd : function () {this.container.element.dom.style.webkitTransitionDuration = "0.4s";}});

事件處理僅僅是簡單的評估用戶是否已將鼠標拖動到carousel,然后更新CSS過渡。




該類完整的Sencha Touch代碼能夠在這里下載。而擴展自Ext.layout.container.Container的Ext JS的代碼與這個非常類似,但在API上還是有一些小小的差別。

Ext JS代碼的演示樣例能夠在這里下載。



回想Ext.ux.layout.Carousel


以下化一點點時間來回想一下發生了什么事。

因為3D Carousel布局僅僅須要繼承布局系統的基本功能。因而選擇了Sencha Touch的Ext.layout.Default類進行擴展。接下來。加入了onItemAdd、onItemRemove和setContainer等重寫方法來加入布局所需的執行配置。最好,實現了一些功能方法和事件處理。以便布局能夠管理子組件的位置。



盡管3D Carousel是一個使用Sencha Touch或Ext JS創建的異想天開的樣例,但它的重點在于怎樣在Sencha 應用程序中創建有創意的布局,而這實際上非常easy。關鍵的地方是丫了解怎樣去初始化布局,以及在這期間發生了什么——其實底層的框架代碼并沒有你所想象的那樣復雜。Sencha Touch和Ext JS的布局系統。盡管在底層會有些許的不同,但實現方法是實際上是一樣的。

請注意:這僅僅是一個技術演示。不能保證代碼能執行在全部瀏覽器上。

而其實,所使用的CSS3轉換已經意味著排查了一些瀏覽器,因此請不要將這個應用到生產中。


Other interesting examples of customized layouts include this Sencha Fiddle by Sencha Support engineer Seth Lemmons involving a circle menu, and this video of a custom navigation component by Andrea Cammarata, Sencha Professional Services engineer.


作者:Arthur Kay
Arthur Kay is the Developer Relations Manager at Sencha, Inc. He studied Music and Computer Science at Loyola University Chicago and has been involved with the Web since the late 1990s.



轉載于:https://www.cnblogs.com/mfrbuaa/p/5134089.html

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/news/256059.shtml
繁體地址,請注明出處:http://hk.pswp.cn/news/256059.shtml
英文地址,請注明出處:http://en.pswp.cn/news/256059.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

PCL中GreedyProjection三角化算法簡介與示例

文章目錄前言一、PCL點云三角化1.1 Delaunay三角剖分1.2 貪婪三角化二、程序示例總結前言 Delaunay三角剖分最初應用于2維領域&#xff0c;而與Greedy三角化算法的結合&#xff0c;使之成為目前在三維重建領域最為基礎的算法原理之一&#xff0c;很多學者針對其原理進行改進用…

[設計模式]中介者模式之Events消息傳遞實現

這篇文章比較短,修改自 寫給大家看的設計模式之中介者中的例子中介者模式的定義和目的自不必說, 參考上文即可. 本文針對實現方式做一個補充. 中介者模式增加了一個第三方對象(中介者)來控制兩個對象(同事)間的交互. 有助于對彼此通信的解耦, 畢竟他們并不需要關心對方的實現細…

【pyqt5】 讀取numpy arrray 顯示圖片

目錄 1、GUI界面&#xff08;QT designer設計&#xff09; 2、邏輯函數&#xff08;回調等&#xff09; 3、顯示圖片在label上 0&#xff09;直接利用QPixmap顯示圖像 1&#xff09;顯示彩色圖 彩色圖顯示色調不正常——opencv&#xff08;BGR&#xff09;QT(RGB)需要進行…

[Django]SE項目回憶錄(二)-注冊/登錄功能的實現及細節

該項目中提供了注冊和登錄兩部分功能&#xff0c;功能描述如下&#xff1a; 注冊&#xff1a; 允許任何用戶進行學生身份的注冊。 教師用戶預先已經保存在數據庫中&#xff0c;不允許以游客身份注冊新的教師用戶。 注冊時需要填寫的信息包括&#xff1a; - 用戶名 - 密碼(…

Zip4j開源jar包的簡單使用

因為對項目突然要發送壓縮加密的郵件附件&#xff0c;所以從網上看了一些資料說Zip4j開源框架比較好使&#xff0c;對中文的支持也比較好&#xff0c;所以從網上找了一個代碼案例&#xff01;自己寫了一寫&#xff0c;現在貼出來&#xff0c;方便以后想用的時候好找 1、 1 pack…

【pyqt5】——入門級模板(ui文件+ui轉py文件+邏輯py文件)(消息提示框)

目錄 1、ui文件 2、ui轉py文件 3、邏輯py文件 4、實例 1&#xff09;ui文件——demo.ui 2&#xff09;ui轉py文件——demo.py 3)邏輯py文件——demoLogic.py 4)運行結果 1、ui文件 這個文件是直接通過pyqt5 designer進行設計的&#xff0c;相關配置可見《配置Qt Design…

PCL中點特征描述子PFH、FPFH和VFH簡述和示例

文章目錄前言一、點特征直方圖1.1 PFH1.1.1 法線估計1.1.2 特征計算1.2 FPFH1.3 VFH二、示例2.1 PFH計算2.2 FPFH2.3 VFH前言 點特征直方圖是PCL中非常重要的特征描述子&#xff0c;在點云匹配、分割、重建等任務中起到關鍵作用&#xff0c;可以對剛體變換、點云密度和噪聲均有…

BZOJ 1005: [HNOI2008]明明的煩惱

BZOJ 1005: [HNOI2008]明明的煩惱 Description 自從明明學了樹的結構,就對奇怪的樹產生了興趣......給出標號為1到N的點,以及某些點最終的度數,允許在 任意兩點間連線,可產生多少棵度數滿足要求的樹? Input 第一行為N(0 < N < 1000), 接下來N行,第i1行給出第i個節點的度…

Apache Directory 指令

<Directory> 指令 語法&#xff1a;<Directory directory-path> ... </Directory> <Directory>和</Directory>用于封裝一組指令&#xff0c;使之僅對某個目錄及其子目錄生效。任何可以在"directory"作用域中使用的指令都可以使用。Dir…

來一個炫酷的導航條

本文分享一個帶動畫效果的中英文切換導航條。 鼠標放上去試一下&#xff1a; INDEX 首頁 BBS 社區 HOME 我 1.用CSS3實現 效果看上去復雜&#xff0c;其實我們先來做出一個樣式&#xff0c;就很簡單了。如下&#xff1a; 代碼&#xff1a; <nav><ul class"list…

基于C++的opencv中Mat矩陣運算方法總結

文章目錄前言一、Mat運算種類1.1 代數運算1.2 類型轉換前言 Mat類是目前opencv最為常用的圖像數據格式&#xff0c;其優點在于無需手動開辟內存空間和實時釋放&#xff0c;針對此類的各種運算方法有很多&#xff0c;本文按照各種運算方法的種類進行簡單的總結和示例。 一、Mat…

【pyqt5】——信號與槽

一、簡單Demo 簡單使用信號和槽&#xff08;之前常用的使用方式&#xff09;&#xff1a; class DemoWin(QMainWindow):def __init__(self):super().__init__()self.initUI()def initUI(self):self.resize(400, 250)self.btn QPushButton("發送信號", self)# 發送…

JSON - 簡介

JSON - 簡介 JSON實例 <!DOCTYPE html> <html> <head> <meta charset"utf-8"> <title>菜鳥教程(runoob.com)</title> </head> <body> <h2>JavaScript 創建 JSON 對象</h2> <p> 網站名稱: <spa…

mysql慢日志管理

一、日志切割 原理&#xff1a; 1、cp一個慢日志備份 2、清空原理的慢日志 3、寫成腳本&#xff0c;每天一切&#xff0c;這樣就ok啦 二、查找日志中的慢日志 1、做了日志切割&#xff08;慢日志文件就小了&#xff09; 2、查找某個時間的慢日志 日志時間格式&#xff1a; # Ti…

【深度學習】mask_rcnn訓練自己的數據集以及模型使用(實踐結合GitHub項目)

根據requirements - 開源項目默認的.txt進行庫安裝 環境&#xff1a;WIN10 Anoconda Pycharm python3.6.2 mask_rcnn基本流程1、訓練 1)labelme進行目標物體標記&#xff0c;生成json文件&#xff0c;含點坐標、以及各個物體的標簽label; json文件的格式&#xff1a;&…

EXCEL小技巧:如何統計非空單元格

http://club.excelhome.net/thread-1187271-1-1.html 下面教大家如果用函數統計非空單元格的數量 首先我們來介紹幾個統計函數&#xff1a; 1.COUNT(value1,value2,...) 統計包含數字的單元格個數 2.COUNTA(value1,value2,...) 統計非空單元格的個數 3.COUNTBLANK(range&…

easyui 頁簽

昨天開始搭后臺框架&#xff0c;到晚上的時候遇到了一個現在覺得挺可笑但是當時一直很糾結很糾結的問題&#xff0c;這個問題剛剛解決出來&#xff0c;把它拿出來說說&#xff0c;讓自己長點兒記性&#xff0c;希望大家不要犯我這個錯誤啊 在backstage.jsp頁面中我寫了一個方法…

未在本地計算機上注冊“Microsoft.Jet.OLEDB.4.0”提供程序。

報錯信息&#xff1a; 解決方案&#xff1a; 1、“設置應用程序池默認屬性”/“常規”/”啟用32位應用程序”&#xff0c;設置為 true。 如下圖所示&#xff1a;&#xff08;已測試&#xff0c;好使&#xff09; 方法二&#xff1a;生成->配置管理器->平臺->點擊Any C…

UserWarning: Matplotlib is currently using agg, which is a non-GUI backend, so cannot show the figur

“UserWarning: Matplotlib is currently using agg, which is a non-GUI backend, so cannot show the figure”在利用mask_rcnn進行物體檢測的時候出現的問題&#xff0c;主要是因為matplotlib的使用格式不對 可以檢查者兩個地方&#xff1a; 1、visualize.py中 import mat…

008. 限制上傳文件的大小

第一種方法: 利用web.config的配置文件項, 進行設置; 前端aspx示例: <% Page Language"C#" AutoEventWireup"true" CodeFile"sendOutEmail.aspx.cs" Inherits"sendOutEmail" %> <!DOCTYPE html PUBLIC "-//W3C//DTD XHT…