目的:现有一个图片的列表,拖动其中一个图片(触发dragstart),当拖动的图片移动到其他图片的位置(触发dragover),则将拖动的图片从原位置移动到该位置(触发dragend)。
dragstart:当用户开始拖动一个元素 dragstart 事件就会触发,事件源是该元素。
dragover:被拖拽元素经过时触发 dragover 事件(每几百毫秒触发一次)。
dragend:拖放事件在拖放操作结束时触发,事件源是拖动元素(和dragstart的事件源是同一个元素)。
事件文档:dragstart - Web API 接口参考 | MDN
效果:
实现组件:
<template>
<div>
<ul class='img-wrapper'
@dragstart="onDragStart"
@dragover="onDragOver"
@dragend="onDragEnd">
<li class="img-box"
v-for="(url,index) in imgList" :key='url+index'>
<img :src="url" draggable="true">
<i @click="remove_img(index)" class="clear"></i>
</li>
<div class="img-box logo-empty"
v-if="imgList.length!==count"
@click="addImage">
</div>
</ul>
<div class="tip">图片宽高要求1:1比例,建议尺寸为640px*640px以上;最多上传5张图片,您可以拖拽图片调整图片顺序。</div>
</div>
</template>
<script setup>
import { toRefs } from 'vue'
const props = defineProps({
imgList: {
required: true,
type: Array,
default: []
},
count: {
required: true,
type: Number,
default: 5
},
change: {
required: true,
type: Function,
default () {
return 'Default function'
}
},
addImage: {
required: true,
type: Function,
default () {
return 'Default function'
}
}
})
let target = undefined;
const { imgList, count, change } = toRefs(props);
function onDragStart(event) {
}
function onDragOver(event) {
event.preventDefault();
let hoverEle = event.target || event.srcElement;
hoverEle.src && (target = hoverEle)
}
function onDragEnd(event) {
let draging = event.target || event.srcElement;
if (target.src && draging.src && draging.src!==target.src) {
let dragingIndxe = imgList.value.indexOf(draging.src)
let targetIndex = imgList.value.indexOf(target.src)
change.value(dragingIndxe, 1, target.src)
change.value(targetIndex, 1, draging.src)
}
}
function remove_img(index) {
change.value(index, 1);
}
</script>
<style lang="scss" scoped>
@import "@/assets/style/common.scss";
.tip {
color: #999;
}
.img-wrapper {
display: flex;
width: 80%;
cursor: pointer;
.img-box {
position: relative;
height: $px120;
width: $px120;
border-radius: $px5;
margin-right: $px12;
border: 1px solid #dcdfe6;
img {
width: 100%;
height: 100%;
border-radius: $px5;
}
.clear {
position: absolute;
top: -$px12;
right: -$px12;
height: $px24;
width: $px24;
border-radius: 50%;
background-color: #d7d7d7;
&::after {
position: absolute;
top: calc(50% - $px10);
left: calc(50% - $px1);
display: block;
content: "";
width: $px2;
height: $px20;
background-color: #fff;
transform: rotate(-45deg)
}
&::before {
position: absolute;
top: calc(50% - $px10);
right: calc(50% - $px1);
display: block;
content: "";
width: $px2;
height: $px20;
background-color: #fff;
transform: rotate(45deg)
}
&:hover {
background-color: red;
&::before {
background-color: #fff;
}
&::after {
background-color: #fff;
}
}
}
}
.logo-empty {
box-sizing: border-box;
border: $px1 solid #dcdfe6;
position: relative;
&::before {
position: absolute;
top: calc(50% - $px2);
left: calc(50% - $px20);
display: block;
content: "";
height: $px4;
width: $px40;
background-color: $placeholder;
}
&::after {
position: absolute;
top: calc(50% - $px20);
right: calc(50% - $px2);
display: block;
content: "";
height: $px40;
width: $px4;
background-color: $placeholder;
}
&:hover {
background-color: #C9C9C9;
&::before {
background-color: #fff;
}
&::after {
background-color: #fff;
}
}
}
}
</style>
组件使用:
<template>
<div>
<imglist :imgList="imgs"
:count="5"
:change="change"
:addImage="addImage"></imglist>
</div>
</template>
<script setup>
import {ref} from "vue"
import imglist from "@/components/imgList.vue"
const imgs =ref([]);
function change(){
imgs.value.splice(...arguments)
}
let imgpath=[
"https://gimg2.baidu.com/image_search/src=http%3A%2F%2Fimg.jj20.com%2Fup%2Fallimg%2F1114%2F0G020114924%2F200G0114924-1-1200.jpg&refer=http%3A%2F%2Fimg.jj20.com&app=2002&size=f9999,10000&q=a80&n=0&g=0n&fmt=auto?sec=1658730246&t=e46ec7fddbc22b7749934cecee37f497",
"https://gimg2.baidu.com/image_search/src=http%3A%2F%2Fimg.jj20.com%2Fup%2Fallimg%2Ftp09%2F21031FKU44S6-0-lp.jpg&refer=http%3A%2F%2Fimg.jj20.com&app=2002&size=f9999,10000&q=a80&n=0&g=0n&fmt=auto?sec=1658730246&t=b3a3d686af67c6b9832d26a54f088862",
"https://gimg2.baidu.com/image_search/src=http%3A%2F%2Fimg.jj20.com%2Fup%2Fallimg%2F4k%2Fs%2F02%2F2109242306111155-0-lp.jpg&refer=http%3A%2F%2Fimg.jj20.com&app=2002&size=f9999,10000&q=a80&n=0&g=0n&fmt=auto?sec=1658730246&t=2d9022c5f303614fc15ccab2eb0b4267",
"https://gimg2.baidu.com/image_search/src=http%3A%2F%2Fimg.jj20.com%2Fup%2Fallimg%2F1113%2F0F420110430%2F200F4110430-6-1200.jpg&refer=http%3A%2F%2Fimg.jj20.com&app=2002&size=f9999,10000&q=a80&n=0&g=0n&fmt=auto?sec=1658730246&t=3d81803a13b4be2bae79bf4dc4b86819",
"https://gimg2.baidu.com/image_search/src=http%3A%2F%2Fimg.jj20.com%2Fup%2Fallimg%2F1114%2F0G020114924%2F200G0114924-15-1200.jpg&refer=http%3A%2F%2Fimg.jj20.com&app=2002&size=f9999,10000&q=a80&n=0&g=0n&fmt=auto?sec=1658730246&t=001736fa40c669dc49bfc182f095bd7c"];
function addImage(){
imgs.value.push(imgpath[imgs.value.length])
}
</script>
<style>
</style>