gpt4 book ai didi

ionic-framework - 在 ionic 4 上添加刷卡火种

转载 作者:行者123 更新时间:2023-12-04 07:13:59 24 4
gpt4 key购买 nike

我想问一下tinder swipeable card with ionic 4。我找不到下面的链接:https://github.com/ionic-team/ionic-ion-swipe-cards

'

最佳答案

我想我实现了它,我希望你能利用这段代码并提供反馈。

组件模板由三部分组成:

  • 用于用户选择的指示器,它会在任何时候获得可见性(不透明度)用户将他们的选择拖到是/否的方向

  • 实际的一叠卡片

  • 用户可以用来做出选择的按钮
    拖动

模板代码+scss代码如下:

//HTML:

<div class="tinder" [hidden]="!cards.length">

<div class="tinder--status">

<div [style.opacity]="crossVisible? '1':'0'">
<svg width="200px" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 512 512">
<svg:path
d="M405 136.798L375.202 107 256 226.202 136.798 107 107 136.798 226.202 256 107 375.202 136.798 405 256 285.798 375.202 405 405 375.202 285.798 256z"
fill="#CDD6DD" />
</svg>
</div>

<div [style.opacity]="heartVisible? '1':'0'">
<svg width="200px" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 512 512">
<svg:path
d="M349.6 64c-36.4 0-70.7 16.7-93.6 43.9C233.1 80.7 198.8 64 162.4 64 97.9 64 48 114.2 48 179.1c0 79.5 70.7 143.3 177.8 241.7L256 448l30.2-27.2C393.3 322.4 464 258.6 464 179.1 464 114.2 414.1 64 349.6 64zm-80.8 329.3l-4.2 3.9-8.6 7.8-8.6-7.8-4.2-3.9c-50.4-46.3-94-86.3-122.7-122-28-34.7-40.4-63.1-40.4-92.2 0-22.9 8.4-43.9 23.7-59.3 15.2-15.4 36-23.8 58.6-23.8 26.1 0 52 12.2 69.1 32.5l24.5 29.1 24.5-29.1c17.1-20.4 43-32.5 69.1-32.5 22.6 0 43.4 8.4 58.7 23.8 15.3 15.4 23.7 36.5 23.7 59.3 0 29-12.5 57.5-40.4 92.2-28.8 35.7-72.3 75.7-122.8 122z"
fill="#FFACE4" />
</svg>
</div>

</div>

<div class="tinder--cards" (pan)="handlePan($event)" (panend)="handlePanEnd($event)">

<div #tinderCard class="tinder--card" (transitionend)="handleShift()" *ngFor="let card of cards; let i = index"
[ngStyle]="{ zIndex: cards.length - i, transform: 'scale(' + (20 - i) / 20 + ') translateY(-' + 20 * i + 'px)' }">

<img #tinderCardImage [src]="card.img" (load)="tinderCardImage.style.opacity = 1">
<h3>{{ card.title }}</h3>
<p>{{ card.description }}</p>

</div>

</div>

<div class="tinder--buttons">

<button (click)="userClickedButton($event, false)">
<svg width="30px" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 512 512">
<svg:path
d="M405 136.798L375.202 107 256 226.202 136.798 107 107 136.798 226.202 256 107 375.202 136.798 405 256 285.798 375.202 405 405 375.202 285.798 256z"
fill="#CDD6DD" />
</svg>
</button>

<button (click)="userClickedButton($event, true)">
<svg width="30px" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 512 512">
<svg:path
d="M349.6 64c-36.4 0-70.7 16.7-93.6 43.9C233.1 80.7 198.8 64 162.4 64 97.9 64 48 114.2 48 179.1c0 79.5 70.7 143.3 177.8 241.7L256 448l30.2-27.2C393.3 322.4 464 258.6 464 179.1 464 114.2 414.1 64 349.6 64zm-80.8 329.3l-4.2 3.9-8.6 7.8-8.6-7.8-4.2-3.9c-50.4-46.3-94-86.3-122.7-122-28-34.7-40.4-63.1-40.4-92.2 0-22.9 8.4-43.9 23.7-59.3 15.2-15.4 36-23.8 58.6-23.8 26.1 0 52 12.2 69.1 32.5l24.5 29.1 24.5-29.1c17.1-20.4 43-32.5 69.1-32.5 22.6 0 43.4 8.4 58.7 23.8 15.3 15.4 23.7 36.5 23.7 59.3 0 29-12.5 57.5-40.4 92.2-28.8 35.7-72.3 75.7-122.8 122z"
fill="#FFACE4" />
</svg>
</button>

</div>

</div>

//SCSS:

.tinder {
width: 100%;
height: 100%;
overflow: hidden;
background-color: rgba(0,0,0,0.4);
position: absolute;
left: 0;
top: 0;
}

.tinder--status {
position: absolute;
top: 50%;
margin-top: -30px;
z-index: 2;
width: 100%;
text-align: center;
pointer-events: none;
}

.tinder--status > div {
transition: all 0.3s ease-in-out;
}

.tinder--status svg {
transition: all 0.3s ease-in-out;
position: absolute;
width: 100px;
margin-left: -50px;
}

.tinder--cards {
text-align: center;
display: flex;
flex-direction: column;
position: fixed;
justify-content: center;
align-items: center;
width: 100%;
height: 100%;
overflow: hidden;
}

.tinder--card {
display: inline-block;
width: 260px;
height: 70%;
background: #FFFFFF;
padding-bottom: 40px;
border-radius: 8px;
overflow: hidden;
position: absolute;
will-change: transform;
transition: all 0.3s ease-in-out;
cursor: -webkit-grab;
cursor: -moz-grab;
cursor: grab;
}

.moving.tinder--card {
transition: none;
cursor: -webkit-grabbing;
cursor: -moz-grabbing;
cursor: grabbing;
}

.tinder--card img {
max-width: 100%;
max-height: 75%;
pointer-events: none;
opacity: 0;
transition: opacity 0.3s ease-in-out;
}

.tinder--card h3 {
margin-top: 16px;
font-size: 24px;
padding: 0 16px;
pointer-events: none;
}

.tinder--card p {
margin-top: 24px;
font-size: 16px;
padding: 0 16px;
pointer-events: none;
}

.tinder--buttons {
position: absolute;
flex: 0 0 100px;
text-align: center;
bottom: 20px;
left: 0;
right: 0;
}

.tinder--buttons button {
border-radius: 50%;
line-height: 50px;
width: 50px;
height: 50px;
border: 0;
background: #FFFFFF;
display: inline-block;
padding-top: 10px;
margin: 0 12px;
}

.tinder--buttons button:focus {
outline: 0;
}

一些注意事项:

  • 模板具有复制每张牌和位置的 *ngFor它在堆栈中
  • 我们利用 hammer.js 的平移和平移结束手势事件来处理拖动
  • 我们正在监听转换结束事件以实际从堆栈中移除卡片

//技术人员:

import { Component, Input, ViewChildren, QueryList, ElementRef, EventEmitter, Output, Renderer2 } from '@angular/core';

@Component({
selector: 'tinder-ui',
templateUrl: 'tinder-ui.component.html',
styleUrls: ['tinder-ui.component.scss'],
})
export class TinderUIComponent {

@Input('cards') cards: Array<{
img: string,
title: string,
description: string
}>;

@ViewChildren('tinderCard') tinderCards: QueryList<ElementRef>;
tinderCardsArray: Array<ElementRef>;

@Output() choiceMade = new EventEmitter();

moveOutWidth: number;
shiftRequired: boolean;
transitionInProgress: boolean;
heartVisible: boolean;
crossVisible: boolean;

constructor(private renderer: Renderer2) {
}

userClickedButton(event, heart) {
event.preventDefault();
if (!this.cards.length) return false;
if (heart) {
this.tinderCardsArray[0].nativeElement.style.transform = 'translate(' + this.moveOutWidth + 'px, -100px) rotate(-30deg)';
this.toggleChoiceIndicator(false,true);
this.emitChoice(heart, this.cards[0]);
} else {
this.tinderCardsArray[0].nativeElement.style.transform = 'translate(-' + this.moveOutWidth + 'px, -100px) rotate(30deg)';
this.toggleChoiceIndicator(true,false);
this.emitChoice(heart, this.cards[0]);
};
this.shiftRequired = true;
this.transitionInProgress = true;
};

handlePan(event) {

if (event.deltaX === 0 || (event.center.x === 0 && event.center.y === 0) || !this.cards.length) return;

if (this.transitionInProgress) {
this.handleShift();
}

this.renderer.addClass(this.tinderCardsArray[0].nativeElement, 'moving');

if (event.deltaX > 0) { this.toggleChoiceIndicator(false,true) }
if (event.deltaX < 0) { this.toggleChoiceIndicator(true,false) }

let xMulti = event.deltaX * 0.03;
let yMulti = event.deltaY / 80;
let rotate = xMulti * yMulti;

this.renderer.setStyle(this.tinderCardsArray[0].nativeElement, 'transform', 'translate(' + event.deltaX + 'px, ' + event.deltaY + 'px) rotate(' + rotate + 'deg)');

this.shiftRequired = true;

};

handlePanEnd(event) {

this.toggleChoiceIndicator(false,false);

if (!this.cards.length) return;

this.renderer.removeClass(this.tinderCardsArray[0].nativeElement, 'moving');

let keep = Math.abs(event.deltaX) < 80 || Math.abs(event.velocityX) < 0.5;
if (keep) {

this.renderer.setStyle(this.tinderCardsArray[0].nativeElement, 'transform', '');
this.shiftRequired = false;

} else {

let endX = Math.max(Math.abs(event.velocityX) * this.moveOutWidth, this.moveOutWidth);
let toX = event.deltaX > 0 ? endX : -endX;
let endY = Math.abs(event.velocityY) * this.moveOutWidth;
let toY = event.deltaY > 0 ? endY : -endY;
let xMulti = event.deltaX * 0.03;
let yMulti = event.deltaY / 80;
let rotate = xMulti * yMulti;

this.renderer.setStyle(this.tinderCardsArray[0].nativeElement, 'transform', 'translate(' + toX + 'px, ' + (toY + event.deltaY) + 'px) rotate(' + rotate + 'deg)');

this.shiftRequired = true;

this.emitChoice(!!(event.deltaX > 0), this.cards[0]);
}
this.transitionInProgress = true;
};

toggleChoiceIndicator(cross, heart) {
this.crossVisible = cross;
this.heartVisible = heart;
};

handleShift() {
this.transitionInProgress = false;
this.toggleChoiceIndicator(false,false)
if (this.shiftRequired) {
this.shiftRequired = false;
this.cards.shift();
};
};

emitChoice(heart, card) {
this.choiceMade.emit({
choice: heart,
payload: card
})
};

ngAfterViewInit() {
this.moveOutWidth = document.documentElement.clientWidth * 1.5;
this.tinderCardsArray = this.tinderCards.toArray();
this.tinderCards.changes.subscribe(()=>{
this.tinderCardsArray = this.tinderCards.toArray();
})
};

}

注释部分:

  • @Input 用于获取卡片列表
  • 我们利用@Output 发出用户的选择
  • 我们使用@ViewChildren 来跟踪卡片堆
  • 只有在转换完成(转换结束事件)时才真正移除卡片(array.shift())
  • 组件本身是隐藏的,以防它在堆栈中没有卡片,想法是我们从页面组件显示这个组件,例如通过引用一个可以包含卡片的数组

希望这是一个很好的例子,说明如何实现这样的组件

编辑器网址:https://stackblitz.com/edit/ionic-4-template-bks4dd

演示:https://ionic-4-template-bks4dd.stackblitz.io

文章:medium post

关于ionic-framework - 在 ionic 4 上添加刷卡火种,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/59652088/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com