白鹭引擎(egret)中锚点(anchoroffset)的位置体会

白鹭引擎(egret,以下简称egret)中对锚点(anchorOffsetX,anchorOffsetY)的使用目的,基本是和CSS3属性中的transform-origin是一致的,大多是基于元素中心的旋转和放大。但使用方法上是有区别的,比如,egret的默认锚点在左上角,而transform-origin默认在元素中心。此外,egret这类工具(还有createjs,pixi等)本身是基于canvas/webgl的画布上进行绘制,如果使用chrome这些调试工具直接调试的话,元素信息无法被浏览器获取,必然给调试增加难度。
纸上得来终觉浅,绝知此事要躬行

1. 锚点的作用

我们以一根线段旋转90度为例:先绘制一根水平的直线,长度为100

protected startCreateScene(): void {
    this.drawOneLine();
}

protected drawOneLine(){
    let ns = new egret.Shape();

    ns.x = 100;
    ns.y = 100;

    ns.graphics.lineStyle(2,0xFF0000);
    ns.graphics.moveTo(0,0);
    ns.graphics.lineTo(100,0);
   
    this.addChild(ns);
}
初始水平线段

现在我们修改下代码,在默认锚点的情况下,旋转90度。为了方便观察,我给线段做了渐变处理,越靠近90度的线段颜色越浅:

protected startCreateScene(): void {
    this.drawLine(0);
}

protected drawLine(angle): void {
    let ns = new egret.Shape();

    ns.x = 100;
    ns.y = 100;

    ns.graphics.lineStyle(2,0xFF0000);
    ns.graphics.moveTo(0,0);
    ns.graphics.lineTo(100,0);
    ns.alpha = 1-(angle/90)*0.9;
    ns.rotation = angle;

    this.addChild(ns);

    if(angle < 90){
        this.drawLine(angle+15);
    }
}

锚点默认时旋转

从图片中我们可以观察到:线段顺时针旋转了90度,中心点位于线段左边的端点

现在我们设置锚点,将中心点居中

protected startCreateScene(): void {
    this.drawLine(0);
    this.drawLineCenter(0);
}

protected drawLineCenter(angle): void {
    let ns = new egret.Shape();

    ns.x = 100;
    ns.y = 300;

    ns.anchorOffsetX = 50; // 设置锚点横坐标,位于线段中心

    ns.graphics.lineStyle(2,0x000000);
    ns.graphics.moveTo(0,0);
    ns.graphics.lineTo(100,0);
    ns.alpha = 1-(angle/90)*0.9;
    ns.rotation = angle;

    this.addChild(ns);

    if(angle < 90){
        this.drawLineCenter(angle+15);
    }
}
锚点设置到线段中心

好了,锚点的示例到此为止。

接下来说这篇文章的关键,上图中,有一个不太正常的地方,即黑色线段往左偏移,这个对于刚接触锚点概念的同学来说,无疑是非常残忍的,说白了就是个坑。明明所有元素都放在其应该出现的位置上,并且实现了动效,所有的属性设置也都正确,怎么元素就偏了呢?我最初发生这种事(createjs里),很不理解,结果从最基础的图片素材开始,把尺寸和位置重新计算一遍,反复查看代码中一切有的没的的配置,最后一点点去掉所有页面中不相关的元素,才能发现是锚点惹的祸。

2. 锚点的正确打开方式

现在,我们仍然以长度100的水平线段为例,将锚点依次设置为0,50,100,观察这三根线段的情况,代码如下:

protected startCreateScene(): void {
    this.drawLineAnchor(100,100,0);
    this.drawLineAnchor(100,150,50);
    this.drawLineAnchor(100,200,100);
}

protected drawLineAnchor(x,y,anchorX):void{
    let ns = new egret.Shape();

    ns.x = x;
    ns.y = y;

    ns.anchorOffsetX = anchorX;

    ns.graphics.lineStyle(2,0x000000);
    ns.graphics.moveTo(0,0);
    ns.graphics.lineTo(100,0);
    this.addChild(ns);
}
从上到下依次为0,50,100

从上图中可以很明显的看到锚点对于画面中真实绘制出线段的影响

即,有元素a,a在画面中实际的横坐标为x',则x' = a.x - a.anchorOffsetX

关键代码实际在于moveTo那一行,比如,当元素根据属性被定位到x=100,y=100后,由于其左上角的锚点由于被设置为anchorOffsetX=50,anchorOffsetY=0的关系,当代码进行到moveTo时,会按照锚点的坐标向左偏移50位置开始绘制初始点。

所以,如果我们必须改变moveTo的初始点和重点,或者改变元素本身的x坐标,才能达到和原线段相同的位置:

protected startCreateScene(): void {
    this.drawLineAnchor(100, 100, 0); 
    this.drawLineAnchorFixMove(100, 150, 50); // 修改起点终点
    this.drawLineAnchorFixX(100, 200, 100); // 修改x坐标
}

protected drawLineAnchor(){...} // 方法略

protected drawLineAnchorFixMove(x, y, anchorX): void {
    let ns = new egret.Shape();

    ns.x = x;
    ns.y = y;

    ns.anchorOffsetX = anchorX;

    ns.graphics.lineStyle(1, 0x000000);
    ns.graphics.moveTo(0 + anchorX, 0); // 修改线段起始点
    ns.graphics.lineTo(100 + anchorX, 0); // 修改线段终点
    this.addChild(ns);
}

protected drawLineAnchorFixX(x, y, anchorX): void {
    let ns = new egret.Shape();

    ns.x = x + anchorX; // 修改整个容器的横坐标
    ns.y = y;

    ns.anchorOffsetX = anchorX;

    ns.graphics.lineStyle(1, 0x000000);
    ns.graphics.moveTo(0, 0);
    ns.graphics.lineTo(100, 0);
    this.addChild(ns);
}
修改后的结果

同理,我们可以得知如果修改了anchorOffsetY会发生怎样的变化,

有元素aa在画面中实际的横坐标为x',纵坐标为y',则
x' = a.x - a.anchorOffsetX
y' = a.y - a.anchorOffsetY

现在大家应该能理解设置锚点之后元素的具体位置了。总之当设置了锚点后,为了回到原位,最通用最简单的做法,就是将其xy减去自己对应的anchorOffset属性

以上。

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 212,332评论 6 493
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 90,508评论 3 385
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 157,812评论 0 348
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 56,607评论 1 284
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 65,728评论 6 386
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 49,919评论 1 290
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 39,071评论 3 410
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 37,802评论 0 268
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 44,256评论 1 303
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 36,576评论 2 327
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 38,712评论 1 341
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 34,389评论 4 332
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 40,032评论 3 316
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 30,798评论 0 21
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,026评论 1 266
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 46,473评论 2 360
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 43,606评论 2 350

推荐阅读更多精彩内容

  • 1.纹理集实际上就是将一些零碎的小图放到一张大图当中。游戏中也经常使用到纹理集。使用纹理集的好处很多,我们通过将大...
    别人家的程序员阅读 8,055评论 1 21
  • 一:canvas简介 1.1什么是canvas? ①:canvas是HTML5提供的一种新标签 ②:HTML5 ...
    GreenHand1阅读 4,674评论 2 32
  • Spring Cloud为开发人员提供了快速构建分布式系统中一些常见模式的工具(例如配置管理,服务发现,断路器,智...
    卡卡罗2017阅读 134,637评论 18 139
  • 娱乐圈每天都在上演着狗血的事情,比如XX给XX求婚,XX和XX结婚,XX其实是小三上位……这种事情犹如轮回一样在娱...
    最爱时尚阅读 374评论 0 0
  • A已经入伙两年了,和一帮兄弟姐妹行骗多年,现在在C国的某岛上和诈骗团伙成员们共30多人集体住在一栋豪华别墅里。 A...
    meilidedoudou阅读 540评论 7 5