当前位置: 首页 > backend >正文

node.js 实战——在express 中将input file 美化,并完成裁剪、上传进度条

美化上传按钮

在这里插入图片描述

在ejs 页面

<!DOCTYPE html>
<html>
<head><meta charset="utf-8"></meta><title><%= title %></title><link rel='stylesheet' href='/stylesheets/form.css'/><!-- 本地 Bootstrap 引入方式 --><link href="/bootstrap/css/bootstrap.min.css" rel="stylesheet"><script src="/bootstrap/js/bootstrap.bundle.min.js"></script><script src="./javascripts/image-upload.js"></script>
</head>
<body>
<div class="container"><h1>文件上传</h1><from action="/upload-img" method="post" enctype="multipart/form-data"><label class="upload-container"><span class="upload-icon" id="uploadIcon">+</span><input accept="image/*" id="avatarInput" type="file" /><img id="avatarPreview" class="preview-img d-done" /><button type="button" class="remove-btn" id="removeBtn">x</button></label><button type="submit" class="btn btn-primary mt-3">提交</button></from>
</div>
</body>
</html>

样式

.upload-container{width: 150px;height: 150px;border: 2px solid #ccc;border-radius: 10px;display: flex;align-items: center;justify-content: center;cursor: pointer;position: relative;overflow: hidden;background-color: #f8f9fa;transition:border-color 0.3s;.upload-icon{font-size:2rem;color:#999;//禁用鼠标事件,该元素变得“不可点击”、“鼠标穿透”pointer-events: none;  //用来控制一个元素是否能响应鼠标事件(点击、悬停、拖动等)}.preview-img{width:100%;height: 100%;object-fit: cover;position: absolute;top: 0;left: 0;}.remove-btn{position: absolute;top:5px;right:5px;background-color:rgba(0,0,0,.6);color:#ffffff;border:none;border-radius:50%;width:24px;height:24px;display:none;align-items: center;justify-content: center;cursor:pointer;font-weight: bold;}
}.upload-container:hover{border-color: #007bff;
}.upload-container input[type="file"]{position: absolute;opacity: 0;height: 100%;width: 100%;cursor: pointer;
}

完成效果

这个效果没有裁剪,进度条、多图片上传
在这里插入图片描述

上传进度条

   <div class="progress mt-2 d-done" id="progressWrapper"><div class="progress-bar" role="progressbar" id="uploadProgress" style="width: 0%">0%</div></div>
 document.getElementById('uploadForm').addEventListener('submit', function(e){e.preventDefault();// const blob =preview._blob;// if(!blob){//     alert("请先选择并裁剪头像");//     return;// }const file =input.files[0];if(!file) return alert('Please upload a valid image!');let formData = new FormData();formData.append('file', file);let xhr = new XMLHttpRequest();xhr.open('POST', '/upload-avatar');xhr.upload.addEventListener('progress', (e) => {if(e.lengthComputable){let percent = Math.round((e.loaded / e.total) * 100);progressWrapper.classList.remove('d-none');progressBar.style.width= percent + '%';progressBar.innerText = percent + '%';}})xhr.onload =function () {if(xhr.status === 200) {alert("successfully uploaded!");}else{alert("fail to upload");}}xhr.send(formData);})

使用cropperjs 裁剪图片

使用npm安装

npm install cropperjs@1.5.13

❗ 关键点:cropperjs@2.x 为模块化版本,不再提供 dist/ 下的浏览器用 JS/CSS 文件

从 v2.0.0 开始,cropperjs 改为 纯 ESM(ES Module)包,它不再包含:

  • cropper.js
  • cropper.css
  • dist/ 文件夹

📌 小提示

版本适合人群是否自带 dist/
1.5.13普通浏览器/EJS 项目✅ 有 JS/CSS,推荐
2.xVite/Webpack 打包项目❌ 无,需构建

引入js、css

   <!--本地开发引入 cropper --><link rel="stylesheet" href="/cropper/cropper.css"><script src="/cropper/cropper.js"></script>

弹框

<!-- 裁剪模态框--><div class="modal fade modal-mask" id="cropModal" tabindex="1" aria-hidden="true"><div class="modal-dialog modal-dialog-centered modal-fullscreen"><div class="modal-content p-3"><div class="modal-body" style="width: 100%; height: 600px;"><img id="cropImg"  /></div><div class="modal-footer"><button type="button" class="btn btn-secondary" data-bs-dismiss="modal">取消</button><button type="button" class="btn btn-success" id="cropConfirm">确认裁剪</button></div></div></div></div>

js

input.addEventListener('change', (e)=> {let that=e.target;let file=that.files[0];if(file && file.type.startsWith('image/')) {let reader=new FileReader();reader.onloadend = (e) => {//未裁剪前使用的代码// preview.src = e.target.result;// preview.classList.remove('d-none');// removeBtn.style.display = 'flex';// uploadIcon.style.display = 'none';//裁剪时的代码cropImage.src = e.target.result;new bootstrap.Modal(document.getElementById('cropModal')).show();cropImage.onload =()=>{if(cropper) cropper.destroy();cropper =new Cropper(cropImage,{aspectRatio: 1,autoCropArea:1,viewMode:2})}}reader.readAsDataURL(file);}})

在这里插入图片描述

http://www.xdnf.cn/news/4708.html

相关文章:

  • 本地可执行命令的智能体部署方案
  • 【WebRTC-12】CreatePeerConnection究竟创建了什么?
  • 开发函数踩坑记 sum(1) over(partition by stock_code order by trade_date asc)
  • 信息系统项目管理工程师备考计算类真题讲解十五
  • java面试OOM汇总
  • 边缘网关(边缘计算)
  • 云平台的技术方向和总体规划
  • 基于卫星遥感数据进行农作物长势监测原理简述
  • BeeWorks IM:专业安全的企业私有化即时通讯软件
  • Linux——Mysql数据库
  • 数据结构*二叉树
  • 软件测试学习笔记
  • 数据结构 - 9( 位图 布隆过滤器 并查集 LRUCache 6000 字详解 )
  • 数据结构 - 10( B- 树 B+ 树 B* 树 4000 字详解 )
  • 谷云科技iPaaS技术实践:集成平台如何解决库存不准等问题
  • 智能外呼机器人的核心优势
  • 《算法导论(第4版)》阅读笔记:p11-p13
  • 图形渲染+事件处理最终版
  • 含铜废水循环利用体系
  • 【杂谈】Godot 2D游戏窗口设置
  • Nginx +Nginx-http-flv-module 推流拉流
  • JAVA:Spring Boot 集成 Lua 的技术博客
  • 深入理解进程与线程、进程池与线程池:企业级开发实战指南
  • Perspective,数据可视化的超级引擎!
  • 【图片合并PDF】一次性将多个文件夹里的图片批量按文件夹为单位合并PDF,多个文件夹图片合并PDF,基于WPF的实现方案
  • win64下cmake+mingw64编译libhv
  • 基于智能家居项目 RGB彩灯(P9813)
  • MIST:一键解锁 macOS 历史版本,旧系统安装不再难!
  • 小米 MiMo 开源:7B 参数凭什么 “叫板” AI行业巨头?
  • COLT_CMDB_linux_userInfo_20250508.sh修复历史脚本输出指标信息中userName与输出信息不一致问题