一,使用creator3.3.2 分别实现手机端和浏览器的适配效果如下 打包web-mobile(居然会有这种需求 /流汗!)
pc浏览器显示
手机端显示
1、首先在项目中设置分辨率 和默认适配 这里是750*1334,默认以宽度来适配
设置Canvas的widget适配,代码挂在Canvas下,pcBg是pc浏览器显示的如图蓝色区域,代码如下
@property(Node)
pcBg: Node = null;
onLoad() {
let design = view.getDesignResolutionSize(); // 设计分辨率,。就是设置的 750 1334 根据不同端做适配
if(!sys.isMobile)
{// pc端
view.setDesignResolutionSize(design.width, design.height, ResolutionPolicy.FIXED_HEIGHT);
}
else
{// 手机端
view.setDesignResolutionSize(design.width, design.height, ResolutionPolicy.FIXED_WIDTH);
}
this.updateSizeFit();
let _this = this;
// 监听浏览器窗口大小变化
view.setResizeCallback(function () {
_this.updateSizeFit();
// rect.left, rect.top, rect.width, rect.height (像素值)
});
}
// 根据浏览器窗口变化适配
updateSizeFit() {
var rect = view.getVisibleSize();// 获取实际显示的尺寸
var design = view.getDesignResolutionSize();// 获取设计分辨率
let wi = this.node.getComponent(Widget);
// 设置手机端和pc端canvas的显示位置,在pc是横屏的,但是canvas应该是中间的手机位置。所以要左右减
// 实际屏幕宽度的一半减去手机屏宽的一半,就是pcBg距离Canvas左侧的距离
if (!sys.isMobile) { // pc端加背景图,实现中间显示手机界面
wi.right = rect.width/2-(rect.height*design.width/design.height)/2;
wi.left = rect.width/2-(rect.height*design.width/design.height)/2;
wi.top = 0;
wi.bottom = 0;
wi.updateAlignment();
}
else
{ // 手机端 屏幕宽度高,就是canvas的宽高。,距离是0就可以
wi.right = 0;
wi.left = 0;
wi.top = 0;
wi.bottom = 0;
wi.updateAlignment();
}
// pc大背景全屏显示,大背景图平铺到pc上,相对于canvas 左右都是负的宽的的一半
var widget = this.pcBg.getComponent(Widget)
widget.right = -rect.width/2;
widget.left = -rect.width/2;
widget.top = 0;
widget.bottom = 0;
widget.target = this.node;
widget.updateAlignment();
}
2、因为我为了防止近大远小,所以照射角色的相机改成了正交相机
3、还是根据camera的targetTexture,把3d投射到2d显示,把RenderTexture赋值给camera和ui要显示投射的sprite,代码如下
start() {
// 投影 吧3d照射的投影到2d ui上
const renderTex = this.render;
this.cam.targetTexture = renderTex;
this.show3d.spriteFrame.texture = renderTex;
}
4、实现血条跟随主角 ,既然跟随,那血条ui就不能加widget, player3dHps是所有玩家的3d下的血条挂点位置,uiHps是所有血条的sprite,通过worldToScreen,把世界坐标转到ui上的位置,再赋值给血条ui
this.player3dHps.forEach((item, i) => {
// 血条
let ve1 = new Vec3(0, 0, 0)
this.cam.worldToScreen(item.worldPosition, ve1);
this.uiHps[i].worldPosition = ve1
})
但是最终的结果在手机端显示没问题,pc端却是这样的效果
那是因为pc端我们的canvas是中间手机位置,世界坐标转屏幕后,是相对于可是蓝色区域的,不是手机canvas深蓝区域的,所以要+(canvas的widget的左侧偏移-中间canvas区域的宽的一半)这区域
let canvasWidget = find("Canvas").getComponent(Widget)
this.uiHps[i].worldPosition = ve1.add(new Vec3(canvasWidget.left,0,0));
就能得到正确位置了
实际显示在手机还有一些小问题,因为手机端是按照宽度适配的,在实际的屏幕高度和设计高度是不一样,因为如果实际手机屏幕比设计高度要高,会导致血条位置高于头顶很多,先看代码
let canvasWidget = find("Canvas").getComponent(Widget)
let offsetHeight = !sys.isMobile?0: ((view.getVisibleSize().width*design.height/design.width)-view.getVisibleSize().height);// 计算出高度比实际分辨率的差距,
this.uiHps[i].worldPosition = ve1.add(new Vec3(canvasWidget.left,-offsetHeight/2,0));
可以理解为在1334高度下血条y是100,在1600下可能是120,导致超过头顶位置正常值,有时间的同学可以调试一下这个offsetHeight,在手机浏览器上看看就明白了
项目地址 中的 GitHub - SuiFengErQu/cocos-creator3d-mini_demo: cocos creator3.3.2练手小功能 adaptationScreen场景
二、pc端浏览器全屏适配,看代码就明白了,设计分辨率是1920*1280,使用cocos creator2.4.4
测试一下图片 基于Canvas 对齐
onLoad() {
this.updateSizeFit();
let _this = this;
// 监听浏览器窗口大小变化
cc.view.setResizeCallback(function () {
_this.updateSizeFit();
// rect.left, rect.top, rect.width, rect.height (像素值)
});
}
// 根据浏览器窗口变化适配
updateSizeFit() {
var rect = cc.game.canvas.getBoundingClientRect();
let rateWidth = Math.round(rect.width / 1920 * 100) / 100;
let rateHeight = Math.round(rect.height / 1080 * 100) / 100;
// console.log("屏幕发生变化", rateWidth, rateHeight) 手机端和pc参数不同
if (Math.abs(rateWidth - rateHeight) > (GameConfig.getPlatform(true)===GameConfig.PLATFORM.PC?0.2:0.5) || rateWidth == rateHeight) {// 宽高差距太大或者宽高比=,不做适配
cc.Canvas.instance.fitHeight = false;
cc.Canvas.instance.fitWidth = false;
UIModalMgr.inst.updateMaskView();// 更新popUI mask大小
EventCenter.emit(EventCenterNameEnum.ScreenChange);
return;
}
if (rateWidth < rateHeight) {
cc.Canvas.instance.fitHeight = false;
cc.Canvas.instance.fitWidth = true;
}
else if (rateHeight < rateWidth) {
cc.Canvas.instance.fitHeight = true;
cc.Canvas.instance.fitWidth = false;
}
UIModalMgr.inst.updateMaskView();// 更新popUI mask大小
EventCenter.emit(EventCenterNameEnum.ScreenChange);
}
这里实际上就是 计算实际宽度和设计宽度的比例,实际高度和设计高度的比例
当比例一样,或者比例相减的绝对值大于0.2,那就不适配,否则会界面错乱,这里如果是手机端是》0.5,因为手机端的比例差距比较大,所以值调大一些,尽可能适配更多的手机。
如果宽度比例小,那就以宽来适配,否则以高来适配
剩下的就是界面上加widget来调了,可以看一下不同情况下显示效果
超过一定比例不再适配,直接部分被隐藏
手机端显示