RError.com

RError.com Logo RError.com Logo

RError.com Navigation

  • 主页

Mobile menu

Close
  • 主页
  • 系统&网络
    • 热门问题
    • 最新问题
    • 标签
  • Ubuntu
    • 热门问题
    • 最新问题
    • 标签
  • 帮助
主页 / 问题 / 1021801
Accepted
Dmytro
Dmytro
Asked:2020-09-09 23:16:29 +0000 UTC2020-09-09 23:16:29 +0000 UTC 2020-09-09 23:16:29 +0000 UTC

Angular 8. 带有侧滑动作的元素列表

  • 772

我想实现如材料设计中所示的滑动手势功能: https ://material.io/components/lists/#behavior (向下滚动一个屏幕到手势部分)。

不幸的是,我是 Angular 的新手,理论上我可以并且可以手动做这样的事情,但我觉得这将是拐杖上的拐杖 + 非常费力。此外,我怀疑人们很少使用它,以至于没有现成的库。我不否认我以某种方式搜索错误的可能性......

在互联网上,我在 git 上挖出了这个问题,他们要求添加功能: https ://github.com/angular/components/issues/4016

进一步的搜索把我带到了这里:

https://demo.mobiscroll.com/angular/listview/swipe-actions#theme=ios 正是我想要的(甚至是不必要的),但据我了解,这是一种显示所有内容的付费服务他们在一段时间后控制铭文DEMO。当然,我什么都懂,但是真的有这样的开源库吗?是的,也依赖于一些第三方服务,不要风水......

这是另一个开源库,在视觉上非常接近我正在寻找的内容,但是它通过滑动从 DOM 中删除了一个元素(这是合乎逻辑的,因为它被称为滑动删除),我需要挂起事件在向两侧滑动时,不从列表中删除元素。

请帮忙,有没有人做过类似的事情?

我看到了以下的实现(如果没有找到库):

  1. 我们创建一个代表列表项的组件。
  2. 我们将 DragDropModule 连接到它并配置元素只能沿 X 轴移动。
  3. 在 TS 中,我们订阅元素移动事件,当向一个方向或另一个方向移动一定百分比时,我们显示动作图标,当移动完成时,我们将元素返回到它的位置并调用一个或另一个回调函数在初始化期间传递给组件。

关于视图组件有几个想法:

  1. 也许我可以使用自定义占位符(此功能由 DragDropModule 提供)。如果它足够灵活,那就太好了。
  2. 取几个嵌套的 DIV 块。Last Child 将是一个移动元素,我会将动作图标附加到将由滑动和后台任务执行的父母。

剩下的就是制作一个漂亮的元素返回动画。接下来,通过 *ngFor 我们输入一个元素列表。鉴于我的经验不佳,我征求您的意见。一切都正确吗,告诉我如何正确地做。或者告诉我一个涵盖所需功能的库。

编辑:

由于我没有找到解决方案,我决定编写自己的实现。该决定尚未最终决定。我还没有检查是否可以通过输入将链接传递给方法(委托),但如果不能,那么我将进行相应的服务。我仍然不知道如何添加动画,以便在滑动后元素顺利返回到它的位置(请帮助解决这个问题)。在项目中我使用材料库。

TS:

import { Component, OnInit, Input } from '@angular/core';

@Component({
  selector: 'table',
  templateUrl: './table.component.html',
  styleUrls: ['./table.component.scss']
})
export class TableComponent implements OnInit {

  basePosition = {x:0,y:0};

  @Input() tableId: string;
  @Input() leftSwipeMethod: any; //test
  @Input() rightSwipeMethod: any; //test


  offsetPercent: number = 0;

  private elementWidth = 0;
  constructor() { }

  ngOnInit() {
  }

  swipeStarted($event){

    console.log("Started:" ,$event)
  }
  swipeMoved($event){
    this.offsetPercent = Math.abs($event.distance.x / $event.source.element.nativeElement.offsetWidth * 2);
    console.log(this.offsetPercent)

  } 
  swipeEnded($event){
    console.log("Ended:" ,$event);
    this.offsetPercent = 0;
    this.basePosition = {x:0,y:0};
  }
}

风格:

.table-container, .table-drag-box {     
     height: 50px;
}
.table-drag-box{   
     width: 99vw;  
     background-color: white;
}
.table-container{
     width: 100vw;
     background-color: red;
}
.left-icon, .right-icon{
     position: absolute;
     height: inherit;
     display: flex;
     align-items: center;
     opacity: 0;
}
.right-icon{
     right: 0;
}
.fill-remaining-space{
     flex: 1 1 auto;
}

HTML

<div class="table-container">
  <span class="left-icon" [ngStyle]="{'opacity': offsetPercent}">
    <mat-icon>credit_card</mat-icon>
    <span>Send to payment</span>
  </span>
  <span class="fill-remaining-space"></span>
  <span class="right-icon" [ngStyle]="{'opacity': offsetPercent}">
      <mat-icon>close</mat-icon>
      <span>Close all sessons</span>
    </span>
     <div class="table-drag-box" cdkDragLockAxis="x" cdkDrag [cdkDragFreeDragPosition]="basePosition" 
(cdkDragStarted)="swipeStarted($event)" (cdkDragMoved)="swipeMoved($event)" (cdkDragReleased)="swipeEnded($event)">
             <span> {{tableId}}</span>
         </div>     
    </div>

用法:

<div *ngFor="let device of myDevicesObservable | async">

    <table [tableId]="device.id"></table>

</div>
angular2
  • 1 1 个回答
  • 10 Views

1 个回答

  • Voted
  1. Best Answer
    Dmytro
    2020-09-11T17:41:08Z2020-09-11T17:41:08Z

    结果一切都比我想象的要容易得多。在编写自己的实现的过程中,我深入研究了 Material Drag&Drop库,并意识到我可以轻松使用它的功能。为了实现,我们需要一个 DropList,它的每个元素只允许沿 x 轴移动(cdkDragLockAxis="x")。我们还设置了一个自定义占位符,用于放置我们的图标。完全按照我的意愿工作!我还没有解决布局的所有问题,但是任何需要它的人都可以轻松地为自己纠正所有的小问题。我希望这可以帮助别人。我只需要挂断滑动和点击操作(参见代码中的注释)。我不会描述如何安装 Material,但我会直接展示实现(我为命名变量道歉——它们与我的上下文相关):

    HTML:

    <div cdkDropList class="tables-list" (cdkDropListDropped)="drop($event)"> <!-- метод cdkDropListDropped в моем случае не задействован, решил для вас оставить. -->
      <div class="table-drag-box" 
          *ngFor="let table of myTables$ | async"
          cdkDragLockAxis="x" cdkDrag  
          (cdkDragStarted)="swipeStarted($event)" (cdkDragMoved)="swipeMoved($event)" (cdkDragReleased)="swipeEnded($event)" (click)="showOrderDetails(table.id)">
          <div class="custom-placeholder" *cdkDragPlaceholder>
              <span class="left-icon" [ngStyle]="{'opacity': offsetDistance > 0 ? offsetPercent *4 : 0}"> <!--умножаем на 4, чтобы быстрее выводить иконку из прозрачности. -->
                  <mat-icon>credit_card</mat-icon> <!--Left swipe icon-->
                  <span>Send to payment</span>
                </span>
                <span class="fill-remaining-space"></span> 
                <span class="right-icon" [ngStyle]="{'opacity': offsetDistance < 0 ? offsetPercent *4 : 0}">
                    <mat-icon>close</mat-icon> <!--Right swipe icon-->
                    <span>Close all sessons</span>
                  </span>
          </div>     
        <span> {{table.id}}</span>
         </div>        
      </div>
    

    CSS:

    .table-container, .table-drag-box {     
         height: 50px;
    }
    .table-drag-box{   
         width: 100vw;  
         background-color: white;
    }
    
    .left-icon, .right-icon{
         position: absolute;
         height: inherit;
         display: flex;
         align-items: center;
         opacity: 0;
    }
    .right-icon{
         right: 0;
    }
    .fill-remaining-space{
         flex: 1 1 auto;
    }
    .cdk-drag-animating {
         transition: transform 250ms cubic-bezier(0, 0, 0.2, 1);
       }
       .tables-list.cdk-drop-list-dragging .table-drag-box:not(.cdk-drag-placeholder) {
         transition: transform 250ms cubic-bezier(0, 0, 0.2, 1);
       }
       .custom-placeholder {
         background: #ccc;
         min-height: 50px;
         transition: transform 250ms cubic-bezier(0, 0, 0.2, 1);
       }
    

    TS:

    import { Component, OnInit, Input, ElementRef } from '@angular/core';
    import { Observable } from 'rxjs';
    import { CdkDragDrop } from '@angular/cdk/drag-drop';
    import { FullscreenOverlayContainer } from '@angular/cdk/overlay';
    
    @Component({
      selector: 'tables',
      templateUrl: './table.component.html',
      styleUrls: ['./table.component.scss']
    })
    export class TableComponent implements OnInit {
    
      @Input() tableId: string;
      @Input() myTables$: Observable<object>;
    
      offsetPercent: number = 0; //данное значение влияет на прозрачность иконок свайпа
      offsetDistance: number = 0; //отрицательное значение отображает правую иконку, а положительное - левую.
      constructor(private element:ElementRef) { }
    
      ngOnInit() {
      }
    
      ngAfterViewInit() {
        //this.elementWidth = this.elementView.nativeElement.offsetWidth;
    
      }
    
      swipeStarted($event){
    
        //console.log("Started:" ,$event)
      }
    
    
      swipeMoved($event){
            this.offsetDistance = $event.distance.x;
            this.offsetPercent = Math.abs($event.distance.x / this.element.nativeElement.offsetWidth);  
      } 
      swipeEnded($event){
    //зная % смещения можно выполнять различные действия. Вот, к примеру вот так:
        if(this.offsetPercent > 0.25){
    //таймер - это костыль так как нужно дождаться окончания анимации смещения элемента. 
    //Если вы знаете как подписаться на событие завершения анимации - ожидаю ваших комментариев. Заранее спасибо.
              timer(250).subscribe(_ => { 
                switch (this.offsetDistance > 0) {
              case true:
                //TODO send to payment
                this.showConfirmationDialog("Send orders on payment?")
                .subscribe(result => {  
                  console.log("TODO send to payment " + result)
                  return result;
                })
            break;
    
          case false:
            //TODO close sessions
            this.showConfirmationDialog("Close all sessions on table " + tableOrders.table.location.deviceNameForLocation)
            .subscribe(result => {              
              console.log("TODO close sessions: " + result)  
              return result;
            })
    
            break;
        }        
        this.offsetDistance = 0;
        this.offsetPercent = 0;
      });      
    }
    else{
      this.offsetDistance = 0;
      this.offsetPercent = 0;
    }
      }
    
      drop(event: CdkDragDrop<string[]>) {
        //console.log("drop: ",event)
        //moveItemInArray(this.movies, event.previousIndex, event.currentIndex);
      }
    
      showOrderDetails(tableId){
        //TODO open full-screen dialog
        console.log(tableId);
      }
    }
    
    • 0

相关问题

  • 可观察的主题

  • Angular 7. 结合延迟加载模块和常规模块时重定向到 404

  • 内部组件对外部 <router-outlet> 的引用。角 7

  • 为什么将事件包装在超时中会破坏事件?如何避免?

  • 有什么方法可以加快 Angular2+ ssr 的速度吗?

  • 在独立的 Angular2 组件之间传递数据

Sidebar

Stats

  • 问题 10021
  • Answers 30001
  • 最佳答案 8000
  • 用户 6900
  • 常问
  • 回答
  • Marko Smith

    根据浏览器窗口的大小调整背景图案的大小

    • 2 个回答
  • Marko Smith

    理解for循环的执行逻辑

    • 1 个回答
  • Marko Smith

    复制动态数组时出错(C++)

    • 1 个回答
  • Marko Smith

    Or and If,elif,else 构造[重复]

    • 1 个回答
  • Marko Smith

    如何构建支持 x64 的 APK

    • 1 个回答
  • Marko Smith

    如何使按钮的输入宽度?

    • 2 个回答
  • Marko Smith

    如何显示对象变量的名称?

    • 3 个回答
  • Marko Smith

    如何循环一个函数?

    • 1 个回答
  • Marko Smith

    LOWORD 宏有什么作用?

    • 2 个回答
  • Marko Smith

    从字符串的开头删除直到并包括一个字符

    • 2 个回答
  • Martin Hope
    Alexandr_TT 2020年新年大赛! 2020-12-20 18:20:21 +0000 UTC
  • Martin Hope
    Alexandr_TT 圣诞树动画 2020-12-23 00:38:08 +0000 UTC
  • Martin Hope
    Air 究竟是什么标识了网站访问者? 2020-11-03 15:49:20 +0000 UTC
  • Martin Hope
    Qwertiy 号码显示 9223372036854775807 2020-07-11 18:16:49 +0000 UTC
  • Martin Hope
    user216109 如何为黑客设下陷阱,或充分击退攻击? 2020-05-10 02:22:52 +0000 UTC
  • Martin Hope
    Qwertiy 并变成3个无穷大 2020-11-06 07:15:57 +0000 UTC
  • Martin Hope
    koks_rs 什么是样板代码? 2020-10-27 15:43:19 +0000 UTC
  • Martin Hope
    Sirop4ik 向 git 提交发布的正确方法是什么? 2020-10-05 00:02:00 +0000 UTC
  • Martin Hope
    faoxis 为什么在这么多示例中函数都称为 foo? 2020-08-15 04:42:49 +0000 UTC
  • Martin Hope
    Pavel Mayorov 如何从事件或回调函数中返回值?或者至少等他们完成。 2020-08-11 16:49:28 +0000 UTC

热门标签

javascript python java php c# c++ html android jquery mysql

Explore

  • 主页
  • 问题
    • 热门问题
    • 最新问题
  • 标签
  • 帮助

Footer

RError.com

关于我们

  • 关于我们
  • 联系我们

Legal Stuff

  • Privacy Policy

帮助

© 2023 RError.com All Rights Reserve   沪ICP备12040472号-5