Я использую вызов API для заполнения изображений и музыки c. Реализованы функции HTML5 drag & drop .
Однако, когда я перетаскиваю определенное изображение и перетаскиваю его на карту (справа), 1-е изображение из списка удаляется.
Когда я перетаскиваю музыку c, , отображается «ноль».
Можно добавить правую панель при нажатии на знак плюса ( ссылка на ссылку Демо-сервер ниже ). Я хочу, чтобы каждый контейнер ограничивал только одно изображение, а тег musi c удалялся .
посадка. vue
<template>
<div>
<div class>
<div class="row">
<div class="col-sm-6">
<div class="card show-panel">
<div class="card-body purple-gradient">
<nav>
<div
class="nav fixed nav-tabs nav-fill"
id="nav-tab"
role="tablist"
>
<a
class="nav-item nav-link active"
id="nav-home-tab"
data-toggle="tab"
href="#nav-home"
role="tab"
aria-controls="nav-home"
aria-selected="true"
>Story</a
>
<a
v-on:click.prevent="toggler()"
@click.prevent="populate()"
class="nav-item nav-link"
id="nav-profile-tab"
data-toggle="tab"
href="#nav-profile"
role="tab"
aria-controls="nav-profile"
aria-selected="false"
>Media</a
>
<a
v-on:click.prevent="toggler()"
@click="populate()"
class="nav-item nav-link"
id="nav-contact-tab"
data-toggle="tab"
href="#nav-contact"
role="tab"
aria-controls="nav-contact"
aria-selected="false"
>Music</a
>
</div>
</nav>
<div class="tab-content py-3 px-3 px-sm-0" id="nav-tabContent">
<div id="nav-home" :class="{ hidden: isActive }">
<div
class="tab-pane fade show active overflow-auto"
role="tabpanel"
aria-labelledby="nav-home-tab"
>
Lorem ipsum dolor sit amet, consectetur adipiscing
</div>
</div>
<div
class="tab-pane fade"
id="nav-profile"
role="tabpanel"
aria-labelledby="nav-profile-tab"
>
<p v-if="loading">Loading...</p>
<ul v-else class="image-grid">
<div
v-for="image in images"
:key="image.id"
class="image-card"
>
<img
class="image-card__image"
:src="image.url_n"
:alt="image.title"
id="image"
draggable="true"
@dragstart="dragStart"
/>
</div>
</ul>
</div>
<div
class="tab-pane fade"
id="nav-contact"
role="tabpanel"
aria-labelledby="nav-contact-tab"
>
<p v-if="loading">Loading...</p>
<ul id="napsterDiv" class="music-grid"></ul>
</div>
</div>
</div>
</div>
</div>
<div class="col-6">
<div
id="container"
@drop="drop"
@dragover="allowDrop"
@dragenter="showzone"
@dragend="end"
>
<div v-for="(sec, i) in secNum" :key="i">
<panelcard :section="sec" v-bind:id="i"></panelcard>
</div>
</div>
</div>
</div>
</div>
</div>
</template>
<script>
import panelcard from "./panelcard";
// import imagecard from "./imagecard";
import config from "../../config";
import axios from "axios";
export default {
data() {
return {
loading: false,
tag: "landscape",
isActive: false,
images: {},
musicList: {},
run: true,
dropped: true
// eslint-disable-next-line prettier/prettier
}
},
components: { panelcard },
computed: {
secNum() {
return this.$store.getters.getSec;
}
},
mounted() {
if (this.$store.state.custom.secCount.length < 1) {
this.$store.commit("addSec");
}
},
methods: {
toggler() {
if (!this.isActive) {
this.isActive = true;
}
},
// eslint-disable-next-line no-unused-vars
showzone(e) {
e.preventDefault();
console.log("enter");
},
dragStart(evt) {
evt.dataTransfer.setData("text", evt.target.id);
console.log(evt);
},
dragMusic(e) {
e.dataTransfer.setData("text", e.target.id);
console.log(e);
},
drop(evt) {
if (this.dropped) {
console.log("dropped");
evt.preventDefault();
var data = evt.dataTransfer.getData("text");
var audioData = evt.dataTransfer.getData("text");
var song = document.getElementById(audioData);
var image = document.getElementById(data);
if (image) {
evt.target.appendChild(image);
} else {
evt.target.append(song);
}
}
},
end(e) {
e.preventDefault();
// this.dropped = false;
},
allowDrop(evt) {
evt.preventDefault();
},
populate() {
this.loading = true;
this.fetchImages().then(response => {
this.images = response.data.photos.photo;
this.loading = false;
});
if (this.run) {
this.fetchMusic();
this.run = false;
}
},
fetchImages() {
return axios({
method: "get",
url: "https://api.flickr.com/services/rest",
params: {
method: "flickr.photos.search",
api_key: config.api_key,
tags: this.tag,
extras: "url_n, owner_name, date_taken, views",
page: 1,
format: "json",
nojsoncallback: 1,
per_page: 12
}
});
},
fetchMusic() {
this.loading = true;
let perPage = 9;
let offset = 0;
const napsterSongURL = `https://api.napster.com/v2.1/playlists/pp.188152066/tracks?apikey=N2Q5N2U3MzQtNDVlYS00MTY5LThhMGQtYWFmMDk5MzBjZjlk&limit=${perPage}&offset=${offset}`;
axios.get(napsterSongURL).then(function(response) {
let napsterSongData = response.data.tracks;
offset += napsterSongData.length;
for (var i = 0; i < napsterSongData.length; i++) {
let myUrl = napsterSongData[i].previewURL;
let artistID = napsterSongData[i].artistId;
let artistImageURL = `https://api.napster.com/imageserver/v2/artists/${artistID}/images/150x150.jpg?apikey=N2Q5N2U3MzQtNDVlYS00MTY5LThhMGQtYWFmMDk5MzBjZjlk&limit=9`;
let artistImage = `<img id='artistImage' src='${artistImageURL}'/>`;
let songDiv = document.createElement("drag");
songDiv.style.cssText =
"width: calc(33% - 1rem);margin: 1rem 0.5rem;border-radius: 5px;box-shadow: 0 5px 15px rgba(0, 0, 0, 0.15);background: white;";
songDiv.classList.add("songDisplay");
let html =
artistImage +
`<audio id="audio" @dragstart="dragMusic" @dragover.prevent style="width: 150px;" draggable="true" controls><source class='audioSource' src= "${myUrl}"x></audio>`;
songDiv.innerHTML += html;
document.getElementById("napsterDiv").append(songDiv);
}
});
}
}
};
</script>
<style scoped>
nav > .nav.nav-tabs {
border: none;
color: #fff;
background: #272e38;
border-radius: 0;
}
nav > div a.nav-item.nav-link,
nav > div a.nav-item.nav-link.active {
border: none;
padding: 18px 25px;
color: #fff;
background: #272e38;
border-radius: 0;
}
.tab-content {
background: #fdfdfd;
line-height: 25px;
border: 1px solid #ddd;
border-top: 5px solid #e74c3c;
border-bottom: 5px solid #e74c3c;
padding: 30px 25px;
min-height: 706px;
}
nav > div a.nav-item.nav-link:hover,
nav > div a.nav-item.nav-link:focus {
border: none;
background: #e74c3c;
color: #fff;
border-radius: 0;
transition: background 0.2s linear;
}
.overflow-auto {
height: 600px;
text-align: justify;
}
.tab-pane {
margin-top: 2rem;
padding: 0px 20px;
}
.hidden {
display: none;
}
nav > div a.nav-item.nav-link.active:after {
content: "";
position: relative;
bottom: -50px;
left: -10%;
border: 10px solid transparent;
border-top-color: #e74c3c;
}
.show-panel {
width: 90%;
min-height: 600px;
margin: 0 auto;
float: right;
}
.image-grid {
list-style: none;
margin-top: 0.5rem;
padding: 0;
display: flex;
align-items: flex-start;
flex-wrap: wrap;
}
.music-grid {
list-style: none !important;
margin: 0.5rem 0;
padding: 0;
display: flex;
align-items: flex-start;
flex-wrap: wrap;
}
.songDisplay {
width: calc(33% - 1rem);
margin: 0.5rem;
border-radius: 5px;
box-shadow: 0 5px 15px rgba(0, 0, 0, 0.15);
background: white;
}
#artistImage {
border-radius: 5px 5px 0 0;
width: 100%;
height: 140px;
object-fit: cover;
}
.image-card {
width: calc(33% - 1rem);
margin: 0.5rem 0.5rem;
border-radius: 5px;
box-shadow: 0 5px 15px rgba(0, 0, 0, 0.15);
background: white;
}
.image-card__image {
border-radius: 5px 5px 0 0;
width: 150px;
height: 135px;
object-fit: cover;
}
.zone {
height: 150px;
width: 135px;
object-fit: cover;
}
</style>
Демонстрационный сервер : https://quizzical-volhard-30f3e6.netlify.com/
репо : https://bitbucket.org/anishjana/playlist-ui/src/325717a59ec9081db76499b8c4754a3b84916a57/?at=feature%2Fdrag-drop