对 Angular 中两个或多个 DIV 位置的位置进行动画处理

2024-01-09

我需要帮助来调整动态渲染的 2 个或更多 div 的位置开关。 这是一个简单的例子:

let objects: Array<number> = [];
objects.push(1);
objects.push(2);

模板:

<div *ngFor="let obj of objects">
    content {{object}}
</div>

从模板中,用户可以更改对象的位置,将对象“1”移动到第二个位置,并且对象“2”将成为第一个位置。

我需要一个动画来向用户清楚地展示运动。实际上 DOM 中的结果是这样的:

Before:

<div>
   content 1
</div>
<div>
  content 2
</div>

After:

<div>
   content 2
</div>
<div>
  content 1
</div>

修改源数组,更改元素位置即可获得结果。

我可以使用哪种解决方案?我可以使用更复杂的对象来处理这个问题,这样我就可以在需要时修改代码。

Thanks


我不知道这是否是一个好的解决方案,但这是我能想象的唯一解决方案。我的想法是拥有绝对位置的 div 的“副本”,并保持不透明度 = 0 或可见性 = 隐藏的“原始”。当更改数组时,包含在 setTimeout 中,制作一个手动动画来更改“副本”的顶部和左侧。

在代码中。假设你有一个数组数据

data:any[]=[1,2,3,4,5]

一个像这样的html

<div >
  <ng-container *ngFor="let item of data;let i=index">
    <div #origin style="opacity:0" >{{item}}</div>
    <div #copy  style="position:absolute" [style.z-index]="i" >{{item}}</div>
  </ng-container>
</div>

我们在 ViewChildren 中获取“原点”和 ngAfterViewInit 中的“副本”,我们将“副本”放置在他的位置

 @ViewChildren("origin") bars: QueryList<ElementRef>;
 @ViewChildren("copy") copies: QueryList<ElementRef>;

  ngAfterViewInit()
  {
    const bars:any[]=this.bars.toArray().map(x=>x.nativeElement.getBoundingClientRect());
    this.copies.forEach((x,index) => {
      x.nativeElement.style.top=bars[index].top+"px"
      x.nativeElement.style.left=bars[index].left+"px"
    });
  }

好吧,只需单击一下,我就可以重新排序数组并制作动画

  click() {
    this.data=this.data
               .map(x=>({item:x,value:Math.random()}))
               .sort((a,b)=>a.value-b.value)
               .map(x=>x.item)

    setTimeout(()=>{
        const bars:any[]=this.bars.toArray().map 
           (x=>x.nativeElement.getBoundingClientRect());
        this.copies.forEach((x,index) => {
           this.animate(x.nativeElement, bars[index].top+"px",bars[index].left+"px");
        });
    })
  }
  animate(element: any, top: string,left:string) {
    const myAnimation = this.builder.build([
      animate(this.timing, style({ top: top,left:left }))
    ]);
    this.player = myAnimation.create(element);
    this.player.play();
  }

您可以在堆栈闪电战 https://stackblitz.com/edit/angular-s4nw4h?file=src%2Fapp%2Fapp.component.ts

Update为什么不制定指令?

Update 2我使用 offsetTop 和 offsetLeft 更新指令并添加 window.scrollX 和 window.scrollY。此外,我添加了一个新属性:pos0,如果为 true,则首先在 pos 0,0 中创建“副本”

@Directive({ selector: "[animate]" })
export class AnimateDirective implements OnInit {
  original: any;
  copy: any;
  timing:string;
  private player: AnimationPlayer;

  @Input() set animate(value: string) {
    this.timing = value || "450ms ease-in-out";
  }
  @Input('animatePos0') pos0:boolean=false;

  constructor(
    private templateRef: TemplateRef<any>,
    private viewContainer: ViewContainerRef,
    private builder: AnimationBuilder,
    private renderer: Renderer2
  ) {}

  ngOnInit() {
    this.original = this.viewContainer.createEmbeddedView(
      this.templateRef
    ).rootNodes[0];
    setTimeout(() => {
      this.copy = this.viewContainer.createEmbeddedView(
        this.templateRef
      ).rootNodes[0];
      this.renderer.setStyle(this.original, "visibility","hidden");
      const rect = !this.pos0?
          {top:this.original.offsetTop,left:this.original.offsetLeft}:
          {top:0,left:0};
      this.renderer.setStyle(this.copy, "position", "absolute");
      this.renderer.setStyle(this.copy, "top", rect.top+ window.scrollY + "px");
      this.renderer.setStyle(this.copy, "left", rect.left+ window.scrollX + "px");
    });
  }
  animateGo() {
    setTimeout(() => {
      const rect = {top:this.original.offsetTop,left:this.original.offsetLeft}
      const myAnimation = this.builder.build([
        animate(this.timing, 
          style({ top: rect.top+ window.scrollY, 
                  left: rect.left+ window.scrollX }))
      ]);
      this.player = myAnimation.create(this.copy);
      this.player.play();
    });
  }
}

好吧,我们需要一些类似的东西

<ng-container *ngFor="let item of data;let i=index">
<div *animate="'150ms ease-in-out'"> {{item}}-{{i}}
</div>
</ng-container>

在我们的组件中,有一个 ViewChildren

@ViewChildren(AnimateDirective) items:QueryList<AnimateDirective>

所以,当我们改变数据时,我们需要

this.items.forEach(x=>x.animateGo())

See a 新堆栈闪电战 https://stackblitz.com/edit/angular-xv78gq?file=src%2Fapp%2Fanimate.directive.ts

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

对 Angular 中两个或多个 DIV 位置的位置进行动画处理 的相关文章

随机推荐

  • Twitter 的 OAuth 系统如何工作?

    我有一个演示脚本 可以让我使用我的应用程序进行授权并发回我的令牌 但这很令人困惑 我一直在 CURL 或 simpleXML 函数中使用用户名和密码来授权 API 调用 我不明白这与 oauth 有什么关系 我知道我将存储令牌 但是一旦我拥
  • Windows 上的 .NET Core 3.0 忽略 NO_PROXY

    我们正在尝试让代理功能在 Windows 上的 NET Core 3 0 或 3 1 应用程序中工作 我们发现 HTTPS PROXY 和 HTTP PROXY 变 量按预期进行识别和处理 但默认代理似乎不支持 NO PROXY 变 量 这
  • Git 通过 ngrok 隧道转发

    我的本地实例上有一个 git 存储库 我想从家庭网络外部访问它 我应该为此在本地实例上创建 git 服务器和 ssh 服务器吗 另外我应该使用 ngrok 建立隧道的端口是什么 任何意见都将不胜感激 如图所示第193期 https gith
  • Perl 中的反向 DNS 查找

    如何执行反向 DNS 查找 即如何在 Perl 中将 IP 地址解析为其 DNS 主机名 如果您需要更详细的 DNS 信息 请使用Net DNS http search cpan org olaf Net DNS 0 63 lib Net
  • 将 HBITMAP 绘制到分层窗口上。怎么了?

    大家好 美好的一天 我的最终目标是在屏幕上绘制一个包含 Alpha 的 PNG 文件 这意味着不是在自己的窗口中 而是在桌面上的某个位置 将 PNG 加载到 HBITMAP 的部分现在可以工作 以不同的方式进行测试 但我无法做到绘制它 包括
  • Java程序查找字符串数组中元音的长度和数量

    我需要从用户那里获取一个字符串并将其输出到一个表中 包括其单词数和元音数 但我不知道如何计算元音 我尝试了以下方法 import java util Scanner public class Array2 public static voi
  • Objective C - iCal 不在 iOS 9 中创建自定义日历和新事件

    这在 iOS 8 中完美运行 但在 iOS 9 中创建问题 这里是代码 self eventManager eventStore requestAccessToEntityType EKEntityTypeEvent completion
  • Xcode Core Data:将现有 XML 更改为 Sqlite(NSXMLStoreType 更改为 NSSQLiteStoreType)

    在我的第一个应用程序中 我在持久存储协调器中使用了 NSXM StoreType storeCooordinator addPersistentStoreWithType NSXMLStoreType configuration nil U
  • 从音频流中提取 SMPTE 时间码

    我正在开发一个录音系统 我的任务涉及从同步器设备生成的音频输入流中提取 SMPTE 时间码 我使用 ASIO SDK 来获取每个回调缓冲区的时间代码 但它始终为零 也许有人有 ASIO SDK 或任何其他可用于从音频流中提取 SMPTE 时
  • 在后台检查互联网连接

    我需要在后台检查互联网连接 我正在数据库中保存一些数据 每当我连接到互联网时 它应该将数据上传到我的服务器上 我需要一个后台服务 即使我关闭我的应用程序 它也会持续检查互联网连接 我尝试了几种方法 但它们只有在我打开我的应用程序时才有效 目
  • Spring Batch - Web 服务到 Web 服务分块

    我有一个托管的网络服务 允许批量提取记录 此 Web 服务以起始记录号 ROWID 和页面大小 最大 800 作为参数 可以从此服务中提取 50 60k 条记录 并调用另一个 Web 服务以块的形式再次发布所有这些数据 而无需在其间保留数据
  • 使用jQuery获取垂直滚动的最大值

    这是我的视图代码 我使用 jQuery 它可以工作 并且在我更改屏幕分辨率之前我没有任何问题 它停止工作 我知道问题出在哪里 但我无法解决它 看看代码 model PNUBOOKIR Models ProductModels Layout
  • B树和B+树有什么区别?

    In a b tree你可以存储两者内部节点和叶节点中的键和数据 但是在一个b tree你必须将数据存储在仅叶节点 在 b 树中执行上述操作有什么好处吗 为什么不到处使用 b 树而不是 b 树 因为直观上它们看起来更快 我的意思是 为什么需
  • SwiftUI 中元素之间的间距?

    我想知道为什么 SwiftUI 中的两个元素之间会出现这种间距 以及如何控制 修改它 我尝试向 ExtractedView 添加一些填充 但它没有改变任何内容 似乎是由某种原因引起的 frame 高度 56 但这正是按钮的高度 因此它不应该
  • 使用CSS将div对齐到另一个div的底部

    我想对齐DIV c在底部DIV b not DIV a div div div Div c div div div 这应该有效 b position relative c position absolute bottom 0px 诀窍是po
  • 在 JavaScript 中,如何从类的字符串名称中检索类? [复制]

    这个问题在这里已经有答案了 我有这样的 xml 文件
  • 在 styles.xml 中设置特定字体

    我正在为我的 Android 应用程序定义样式 XML 我有一些想要使用的 TTF 文件 如何设置字体以使用这些文件作为字体 而不是通用的 sans serif 和 monospace 谢谢 您只能通过 Java 代码使用自定义字体 而不能
  • Android gradle 构建错误:(9, 0) 未找到 Gradle DSL 方法:“compile()”。

    当我尝试同步我的项目时 出现以下构建错误 Error 9 0 Gradle DSL method not found compile Possible causes The project AlexTest may be using a v
  • 对不同大小的输入运行 Haskell 基准测试

    我经常想比较同一函数的多个实现的运行时性能 对于个人输入 标准是一个很好的工具 但是 有什么简单的方法可以在不同的输入大小上绘制代码的性能 例如查看算法复杂度 理想情况下 我向库传递一个类型的值Benchmarkable r gt Stri
  • 对 Angular 中两个或多个 DIV 位置的位置进行动画处理

    我需要帮助来调整动态渲染的 2 个或更多 div 的位置开关 这是一个简单的例子 let objects Array