web前端之拖拽API、vue3实现图片上传拖拽排序、拖放、投掷、复制、若依、vuedraggable
MENU
- vue2+html5+原生dom+原生JavaScript实现跨区域拖放
- vue2实现跨区域拖放
- vue2+mousedown实现全屏拖动,全屏投掷
- vue3+element-plus+vuedraggable实现图片上传拖拽排序
- vue2+transition-group实现拖动排序
- 原生拖拽排序
vue2+html5+原生dom+原生JavaScript实现跨区域拖放
关键代码
// 放
function drop(ev) {let data = ev.dataTransfer.getData("Text"),i = ev.path[1].getAttribute("i"),text = document.getElementById(data).cloneNode(true).innerText.trim();if (i == null) return alert('请放置在文件名上');if (app.fileS[i].divs.includes(text)) return alert('不能放重复数据');app.fileS[i].divs.push(text);for (let is = 0; is < app.fileS.length; is++) {if (i == is) {app.fileS[is].isShow = true;} else {app.fileS[is].isShow = false;}}
}
完整代码
gitee(码云) - mj01分支 - copyDragAndDrop 文件
vue2实现跨区域拖放
关键代码
dragend(item) {console.log(item);if (this.oldItem != this.newItem) {let oldIndex = this.List.indexOf(this.oldItem);let newIndex = this.List.indexOf(this.newItem);let oldflag = falselet newflag = falseif (oldIndex === -1) {oldflag = trueoldIndex = this.list.indexOf(this.oldItem);}if (newIndex === -1) {newflag = truenewIndex = this.list.indexOf(this.newItem);}let newList = [...this.List]; // 中间数组,用于交换两个节点let newlist = [...this.list]; // 中间数组,用于交换两个节点if (!oldflag) {newList.splice(oldIndex, 1);} else {newlist.splice(oldIndex, 1);}if (!newflag) {newList.splice(newIndex, 0, this.oldItem);} else {newlist.splice(newIndex, 0, this.oldItem);}// 删除老的节点// newList.splice(oldIndex, 1);// // 在列表目标位置增加新的节点// newList.splice(newIndex, 0, this.oldItem);// // 更新this.List,触发transition-group的动画效果this.List = [...newList];this.list = [...newlist];}
}
完整代码
gitee(码云) - mj01分支 - dragAndDrop 文件
vue2+mousedown实现全屏拖动,全屏投掷
html
<!DOCTYPE html>
<html lang="en"><head><meta charset="UTF-8"><meta http-equiv="X-UA-Compatible" content="IE=edge"><meta name="viewport" content="width=device-width, initial-scale=1.0"><title>鼠标滑动</title><link rel="stylesheet" href="./index.css">
</head><body><div id="app"><div class="ctn ctn1"><div class="sub sub1" v-for="(site, index) in list1"><div class="dragCtn fixed" @mousedown="mousedown(site, $event)"@mousemove.prevent='mousemove(site, $event)' @mouseup='mouseup(site, $event)'>{{ site.name }}</div></div></div><div class="ctn ctn2"><div class="sub sub2" v-for="(site, index) in list2"><div class="dragCtn">{{ index }} : {{ site.name }}</div></div></div></div><script src="/node_modules/vue/dist/vue.js"></script><script src="./index.js"></script>
</body></html>
JavaScript
new Vue({el: '#app',data: {list1: [{ name: '拖动我', index: 0 }],list2: [{ name: 'a', index: 0 }, { name: 'b', index: 1 }, { name: 'c', index: 2 }, { name: 'd', index: 3 }],vm: '',sb_bkx: 0,sb_bky: 0,is_moving: false},methods: {mousedown: function (site, event) {var startx = event.x;var starty = event.y;this.sb_bkx = startx - event.target.offsetLeft;this.sb_bky = starty - event.target.offsetTop;this.is_moving = true;},mousemove: function (site, event) {var endx = event.x - this.sb_bkx;var endy = event.y - this.sb_bky;var _this = thisif (this.is_moving) {event.target.style.left = endx + 'px';event.target.style.top = endy + 'px';}},mouseup: function (e) {this.is_moving = false;}}
});
css
.ctn {line-height: 50px;cursor: pointer;font-size: 20px;text-align: center;float: left;
}.sub:hover {background: #e6dcdc;color: white;width: 100px;
}.ctn1 {border: 1px solid green;width: 100px;
}.ctn2 {border: 1px solid black;width: 100px;margin-left: 50px;
}.fixed {width: 100px;height: 100px;position: fixed;background: red;left: 10px;top: 10px;cursor: move;
}
vue3+element-plus+vuedraggable实现图片上传拖拽排序
前言
安装对应的
vuedraggable组件
npm install vuedraggable@4.1.0 --save
package.json文件中记录对应的版本号为:"vuedraggable": "4.1.0",这里要注意咯!!!克隆项目的时候这里的4.1.0可能会变为^4.1.0,一定要改为4.1.0;如果不是可以先卸载然后安装正确的版本即可。
如果版本不对会报错,并且不能运行。
本案例基于若依vue3前后端分离项目做二次开发
若依自带二次封装element-plus图片上传组件,但是没有实现拖拽排序功能。
于是又自己封装了一个ImageUploadDraggable图片上传组件,此组件基于若依自带的图片上传组件的基础上进行再次封装。
组件正常引入即可,可以全局引入或局部引入,引入方式跟我们自定的组件一样。
html
<el-form-item label="图片" class="ws_n"><image-upload-draggable v-model="dialogForm.images" :limit="5"></image-upload-draggable>
</el-form-item>
JavaScript
let info = reactive({dialogForm: {// 图片images: []}}),{dialogForm} = toRefs(info);
二次封装上传组件
<template><div class="component-upload-image"><ul class="el-upload-list el-upload-list--picture-card"><vue-draggable-next v-model="fileList"><li v-for="(item, index) in fileList" :key="item.index" class="el-upload-list__item is-success animated"><img :src="item.url" alt="" class="el-upload-list__item-thumbnail" /><i class="el-icon-close"></i><span class="el-upload-list__item-actions"><!-- 预览 --><span class="el-upload-list__item-preview" @click="handlePictureCardPreviewFileDetail(item)"><el-icon><zoom-in></zoom-in></el-icon></span><!-- 删除 --><span class="el-upload-list__item-delete" @click="handleRemoveFileDetail(index)"><el-icon><delete></delete></el-icon></span></span></li></vue-draggable-next></ul><el-upload multiple :action="uploadImgUrl" list-type="picture-card" :on-success="handleUploadSuccess":before-upload="handleBeforeUpload" :limit="limit" :on-error="handleUploadError" :on-exceed="handleExceed"ref="imageUpload" :show-file-list="false" :headers="headers" :class="{ hide: fileList.length >= limit }"><el-icon class="avatar-uploader-icon"><plus /></el-icon></el-upload><!-- 上传提示 --><div class="el-upload__tip" v-if="showTip">请上传<template v-if="fileSize">大小不超过<b style="color: #f56c6c">{{ fileSize }}MB</b></template><template v-if="fileType">格式为<b style="color: #f56c6c">{{ fileType.join("/") }}</b></template>的文件</div><el-dialog v-model="dialogVisible" title="预览" width="800px" append-to-body><img :src="dialogImageUrl" style="display: block; max-width: 100%; margin: 0 auto" /></el-dialog></div>
</template><script setup>
import { VueDraggableNext } from "vue-draggable-next";
import { getToken } from "@/utils/auth";const props = defineProps({modelValue: [String, Object, Array],// 图片数量限制limit: {type: Number,default: 5,},// 大小限制(MB)fileSize: {type: Number,default: 5,},// 文件类型, 例如['png', 'jpg', 'jpeg']fileType: {type: Array,default: () => ["png", "jpg", "jpeg"],},// 是否显示提示isShowTip: {type: Boolean,default: true,},
});const { proxy } = getCurrentInstance();
const emit = defineEmits();
const number = ref(0);
const uploadList = ref([]);
const dialogImageUrl = ref("");
const dialogVisible = ref(false);
const baseUrl = import.meta.env.VITE_APP_BASE_API;
// 上传的图片服务器地址
const uploadImgUrl = ref(import.meta.env.VITE_APP_BASE_API + "/file/upload");
const headers = ref({Authorization: "Bearer " + getToken(),appid: import.meta.env.VITE_APP_ID,
});
const fileList = ref([]);
const showTip = computed(() => props.isShowTip && (props.fileType || props.fileSize)
);watch(() => props.modelValue,(val) => {if (val) {// 首先将值转为数组const list = Array.isArray(val) ? val : props.modelValue.split(",");// 然后将数组转为对象数组fileList.value = list.map((item) => {if (typeof item === "string") {item = { name: item, url: item };}return item;});} else {fileList.value = [];return [];}},{ deep: true, immediate: true }
);// 上传前loading加载
function handleBeforeUpload(file) {let isImg = false;if (props.fileType.length) {let fileExtension = "";if (file.name.lastIndexOf(".") > -1) {fileExtension = file.name.slice(file.name.lastIndexOf(".") + 1);}isImg = props.fileType.some((type) => {if (file.type.indexOf(type) > -1) return true;if (fileExtension && fileExtension.indexOf(type) > -1) return true;return false;});} else {isImg = file.type.indexOf("image") > -1;}if (!isImg) {proxy.$modal.msgError(`文件格式不正确, 请上传${props.fileType.join("/")}图片格式文件!`);return false;}if (props.fileSize) {const isLt = file.size / 1024 / 1024 < props.fileSize;if (!isLt) {proxy.$modal.msgError(`上传头像图片大小不能超过 ${props.fileSize} MB!`);return false;}}proxy.$modal.loading("正在上传图片,请稍候...");number.value++;
}// 文件个数超出
function handleExceed() {proxy.$modal.msgError(`上传文件数量不能超过 ${props.limit} 个!`);
}// 上传成功回调
function handleUploadSuccess(res, file) {if (res.code === 0) {uploadList.value.push({ name: res.data.url, url: res.data.url });uploadedSuccessfully();} else {number.value--;proxy.$modal.closeLoading();proxy.$modal.msgError(res.msg);proxy.$refs.imageUpload.handleRemove(file);uploadedSuccessfully();}
}function handlePictureCardPreviewFileDetail(file) {dialogImageUrl.value = file.url;dialogVisible.value = true;
}// 删除
function handleRemoveFileDetail(index) {fileList.value.splice(index, 1);
}// 上传结束处理
function uploadedSuccessfully() {if (number.value > 0 && uploadList.value.length === number.value) {fileList.value = fileList.value.filter((f) => f.url !== undefined).concat(uploadList.value);uploadList.value = [];number.value = 0;emit("update:modelValue", listToString(fileList.value));proxy.$modal.closeLoading();}
}
// 上传失败
function handleUploadError() {proxy.$modal.msgError("上传图片失败");proxy.$modal.closeLoading();
}// 对象转成指定字符串分隔
function listToString(list, separator) {let strs = "";separator = separator || ",";for (let i in list) {if (undefined !== list[i].url && list[i].url.indexOf("blob:") !== 0) {strs += list[i].url.replace(baseUrl, "") + separator;}}return strs != "" ? strs.substr(0, strs.length - 1) : "";
}
</script><style scoped lang="scss">
// .el-upload--picture-card 控制加号部分
:deep(.hide .el-upload--picture-card) {display: none;
}
</style>
vue2+transition-group实现拖动排序
html
<transition-group id='app' name="drog" tag="ul"><div draggable="true" v-for="(item, index) in lists" @dragstart="dragStart($event, index)" @dragover="allowDrop" @drop="drop($event, index)" v-bind:key="item">{{item}}</div>
</transition-group>
JavaScript
new Vue({el: '#app',data: {lists: ['1: apple', '2: banana', '3: orange', '4: melon']},methods: {// 取消默认行为allowDrop(e){e.preventDefault();},// 开始拖动dragStart(e, index){let tar = e.target;e.dataTransfer.setData('Text', index);if (tar.tagName.toLowerCase() == 'li') {// console.log('drag start')// console.log('drag Index: ' + index)}},// 放置drop(e, index){this.allowDrop(e);// console.log('drop index: ' + index);//使用一个新数组重新排序后赋给原变量let arr = this.lists.concat([]),dragIndex = e.dataTransfer.getData('Text');temp = arr.splice(dragIndex, 1);arr.splice(index, 0, temp[0]);// console.log('sort');this.lists = arr;}}
});
原生拖拽排序
html
<ul id="idUl"><li class="m_36 ta_c bc_87ceeb fs_68">1</li><li class="m_36 ta_c bc_87ceeb fs_68">2</li><li class="m_36 ta_c bc_87ceeb fs_68">3</li><li class="m_36 ta_c bc_87ceeb fs_68">4</li><li class="m_36 ta_c bc_87ceeb fs_68">5</li>
</ul>
JavaScript
(function () {let ulList = document.querySelector('#idUl'),liList = document.querySelectorAll('li'),currentLi = undefined;liList.forEach(item => item.draggable = "true");ulList.addEventListener('dragstart', (e) => {e.dataTransfer.effectAllowed = 'move';currentLi = e.target;setTimeout(() => currentLi.classList.add('bc_transparent color_transparent'), 0);});ulList.addEventListener('dragenter', (e) => {e.preventDefault();if (e.target === currentLi || e.target === ulList) return false;let liArray = Array.from(ulList.childNodes),currentIndex = liArray.indexOf(currentLi),targetindex = liArray.indexOf(e.target)if (currentIndex < targetindex) {ulList.insertBefore(currentLi, e.target.nextElementSibling);} else {ulList.insertBefore(currentLi, e.target);}});ulList.addEventListener('dragover', (e) => e.preventDefault());ulList.addEventListener('dragend', (e) => currentLi.classList.remove('bc_transparent color_transparent'));
})();
相关文章:
web前端之拖拽API、vue3实现图片上传拖拽排序、拖放、投掷、复制、若依、vuedraggable
MENU vue2html5原生dom原生JavaScript实现跨区域拖放vue2实现跨区域拖放vue2mousedown实现全屏拖动,全屏投掷vue3element-plusvuedraggable实现图片上传拖拽排序vue2transition-group实现拖动排序原生拖拽排序 vue2html5原生dom原生JavaScript实现跨区域拖放 关键代…...
第11章 GUI Page403~405 步骤三 设置滚动范围
运行效果: 源代码: /**************************************************************** Name: wxMyPainterApp.h* Purpose: Defines Application Class* Author: yanzhenxi (3065598272qq.com)* Created: 2023-12-21* Copyright: yanzhen…...
【Spring Security】打造安全无忧的Web应用--使用篇
🥳🥳Welcome Huihuis Code World ! !🥳🥳 接下来看看由辉辉所写的关于Spring Security的相关操作吧 目录 🥳🥳Welcome Huihuis Code World ! !🥳🥳 一.Spring Security中的授权是…...
体验一下 CodeGPT 插件
体验一下 CodeGPT 插件 0. 背景1. CodeGPT 插件安装2. CodeGPT 插件基本配置3. (可选)CodeGPT 插件预制提示词原始配置(英文)4. CodeGPT 插件预制提示词配置(中文)5. 简单验证一下 0. 背景 看到B站Up主 “wwwzhouhui” 一个关于 CodeGPT 的视频,感觉挺有意思&#…...
深度学习 | 基础卷积神经网络
卷积神经网络是人脸识别、自动驾驶汽车等大多数计算机视觉应用的支柱。可以认为是一种特殊的神经网络架构,其中基本的矩阵乘法运算被卷积运算取代,专门处理具有网格状拓扑结构的数据。 1、全连接层的问题 1.1、全连接层的问题 “全连接层”的特点是每个…...
[字符编码]windwos下使用libiconv转换编码格式(二)
在http://t.csdnimg.cn/PLUuz笔记中实现了常用编码格式转换的功能,但这还是一个demo。因为代码中向libiconv库函数传递的字符串是存放在堆空间中的(我也是从网上找例子测试,是否一定要开辟堆空间存放还有待考证),如果一次性转换的字节数很巨大的话,就会导致内存空间不足,进而引…...
textile 语法
1、文字修饰 修饰行内文字 字体样式textile 语法对应的 XHTML 语法实际显示效果加强*strong*<strong>strong</strong>strong强调_emphasis_<em>emphasis</em>emphasis加粗**bold**<b>bold</b>bold斜体__italics__<i>italics</i…...
【快速开发】使用SvelteKit
自我介绍 做一个简单介绍,酒架年近48 ,有20多年IT工作经历,目前在一家500强做企业架构.因为工作需要,另外也因为兴趣涉猎比较广,为了自己学习建立了三个博客,分别是【全球IT瞭望】,【…...
【docker笔记】docker常用命令
1、帮助启动类命令 1.1 启动、重启、查询当前状态、停止 systemctl start docker systemctl stop docker systemctl restart docker systemctl status docker1.2 设置开机启动 systemctl enable docker1.3 查看docker概要信息 docker info1.4 查看docker帮助文档 docker -…...
API 接口怎样设计才安全?
设计安全的API接口是确保应用程序和数据安全的重要方面之一。下面是一些设计安全的API接口的常见实践: 1. 身份验证和授权: 使用适当的身份验证机制,如OAuth、JWT或基本身份验证,以确保只有经过身份验证的用户可以访问API。实施…...
网站被CC攻击了怎么办?CC攻击有什么危害
网络爆炸性地发展,网络环境也日益复杂和开放,同时各种各样的恶意威胁和攻击日益增多,其中网站被CC也是常见的情况。 CC攻击有什么危害呢? 被CC会导致: 1.访问速度变慢:网站遭受CC攻击后,由于…...
Docker - 镜像 | 容器 日常开发常用指令 + 演示(一文通关)
目录 Docker 开发常用指令汇总 辅助命令 docker version docker info docker --help 镜像命令 查看镜像信息 下载镜像 搜索镜像 删除镜像 容器命令 查看运行中的容器 运行容器 停止、启动、重启、暂停、恢复容器 杀死容器 删除容器 查看容器日志 进入容器内部…...
要参加微软官方 Copilot 智能编程训练营了
GitHub Copilot 是由 GitHub、OpenAI 和 Microsoft 联合开发的生成式 AI 模型驱动的。 GitHub Copilot 分析用户正在编辑的文件及相关文件的上下文,并在编写代码时提供自动补全式的建议。 刚好下周要参加微软官方组织的 GitHub Copilot 工作坊-智能编程训练营&…...
Python入门学习篇(五)——列表字典
1 列表 1.1 定义 ①有序可重复的元素集合 ②可以存放不同类型的数据 ③个人理解:类似于java中的数组1.2 相关方法 1.2.1 获取列表长度 a 语法 len(列表名)b 示例代码 list2 [1, 2, "hello", 4] print(len(list2))c 运行结果 1.2.2 获取列表值 a 语法 列表名…...
React尝鲜
组件 React的组件就是一个js函数,函数内部return一个由jsx语法创建的html代码片段。 //MyComp.js export default function MyComp(){return (<h1>我是新组件MyComp</h1>) } 在需要引入组件的地方import导入组件,并放在相应位置 //App.js…...
锯齿云服务器租赁使用教程
首先登陆锯齿云账号 网盘上传数据集与代码 随后我们需要做的是将所需要的数据集与代码上传到网盘(也可以直接在租用服务器后将数据集与代码传到服务器的硬盘上,但这样做会消耗大量时间,造成资源浪费) 点击工作空间:…...
HarmonyOS和OpenHarmony的区别
1.概要 众所周知,鸿蒙是华为开发的一款分布式操作系统。因为开发系统,最重要的是集思广益,大家共同维护。为了在IOS和Android之间生存,鸿蒙的茁壮成长一定是需要开源,各方助力才能实现。 在这种思想上,…...
Redis Stream消息队列之基本语法与使用方式
前言 本文的主角是Redis Stream,它是Redis5.0版本新增加的数据结构,主要用于消息队列,提供了消息的持久化和主备复制功能,可以让任何客户端访问任何时刻的数据,并且能记住每一个客户端的访问位置,还能保证…...
制造行业定制软件解决方案——工业信息采集平台
摘要:针对目前企业在线检测数据信号种类繁多,缺乏统一监控人员和及时处置措施等问题。蓝鹏测控开发针对企业工业生产的在线数据的集中采集分析平台,通过该工业信息采集平台可将企业日常各种仪表设备能够得到数据进行集中分析处理存储…...
[python]用python实现对arxml文件的操作
目录 关键词平台说明一、背景二、方法2.1 库2.2 code 关键词 python、excel、DBC、openpyxl 平台说明 项目Valuepython版本3.6 一、背景 有时候需要批量处理arxml文件(ARXML 文件符合 AUTOSAR 4.0 标准),但是工作量太大,阔以考虑用python。 二、方…...
.Net框架,除了EF还有很多很多......
文章目录 1. 引言2. Dapper2.1 概述与设计原理2.2 核心功能与代码示例基本查询多映射查询存储过程调用 2.3 性能优化原理2.4 适用场景 3. NHibernate3.1 概述与架构设计3.2 映射配置示例Fluent映射XML映射 3.3 查询示例HQL查询Criteria APILINQ提供程序 3.4 高级特性3.5 适用场…...
通过Wrangler CLI在worker中创建数据库和表
官方使用文档:Getting started Cloudflare D1 docs 创建数据库 在命令行中执行完成之后,会在本地和远程创建数据库: npx wranglerlatest d1 create prod-d1-tutorial 在cf中就可以看到数据库: 现在,您的Cloudfla…...
YSYX学习记录(八)
C语言,练习0: 先创建一个文件夹,我用的是物理机: 安装build-essential 练习1: 我注释掉了 #include <stdio.h> 出现下面错误 在你的文本编辑器中打开ex1文件,随机修改或删除一部分,之后…...
系统设计 --- MongoDB亿级数据查询优化策略
系统设计 --- MongoDB亿级数据查询分表策略 背景Solution --- 分表 背景 使用audit log实现Audi Trail功能 Audit Trail范围: 六个月数据量: 每秒5-7条audi log,共计7千万 – 1亿条数据需要实现全文检索按照时间倒序因为license问题,不能使用ELK只能使用…...
使用van-uploader 的UI组件,结合vue2如何实现图片上传组件的封装
以下是基于 vant-ui(适配 Vue2 版本 )实现截图中照片上传预览、删除功能,并封装成可复用组件的完整代码,包含样式和逻辑实现,可直接在 Vue2 项目中使用: 1. 封装的图片上传组件 ImageUploader.vue <te…...
Python如何给视频添加音频和字幕
在Python中,给视频添加音频和字幕可以使用电影文件处理库MoviePy和字幕处理库Subtitles。下面将详细介绍如何使用这些库来实现视频的音频和字幕添加,包括必要的代码示例和详细解释。 环境准备 在开始之前,需要安装以下Python库:…...
【HTTP三个基础问题】
面试官您好!HTTP是超文本传输协议,是互联网上客户端和服务器之间传输超文本数据(比如文字、图片、音频、视频等)的核心协议,当前互联网应用最广泛的版本是HTTP1.1,它基于经典的C/S模型,也就是客…...
深度学习习题2
1.如果增加神经网络的宽度,精确度会增加到一个特定阈值后,便开始降低。造成这一现象的可能原因是什么? A、即使增加卷积核的数量,只有少部分的核会被用作预测 B、当卷积核数量增加时,神经网络的预测能力会降低 C、当卷…...
SiFli 52把Imagie图片,Font字体资源放在指定位置,编译成指定img.bin和font.bin的问题
分区配置 (ptab.json) img 属性介绍: img 属性指定分区存放的 image 名称,指定的 image 名称必须是当前工程生成的 binary 。 如果 binary 有多个文件,则以 proj_name:binary_name 格式指定文件名, proj_name 为工程 名&…...
安宝特案例丨Vuzix AR智能眼镜集成专业软件,助力卢森堡医院药房转型,赢得辉瑞创新奖
在Vuzix M400 AR智能眼镜的助力下,卢森堡罗伯特舒曼医院(the Robert Schuman Hospitals, HRS)凭借在无菌制剂生产流程中引入增强现实技术(AR)创新项目,荣获了2024年6月7日由卢森堡医院药剂师协会࿰…...
