layer 订阅
layer是一款web弹层组件,致力于服务各个水平段的开发人员。 展开全文
layer是一款web弹层组件,致力于服务各个水平段的开发人员。
信息
案    例
八圆包
外文名
layer
作    者
贤心
中文名
layer
简    介
可以让你想到即可做到的web弹窗
layer弹出层组件
[1]  layer,一个可以让你想到即可做到的web弹窗(层)解决方案(js组件),作者贤心(前端开发工程师)。layer侧重于用户灵活的自定义,为不同人的使用习惯提供动力。其意义在于,可以让您的页面拥有更丰富与便捷的操作体验,而您只需在调用时简单地配置相关参数,即可轻松实现。与同类弹出层组件相比,layer的优势明显,她尽可能地在以更少的代码展现出更强健的功能。layer格外注重性能的提升,在多层模式的回调处理中,具备其它多数层组件所没有的“独立不冲突”(截至到2013年10月23,已有115859人次关注新版layer)。您完全可以大可放心地在页面弹出任意数量的层,她们彼此不妨碍。当你问及她的兼容时,layer必须告诉你,她兼容了一切浏览器,包括古老的ie6。layer公开了如此多的接口(api),这使得您可以DIY太多您需要的风格,尤其是页面层模式,意味着必要时您可以完全抛弃layer的现有皮肤,并用你的思维去勾勒她的衣着。而问题在于,我必须中止“王婆卖瓜”的陈述。因为一切的不足或友好,都需要您在使用过程中去发现。据不完全统计,截至到2013年8月30号,layer已服务于6000多家web平台。layer作为layUI库的成员,将一直致力于为web开发提供动力。八圆包,该站所有页面都有用到layer。
收起全文
精华内容
下载资源
问答
  • Layer1,Layer2 千次阅读
    2022-04-02 17:21:48

    Layer0 层代表的是基础资源和通讯。

    Layer 1网络是底层区块链的别称。 币安智能链(BNB)、以太坊(ETH)、比特币(BTC)和Solana都属于Layer-1协议。我们称之为Layer 1,是因为它们是所在生态系统中的主要网络。

    Layer1 层的共识决定了 Layer0 层的资源利用规则,所以把 Layer0+Layer1 可以当成一体讨论,也就是链上。

    在以太坊上,DeFi 协议的总锁仓价值 (TVL) 从 2021 年初的约 161 亿美元上升到 11 月 30 日的 1014 亿美元,这一年中增长了约 530%。L1 生态系统的 DeFi 项目 TVL 整体增长更快,自年初以来增加了超过 1660 亿美元,增长了约 974%。

    随着以太坊交易量在2021年1 月至 5 月间不断创下历史新高,在更广泛的加密市场激增的背景下,网络需求巨大、成本快速增长的环境中,上半年的平均交易费用升至历史最高水平,在网络需求极端的时期,过高的gas费和长时间的确认时间有时会让用户瘫痪。

    费用相对较低的非以太坊 L1 开始占据舞台中心,像币安智能链 (BSC) 这样的 EVM (以太坊虚拟机)兼容链特别适合吸收大量新老用户。在2021年下半年,EVM 兼容链的用户和活动急剧增加,部分原因是 L1 团队提供的奖励和他们的资金大幅增加。

    Layer1的爆发式增长是2021年加密行业最主要的发展脉络之一。

    Layer1例如 Fantom (FTM)、Solana (SOL非 EVM 兼容,仅次于以太坊和 BSC) 和 Terra (LUNA)和Avalanche(AVAX)。表现明显优于 ETH 的价格收益。

    随着第 1 层链继续威胁以太坊作为智能合约平台的主导地位,以太坊已经通过利用第 2 层技术rollup 推进其基础设施。目前市场有两类rollup,分别是Zero-Knowledge和Optimistic,这两类rollup目前都存在于以太坊主网上。

    layer2(是提升L1性能的扩容方案,L1交拥堵,交易费高,L2提高eth交易处理速度)

    以太坊节点的数据包括两部分:世界状态(以太坊全网所有地址的账户余额表),交易直接驱动修改区块链。

    btc区块容纳交易量受区块大小限制(现在1m)eth受区块的gas(现在是1500万)上限限制,每次交易消耗一定的gas。消耗的包括两部分:一部分是修改世界状态,另一部分把交易数据写入区块,前者消耗远大于后者

    layer2目的降低交易消耗的gas。rollup把多笔交易打包给layer1,不修改L1点世界状态,只是存储交易数据。设计本质就是L2完全符合L1执行规则。

    更多相关内容
  • Layer 弹窗入门

    千人学习 2019-05-28 18:42:10
    Layer弹窗,《Layer弹窗 基础参数 入门》 通过24个小视频,系统的对Layer34个基础参数,全部逐一进行了视频讲解。继续和大家一起学习进步,内容较为浅显易懂,适合新手上手。 课程首先通过快速上手基本了解layer弹窗...
  • 弹出层插件layer.js

    2018-04-17 16:34:11
    用于方便以后使用弹出层 或弹出框之类的,、使用时,请把文件夹layer整个放置在您站点的任何一个目录,只需引入layer.js即可,除jQuery外,其它文件无需再引入。 如果您的js引入是通过合并处理或者您不想采用layer...
  • layer 下拉树形菜单带有复选框

    热门讨论 2017-05-22 10:17:46
    该插件是改良的layer的树形插件,在原始的layer插件中的树形结构是没有复选框的,改良后可用以拿来做权限系统的权限选择
  • batch normalization 和 layer normalization 在RNN(LSTM、GRU)上的TensorFlow实现;运行无误,示例为mnist手写体识别
  • layer mobile手机端弹出框,询问框http://blog.csdn.net/libin_1/article/details/50726055
  • layer_API_帮助手册

    2015-08-21 11:31:50
    layer_API_帮助手册.pdf 包含了 layer 接口及参数说明。
  • layui——layer模块

    千次阅读 2021-02-06 23:35:09
    使用场景a 作为独立模块使用如果你只是单独想使用 layer,你可以去 layer独立版本官网下载组件包。你需要在你的页面引入jQuery1.8以上的任意版本,并引入layer.js。b layui模块化使用如果你使用的是 layui,那么你...

    介绍

    功能强大的弹层组件,可以以内置模块来引用,也可以作为独立模块引用;独立模块见:http://layer.layui.com/

    1 使用场景

    a 作为独立模块使用

    如果你只是单独想使用 layer,你可以去 layer

    独立版本官网下载组件包。你需要在你的页面引入jQuery1.8以上的任意版本,并引入layer.js。

    b layui模块化使用

    如果你使用的是 layui,那么你直接在官网下载 layui 框架即可,无需引入 jQuery 和

    layer.js,但需要引入layui.css和layui.js

    2 基础参数

    2.1 type(类型:Number,默认:0),基本层类型

    layer提供了5种层类型。可传入的值有:0(信息框,默认)1(页面层)2(iframe层)3(加载层)4(tips层)。

    若你采用layer.open({type: 1})方式调用,则type为必填项(信息框除外)

    2.2 title(类型:String/Array/Boolean,默认:'信息'),标题(灵活!!!Array的做法是layui的个性所在!);

    title支持三种类型的值,若你传入的是普通的字符串,如title

    :'我是标题',那么只会改变标题文本;若你还需要自定义标题区域样式,那么你可以title: ['文本',

    'font-size:18px;'],数组第二项可以写任意css样式;如果你不想显示标题栏,你可以title: false

    2.3 content(类型:String/DOM/Array,默认:''),内容;

    content可传入的值是灵活多变的,不仅可以传入普通的html内容,还可以指定DOM,更可以随着type的不同而不同。

    layer.open({

    type: 1,

    content: '传入任意的文本或html'

    //这里content是一个普通的String

    });

    layer.open({

    type: 1,

    content: $('#id')

    //这里content是一个DOM,注意:最好该元素要存放在body最外层,否则可能被其它的相对元素所影响

    });

    //Ajax获取

    $.post('url', {}, function(str){

    layer.open({

    type: 1,

    content: str

    //注意,如果str是object,那么需要字符拼接。

    });

    });

    layer.open({

    type: 2,

    content: 'http://sentsin.com'

    //这里content是一个URL,如果你不想让iframe出现滚动条,你还可以content:

    ['http://sentsin.com', 'no']

    });

    layer.open({

    type: 4,

    content: ['内容', '#id']

    //数组第二项即吸附元素选择器或者DOM

    });

    2.4 skin(类型:String,默认:''),样式;

    skin不仅允许你传入layer内置的样式class名,还可以传入您自定义的class名。这是一个很好的切入点,意味着你可以借助skin轻松完成不同的风格定制。目前layer内置的skin有:layui-layer-lanlayui-layer-molv,未来我们还会选择性地内置更多,但更推荐您自己来定义

    反正,我用不着~~~

    2.5 area(类型:String/Array,默认:'auto'),宽高;

    在默认状态下,layer是宽高都自适应的,但当你只想定义宽度时,你可以area:

    '500px',高度仍然是自适应的。当你宽高都要定义时,你可以area: ['500px', '300px']

    2.6 offset(类型:String/Array,默认:垂直水平居中),坐标;

    offset默认情况下不用设置。但如果你不想垂直水平居中,你还可以进行以下赋值:

    值  备注

    offset: 'auto'  默认坐标,即垂直水平居中

    offset: '100px'  只定义top坐标,水平保持居中

    offset: ['100px', '50px'] 同时定义top、left坐标

    offset: 't'  快捷设置顶部坐标

    offset: 'r'  快捷设置右边缘坐标

    offset: 'b'  快捷设置底部坐标

    offset: 'l'  快捷设置左边缘坐标

    offset: 'lt'  快捷设置左上角

    offset: 'lb'  快捷设置左下角

    offset: 'rt'  快捷设置右上角

    offset: 'rb'  快捷设置右下角

    2.7 icon(类型:Number,默认:-1信息框 / 0加载层),图标;

    信息框默认不显示图标。当你想显示图标时,默认皮肤可以传入0-6。如果是加载层,可以传入0-2。

    信息框默认定义:0 感叹号、1 对号、2 叉号、3 问号、4 锁、5 哭、6 微笑;

    加载层默认定义:0 默认,三个点循环、1 大星号转圈 、2 小星号转圈;

    2.8 btn(类型:String/Array,默认:'确认'),按钮;

    信息框模式时,btn默认是一个确认按钮,其它层类型则默认不显示,加载层和tips层则无效。当您只想自定义一个按钮时,你可以btn:

    '我知道了',当你要定义两个按钮时,你可以btn: ['yes', 'no']。当然,你也可以定义更多按钮,比如:btn:

    ['按钮1', '按钮2', '按钮3', …],按钮1的回调是yes,而从按钮2开始,则回调为btn2:

    function(){},以此类推。如:

    layer.{  // 标题默认“信息”,确认按钮;

    layer.msg("Ok");

    layer.close(index);

    });

    layer.confirm("默认询问框", function(index) { //

    标题默认“信息”,确认|取消按钮;

    layer.msg("Yes");

    layer.close(index);

    }, function(index) {

    layer.msg("Cancel");

    layer.close(index);

    });

    layer.confirm('自定义询问框Yes|No', {

    btn: ['是', '否']

    }, function(index, layero){

    layer.msg("Yes");

    layer.close(index);

    }, function(index){

    layer.msg("No");

    layer.close(index);

    });

    layer.confirm('自定义询问框Yes|No|Cancel', { //

    默认后面两个回调是指前两个按钮的回调;

    btn: ['是', '否', '取消'],

    btn3: function(index){

    layer.msg("Cancel");

    layer.close(index);

    }

    }, function(index, layero){

    layer.msg("Yes");

    layer.close(index);

    }, function(index){

    layer.msg("No");

    layer.close(index);

    });

    layer.confirm('自定义询问框No|Yes|Cancel', { // 使用yes, btn2,

    btn3来定义回调;yes代表第一个按钮,btn2第二个,依此类推;

    btn: ['拒绝', '确定', '取消'],

    yes: function(index, layero){

    layer.msg("拒绝");

    layer.close(index);

    },

    btn2: function(index){ // 一般放在第一个

    layer.msg("确定");

    layer.close(index);

    },

    btn3: function(index){

    layer.msg("取消");

    layer.close(index);

    }

    });

    2.9 btnAlign(类型:String,默认:r),按钮摆放位置定义;

    值  备注

    btnAlign: 'l' 按钮左对齐

    btnAlign: 'c' 按钮居中对齐

    btnAlign: 'r' 按钮右对齐。默认值,不用设置

    2.10 closeBtn(类型:String/Boolean,默认:1),关闭按钮设置;

    layer提供了两种风格的关闭按钮,可通过配置1和2来展示,如果不显示,则closeBtn: 0

    2.11

    shade(类型:String/Array/Boolean,默认:0.3),遮罩颜色、透明度设置;

    即弹层外区域。默认是0.3透明度的黑色背景('#000')。如果你想定义别的颜色,可以shade: [0.8,

    '#393D49'];如果你不想显示遮罩,可以shade: 0

    2.12 shadeClose(类型:Boolean,默认:false),是否点击遮罩关闭;

    如果你的shade是存在的,那么你可以设定shadeClose来控制点击弹层外区域关闭。

    2.13 time(类型:Number,默认:0),自动关闭所需毫秒;

    默认不会自动关闭。当你想自动关闭时,可以time:

    5000,即代表5秒后自动关闭,注意单位是毫秒(1秒=1000毫秒)

    2.14 id(类型:String,默认:空字符),用于控制弹层唯一标识;

    设置该值后,不管是什么类型的层,都只允许同时弹出一个。一般用于页面层和iframe层模式

    2.15 anim(类型:Number,默认:0),弹出动画;

    我们的出场动画全部采用CSS3。这意味着除了ie6-9,其它所有浏览器都是支持的。目前anim可支持的动画类型有0-6

    如果不想显示动画,设置 anim: -1 即可。另外需要注意的是,3.0之前的版本用的是 shift 参数

    anim: 0 平滑放大。默认

    anim: 1 从上掉落

    anim: 2 从最底部往上滑入

    anim: 3 从左滑入

    anim: 4 从左翻滚

    anim: 5 渐显

    anim: 6 抖动

    2.16 isOutAnim(类型:Boolean,默认:true),关闭时的动画效果;

    默认情况下,关闭层时会有一个过度动画。如果你不想开启,设置 isOutAnim: false 即可;

    2.17 maxmin(类型:Boolean,默认:false),最大|最小化;

    该参数值对type:1和type:2有效。默认不显示最大小化按钮。需要显示配置maxmin: true即可;

    2.18 fixed(类型:Boolean,默认:true),是否固定不动;

    即鼠标滚动时,层是否固定在可视区域。如果不想,设置fixed: false即可;

    2.19 resize(类型:Boolean,默认:true),是否允许拉伸;

    默认情况下,你可以在弹层右下角拖动来拉伸尺寸。如果对指定的弹层屏蔽该功能,设置

    false即可。该参数对loading、tips层无效;

    2.20

    resizing(类型:Function,默认:null),监听窗口拉伸动作;

    当你拖拽弹层右下角对窗体进行尺寸调整时,如果你设定了该回调,则会执行。回调返回一个参数返回:当前层的DOM对象;

    2.21 scrollbar(类型:Boolean,默认:true),是否允许浏览器出现滚动条;

    默认允许浏览器滚动,如果设定scrollbar: false,则屏蔽;

    2.22 maxWidth(类型:Number,默认:360),最大宽度;

    请注意:只有当area: 'auto'时,maxWidth的设定才有效。

    2.23 maxHeight(类型:Number,默认:无),最大高度;

    请注意:只有当高度自适应时,maxHeight的设定才有效。

    2.24 zIndex(类型:Number,默认:19891014(贤心生日 0.0)^_^),层叠顺序;

    一般用于解决和其它组件的层叠冲突。

    2.25

    move(类型:String/DOM/Boolean,默认:'.layui-layer-title'),触发拖动的元素;

    默认是触发标题区域拖拽。如果你想单独定义,指向元素的选择器或者DOM即可。如move:

    '.mine-move'。你还配置设定move: false来禁止拖拽

    2.26 moveOut(类型:Boolean,默认:false),是否允许拖拽到窗口外(用不着!);

    默认只能在窗口内拖拽,如果你想让拖到窗外,那么设定moveOut: true即可;

    2.27

    moveEnd(类型:Function,默认:null),拖动完毕后的回调;

    默认不会触发moveEnd,如果你需要,设定moveEnd:

    function(layero){}即可。其中layero为当前层的DOM对象;

    2.28 tips(类型:Number/Array,默认:2),tips方向和颜色;

    tips层的私有参数。支持上右下左四个方向,通过1-4进行方向设定。如tips:

    3则表示在元素的下面出现。有时你还可能会定义一些颜色,可以设定tips: [1, '#c00'];

    2.29

    tipsMore(类型:Boolean,默认:false),是否允许多个tips同时显示;

    允许多个意味着不会销毁之前的tips层。通过tipsMore: true开启;

    2.30

    success(类型:Function,默认:null),层弹出后的成功回调;

    当你需要在层创建完毕时即执行一些语句,可以通过该回调。success会携带两个参数,分别是当前层DOM当前层索引。如:

    layer.open({

    content: '测试回调',

    success: function(layero, index){

    console.log(layero,

    index);

    }

    });

    2.31

    yes(类型:Function,默认:null),确定按钮回调;

    该回调携带两个参数,分别为当前层索引、当前层DOM对象。如:

    layer.open({

    content: '测试回调',

    yes: function(index, layero){

    //do something

    layer.close(index);

    //如果设定了yes回调,需进行手工关闭

    }

    });

    2.32

    cancel(类型:Function,默认:null),右上角关闭按钮的回调;

    该回调携带两个参数,分别为:当前层索引参数(index)、当前层的DOM对象(layero),默认会自动触发关闭。如果不想关闭,return

    false即可,如;

    cancel: function(index, layero){

    if(confirm('确定要关闭么')){

    //只有当点击confirm框的确定时,该层才会关闭

    layer.close(index)

    }

    return false;

    }

    2.33

    end(类型:Function,默认:null),层销毁后触发的回调;

    无论是确认还是取消,只要层被销毁了,end都会执行,不携带任何参数。

    2.34

    full/min/restore(类型:Function,默认:null),分别代表最大化、最小化、还原后触发的回调;

    携带一个参数,即当前层DOM;

    3 调用方法

    3.1 layer.config(options),初始化全局配置;

    可以配置加载路径、默认动画、默认皮肤,我应该用不上的! ←_←

    3.2 layer.ready(callback),初始化就绪;

    由于我们的layer内置了轻量级加载器,所以你根本不需要单独引入css等文件。但是加载总是需要过程的。当你在页面一打开就要执行弹层时,你最好是将弹层放入ready方法中,如:

    //页面一打开就执行弹层

    layer.ready(function(){

    layer.msg('很高兴一开场就见到你');

    });

    3.3 layer.open(options),原始核心方法;

    基本上是露脸率最高的方法,不管是使用哪种方式创建层,都是走layer.open(),创建任何类型的弹层都会返回一个当前层索引,上述的options即是基础参数,另外,该文档统一采用options作为基础参数的标识例子:

    var index = layer.open({

    content: 'test'

    });

    //拿到的index是一个重要的凭据,它是诸如layer.close(index)等方法的必传参数。

    3.4 layer.alert(content, options,

    yes),普通信息框,yes是指回调函数;

    调用很简单,关键设计灵便,它的参数是自动向左补齐的。通过第二个参数,可以设定各种你所需要的基础参数,但如果你不需要的话,直接写回调即可。

    3.5 layer.confirm(content, options, yes,

    cancel),询问框;

    类似系统confirm,但却远胜confirm,另外它不是和系统的confirm一样阻塞你需要把交互的语句放在回调体中。同样的,它的参数也是自动补齐的。

    3.6 layer.msg(content, options, end),提示框;

    它简单,而且足够得自觉,它不仅占据很少的面积,而且默认还会3秒后自动消失;还有“它的参数也是自动补齐的”;

    3.7 layer.load(icon, options),加载层;

    特别注意一点:load默认是不会自动关闭的,因为你一般会在ajax回调体中关闭它。

    //eg1

    var index = layer.load();

    //eg2

    var index = layer.load(1); //换了种风格

    //eg3

    var index = layer.load(2, {time: 10*1000});

    //又换了种风格,并且设定最长等待10秒

    //关闭

    layer.close(index);

    3.8 layer.tips(content, follow,

    options),tips层,follow是指在哪个元素上提示;

    它拥有和msg一样的低调和自觉,而且会智能定位,即灵活地判断它应该出现在哪边。默认是在元素右边弹出;

    //eg1

    layer.tips('只想提示地精准些', '#id');

    //eg 2

    $('#id').on('click', function(){

    var that = this;

    layer.tips('只想提示地精准些', that);

    //在元素的事件回调体中,follow直接赋予this即可

    });

    //eg 3

    layer.tips('在上面', '#id', {

    tips: 1

    });

    4 辅助方法

    4.1 layer.close(index),关闭特定层;

    关键看以下示例:

    //当你想关闭当前页的某个层时

    var index = layer.open();

    var index = layer.;

    var index = layer.load();

    var index = layer.tips();

    //正如你看到的,每一种弹层调用方式,都会返回一个index

    layer.close(index); //此时你只需要把获得的index,轻轻地赋予layer.close即可

    //如果你想关闭最新弹出的层,直接获取layer.index即可

    layer.close(layer.index);

    //它获取的始终是最新弹出的某个层,值是由layer内部动态递增计算的

    //当你在iframe页面关闭自身时

    var index = parent.layer.getFrameIndex(window.name);

    //先得到当前iframe层的索引

    parent.layer.close(index); //再执行关闭

    4.2 layer.closeAll(type),关闭所有层;

    如果你很懒,你不想去获取index你只想关闭。那么closeAll真的可以帮上你。如果你不指向层类型的话,它会销毁掉当前页所有的layer层。当然,如果你只想关闭某个类型的层,那么你可以

    layer.closeAll(); //疯狂模式,关闭所有层

    layer.closeAll('dialog'); //关闭信息框

    layer.closeAll('page'); //关闭所有页面层

    layer.closeAll('iframe'); //关闭所有的iframe层

    layer.closeAll('loading'); //关闭加载层

    layer.closeAll('tips'); //关闭所有的tips层

    4.3 layer.style(index, cssStyle),重新定义层的样式;

    该方法对loading层和tips层无效。参数index为层的索引,cssStyle允许你传入任意的css属性

    //重新给指定层设定width、top等

    layer.style(index, {

    width: '1000px',

    top: '10px'

    });

    4.4 layer.title(title, index),改变层的标题;

    使用方式:layer.title('标题变了', index);

    4.5 layer.getChildFrame(selector,

    index),获取iframe页的DOM;

    当你试图在当前页获取iframe页的DOM元素时,你可以用此方法。selector即iframe页的选择器;

    示例如下:

    layer.open({

    type: 2,

    content: 'test/iframe.html',

    success: function(layero, index){

    var body =

    layer.getChildFrame('body', index);

    var iframeWin =

    window[layero.find('iframe')[0]['name']];

    //得到iframe页的窗口对象,执行iframe页的方法:iframeWin.method();

    console.log(body.html())

    //得到iframe页的body内容

    body.find('input').val('Hi,我是从父页来的')

    }

    });

    4.6

    layer.getFrameIndex(windowName),获取特定iframe层的索引;

    此方法一般用于在iframe页关闭自身时用到。

    //假设这是iframe页

    var index = parent.layer.getFrameIndex(window.name);

    //先得到当前iframe层的索引

    parent.layer.close(index); //再执行关闭

    4.7 layer.iframeAuto(index),指定iframe层自适应;

    调用该方法时,iframe层的高度会重新进行适应;

    4.8 layer.iframeSrc(index, url),重置特定iframe url;

    似乎不怎么常用的样子。使用方式:layer.iframeSrc(index,

    'http://sentsin.com')

    4.9 layer.setTop(layero),置顶当前窗口;

    非常强大的一个方法,虽然一般很少用。但是当你的页面有很多很多layer窗口,你需要像Window窗体那样,点击某个窗口,该窗体就置顶在上面,那么setTop可以来轻松实现。它采用巧妙的逻辑,以使这种置顶的性能达到最优

    //通过这种方式弹出的层,每当它被选择,就会置顶。

    layer.open({

    type: 2,

    shade: false,

    area: '500px',

    maxmin: true,

    content: 'http://www.layui.com',

    zIndex: layer.zIndex, //重点1

    success: function(layero){

    layer.setTop(layero);

    //重点2

    }

    });

    4.10

    layer.full()、layer.min()、layer.restore(),手工执行最大小化、还原;

    一般用于在自定义元素上触发最大化、最小化和全屏。

    5 其他弹出层

    5.1 layer.prompt(options, yes),输入层;

    prompt的参数也是向前补齐的。options不仅可支持传入基础参数,还可以传入prompt专用的属性。当然,也可以不传。yes携带value

    表单值index 索引elem 表单元素

    //prompt层新定制的成员如下

    {

    formType: 1,

    //输入框类型,支持0(文本)默认1(密码)2(多行文本)

    value: '', //初始时的值,默认空字符

    maxlength: 140, //可输入文本的最大长度,默认500

    }

    //例子1

    layer.prompt(function(value, index, elem){

    ; //得到value

    layer.close(index);

    });

    //例子2

    layer.prompt({

    formType: 2,

    value: '初始值',

    title: '请输入值',

    area: ['800px', '350px'] //自定义文本域宽高

    }, function(value, index, elem){

    ; //得到value

    layer.close(index);

    });

    5.2 layer.tab(options),tab层(强大!!!);

    tab层只单独定制了一个成员,即tab: [],这个好像没有什么可介绍的,简单粗暴看例子

    layer.tab({

    area: ['600px', '300px'],

    tab: [{

    title:

    'TAB1',

    content: '内容1'

    }, {

    title:

    'TAB2',

    content: '内容2'

    }, {

    title:

    'TAB3',

    content: '内容3'

    }]

    });

    5.3 layer.photos(options),相册层;

    相册层=图片查看器。它的出场动画从layer内置的动画类型中随机展现。photos支持传入json和直接读取页面图片两种方式。

    这块功能参考官方文档,因为需要看下效果图!官方文档:http://www.layui.com/doc/modules/layer.html#layer.photos

    小结

    平时经常使用的消息对话框、状态提示信息、弹窗、输入框、图片查看器,还有弹出选项卡这些功能就是layer具备的能力!设计简洁功能多样!可以说很强大!

    参考官方文档:http://www.layui.com/doc/

    展开全文
  • Unity 基础 之 Layer(层layer) 、LayerMask (遮罩层) 的 总结 和 使用(CullingMask、Ray 射线的使用等) 目录 Unity 基础 之 Layer(层layer) 、LayerMask (遮罩层) 的 总结 和 使用(CullingMask、Ray 射线的...

    Unity 基础 之 Layer(层layer) 、LayerMask (遮罩层) 的 总结 和 使用(CullingMask、Ray 射线的使用等)

     

    目录

    Unity 基础 之 Layer(层layer) 、LayerMask (遮罩层) 的 总结 和 使用(CullingMask、Ray 射线的使用等)

    一、简单介绍

    二、layer 层查看与创建

    layer 层查

    layer 层创建

    三、层的设置(手动设置和代码设置)

    层的手动设置

    层的代码设置

    四、LayerMask 的介绍和使用

    LayerMask 的介绍

    LayerMask 的使用(Main Camera CullingMask)

    LayerMask 的使用(Physics.Raycast)

    附录:

    1、批量获取GameObject 及底下子节点的Layer层

    2、批量设置GameObject 及子节点同一个Layer层


     

    一、简单介绍

    Unity中的一些基础知识点。

    本节介绍,在Unity 应用的时候,层和层遮罩的创建和使用。

     

    官网:Layers are most commonly used by Cameras to render only a part of the scene, and by Lights to illuminate only parts of the scene. But they can also be used by raycasting to selectively ignore colliders or to create collisions


    中文:Layers通常被摄像机用来渲染部分场景,和灯光照射部分场景使用。但是它们也可以用来做射线检测时忽略一些collder或Collision使用

     

    Unity中是用int32来表示32个Layer层。int32表示二进制一共有32位(0—31)

    在Unity中每个GameObject都有Layer属性,默认的Layer都是Default。在Unity中可编辑的Layer共有24个(8—31层),官方已使用的是0—7层,默认不可编辑!

     

    二、layer 层查看与创建

    layer 层查

    1、任意选择场景中的一个 GameObject 即可查看该 GameObject 所在的层

     

    2、前面的序号是所在层序号

     

    layer 层创建

    1、点击 Add Layer...

     

    2、在可以编辑的地方取个一个层名即可

     

    3、你新建的 layer 就会显示在层中

     

    4、前面的序号是所在层序号

     

    三、层的设置(手动设置和代码设置)

    层的手动设置

    1、选择要设置的 GameObject ,点击即可设置为指定层

     

    2、指定 GameObject 设置为指定层

     

    层的代码设置

    // Given a layer name, returns the layer index as defined by either a Builtin or a User Layer in the.

    public static int NameToLayer(string layerName);

    // Given a layer number, returns the name of the layer as defined in either a Builtin or a User Layer in the.

    public static string LayerToName(int layer);

    1、Cube 的 Layer Default

     

    2、代码设置 Cube 的 层

     

    3、运行场景,Cube 设置层为 “TestLayer” 或者对应的层序号 8

     

    4、关键代码

    using UnityEngine;
    
    public class Test_LayerAndLayerMask : MonoBehaviour
    {
    
        public GameObject Cube;
        // Start is called before the first frame update
        void Start()
        {
            SetGameObjectLayer(Cube, "TestLayer");
        }
    
        /// <summary>
        /// 通过层的名称设置层
        /// </summary>
        /// <param name="go"></param>
        /// <param name="layerName"></param>
        private void SetGameObjectLayer(GameObject go, string layerName) {
            int layer = LayerMask.NameToLayer(layerName);
    
            Debug.Log(GetType()+ "/SetGameObjectLayer()/ layer : "+ layer);
    
            SetGameObjectLayer(go, layer);
        }
    
        /// <summary>
        /// 通过层的序号设置层
        /// </summary>
        /// <param name="go"></param>
        /// <param name="layer"></param>
        private void SetGameObjectLayer(GameObject go, int layer) {
            go.layer = layer;
        }
    }

     

    四、LayerMask 的介绍和使用

    LayerMask 的介绍

    LayerMask 实际上是一个位码操作,在Unity3D中一共有32个Layer层,并且不可增加。

     

    位运算符

    按位运算符:~、|、&、^。位运算符主要用来对二进制位进行操作。

    逻辑运算符:&&、||、!。逻辑运算符把语句连接成更复杂的复杂语句。

    按位运算符:左移运算符<<,左移表示乘以2,左移多少位表示乘以2的几次幂。

    例如:var temp = 14 << 2; 表示十进制数14转化为二进制后向左移动2位。

    temp最后计算的值为 14乘以2的平方,temp = 56;

    同理,右移运算符>>,移动多少位表示除以2的几次幂。

     

    Unity 中的使用:

    LayerMask mask = 1 << 3;表示开启Layer3。

    LayerMask mask = 0 << 8;表示关闭Layer8。

    LayerMask mask = 1<<1|1<<9;表示开启Layer1和Layer9。

    LayerMask mask = 0<<4|0<<5;表示关闭Layer4和Layer5。

    LayerMask mask = ~(1 << 0) 打开所有的层。

    LayerMask mask = ~(1 << 9) 打开除了第9之外的层。

     

    上面可以等价为:

    LayerMask mask = ~(1<<2|1<<8);表示关闭Layer2和Layer8。

    LayerMask mask = 1<<3|0<<5;表示开启Layer3并且同时关闭Layer5。

     

    也可以使用层的名称设置,例如:

    LayerMask mask  = 1 << LayerMask.NameToLayer(“TestLayer”);  表示开启层名“TestLayer” 的层 。

    LayerMask mask  = 0 << LayerMask.NameToLayer(“TestLayer”);  表示关闭层名“TestLayer” 的层 。

     

    LayerMask 的使用(Main Camera CullingMask)

    1、开始 Main Camera 的 CullingMask 为 Everything

     

    2、编写脚本,设置 Cube 的 Layer 和 Main Camera 的 CullingMask 为 “TestLayer”

     

    3、运行场景,场景中的 Sphere 就不会显示了

    运行前:

    运行后:

     

    4、关键代码

    using UnityEngine;
    
    public class Test_LayerAndLayerMask : MonoBehaviour
    {
    
        public GameObject Cube;
     
        // Start is called before the first frame update
        void Start()
        {
            SetGameObjectLayer(Cube, "TestLayer");
    
            SetCameraCullingMask("TestLayer");
        }
    
        /// <summary>
        /// 通过层的名称设置层
        /// </summary>
        /// <param name="go"></param>
        /// <param name="layerName"></param>
        private void SetGameObjectLayer(GameObject go, string layerName) {
            int layer = LayerMask.NameToLayer(layerName);
    
            Debug.Log(GetType()+ "/SetGameObjectLayer()/ layer : "+ layer);
    
            SetGameObjectLayer(go, layer);
        }
    
        /// <summary>
        /// 通过层的序号设置层
        /// </summary>
        /// <param name="go"></param>
        /// <param name="layer"></param>
        private void SetGameObjectLayer(GameObject go, int layer) {
            go.layer = layer;
        }
    
    
        /// <summary>
        /// 通过层的名称设置 Camera CullingMask
        /// </summary>
        /// <param name="layerName"></param>
        private void SetCameraCullingMask(string layerName) {
            int layer = LayerMask.NameToLayer(layerName);
            SetCameraCullingMask(layer);
        }
    
        /// <summary>
        /// 通过层的序号设置 Camera CullingMask
        /// </summary>
        /// <param name="layer"></param>
        private void SetCameraCullingMask(int layer)
        {
            Camera.main.cullingMask = 1 << layer;
        }
    }
    

     

    LayerMask 的使用(Physics.Raycast)

     //   layerMask:
     //     A that is used to selectively ignore Colliders when casting a ray.

    public static bool Raycast(Vector3 origin, Vector3 direction,  float maxDistance, int layerMask,  QueryTriggerInteraction queryTriggerInteraction);

    RaycastHit hit;
    Ray ray = Camera.main.ScreenPointToRay(Input.mousePosition);
    if (Physics.Raycast(ray, out hit, 1000, 1<<LayerMask.NameToLayer("TestLayer")))
    {
           Log.Debug(" hit :" + hit.point );
    }
    else
    {
           Log.Debug("ray cast null!");
    }

     

    附录:

    1、批量获取GameObject 及底下子节点的Layer层

    private void SetLayerToTheTransAndChildren(Transform theTrans, string layerName) {
            try{
                int[] layers = new int[theTrans.GetComponentsInChildren<Transform>()];
                foreach (Transform tran in theTrans.GetComponentsInChildren<Transform>())
                {//遍历当前物体及其所有子物体
                    tran.gameObject.layer = LayerMask.NameToLayer(layerName);//更改物体的Layer层 NoWrieframeEffect
                }
            }
            catch (Exception e)
            {
                  Debug.Log(e);
            }
    }
     
    
    
    private int[] GetGoLayers(GameObject go)
     {
          try
          {
              var childTransform= go.GetComponentsInChildren<Transform>();
              int[] layers = new int[childTransform.Length];
              for (int i = 0; i < childTransform.Length; i++)
              {
                  layers[i] = childTransform[i].gameObject.layer;
              }
              return layers;
          }
          catch (Exception e)
          {
                  Debug.Log(e);
          }
      }
    

     

    2、批量设置GameObject 及子节点同一个Layer层

    private void SetLayerToTheTransAndChildren(Transform theTrans, string layerName) {
            foreach (Transform tran in theTrans.GetComponentsInChildren<Transform>())
            {//遍历当前物体及其所有子物体
                tran.gameObject.layer = LayerMask.NameToLayer(layerName);//更改物体的Layer层 NoWrieframeEffect
            }
        }
    
    
    
    private void SetGoLayers(GameObject go, int layer)
      {
           try
           {
               var childrenTrans = go.GetComponentsInChildren<Transform>();
               for (int i = 0; i < childrenTrans.Length; i++)
               {
                   childrenTrans[i].gameObject.layer = layer;
               }
           }
           catch (Exception e)
           {
               Debug.LogError(e.ToString());
           }
       }

     

    展开全文
  • Each Layer has: Z order Alpha value from 0 to 255 visibleRegion crop region transformation: rotate 0, 90, 180, 270: flip H, V: scale 当多个Layer进行合成的时候,并不是整个Layer的空间都会被完全显示,...

    前言

    上一篇我们分析了,app与SurfaceFlinger建立连接的过程,现在我们就可以继续往下分析,看下创建Surface的过程。

    我们可以将Surface理解为一个绘图表面,Android应用程序负责往这个绘图表面上填内容,而SurfaceFlinger服务负责将这个绘图表面的内容取出来,并且渲染在显示屏上。

    Android 图形架构 之一 ——概述
    Android 图形架构 之二—— SurfaceFlinger 启动和连接
    Android 图形架构 之三—— 创建Layer、Surface、SurfaceControl
    Android 图形架构 之四——图形缓冲区的申请和消费流程及核心类
    Android 图形架构 之五——深入分析addView所发生的的一切
    Android 图形架构 之六——深入分析draw()是如何工作的
    Android 图形架构 之七——Choreographer 源码分析
    Android图形架构 之八——硬件VSync、VSync-app、Vsync-sf

    概述

    在Android中,Window与Surface一一对应。 如果说Window关心的是层次和布局,是从设计者角度定义的类,Surface则从实现角度出发,是工程师关系和考虑的类。Window的内容是变化 的,Surface需要有空间来记录每个时刻Window的内容。

    在Android的SurfaceFlinger实现里,使用了三缓冲,保证了界面更新的稳定性和低延时。可参考这篇文章 了解更多

    SurfaceFlinger 是运行在独立进程的Service, 它接收所有Window的Surface作为输入,根据Z-Order, 透明度,大小,位置等参数,计算出每个Surface在最终合成图像中的位置,然后交由HWComposer或OpenGL生成最终的显示Buffer, 然后显示到特定的显示设备上。SurfaceFlinger的会定期检查所有Layer的参数更新(LayerStack等),计算新的DirtyRegion,然后将结果推送给底层显示驱动进行显示。

    在SurfaceFlinger服务中,绘图使用Layer类来描述。Layer是SurfaceFlinger 进行合成的基本操作单元。当应用创建Surface的时候在SurfaceFlinger内部创建Layer,因此一个Surface对应一个 Layer, 但注意,Surface不一定对应于Window,Android中有些Surface并不跟某个Window相关,而是有程序直接创建,比如说 StrictMode, 一块红色的背景,用于提示示Java代码中的一些异常, 还有SurfaceView, 用于显示有硬件输出的视频内容等。

    Each Layer has:

    • Z order
    • Alpha value from 0 to 255
    • visibleRegion
    • crop region
    • transformation: rotate 0, 90, 180, 270: flip H, V: scale

    当多个Layer进行合成的时候,并不是整个Layer的空间都会被完全显示,根据这个Layer最终的显示效果,一个Layer可以被划分成很多的Region, Android SurfaceFlinger 定义了以下一些Region类型:

    • TransparantRegion: 完全透明的区域,在它之下的区域将被显示出来。
    • OpaqueRegion: 完全不透明的区域,是否显示取决于它上面是否有遮挡或是否透明。
    • VisibleRegion: 可见区域,包括完全不透明无遮挡区域或半透明区域。 visibleRegion = Region - above OpaqueRegion.
    • CoveredRegion: 被遮挡区域,在它之上,有不透明或半透明区域。
    • DirtyRegion: 可见部分改变区域,包括新的被遮挡区域,和新的露出区域。

    Android 系统支持多种显示设备,比如说,输出到手机屏幕,或者通过WiFi 投射到电视屏幕。Android用DisplayDevice类来表示这样的设备。不是所有的Layer都会输出到所有的Display, 比如说,我们可以只将Video Layer投射到电视, 而非整个屏幕。LayerStack 就是为此设计,LayerStack 是一个Display 对象的一个数值, 而类Layer里成员State结构体也有成员变量mLayerStack, 只有两者的mLayerStack 值相同,Layer才会被输出到给该Display设备。所以LayerStack 决定了每个Display设备上可以显示的Layer数目。

    上面描述的几个概念,均是针对于显示这个层面,更多是涉及到中下层模块,应用层并不参与也无需关心。对于应用而言,它关心的是如何将内容画出来。Canvas 是Java层定义的一个类,它对应与Surface上的某个区域并提供了很多的2D绘制函数(借助于底层的Skia或OpenGL)。应用只需通过 LockCanvas() 来获取一个Canvas对象,并调用它的绘画方法,然后 unLockCanvasAndPost()来通知底层将更新内容进行显示。当然,并不是所有应用程序都需要直接操作Canva, 事实上只有少量应用需要直接操作Canvas, Android提供了很多封装好的控件 Widget,应用只需提供素材,如文字,图片,属性等等,这些控件会调用Canvas提供的接口帮用户完成绘制工作。

    一、App进程中 相关 过程分析

    下图是主要函数的时序图,接下来我们分析,如何调用和获取 SurfaceFlinger、SurfaceControl、Surface。也就是从下图中的第8步,开始分析, 在后续的文章会分析第8步之前的流程
    在这里插入图片描述

    和Native 层创建Surface 一样,通过 SurfaceFlinger,先创建一个SurfaceControl,然后利用SurfaceControl创建Surface。下面就来具体看看在Java层是如何实现的,其实都是通过jni 调用对应的Native函数

    1.1、创建SurfaceSession

    代码位于frameworks/base/core/java/android/view/SurfaceSession.java:

    代码一:
    public final class SurfaceSession {
        // Note: This field is accessed by native code.
        private long mNativeClient; // SurfaceComposerClient*
        
        private static native long nativeCreate();
        
        /** Create a new connection with the surface flinger. */
        public SurfaceSession() {
            mNativeClient = nativeCreate();
        }
    }    
    

    nativeCreate 是一个JNI调用,来看看对应代码frameworks/base/core/jni/android_view_SurfaceSession.cpp:

    代码二:
    static jlong nativeCreate(JNIEnv* env, jclass clazz) {
        //SurfaceComposerClient专门用来和surfaceflinger建立connection(ISurfaceComposerClient)
        SurfaceComposerClient* client = new SurfaceComposerClient();
        client->incStrong((void*)nativeCreate);
        return reinterpret_cast<jlong>(client);
    }
    

    在文章Android 图形架构 之二—— SurfaceFlinger 启动和连接介绍过,SurfaceFlinger 进行通信的就是通过SurfaceComposerClient,他们是进程间通信,在SurfaceComposerClient中有对应的Binder代理对象mClient,对应 SurfaceFlinger 的Binder本地 Client 对象。

    在SurfaceSession中获取到了SurfaceComposerClient对象,接下来就可以与SurfaceFlinger 进行通信了。

    1.2、创建SurfaceControl

    在App进程中,每一个界面都用一个Surface对象来描述,每一个Surface对象都是由一个SurfaceControl对象来创建的。Surface类和SurfaceControl类的关系以及实现如图所示:

    在这里插入图片描述

    位于frameworks/native/libs/gui/SurfaceControl.java:

    代码三:
    public SurfaceControl(SurfaceSession session,
            String name, int w, int h, int format, int flags)
                    throws OutOfResourcesException {
        ......
        mName = name;
        //调用nativeCreate本地方法
        mNativeObject = nativeCreate(session, name, w, h, format, flags);
        ......
    }
    private final String mName;
    long mNativeObject; // package visibility only for Surface.java access
    private static native long nativeCreate(SurfaceSession session, String name,
            int w, int h, int format, int flags)
            throws OutOfResourcesException;
    

    nativeCreate 是一个JNI调用,来看看对应代码frameworks/base/core/jni/android_view_SurfaceControl.cpp:

    代码四:
    static jlong nativeCreate(JNIEnv* env, jclass clazz, jobject sessionObj,
            jstring nameStr, jint w, jint h, jint format, jint flags) {
        ScopedUtfChars name(env, nameStr);
        sp<SurfaceComposerClient> client(android_view_SurfaceSession_getClient(env, sessionObj));
        //调用SurfaceComposerClient的createSurface,就会调用到代码五的createSurfaceChecked,在Native层,
        //createSurface 返回是的 SurfaceControl 对象
        sp<SurfaceControl> surface = client->createSurface(
                String8(name.c_str()), w, h, format, flags);
        。。。
        surface->incStrong((void *)nativeCreate);
        return reinterpret_cast<jlong>(surface.get());
    }
    

    调用到SurfaceComposerClient类的createSurfaceChecked,创建Layer(到SurfaceFling进程中)和Surface(在App进程中)

    代码五:
    status_t SurfaceComposerClient::createSurfaceChecked(const String8& name, uint32_t w, uint32_t h,
                                                         PixelFormat format,
                                                         sp<SurfaceControl>* outSurface, uint32_t flags,
                                                         SurfaceControl* parent,
                                                         LayerMetadata metadata) {
        sp<SurfaceControl> sur;
        status_t err = mStatus;
    
        if (mStatus == NO_ERROR) {
            sp<IBinder> handle;
            sp<IBinder> parentHandle;
            sp<IGraphicBufferProducer> gbp;
    
            if (parent != nullptr) {
                parentHandle = parent->getHandle();
            }
    		// 这里是创建Layer,使用mClient 进程间通信,最终在Client类中进行具体操作
            err = mClient->createSurface(name, w, h, format, flags, parentHandle, std::move(metadata),
                                         &handle, &gbp);
    
            if (err == NO_ERROR) {
                //创建一个SurfaceControl,使用它创建surface
                *outSurface = new SurfaceControl(this, handle, gbp, true /* owned */);
            }
        }
        return err;
    }
    

    该函数的流程图如下
    在这里插入图片描述

    在文章Android 图形架构 之二—— SurfaceFlinger 启动和连接分析过,SurfaceComposerClient中的mClient 是通过SurfaceFling进程返回的,用于进程间通信。所以mClient->createSurface 会调用到SurfaceFling进程中。

    下面先分析 new SurfaceControl流程(上图第11步之后)。后面章节再分析SurfaceFling进程的mClient->createSurface流程(上图第2步之后)

    SurfaceControl的构造函数也比较简单,位于frameworks/native/libs/gui/SurfaceControl.cpp中:

    代码六:
    SurfaceControl::SurfaceControl(
            const sp<SurfaceComposerClient>& client,
            const sp<IBinder>& handle,
            const sp<IGraphicBufferProducer>& gbp,
            bool owned)
        : mClient(client), mHandle(handle), mGraphicBufferProducer(gbp), mOwned(owned)
    {
    }
    
    • SurfaceControl类的成员变量mClient是一个类型为SurfaceComposerClient对象,Android应用程序主要就是通过SurfaceComposerClient来和SurfaceFlinger服务建立连接的

    • SurfaceControl类的成员变量mHandle是指向创建Layer时,将Layer和SurfaceFlinger作为构造函数的参数创建一个Handle对象,这个Handle是一个Binder的实现,就是标识Surface的全局唯一性。

    • SurfaceControl类的成员变量mGraphicBufferProducer是指向Layer中的gbp参数,

    • SurfaceControl类的成员变量mSurfaceData是一个类型为Surface的强指针,它指向了一个Surface对象。

    1.3、 创建Surface

    从SurfaceControl获取Surface信息。位于frameworks/base/core/java/android/view/Surface.java:

    代码七:
    public void copyFrom(SurfaceControl other) {
        。。。 
    
        long surfaceControlPtr = other.mNativeObject;
        。。。
        //在Native层创建surface,并返回给newNativeObject
        //代码八分析
        long newNativeObject = nativeCreateFromSurfaceControl(surfaceControlPtr);
    
        synchronized (mLock) {
            if (mNativeObject != 0) {
                nativeRelease(mNativeObject);
            }
            //把Native的surface 句柄 ,赋值给java层的surface 的成员变量
            //代码十一分析
            setNativeObjectLocked(newNativeObject);
        }
    }
    

    nativeCreateFromSurfaceControl 是jni调用
    对应的代码 位于 frameworks/base/core/jni/android_view_Surface.cpp:

    代码八:
    static jlong nativeCreateFromSurfaceControl(JNIEnv* env, jclass clazz,
            jlong surfaceControlNativeObj) {
        sp<SurfaceControl> ctrl(reinterpret_cast<SurfaceControl *>(surfaceControlNativeObj));
         //调用SurfaceControl的getSurface函数,最终会调用代码九 generateSurfaceLocked,创建了Native层的surface,
        sp<Surface> surface(ctrl->getSurface());
        if (surface != NULL) {
            surface->incStrong(&sRefBaseOwner);
        }
        return reinterpret_cast<jlong>(surface.get());
    }
    

    最终调用到SurfaceControl的generateSurfaceLocked() ,来创建一个Surface

    代码九:
    sp<Surface> SurfaceControl::generateSurfaceLocked() const
    {
        // This surface is always consumed by SurfaceFlinger, so the
        // producerControlledByApp value doesn't matter; using false.
        mSurfaceData = new Surface(mGraphicBufferProducer, false);
    
        return mSurfaceData;
    }
    

    参数 mGraphicBufferProducer 是Layer中的gbp 参数,它是一个sp< IGraphicBufferProducer > 类型的对象,MonitoredProducer只是一个代理类,真正的实现是producer参数。

    Android系统是通过OpenGL库来绘制UI的。OpenGL库在绘制UI的时候,需要底层的系统提供一个本地窗口给它,以便它可以将UI绘制在这个本地窗口上。Android系统为OpenGL库定提供的本地窗口是ANativeWindow,Surface类通过ANativeObjectBase类间接地继承了ANativeWindow类,因此,Surface类就是一个本地窗口。因此可以将Surface类看作OpenGL库与Android的UI系统之间的一个桥梁。

    看看Surface的构造函数,位于frameworks/native/libs/gui/Surface.cpp:

    代码十:
    Surface::Surface(const sp<IGraphicBufferProducer>& bufferProducer, bool controlledByApp)
          : mGraphicBufferProducer(bufferProducer),
            mCrop(Rect::EMPTY_RECT),
            mBufferAge(0),
            mGenerationNumber(0),
            mSharedBufferMode(false),
            mAutoRefresh(false),
            mSharedBufferSlot(BufferItem::INVALID_BUFFER_SLOT),
            mSharedBufferHasBeenQueued(false),
            mQueriedSupportedTimestamps(false),
            mFrameTimestampsSupportsPresent(false),
            mEnableFrameTimestamps(false),
            mFrameEventHistory(std::make_unique<ProducerFrameEventHistory>()) {
        // Initialize the ANativeWindow function pointers.
        ANativeWindow::setSwapInterval  = hook_setSwapInterval;
        ANativeWindow::dequeueBuffer    = hook_dequeueBuffer;
        ANativeWindow::cancelBuffer     = hook_cancelBuffer;
        ANativeWindow::queueBuffer      = hook_queueBuffer;
        ANativeWindow::query            = hook_query;
        ANativeWindow::perform          = hook_perform;
    
        ANativeWindow::dequeueBuffer_DEPRECATED = hook_dequeueBuffer_DEPRECATED;
        ANativeWindow::cancelBuffer_DEPRECATED  = hook_cancelBuffer_DEPRECATED;
        ANativeWindow::lockBuffer_DEPRECATED    = hook_lockBuffer_DEPRECATED;
        ANativeWindow::queueBuffer_DEPRECATED   = hook_queueBuffer_DEPRECATED;
    
        const_cast<int&>(ANativeWindow::minSwapInterval) = 0;
        const_cast<int&>(ANativeWindow::maxSwapInterval) = 1;
    
        mReqWidth = 0;
        mReqHeight = 0;
        mReqFormat = 0;
        mReqUsage = 0;
        mTimestamp = NATIVE_WINDOW_TIMESTAMP_AUTO;
        mDataSpace = Dataspace::UNKNOWN;
        mScalingMode = NATIVE_WINDOW_SCALING_MODE_FREEZE;
        mTransform = 0;
        mStickyTransform = 0;
        mDefaultWidth = 0;
        mDefaultHeight = 0;
        mUserWidth = 0;
        mUserHeight = 0;
        mTransformHint = 0;
        mConsumerRunningBehind = false;
        mConnectedToCpu = false;
        mProducerControlledByApp = controlledByApp;
        mSwapIntervalZero = false;
    }
    

    主要是设置了一些钩子方法,用于创建GraphicBuffer等等。还有一些变量的初始化。所以重点应该在这些钩子方法当中。

    Surface 创建完成了,回到代码七,继续执行 setNativeObjectLocked()

    代码十一:
        private void setNativeObjectLocked(long ptr) {
            //句柄值,是否与上一次的一样
            if (mNativeObject != ptr) {
                if (mNativeObject == 0 && ptr != 0) {
                    mCloseGuard.open("release");
                } else if (mNativeObject != 0 && ptr == 0) {
                    mCloseGuard.close();
                }
                //赋值句柄值,到surface 的成员变量mNativeObject
                mNativeObject = ptr;
                mGenerationId += 1;
                if (mHwuiContext != null) {
                    mHwuiContext.updateSurface();
                }
            }
        }
    

    到此,Layer、Surface、SurfaceControl 的创建过程,分析完了,但是前后的流程还不完整。
    例如: -> java 层surface -> native 层 surface ,谁来调用java层的,也就是这个? 是什么样的逻辑,实现什么功能。在文章Android 图形架构 之五—— 深入分析addView所发生的的一切进行了详细分析

    下面我们接着上面代码五的流程分析 mClient->createSurface ,进入到SurfaceFlinger进程中

    二、 SurfaceFlinger进程中创建Layer

    Android应用程序主要就是通过SurfaceComposerClient来和SurfaceFlinger服务建立连接,建立完成后,会得到一个Client的Binder代理对象,保存变量mClient中。(这个过程查看 Android 图形架构 之二—— SurfaceFlinger 启动和连接

    2.1、 Layer创建

    因为mClient 是Client 的代理对象,所以会执行到 SurfaceFling进程中 Client的createSurface 函数
    在frameworks/native/services/surfaceflinger/Client.cpp中

    代码十二:
    status_t Client::createSurface(const String8& name, uint32_t w, uint32_t h, PixelFormat format,
                                   uint32_t flags, const sp<IBinder>& parentHandle,
                                   LayerMetadata metadata, sp<IBinder>* handle,
                                   sp<IGraphicBufferProducer>* gbp) {
        // We rely on createLayer to check permissions.
        //这个mFlinger 就是SurfaceFlinger对象
        return mFlinger->createLayer(name, this, w, h, format, flags, std::move(metadata), handle, gbp,
                                     parentHandle);
    }
    

    下面来看看SurfaceFlinger的createLayer函数

    代码十三:
    status_t SurfaceFlinger::createLayer(const String8& name, const sp<Client>& client, uint32_t w,
                                         uint32_t h, PixelFormat format, uint32_t flags,
                                         LayerMetadata metadata, sp<IBinder>* handle,
                                         sp<IGraphicBufferProducer>* gbp,
                                         const sp<IBinder>& parentHandle,
                                         const sp<Layer>& parentLayer) {
    
    
         。。。省略代码。。。
        switch (flags & ISurfaceComposerClient::eFXSurfaceMask) {
            case ISurfaceComposerClient::eFXSurfaceBufferQueue:
                result = createBufferQueueLayer(client, uniqueName, w, h, flags, std::move(metadata),
                                                format, handle, gbp, &layer);
    
                break;
            。。。省略代码,这里是有多种Layer的,由于时间和能力有限、暂不分析其他的Layer,和本系列文章关系最紧要的就是BufferQueueLayer。。。
            default:
                result = BAD_VALUE;
                break;
        }
    
        if (result != NO_ERROR) {
            return result;
        }
    
        if (primaryDisplayOnly) {
            layer->setPrimaryDisplayOnly();
        }
    
        bool addToCurrentState = callingThreadHasUnscopedSurfaceFlingerAccess();
        result = addClientLayer(client, *handle, *gbp, layer, parentHandle, parentLayer,
                                addToCurrentState);
        if (result != NO_ERROR) {
            return result;
        }
        mInterceptor->saveSurfaceCreation(layer);
    
        setTransactionFlags(eTransactionNeeded);
        return result;
    }
    

    下面来看看createBufferQueueLayer

    代码十四:
    status_t SurfaceFlinger::createBufferQueueLayer(const sp<Client>& client, const String8& name,
                                                    uint32_t w, uint32_t h, uint32_t flags,
                                                    LayerMetadata metadata, PixelFormat& format,
                                                    sp<IBinder>* handle,
                                                    sp<IGraphicBufferProducer>* gbp,
                                                    sp<Layer>* outLayer) {
        // initialize the surfaces
        switch (format) {
        case PIXEL_FORMAT_TRANSPARENT:
        case PIXEL_FORMAT_TRANSLUCENT:
            format = PIXEL_FORMAT_RGBA_8888;
            break;
        case PIXEL_FORMAT_OPAQUE:
            format = PIXEL_FORMAT_RGBX_8888;
            break;
        }
    	//使用工厂模式,创建BufferQueueLayer,
        sp<BufferQueueLayer> layer = getFactory().createBufferQueueLayer(
                LayerCreationArgs(this, client, name, w, h, flags, std::move(metadata)));
        //设置layer的缓冲区默认属性        
        status_t err = layer->setDefaultBufferProperties(w, h, format);
        if (err == NO_ERROR) {
            //参数handle 和 gbp,在创建应用端 的surface 使用到了,下面会分析
            *handle = layer->getHandle();
            *gbp = layer->getProducer();
            *outLayer = layer;
        }
    
        ALOGE_IF(err, "createBufferQueueLayer() failed (%s)", strerror(-err));
        return err;
    }
    

    BufferQueueLayer 继承了BufferLayer,后者继承了Layer,主要是在Layer构造函数中进行了一些初始化的工作,宽高、z轴、透明度等(其实很多值 的含义,我还不知道)

    代码十五:
    BufferQueueLayer::BufferQueueLayer(const LayerCreationArgs& args) : BufferLayer(args) {}
    
    

    对象第一次被赋值给强指针会调用onFirstRef函数:

    代码十六:
    void BufferQueueLayer::onFirstRef() {
        BufferLayer::onFirstRef();
    
        // Creates a custom BufferQueue for SurfaceFlingerConsumer to use
        //创建了生产者和消费者缓冲区,这两个缓冲区将来会存放UI的内容数据
        //这里是重点,会面会有文章详细分析
        sp<IGraphicBufferProducer> producer;
        sp<IGraphicBufferConsumer> consumer;
        //BufferQueue创建图形缓冲区管理成员,我们以后分析图形缓冲区管理会讲到
        BufferQueue::createBufferQueue(&producer, &consumer, true);
        //new 一个 生成者,它继承了BnGraphicBufferProducer,MonitoredProducer只是一个代理类,真正的实现是producer参数。
        // *gbp 就是mProducer
        mProducer = new MonitoredProducer(producer, mFlinger, this);
        {
            // Grab the SF state lock during this since it's the only safe way to access RenderEngine
            Mutex::Autolock lock(mFlinger->mStateLock);
            //new 一个 消费者,
            mConsumer = new BufferLayerConsumer(consumer, mFlinger->getRenderEngine(), mTextureName, this);
        }
        //消费者相关设置
        mConsumer->setConsumerUsageBits(getEffectiveUsage(0));
        mConsumer->setContentsChangedListener(this);
        mConsumer->setName(mName);
    
        // BufferQueueCore::mMaxDequeuedBufferCount is default to 1
        if (!mFlinger->isLayerTripleBufferingDisabled()) {
            //如果不是三级缓冲,就使用两级缓冲
            mProducer->setMaxDequeuedBufferCount(2);
        }
        //获取默认显示器
        if (const auto display = mFlinger->getDefaultDisplayDevice()) {
            //
            updateTransformHint(display);
        }
    }
    

    *gbp = layer->getProducer(); 这里就是返回mProducer 给*gbp ,类型是sp< IGraphicBufferProducer >

    下面来看看 *handle = layer->getHandle();

    代码十七:
    sp<IBinder> Layer::getHandle() {
        Mutex::Autolock _l(mLock);
        if (mGetHandleCalled) {
            ALOGE("Get handle called twice" );
            return nullptr;
        }
        mGetHandleCalled = true;
        return new Handle(mFlinger, this);
    }
    
        class Handle : public BBinder, public LayerCleaner {
        public:
            Handle(const sp<SurfaceFlinger>& flinger, const sp<Layer>& layer)
                  : LayerCleaner(flinger, layer), owner(layer) {}
    
            wp<Layer> owner;
        };
    
    

    新建一个Handle,而这个Handle只是一个Binder的实现,每一个Layer 对应一个Handle

    至此,Layer创建的粗略流程,分析完了

    请点赞、收藏,感谢大家的支持,欢迎评论区提问、吐槽

    展开全文
  • 区块链Layer2真能化腐朽为神奇吗

    千次阅读 2022-02-23 22:19:30
    写这篇文章的初衷是想回答前段时间一个朋友提出的问题:“Arbitrum和币安智能链用起来感觉差不多,他俩有什么不一样?一个说是Layer2,一个说是跨链,到底有啥区别?
  • nn.LayerNorm的实现及原理

    万次阅读 2022-02-03 19:33:15
    LayerNorm 在transformer中一般采用LayerNorm,LayerNorm也是归一化的一种方法,与BatchNorm不同的是它是对每单个batch进行的归一化,而batchnorm是对所有batch一起进行归一化的 y=x−E(x)Var(x)+ϵ∗γ+β y = \...
  • LayerNorm

    千次阅读 2021-01-14 10:42:22
    MXnet LayerNorm pytorch LayerNorm 说明 LayerNorm中不会像BatchNorm那样跟踪统计全局的均值方差,因此train()和eval()对LayerNorm没有影响。 LayerNorm参数 torch.nn.LayerNorm( normalized_shape: ...
  • pytorch 层标准化 LayerNorm 的用法

    千次阅读 2022-04-19 17:01:22
    2、LayerNorm 解释 3、举例-只对最后 1 个维度进行标准化 4、举例-对最后 D 个维度进行标准化 1、为什么要标准化(理解的直接跳过到这部分) Batch Normalization 的作用就是把神经元在经过非线性函数映射后向...
  • Unity中SortingLayer、Order in Layer和RenderQueue的讲解

    万次阅读 多人点赞 2020-04-07 15:33:57
    文章目录一.... Sorting Layer2. Order in Layer四. Shader的RenderQueue 一. 前言 Unity游戏开发中,模型、界面、特效等等,需要规划好层的概念,涉及到摄像机(Camera)、画布(Canvas)、Sha...
  • layer弹窗二次确认(ajax请求)

    千次阅读 2019-07-30 12:06:25
    注意:需要引入jquery.js $(function (){ layer.config({ path : 'js/layer.js' }); ...layer.css ....layui-layer-imgbar,.layui-layer-imgtit a,.layui-layer-tab .layui-layer-title span,.la...
  • Layer Normalization解析

    万次阅读 多人点赞 2021-06-07 10:54:19
    原论文名称:Layer Normalization 原论文地址: https://arxiv.org/abs/1607.06450 之前有讲过Batch Normalization的原理,链接,今天来简单讲讲Layer Normalization。Layer Normalization是针对自然语言处理领域...
  • layer iframe

    千次阅读 2019-07-04 09:17:43
    2.layer.open() + iframe + form: 回调操作 3.layer.open + iframe + form: 数据传递 4.<iframe> + form:数据反填, 表单反填数据失败 1. iframe父子操作 2.layer.open() + iframe +form: 回调操作 3....
  • layer.js

    千次阅读 2016-12-15 20:02:48
     我们提到的基础参数主要指调用方法时用到的配置项,如:layer.open({content: ''})layer.msg('', {time: 3})等,其中的content和time即是基础参数,以键值形式存在,基础参数可合理应用于任何层类型中,您不需要...
  • 文章目录方差(Variance)和标准差(Standard Deviation)方差标准差Layer Normalization 计算方法python 手工实现TensorFlow中的计算方式验证两种方式Reference 方差(Variance)和标准差(Standard Deviation) ...
  • 58、Flutter核心原理--绘制原理及Layer

    千次阅读 2022-02-18 10:47:43
    Flutter中和绘制相关的对象有三个,分别是Canvas、Layer 和 Scene: Canvas:封装了Flutter Skia各种绘制指令,比如画线、画圆、画矩形等指令。 Layer:分为容器类和绘制类两种;暂时可以理解为是绘制产物的载体,...
  • layer-list -- layer-list的基本使用介绍

    万次阅读 2018-07-05 13:41:34
    from:https://blog.csdn.net/north1989/article/details/53485729/ 1. layer-list 是啥?有啥作用? 点击查看 安卓官方开发指南中关于layerlsit的...(1). layer-list 是啥?...简单理解,layer 是层,list 是列...
  • layui的layer弹出层内置方法

    千次阅读 2019-08-15 14:42:36
    文章目录基础参数layer.config(options) - 初始化全局配置layer.ready(callback) - 初始化就绪layer.open(options) - 原始核心方法layer.alert(content, options, yes) - 普通信息框layer.confirm(content, options,...
  • Layer Tree 创建

    千次阅读 2018-08-19 16:24:59
    站在老罗的肩膀上:... 网页的Graphics Layer Tree是根据Paint Layer Tree创建的,而Graphics Layer Tree与CC模块创建的Layer Tree的节点是一一对应的关系,如图1所示: 图1 Graphics Layer Tree与CC...
  • 层标准化详解(Layer Normalization)

    万次阅读 2020-05-17 19:18:57
    Torch中的LayerNorm、BatchNorm1D和BatchNorm2D对比 import torch import numpy as np with torch.no_grad(): # LayerNorm基于最后一维统计量执行标准化,即最后一维向量内部执行标准化 print("\n------ TEST ...
  • keras源码分析之Layer

    千次阅读 2019-08-02 17:26:07
    本文主要是对class Layer(object)代码的分析,keras所有的层都是Layer的父类,class Sequential(Model)继承了keras/engine/training.py中的Model类,而Model类则继承了同目录下的keras/engine/topology.py中的...
  • 一、分层 通过借鉴计算机网络通信体系架构的OSI模型,可将区块链逻辑架构划分为三层。 1. layer0 ...其中第0层(Layer 0)对应OSI模型的1-4层(底层协议),...Layer 1 解决信任,Layer 1 的代币的存在是为了让这...
  • 关于tensorflow中layernormalization

    千次阅读 2020-04-22 18:16:41
    众所周知循环神经网络不是十分适合LayerNormalization 关于LayerNormalization:https://blog.csdn.net/liuxiao214/article/details/81037416 LN中同层神经元输入拥有相同的均值和方差,不同的输入样本有不同的均值...
  • layer.prompt弹层

    千次阅读 2020-12-02 13:21:15
    使用layer.open实现方式: 附:源码如下 layer.open({ //formType: 2,//这里依然指定类型是多行文本框,但是在下面content中也可绑定多行文本框在这里插入代码片 title: '是否确信将账号临时挂账?', area: ['300px...
  • BatchNorm和LayerNorm——通俗易懂的理解

    千次阅读 多人点赞 2022-03-08 09:16:28
    以通俗易懂的方式解释了BatchNorm和LayerNorm的原理,并指出它们的区别

空空如也

空空如也

1 2 3 4 5 ... 20
收藏数 536,621
精华内容 214,648
关键字:

layer