效果

源码
html
<div class="draggable-wrap">
<div class="draggable-box" draggable="true" data-json='{"name": "Lee"}'>
<h1>Lee</h1>
<div class="drop-box" data-json='{"name": "Lee"}'>
<svg class="icon" viewBox="0 0 1024 1024" version="1.1" xmlns="http://www.w3.org/2000/svg" width="64" height="64">
<path d="M639.996 1023.988H384.002l42.656-512.582h170.684z" fill="#ED5564"></path>
<path
d="M939.552 310.66l-295.43-42.936L512 0.012l-132.124 267.712L84.448 310.66l213.774 208.402-50.466 294.242L512 674.372l264.244 138.932-50.468-294.242z"
fill="#FFCE54"></path>
<path d="M939.552 310.66L512 469.312l213.776 49.75z" fill="#F6BB42"></path>
<path
d="M512 874.648c-11.782 0-21.344 9.562-21.344 21.344v127.996h42.686v-127.996c0-11.782-9.562-21.344-21.342-21.344z"
fill="#DA4453"></path>
<path
d="M512 469.312v205.06l264.244 138.932zM298.222 519.062l-50.466 294.242L512 469.312zM379.876 267.724L84.448 310.66 512 469.312zM512 0.012v469.3l132.122-201.588z"
fill="#F6BB42"></path>
</svg>
</div>
</div>
<div class="draggable-box" draggable="true" data-json='{"name": "Tom"}'>
<h1>Tom</h1>
<div class="drop-box" data-json='{"name": "Tom"}'>
<svg class="icon" viewBox="0 0 1024 1024" version="1.1" xmlns="http://www.w3.org/2000/svg" width="64" height="64">
<path d="M639.996 1023.988H384.002l42.656-512.582h170.684z" fill="#ED5564"></path>
<path
d="M939.552 310.66l-295.43-42.936L512 0.012l-132.124 267.712L84.448 310.66l213.774 208.402-50.466 294.242L512 674.372l264.244 138.932-50.468-294.242z"
fill="#FFCE54"></path>
<path d="M939.552 310.66L512 469.312l213.776 49.75z" fill="#F6BB42"></path>
<path
d="M512 874.648c-11.782 0-21.344 9.562-21.344 21.344v127.996h42.686v-127.996c0-11.782-9.562-21.344-21.342-21.344z"
fill="#DA4453"></path>
<path
d="M512 469.312v205.06l264.244 138.932zM298.222 519.062l-50.466 294.242L512 469.312zM379.876 267.724L84.448 310.66 512 469.312zM512 0.012v469.3l132.122-201.588z"
fill="#F6BB42"></path>
</svg>
</div>
</div>
<div class="draggable-box" draggable="true" data-json='{"name": "Jerry"}'>
<h1>Jerry</h1>
<div class="drop-box" data-json='{"name": "Jerry"}'>
<svg class="icon" viewBox="0 0 1024 1024" version="1.1" xmlns="http://www.w3.org/2000/svg" width="64" height="64">
<path d="M639.996 1023.988H384.002l42.656-512.582h170.684z" fill="#ED5564"></path>
<path
d="M939.552 310.66l-295.43-42.936L512 0.012l-132.124 267.712L84.448 310.66l213.774 208.402-50.466 294.242L512 674.372l264.244 138.932-50.468-294.242z"
fill="#FFCE54"></path>
<path d="M939.552 310.66L512 469.312l213.776 49.75z" fill="#F6BB42"></path>
<path
d="M512 874.648c-11.782 0-21.344 9.562-21.344 21.344v127.996h42.686v-127.996c0-11.782-9.562-21.344-21.342-21.344z"
fill="#DA4453"></path>
<path
d="M512 469.312v205.06l264.244 138.932zM298.222 519.062l-50.466 294.242L512 469.312zM379.876 267.724L84.448 310.66 512 469.312zM512 0.012v469.3l132.122-201.588z"
fill="#F6BB42"></path>
</svg>
</div>
</div>
</div>
css
body {
margin: 0;
user-select: none;
}
.draggable-wrap {
height: 100vh;
display: flex;
justify-content: center;
align-items: center;
gap: 80px;
.draggable-box {
position: relative;
width: 240px;
height: 140px;
border: 3px solid black;
scale: 1.2;
h1 {
text-align: center;
}
&:nth-child(1) {
background-color: red;
}
&:nth-child(2) {
background-color: green;
}
&:nth-child(3) {
background-color: blue;
}
&[drag="start"] {
opacity: .2;
}
&[drag="end"] {
opacity: 1;
}
.drop-box {
opacity: 0;
position: absolute;
top: 0;
right: 0;
bottom: 0;
left: 0;
border: 3px dashed black;
background-color: rgba(0, 0, 0, .5);
transition: 1s;
display: flex;
justify-content: center;
align-items: center;
gap: 20px;
.icon {
display: none;
width: 80px;
height: 80px;
}
&[drag="enter"] {
opacity: 1;
&::after {
content: '';
display: block;
position: absolute;
top: 0;
right: 0;
bottom: 0;
left: 0;
}
.icon {
display: block;
}
}
&[drag="leave"] {
opacity: 0;
.icon {
display: none;
}
}
&[drag="drop"] {
opacity: 1;
.icon {
display: block;
}
}
}
}
}
js
const draggables = document.querySelectorAll('.draggable-box');
const drops = document.querySelectorAll('.drop-box');
draggables.forEach(el => {
el.addEventListener('dragstart', e => {
e.target.setAttribute('drag', 'start');
e.dataTransfer.setData('data', e.target.getAttribute('data-json'));
});
el.addEventListener('dragend', e => {
e.target.setAttribute('drag', 'end');
});
});
drops.forEach(el => {
el.addEventListener('dragenter', e => {
e.stopPropagation();
e.target.setAttribute('drag', 'enter');
});
el.addEventListener('dragover', e => e.preventDefault());
el.addEventListener('dragleave', e => {
e.stopPropagation();
e.target.setAttribute('drag', 'leave');
});
el.addEventListener('drop', e => {
e.target.setAttribute('drag', 'drop');
const source = JSON.parse(e.dataTransfer.getData('data'));
const target = JSON.parse(e.target.getAttribute('data-json'));
console.log(source, target);
});
});