在开发web的游戏时候,我需要把dom元素放到舞台上,但是我没有找到相应的api可以准确的根据Sprite的位置来确定dom所在的位置,layaair3有一个api是SpiritUtils可以完成这个任务,我不知道在cocos中如何完成这个任务!
为了更方便地在Cocos Creator中使用DOM元素与Cocos节点对齐的功能,我们可以将上述逻辑封装成一个工具库。以下是一个简单的工具库实现:
工具库代码
export class DOMAlignUtils {
/**
* 将DOM元素对齐到Cocos节点
* @param node Cocos节点
* @param domElement DOM元素
* @param offsetX 水平偏移量(可选)
* @param offsetY 垂直偏移量(可选)
*/
public static alignToNode(node: cc.Node, domElement: HTMLElement, offsetX: number = 0, offsetY: number = 0): void {
if (!node || !domElement) {
console.error("Node or DOM element is null!");
return;
}
// 获取节点的世界坐标
const worldPos = node.convertToWorldSpaceAR(cc.v2(0, 0));
// 将世界坐标转换为屏幕坐标
const screenPos = cc.view.projectToScreen(worldPos);
// 设置DOM元素的位置
domElement.style.position = 'absolute';
domElement.style.left = `${screenPos.x + offsetX}px`;
domElement.style.top = `${screenPos.y + offsetY}px`;
}
/**
* 实时更新DOM元素的位置(需要在update中调用)
* @param node Cocos节点
* @param domElement DOM元素
* @param offsetX 水平偏移量(可选)
* @param offsetY 垂直偏移量(可选)
*/
public static updateAlign(node: cc.Node, domElement: HTMLElement, offsetX: number = 0, offsetY: number = 0): void {
this.alignToNode(node, domElement, offsetX, offsetY);
}
}
使用方法
1. 初始化对齐
在需要将DOM元素对齐到Cocos节点的地方调用alignToNode方法:
const node = this.node; // 你的Cocos节点
const domElement = document.getElementById('your-dom-element-id'); // 你的DOM元素
DOMAlignUtils.alignToNode(node, domElement);
2. 实时更新
如果Cocos节点的位置会动态变化,可以在update方法中调用updateAlign来实时更新DOM元素的位置:
update() {
const node = this.node; // 你的Cocos节点
const domElement = document.getElementById('your-dom-element-id'); // 你的DOM元素
DOMAlignUtils.updateAlign(node, domElement);
}
3. 添加偏移量
如果需要调整DOM元素的位置,可以通过offsetX和offsetY参数设置偏移量:
DOMAlignUtils.alignToNode(node, domElement, 10, -20); // 向右偏移10px,向上偏移20px
示例场景
假设你有一个Cocos节点player,并且需要在屏幕上显示一个DOM元素(如血条)跟随该节点移动:
const { ccclass, property } = cc._decorator;
@ccclass
export class PlayerController extends cc.Component {
@property(cc.Node)
player: cc.Node = null; // Cocos节点
private domElement: HTMLElement;
onLoad() {
// 获取DOM元素
this.domElement = document.getElementById('health-bar');
}
start() {
// 初始化对齐
DOMAlignUtils.alignToNode(this.player, this.domElement);
}
update() {
// 实时更新DOM元素位置
DOMAlignUtils.updateAlign(this.player, this.domElement);
}
}
注意事项
-
DOM元素的样式:确保DOM元素的
position设置为absolute或fixed,否则无法通过left和top属性调整位置。 -
性能优化:如果DOM元素较多或需要频繁更新,可以考虑使用
requestAnimationFrame来优化性能。 - 跨平台兼容性:在移动端或某些平台上,DOM元素的支持可能有限,需要测试兼容性。
总结
通过封装这个工具库,你可以轻松地将DOM元素与Cocos节点对齐,并支持实时更新位置。这个工具库可以复用于多个项目,提高开发效率!
这是cocos2的代码,有没有cocos3.8的代码,它们之间的api有很多不一样
2.x也没有这个api啊,是不是被移除了?
用了不少时间,探究出了对齐方案
import { _decorator, Camera, Component, Node, UITransform, Vec3, screen, view } from ‘cc’;
const { ccclass, property } = _decorator;
@ccclass(‘Test’)
export class Test extends Component {
private div:HTMLDivElement;
// @property(Camera)
// public camera:Camera;
start() {
this.div=document.createElement("div");
this.alignDom(this.div,this.node);
}
private alignDom(div:HTMLDivElement,node:Node,zIndex:number=1){
//这一行背景代码仅用作测试,实际中应该删除
div.style.background = "rgba(255,0,0,0.5)";
div.style.position = "absolute";
div.style.zIndex = Math.ceil(zIndex)+"";
let wh=this.getCssSize(this.node);
div.style.width=wh[0]+"px";
div.style.height=wh[1]+"px";
if(!div.parentNode){
document.body.appendChild(div);
}
let wpos = new Vec3();
node.getWorldPosition(wpos);
// 这个是canvas的宽高
let dpi=screen.devicePixelRatio
let viewRect=view.getViewportRect();
let scale_y=view.getViewportRect().height/view.getVisibleSize().height;
let GameCanvas = document.getElementById("GameCanvas") as HTMLCanvasElement;
let bc = GameCanvas.getBoundingClientRect();
let node_x = (wpos.x *view.getScaleX() + viewRect.x) / dpi + bc.x;
let node_y = ((view.getVisibleSize().height - wpos.y) * scale_y + viewRect.y) / dpi + bc.top;
let offsetx=wh[0]*this.getComponent(UITransform).anchorX;
let offsety=wh[1]*(1-this.getComponent(UITransform).anchorY);
div.style.left = node_x-offsetx + "px";
div.style.top = node_y -offsety+ "px";
}
private getCssSize(node:Node){
let scale_y = view.getViewportRect().height / view.getVisibleSize().height;
let wordscale=node.getWorldScale();
let size=node.getComponent(UITransform).contentSize;
let width=size.width*wordscale.x
let height=size.height*wordscale.y;
width=width*view.getScaleX()/screen.devicePixelRatio;
height = height * scale_y /screen.devicePixelRatio;
return [width,height]
}
update(deltaTime: number) {
}
}