egret适配模式

蚀纹容器
• 阅读 4084

项目中,通过devtool模拟器为iphone6/7/8 plus中设备像素为414*736,canvas的宽高为1242 * 2208,根据设计稿配置的内容宽高是750 * 1204,这么多数据到底是怎么计算出来的,如何适配的?
egret适配模式

全局函数 updateAllScreens

这个方法用于刷新所有 Egret 播放器的显示区域尺寸。仅当使用外部 JavaScript 代码动态修改了 Egret 容器大小时,需要手动调用此方法刷新显示区域。当网页尺寸发生改变时(触发 resize 事件)此方法会自动被调用。
这里说的播放器WebPlayer实际上是指有 css 类选择器为 .egret-player的区域,WebPlayer 并不是语义上的播放器意思,而是根据获取的.egret-player dom元素初始化的一个对象。
另外class="egret-player" 这个模版文件的class是webplayer获取的dom的唯一途径要是不小心删了就无法渲染了。

更新播放器视口尺寸

通过container.getBoundingClientRect()分别计算screenWidth、screenHeight,container就是上面所说的webplayer dom元素,通过传以下4个参数调用calculateStageSize方法调整视口。

* 计算舞台显示尺寸
* @param scaleMode 当前的缩放模式
* @param screenWidth 播放器视口宽度 screenRect.width
* @param screenHeight 播放器视口高度 screenRect.height
* @param contentWidth 初始化内容宽度 option.contentWidth
* @param contentHeight 初始化内容高度 option.contentHeight

以设计稿为750 * 1204, iphone6/7/8 plus 414 * 736为例分析各种适配模式下视口尺寸的大小。

// 初始化
let displayWidth = screenWidth; // 414
let displayHeight = screenHeight; // 736
let stageWidth = contentWidth; // 750
let stageHeight = contentHeight; //1204

calculateStageSize方法返回调整后的displayWidth、displayHeight、stageWidth、stageHeight4个参数

FIXED_WIDTH模式

1.计算width缩放比例:scaleX = 视口宽度/内容宽度 = screenWidth/contentWidth = 0.522
2.改变内容高度 :stageHeight = 内容高度= 视口高度/scaleX = 736 / 0.522 = 1333
也就是将内容高度改变从1204变为1333,但由于宽高不是2的整数倍会导致图片绘制出现问题,所以最后调整为1334

根据调整后的视口尺寸和container的宽高计算画布距离container的距离。因为fixed_width模式下视口宽高没有发生变化,所以top、left为0,画布贴合左上角

canvas.style.top = (boundingClientHeight - displayHeight) / 2 + "px";
canvas.style.left = (boundingClientWidth - displayWidth) / 2 + "px";

由于iphone6/7/8plus为dpr为3的高清屏,为了解决1:1像素画布在retina屏下模糊的问题,egret会对画布宽高乘以dpr大小再进行缩放。

let scalex = displayWidth / stageWidth, // 0.552
scaley = displayHeight / stageHeight; // 0.551724138
// 这里的$canvasScaleFactor是window.devicePixelRatio: 3
let canvasScaleX = scalex * sys.DisplayList.$canvasScaleFactor; // 约1.656
let canvasScaleY = scaley * sys.DisplayList.$canvasScaleFactor; // 约1.6551

let m = egret.Matrix.create();
// 初始化
m.identity();
// 这里scalex/(scalex / canvasScaleX)约分之后其实就是1/canvasScaleX,也就是1/3。
m.scale(scalex / canvasScaleX, scaley / canvasScaleY);
m.rotate((rotation * Math.PI) / 180);
/** Matrix的6个参数
a,       b,           c,      d,     x,     y
|        | 旋转或者倾斜 |       |      |      |
|                             |      |      |
|_ _ _ _ _  缩放或旋转 _ _ _ _  |    x偏移    y偏移
*
*/
let transform = `matrix(${m.a},${m.b},${m.c},${m.d},${m.tx},${m.ty})`;
egret.Matrix.release(m);
canvas.style[egret.web.getPrefixStyleName("transform")] = transform;

上面代码最终呈现的效果是transform: matrix(0.333333, 0, 0, 0.333333, 0, 0),使得画布缩放至0.3333倍,通过updateStageSize(stageWidth, stageHeight)方法将画布宽高设置为原来的三倍以适配retina屏。

小结:当fixed_width下的不同手机屏幕设备像素不同时,只会影响内容的高度,这里的内容在egret中指的是舞台stage。回顾下egret对舞台的定义:

在这个树状结构中,处于最上层的是“舞台”。对应到程序中,是stage对象。舞台是Egret显示架构中最根本的显示容器。每个Egret应有且只有一个stage对象。舞台是这个显示树结构的根节点。

通过适配计算出来的内容宽高都将变成stage的宽高,而不是canvas对象的宽高。

其他的适配模式

EXACT\_FIT 不改变适口和内容宽高
  
FIXED\_HEIGHT

1.计算height缩放比例:scaleY = 视口高度/内容高度

2.改变内容宽度  :内容宽度\= 视口宽度/scale


NO\_BORDER

1.分别计算width/height的缩放比例:scaleX,scaleY

2.如果scaleX > scaleY: displayHeight = Math.round(stageHeight \* scaleX);

3.如果scaleY > scaleX: displayWidth = Math.round(stageWidth \* scaleY);


SHOW\_ALL

1.分别计算width/height的缩放比例:scaleX,scaleY

2.如果scaleX > scaleY : displayWidth = Math.round(stageWidth \* scaleY);

3..如果scaleY > scaleX: displayHeight = Math.round(stageHeight \* scaleX);

FIXED\_NARROW

1.分别计算width/height的缩放比例:scaleX,scaleY

2.如果scaleX > scaleY : stageWidth = Math.round(screenWidth / scaleY);

3.如果scaleY> scaleX :  stageHeight = Math.round(screenHeight / scaleX);

FIXED\_WIDE

1.  scaleX > scaleY : stageHeight = Math.round(screenHeight / scaleX)
2.  scaleY > scaleX: stageWidth = Math.round(screenWidth / scaleY)

Default

stageWidth = screenWidth;

stageHeight = screenHeight;

事件位置计算

事件中获取的x,y位置都是相对于视口的位置,因此需要将计算出相对于内容宽高的x,y

private getLocation(event:any):Point {
    event.identifier = +event.identifier || 0;
    let doc = document.documentElement;
    let box = this.canvas.getBoundingClientRect();
    let left = box.left + window.pageXOffset - doc.clientLeft;
    let top = box.top + window.pageYOffset - doc.clientTop;
    let x = event.pageX - left, newx = x;
    let y = event.pageY - top, newy = y;
    if (this.rotation == 90) {
        newx = y;
        newy = box.width - x;
    }
    else if (this.rotation == -90) {
        newx = box.height - y;
        newy = x;
    }
    // 除以视口和内容宽度比值
    newx = newx / this.scaleX;
     // 除以视口和内容的高度比值
    newy = newy / this.scaleY;
    return $TempPoint.setTo(Math.round(newx), Math.round(newy));
}
点赞
收藏
评论区
推荐文章
blmius blmius
4年前
MySQL:[Err] 1292 - Incorrect datetime value: ‘0000-00-00 00:00:00‘ for column ‘CREATE_TIME‘ at row 1
文章目录问题用navicat导入数据时,报错:原因这是因为当前的MySQL不支持datetime为0的情况。解决修改sql\mode:sql\mode:SQLMode定义了MySQL应支持的SQL语法、数据校验等,这样可以更容易地在不同的环境中使用MySQL。全局s
Oracle 分组与拼接字符串同时使用
SELECTT.,ROWNUMIDFROM(SELECTT.EMPLID,T.NAME,T.BU,T.REALDEPART,T.FORMATDATE,SUM(T.S0)S0,MAX(UPDATETIME)CREATETIME,LISTAGG(TOCHAR(
皕杰报表之UUID
​在我们用皕杰报表工具设计填报报表时,如何在新增行里自动增加id呢?能新增整数排序id吗?目前可以在新增行里自动增加id,但只能用uuid函数增加UUID编码,不能新增整数排序id。uuid函数说明:获取一个UUID,可以在填报表中用来创建数据ID语法:uuid()或uuid(sep)参数说明:sep布尔值,生成的uuid中是否包含分隔符'',缺省为
待兔 待兔
1年前
手写Java HashMap源码
HashMap的使用教程HashMap的使用教程HashMap的使用教程HashMap的使用教程HashMap的使用教程22
Karen110 Karen110
4年前
一篇文章带你了解JavaScript日期
日期对象允许您使用日期(年、月、日、小时、分钟、秒和毫秒)。一、JavaScript的日期格式一个JavaScript日期可以写为一个字符串:ThuFeb02201909:59:51GMT0800(中国标准时间)或者是一个数字:1486000791164写数字的日期,指定的毫秒数自1970年1月1日00:00:00到现在。1\.显示日期使用
九路 九路
5年前
图形处理:给 Canvas 文本填充线性渐变
在Canvas中对文本填充水平或垂直的线性渐变可以轻易实现,而带角度的渐变就复杂很多;就好像下面这样,假设文本矩形宽为W,高为H,左上角坐标为X,Y。渐变示例.jpg(https://imghelloworld.osscnbeijing.aliyuncs.com/imgs/48edf7ce289dab3e1972d973aa
Jacquelyn38 Jacquelyn38
4年前
2020年前端实用代码段,为你的工作保驾护航
有空的时候,自己总结了几个代码段,在开发中也经常使用,谢谢。1、使用解构获取json数据let jsonData  id: 1,status: "OK",data: 'a', 'b';let  id, status, data: number   jsonData;console.log(id, status, number )
Stella981 Stella981
4年前
KVM调整cpu和内存
一.修改kvm虚拟机的配置1、virsheditcentos7找到“memory”和“vcpu”标签,将<namecentos7</name<uuid2220a6d1a36a4fbb8523e078b3dfe795</uuid
Stella981 Stella981
4年前
Android So动态加载 优雅实现与原理分析
背景:漫品Android客户端集成适配转换功能(基于目标识别(So库35M)和人脸识别库(5M)),导致apk体积50M左右,为优化客户端体验,决定实现So文件动态加载.!(https://oscimg.oschina.net/oscnet/00d1ff90e4b34869664fef59e3ec3fdd20b.png)点击上方“蓝字”关注我
Stella981 Stella981
4年前
Django中Admin中的一些参数配置
设置在列表中显示的字段,id为django模型默认的主键list_display('id','name','sex','profession','email','qq','phone','status','create_time')设置在列表可编辑字段list_editable
Python进阶者 Python进阶者
2年前
Excel中这日期老是出来00:00:00,怎么用Pandas把这个去除
大家好,我是皮皮。一、前言前几天在Python白银交流群【上海新年人】问了一个Pandas数据筛选的问题。问题如下:这日期老是出来00:00:00,怎么把这个去除。二、实现过程后来【论草莓如何成为冻干莓】给了一个思路和代码如下:pd.toexcel之前把这
蚀纹容器
蚀纹容器
Lv1
慊慊思归恋故乡,君为淹留寄他方。
文章
6
粉丝
0
获赞
0