【翻译】在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.mzph.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…