drag-and-drop 相关问题

在视口边缘拖动时如何防止页面滚动

将内容拖动到溢出页面的边缘时,页面将开始滚动。如何通过本机浏览器功能/样式来防止这种行为?仅在 Firefox 上工作是可以的。 (我是...

回答 1 投票 0

如何使用 JavaScript 中应用的缩放比例平移来计算拖动时元素的正确位置

我正在将以下拖放库作为业余项目进行工作。我正在使用变换翻译来使元素可拖动。我存储初始的 client.x 和 client.y 并计算翻译...

回答 1 投票 0

React,如何阻止拖动后执行点击事件?

我有 Draggable 元素,在它的内部,我有一个带有 onClick 事件的组件。拖动结束时,触发点击事件。 我的可拖动元素如下所示。我使用了一个名为...

回答 6 投票 0

如何在 React 中仅在 SVG 路径上拖动标签

我正在使用 ReactFlow,我只想在 SVG 路径上拖动标签。 https://codesandbox.io/p/sandbox/elastic-tdd-skl3ph。 在此示例中,我只想将“边缘标签”拖动到

回答 1 投票 0

dndkit (React):取消拖放

在 dndkit (https://dndkit.com/) 中,我需要能够在发生特定事件(例如更改道具)时取消拖动。我似乎在文档中找不到任何方法来做到这一点。我失踪了

回答 1 投票 0

菜单栏上图像图标位置重置点击

我正在尝试将图像图标拖放到屏幕上,但每当我在移动图标后单击菜单栏时,它都会重置到原来的位置。我认为这与屏幕有关...

回答 1 投票 0

react dnd-kit sortable:为什么我的 sortable 的第一个元素不可拖动?

我正在尝试使用react dnd-kit构建一个非常基本的可排序,并且一切正常,除了一件事:我的可排序数组的第一个元素在拖动时不会移动(当其他元素时它会移动

回答 2 投票 0

在 MIT Scratch 上重制的 PONG 中,球总是卡在墙边

我正在为一个班级项目设计一款乒乓球游戏重制版,但我的球总是卡在某些墙壁上来回卡住...... 这是负责检测墙壁碰撞和反转的块...

回答 1 投票 0

如何提取通过 OLE 拖放到窗口的 Outlook 邮件?

我的程序(C++,Windows)实现了一个窗口,接收OLE拖放对象(从MS Outlook拖拽的消息),枚举拖拽对象的格式,当TYMED_ISTREAM重新时读取流...

回答 1 投票 0

当格式非标准等情况下如何处理OLE拖放数据?

我已经实现了 OLE 拖放接收器(C++、Visual Studio 2019)。 我尝试过将 MS Word 中的选定文本或 MS Outlook 中的一封信拖动到接收器窗口。 我有

回答 1 投票 0

如何让dragover/dragleave不粗略?

这是我的代码: var DragStart = _.debounce(function () { 控制台.log(“开始”); $dropIndicator.appendTo(document.body).show(); }, 10, { 领先:真实, 尾随:假 }); var DragS...

回答 2 投票 0

C 编程:将文件拖放到程序图标上

我刚刚制作了一个小程序,它读取拖动到其图标上的文件的名称并将其写入输出文本文件 但是如果我编译这个程序,当我尝试将文件拖到它上面时它会崩溃......

回答 1 投票 0

WPF 拖放无效果未触发

因此,我几乎遵循了我能找到的所有示例,了解如何将 WPF 控件上的拖/放效果设置为“无”以显示带有线条符号的圆圈,但无济于事。 这是我的代码...

回答 2 投票 0

如何将项目拖放到扩展图块内并拖放到扩展图块外部?

如何处理将列表拖放到另一个列表中? 我怎样才能实现这个目标? 感谢您的帮助! 我尝试过使用 Drag_and_drop_lists 包,但我被困在手柄内部和外部项目中。 满

回答 1 投票 0

如何将项目拖放到扩展图块内,并将项目拖放到扩展图块外部?

如何处理将列表拖放到另一个列表中? 我怎样才能实现这个目标? 感谢您的帮助! 我尝试过使用 Drag_and_drop_lists 包,但我被困在手柄内部和外部项目中。 满

回答 1 投票 0

启用从资源管理器拖放到以管理员身份运行应用程序

我构建了一个winforms应用程序,并实现了拖放功能。此功能在 WinXP 或 Win7 中通过“以管理员身份运行”应用程序运行良好。 当三...

回答 1 投票 0

SwiftUI 拖放中的 NSItemProvider loadObject

我正在 SwiftUI 中使用 DropDelegate 拖放视图。 我成功使用 .onDrag View Modifier 将数据包装在 NSItemProvider 中,如果我是 ab,我什至可以让 .onDrop 工作...

回答 1 投票 0

当 DragImage.Height > 300 时,IFMXDragDropService 出现意外的渐变效果

我有一个纸牌游戏,我使用 IFMXDragDropService 将一系列纸牌从一个堆栈拖动到另一个堆栈。我更喜欢非半透明的拖动图像(这个 VCL 解决方案不起作用......

回答 1 投票 0

如何通过cdkDrag获取放下后的位置?

嗨,我需要能够拖放一些 html 元素,但我需要知道拖放的结束位置。 使用 cdkDrag 指令,我从文档中看到有一个事件 cdkDragEnded。 这……

回答 4 投票 0

Angular 18拖放部分数据

在此component.html中: 在此组件.html中: <div cdkDropListGroup> <div cdkDropList [cdkDropListData]="meals" class="makeMeal" (cdkDropListDropped)="drop($event)"> <div *ngFor="let meal of meals" class="meal-drop"> <img src="page_delete.png" (click)="deleteFood()" title="delete" /> <h4>{{meal.name}}</h4> <label id="lblID" class="hidden">{{meal.id}}</label> </div> Add a meal: <input id="mealName" type="text" [(ngModel)]="mealName" name="mealName" required style="margin-left:10px;" /> <img src="page_white_add.png" (click)="addMeal()" /> </div> <p>My foods:</p> <div cdkDropList [cdkDropListData]="foods" class="food-grid" (cdkDropListDropped)="drop($event)"> <div *ngFor="let food of foods" class="food-item"> <img src="page_delete.png" (click)="deleteFood()" title="delete" /> <h4>{{ food.name }}</h4> <ul> --> bunch of data <-- </ul> </div> </div> 我想拖动食物项目,然后将项目名称及其 ID 添加到餐食项目中 我已经尝试过这个,但它不起作用,因为我无法克服数据不匹配的问题: drop(event: CdkDragDrop<Foods[] | Meals[]>) { if (event.previousContainer === event.container) { moveItemInArray(event.container.data, event.previousIndex, event.currentIndex); } else { if (event.previousContainer.id === 'cdk-drop-list-foods') { const foodItem = event.previousContainer.data[event.previousIndex]; const mealIndex = event.container.data.findIndex(meal => meal.id === event.container.id); if (mealIndex !== -1) { this.meals[mealIndex].foods.push(foodItem); } } else { const mealIndex = this.meals.findIndex(meal => meal.id === event.previousContainer.id); const foodItem = this.meals[mealIndex].foods[event.previousIndex]; this.meals[mealIndex].foods.splice(event.previousIndex, 1); // Add food back to foods array this.foods.push(foodItem); } } } export interface Foods { name: string, calories: number, protein: number carbs: number, potassium: number, id: number } export interface Meals { name: string, id: string, foods: Foods[] } 我真的只是想从 Food 中删除名称和 ID。 这很难查找,为此我想发布一个答案。这就是我们正在做的事情: 您有一系列食物,并且您有一系列含有食物的餐食。 您想在膳食中添加食物: export interface Foods { name: string, calories: number, protein: number carbs: number, potassium: number, id: string, isActive: boolean } export interface Meals { name: string, id: string, calCount: number, foods: Foods[] } 这其中的关键是一开始就将食物集合添加到膳食集合中。 然后,您将在 HTML 组件中设置数组来接受数据。这将让您将一种类型的数据合并到另一种类型中。 private draggedFoodItem: Foods | null = null; onTaskDragStart(event: any, food: Foods) { this.draggedFoodItem = food; event.dataTransfer.setData('text/plain', JSON.stringify(food)); } onTaskDragOver(event: any) { event.preventDefault(); } onTaskDrop(event: any, meal: Meals) { event.preventDefault(); if (this.draggedFoodItem) { // Add the dragged food item to the meal's food list meal.foods.push(this.draggedFoodItem); // Remove the dragged food item from the original foods list this.foods = this.foods.filter(food => food.id !== this.draggedFoodItem?.id); // Clear the dragged item reference this.draggedFoodItem = null; const totalCalories = meal.foods.reduce((sum, food) => sum + (food.calories || 0), 0); meal.calCount = totalCalories; } } 代码的其余部分(我这里有所有相关组件,除了处理用户的组件之外)在保存数据、离开并返回后将数据重新加载到页面。 这会将数据写入 API,我没有包含该 API,因为这几乎只是关于拖放功能 组件.css: .container { margin-left: auto; margin-right: auto; max-width: 400px; text-align: center; } .container input[type=text] { width: 150px; } div.settings { display: grid; grid-template-columns: max-content max-content; grid-gap: 5px; } div.settings label { text-align: right; } div.settings label:after { content: ":"; } .food-item { padding: 5px; border: 1px solid #ccc; background-color: #f9f9f9; text-align: left; position: relative; } .food-item ul{ list-style:none; padding:0; } .food-item ul li{ padding:0; white-space:nowrap; font-size:small; } .food-item ul li ul li{ display:inline-block; margin-right:10px; min-width:70px; } .food-item img { width: 25px; height: 25px; position:absolute; top:1px; right:1px; z-index:5; } .food-item div{ padding: 10px; } .meal-item { padding: 5px; border: 1px solid #ccc; background-color: #f9f9f9; text-align: left; position: relative; width: 90%; min-height:30px; } .meal-item div { border: 1px green solid; border-radius: 15px; margin-left: 5px; margin-top: 2px; padding: 5px; } .makeMeal{ } .makeMeal img{ width:25px; height:25px; } .meal-drop{ border:1px solid red; position: relative; min-height:25px; } .meal-drop img{ height:15px; width:15px; position:absolute; top: 2px; right: 2px; } .meal-drop div{ clear:both; width:fit-content; height:auto; } .meal-drop button{ position:absolute; bottom: 2px; right: 6px; width: fit-content; } .hidden{ display:none; } .target{ border: 1px blue solid; min-width:90%; min-height:25px; } .plainList{ list-style:none; } .plainList ul { display: grid; grid-template-columns: repeat(3, 1fr); gap: 5px; padding:10px; } .plainList li{ padding:10px; position:relative; display:inline-block; margin-left:5px; margin-bottom:5px; border-radius:15px; } .plainList li img{ height:20px; width:20px; position:absolute; top:1px; right:1px; cursor:pointer; } .hideFood{ display:none; } .showFood{ display:block; border: 1px solid purple; } 组件.html: <div class="container"> <h2>Build A Meal:</h2> <p>My meals:</p> <div cdkDropListGroup> <div class="makeMeal"> <ul class="plainList"> @for(meal of meals; track meal.id; let i = $index){ <li class="meal-item"> {{meal.name}}<img src="page_delete.png" (click)="deleteMeal(meal.id, i)" /> <div class="meal-drop" [attr.draggable]="true" (dragover)="onTaskDragOver($event)" (drop)="onTaskDrop($event, meal)"> @for(droppedFood of meal.foods; track droppedFood.id; let j = $index){ <div>{{ droppedFood.name }}<img src="page_delete.png" (click)="deleteMealFood(meal.id, i, j)" /></div> } <button (click)="mealSave(meal)">Save</button> </div> Total calores: {{meal.calCount}} </li> } @empty{ <li>No meals found</li> } </ul> Add a meal: <input id="mealName" type="text" [(ngModel)]="mealName" name="mealName" required style="margin-left:10px;" /> <img src="page_white_add.png" (click)="addMeal()" /> </div> </div> <p>My foods:</p> <div class="food-grid"> <ul class="plainList"> @for(food of foods; track food.id; let i = $index){ <li class="food-item" [attr.draggable]="true" (dragstart)="onTaskDragStart($event, food)"> <div (click)="toggleActive(food)"> <img src="page_delete.png" (click)="deleteFood(food.id, i)" /> {{food.name}} <div [ngClass]="food.isActive? 'showFood' : 'hideFood'"> calories: {{food.calories}}<br /> protein: {{food.protein}}<br /> carbs: {{food.carbs}}<br /> potassium: {{food.potassium}} </div> </div> </li> } @empty{ <li>No food items found</li> } </ul> </div> </div> 组件.ts: import { Component, OnInit, NgModule, ChangeDetectorRef } from '@angular/core'; import { Router } from '@angular/router'; import { AuthService } from '../services/auth.service'; import { SaveMealService, Foods, Meals } from '../services/save-meal.service'; import { FormsModule } from '@angular/forms'; import { CommonModule } from '@angular/common'; @Component({ selector: 'app-build-meal', standalone: true, imports: [FormsModule, CommonModule], templateUrl: './build-meal.component.html', styleUrl: './build-meal.component.css' }) export class BuildMealComponent { private isUserLoggedIn: boolean = false; private userId: string = ''; private bmr: number = 0; public message: string = ''; public calCount: number = 0; public foods: Foods[] = []; public meals: Meals[] = []; public mealName: string = ''; private draggedFoodItem: Foods | null = null; public isActive = false; constructor( private authService: AuthService, private foodService: SaveMealService, private router: Router, private cdRef: ChangeDetectorRef ) { } ngAfterViewChecked() { this.cdRef.detectChanges(); } ngOnInit() { if (this.authService.isLoggedIn()) { this.isUserLoggedIn = true; var logUser = this.authService.getUserInfo(); this.userId = this.authService.userID; this.bmr = this.authService.bmr; this.getFood(); this.getMeals(); } } addMeal() { if (this.mealName.trim()) { this.foodService.createMeal(this.userId, this.mealName).subscribe({ next: (response: number) => { this.message = 'Meal created successfully'; this.getMeals(); // Refresh meal list after adding this.mealName = ''; // Clear the input field }, error: (err: number) => { this.message = 'Error creating meal: ' + err; } }); } } deleteFood(id: string, index: number) { this.foodService.removeFood(this.userId, id).subscribe({ next: (response: any) => { console.log(response); this.foods.splice(index, 1); } }); } deleteMeal(id: string, meal_index: number) { this.foodService.removeMeal(this.userId, id); this.meals.splice(meal_index, 1); } deleteMealFood(meal_id: string, meal_index: number, food_index: number) { const id = parseInt(meal_id); const foodId = this.meals[id].foods[food_index]; this.foodService.RemoveMealFood(meal_id, foodId.toString()); } getFood() { this.foodService.getAllFood(this.userId).subscribe({ next: (response: Foods[]) => { this.foods = response; }, error: (err: any) => { this.message = 'Error retrieving food: ' + err; } }); } getMeals() { this.foodService.getAllMeals(this.userId).subscribe({ next: (response: Meals[]) => { // Initialize foods array if not already present this.meals = response.map(meal => ({ ...meal, foods: meal.foods || [] // Initialize as an empty array if undefined })); }, error: (err: any) => { this.message = 'Error retrieving meals: ' + err; } }); } mealSave(meal: Meals) { this.foodService.saveMeal(meal, meal.id).subscribe(results => { console.log('All requests completed:', results); }); } onTaskDragStart(event: any, food: Foods) { this.draggedFoodItem = food; event.dataTransfer.setData('text/plain', JSON.stringify(food)); } onTaskDragOver(event: any) { event.preventDefault(); } onTaskDrop(event: any, meal: Meals) { event.preventDefault(); if (this.draggedFoodItem) { // Add the dragged food item to the meal's food list meal.foods.push(this.draggedFoodItem); // Remove the dragged food item from the original foods list this.foods = this.foods.filter(food => food.id !== this.draggedFoodItem?.id); // Clear the dragged item reference this.draggedFoodItem = null; const totalCalories = meal.foods.reduce((sum, food) => sum + (food.calories || 0), 0); meal.calCount = totalCalories; } } toggleActive(food: any) { food.isActive = !food.isActive; } trackById(index: number, item: any): number { return item.id; } } 节省餐食.service.ts: import { Injectable } from '@angular/core'; import { HttpClient, HttpErrorResponse, HttpHeaders } from '@angular/common/http'; import { forkJoin, Observable, of, throwError } from 'rxjs'; import { catchError, map, switchMap } from 'rxjs/operators'; import { jwtDecode } from "jwt-decode"; import { tap } from 'rxjs/operators'; export interface Foods { name: string, calories: number, protein: number carbs: number, potassium: number, id: string, isActive: boolean } export interface Meals { name: string, id: string, calCount: number, foods: Foods[] } @Injectable({ providedIn: 'root' }) export class SaveMealService { private apiUrl = 'https://127.0.0.1:7010/api/Food'; private apiMealUrl = 'https://localhost:7010/api/Meal'; private apiTemplateUrl = 'https://127.0.0.1:7010/api/MealTemplate' constructor( private http: HttpClient ) { } createMeal( userId: string, mealName: string ): Observable<number> { const meal = { userId, mealName }; return this.http.post<number>(`${this.apiMealUrl}/CreateMeal`, meal).pipe( tap(response => { }) ); } removeFood(userid: string, id: string ): Observable<any> { const food = { id }; return this.http.post<any>(`${this.apiUrl}/removeFood?id=${id}`, { headers: { 'Content-Type': 'application/json' }, observe: 'response' // Observe the full HTTP response }).pipe( map(response => { if (response.status === 200) { // Check for 'OK' status // Perform navigation to login page here (optional) console.log(response); return response.body as number; // Return true if the response status is 200 OK } return -2; }), catchError(() => of(-3)) // Handle error and return false ); } removeMeal(userId: string, id: string) { const item = { userId, id }; return this.http.post<any>(`${this.apiMealUrl}/removeMeal`, item, { headers: { 'Content-Type': 'application/json' }, observe: 'response' // Observe the full HTTP response }).pipe( tap(response => { }) ); } saveMeal(meal: Meals, mealId: string) { const foods: Foods[] = meal.foods; const requests = foods.map(item => { const foodId = item.id.toString(); // Ensure foodId is a string return this.http.post<any>(`${this.apiTemplateUrl}/SaveMealAsync?foodId=${foodId}&mealId=${mealId}`, { // Wrap menuItem in an "item" property headers: { 'Content-Type': 'application/json' }, observe: 'response' }).pipe( map(response => response.status === 200), catchError(err => { this.errorHandler(err); return [false]; // Return false if an error occurs }) ); }); return forkJoin(requests); // Return an observable that completes when all requests are done } errorHandler(error: HttpErrorResponse) { console.log(error.message); return throwError(error.message || "server error."); } getAllFood(userID: string): Observable<Foods[]> { return this.http.get<Foods[]>(`${this.apiUrl}/getFoods?id=${userID}`).pipe( tap(response => { }) ); } getAllMeals(userId: string): Observable<Meals[]> { return this.http.get<Meals[]>(`${this.apiMealUrl}/getMeals?userID=${userId}`).pipe( switchMap((meals: Meals[]) => { // For each meal, get the associated foods const mealsWithFoods$ = meals.map(meal => this.http.get<Foods[]>(`https://127.0.0.1:7010/api/MealTemplate/getFoodsByMeal?mealId=${meal.id}`) .pipe( map(foods => { // Calculate the total calorie count for the meal const totalCalories = foods.reduce((acc, food) => acc + food.calories, 0); return { ...meal, foods, calCount: totalCalories }; // Include calCount in the meal object }) ) ); // Combine all observables into one return forkJoin(mealsWithFoods$); }), tap(response => { console.log('Meals with foods and calorie counts:', response); }) ); } RemoveMealFood( meal_id: string, foodId: string): Observable<any> { return this.http.post<any>(`${this.apiTemplateUrl}/RemoveFood?mealId=${meal_id}&foodId=${foodId}`, { headers: { 'Content-Type': 'application/json' }, observe: 'response' // Observe the full HTTP response }).pipe( map(response => { if (response.status === 200) { // Check for 'OK' status // Perform navigation to login page here (optional) console.log(response); return response; } return false; }), catchError(() => of(false)) ); } saveFood( userid: string, foodName: string, calories: number, carbohydrates: number, protein: number, potassium: number, servingSize: number, portion: number ): Observable<number> { const food = { userid, foodName, calories, protein, carbohydrates, potassium, servingSize, portion }; return this.http.post<any>(`${this.apiUrl}/SaveFood`, food, { headers: { 'Content-Type': 'application/json' }, observe: 'response' // Observe the full HTTP response }).pipe( map(response => { if (response.status === 200) { // Check for 'OK' status // Perform navigation to login page here (optional) console.log(response); return response.body as number; // Return true if the response status is 200 OK } return -2; }), catchError(() => of(-3)) // Handle error and return false ); } }

回答 1 投票 0

© www.soinside.com 2019 - 2024. All rights reserved.