二、拖拽点击、粘贴、选择文件夹上传图片
我们可以通过三种方式来上传我们本地的图片
1、拖拽或点击上传图片
前面有写了一篇实现拖拽或点击上传图片的文章,这里就不详细再赘述了,有兴趣的可以去看看:《文件拖拽上传功能已经烂大街了,你还不会吗?》
2、粘贴上传
平时我们经常会使用到截图,所以我们希望可以直接将截图粘贴到工具中进行上传,这里我们可以通过监听页面上的paste
事件,直接读取剪切板的图片展示到页面上并进行上传。
document.addEventListener("paste", function (e) { const items = e.clipboardData.items; for (const item of items) { if (item.type.indexOf("image") !== -1) { const blob = item.getAsFile(); showPreview(blob); } } });
3、选择文件夹上传文件夹中的所有图片
一张图片一张图片上传太慢了,所以我们也支持直接选择一个文件夹,将文件夹里的所有图片一次性上传到gitee上,
- 创建一个 HTML 文件,包含一个用于选择文件夹的
<input>
元素和一个按钮用于触发上传操作。代码如下:
<input type="file" style="display: none" id="folderInput" onchange="uploadImages()" webkitdirectory multiple /> <button class="upload-btn" onclick="selectFolder()" style="background: #FFD04C;"> 选择文件夹上传 </button>
webkitdirectory
:告诉浏览器文件选择器应该允许选择文件夹(目录),而不仅仅是单个文件。
multiple
:告诉浏览器文件选择器应该允许选择多个文件或文件夹。
- 2、获取到选择的文件并做相关处理
function blobToBase64(blob) { return new Promise((resolve, reject) => { const reader = new FileReader(); reader.onloadend = () => { const base64String = reader.result.split(",")[1]; resolve(base64String); }; reader.onerror = reject; reader.readAsDataURL(blob); }); } function selectFolder() { const folderInput = document.getElementById("folderInput"); folderInput.click(); } async function uploadImages() { const folderInput = document.getElementById("folderInput"); let files = folderInput.files || []; files = [...files].filter((file) => file.type.startsWith("image/")); for (let i = 0; i < files.length; i++) { Toast.showLoading(`上传中,${i}/${files.length}`); const file = files[i]; const base64Data = await blobToBase64(file); await gitOperate.uploadToGitee(base64Data,false); } Toast.hide(); Toast.showToast(`已全部上传`); waterfall.init(); }
三、瀑布流展示图片
上传完图片后,我们还希望可以看到之前上传的图片,这里我们需要对图片列表做一个瀑布流展示。
之前我也有写过一个瀑布流组件详细的实现步骤,有兴趣的同学可以看看:《Vue封装一个瀑布流图片容器组件》。
这里我们可以通过原生JavaScrip来快速实现一个,具体代码如下:
class WaterfallContent { constructor(config = {}) { this.init(config); } init(config = {}) { this.imgList = config.imgList || []; this.column = config.column || 8; this.imgMargin = config.imgMargin || 0.5; this.domId = config.domId || "waterfall-container"; this.minHeight = []; this.arr = []; const ul = document.getElementById(this.domId); ul.innerHTML = ""; } async create(imgList = this.imgList, cb) { this.init(); this.imgList = imgList; const ul = document.getElementById(this.domId); ul.innerHTML = ""; let trueWidth = Math.floor( (100 - this.column * this.imgMargin * 2) / this.column ); let trueWidthPx = 0; for (let i = 0; i < this.column; i++) { let li = document.createElement("li"); li.style.listStyle = "none"; li.style.float = "left"; li.style.width = `${trueWidth}%`; li.style.margin = `0 ${this.imgMargin}%`; li.classList.add("git-img"); ul.appendChild(li); this.arr.push(li); this.minHeight.push(0); trueWidthPx = li.offsetWidth; } this.loadHandler(trueWidthPx, cb); } getBase64(file) { const reader = new FileReader(); reader.readAsDataURL(file); return new Promise((resolve) => { reader.onload = () => { resolve(reader.result); }; }); } getImgPx(img, maxWidth) { const image = new Image(); image.src = img; return new Promise((resolve) => { image.onload = () => { const width = image.width; const height = image.height; image.width = maxWidth; image.height = image.height * (maxWidth / width); resolve({ width, height, image }); }; }); } async loadHandler(trueWidth, cb) { for (let i = 0; i < this.imgList.length; i++) { const imgItem = this.imgList[i]; const src = imgItem.download_url; const res = await this.getImgPx(src, trueWidth); const { image } = res; const minHeight = this.minHeight; const arr = this.arr; // 高度数组的最小值 const min = Math.min.apply(null, minHeight); // 高度数组的最小值索引 const minIndex = minHeight.indexOf(min); // 克隆一份图片 const im = image.cloneNode(true); im.setAttribute("data-sha", imgItem.sha); im.onclick = this.imgClick; // 将图片假如对应最小值索引的容器中 arr[minIndex].appendChild(im); // 更新最小值索引的容器的高度 minHeight[minIndex] += im.height; if (i === 0 && cb) { cb(); } } }
四、自定义鼠标右键菜单栏
查看图片的时候我们希望可以对图片进行操作,这里的操作我们通过鼠标右键点击弹出,所以我们可以实现一个自定义鼠标右键菜单栏。
具体代码如下:
class MouseMenu { constructor(config) { this.menuClass = config.menuClass || "j-mouse-menu"; this.menuId = config.menuId || "JMouseMenu"; this.contentId = config.contentId || "j-mouse-content"; this.init(); } init() { const dom = document.getElementById(this.contentId); dom.oncontextmenu = (e) => { const clickItem = e.path[0]; if (clickItem.localName !== "img") return; const menu = document.getElementById(this.menuId); this.clickItem = clickItem; this.hideAllMenu(); // 自定义body元素的鼠标事件处理函数 e = e || window.event; e.preventDefault(); let scrollTop = document.documentElement.scrollTop || document.body.scrollTop; // 获取垂直滚动条位置 let scrollLeft = document.documentElement.scrollLeft || document.body.scrollLeft; // 获取水平滚动条位置 menu.style.display = "block"; let left = e.clientX + scrollLeft; let top = e.clientY + scrollTop; if (menu.offsetHeight + top > window.innerHeight) { top = window.innerHeight - menu.offsetHeight - 5; } if (menu.offsetWidth + left > window.innerWidth) { left = window.innerWidth - menu.offsetWidth - 5; } menu.style.left = left + "px"; menu.style.top = top + "px"; document.onclick = () => { this.hideAllMenu(); }; }; } hideAllMenu() { const jMenu = document.getElementsByClassName("j-mouse-menu"); for (const item of jMenu) { item.style.display = "none"; } } }
五、Toast提示功能
交互少不了Toast弹窗提示,这里我们使用JavaScrip简单实现一个,具体代码如下:
class ToastC { constructor(config) { this.config = config; this.init(); } init() { const body = document.body; const toastContainer = document.createElement("div"); toastContainer.id = "toastContainer"; const styleObj = { position: "fixed", top: "50%", left: "50%", transform: "translate(-50%, -50%)", background: "rgba(0, 0, 0, 0.8)", color: "#ffffff", fontSize: "16px", opacity: 0.7, transition: "opacity 0.3s ease-in-out", padding: "10px", "border-radius": "5px", display: "none", textAlign: "center", }; for (const key in styleObj) toastContainer.style[key] = styleObj[key]; body.appendChild(toastContainer); const loader = document.createElement("div"); loader.id = "toastLoader"; const loaderStyleObj = { border: "4px solid #f3f3f3", borderTop: "4px solid #3498db", borderRadius: "50%", width: "20px", height: "20px", animation: "spin 1s linear infinite", margin: "0 auto 10px", display: "none", }; for (const key in loaderStyleObj) loader.style[key] = loaderStyleObj[key]; toastContainer.appendChild(loader); const text = document.createElement("div"); text.id = "toastText"; const textStyleObj = { marginTop: "5px", }; for (const key in textStyleObj) text.style[key] = textStyleObj[key]; toastContainer.appendChild(text); const keyframes = ` @keyframes spin { 0% { transform: rotate(0deg); } 100% { transform: rotate(360deg); } } `; const style = document.createElement("style"); style.innerHTML = keyframes; document.head.appendChild(style); } showToast(text) { const textElem = document.getElementById("toastText"); // 设置Toast提示文本 textElem.innerText = text; // 显示Toast提示 toastContainer.style.display = "block"; // 3秒后隐藏Toast提示 setTimeout(() => this.hide(), 3000); } showLoading(text = "加载中...") { const loader = document.getElementById("toastLoader"); const textElem = document.getElementById("toastText"); // 设置Toast提示文本为加载中 textElem.innerText = text; // 显示Toast提示和加载动画 loader.style.display = "block"; this.show(); } show() { const toastContainer = document.getElementById("toastContainer"); // 显示Toast提示 toastContainer.style.display = "block"; } hide() { try { const toastContainer = document.getElementById("toastContainer"); const loader = document.getElementById("toastLoader"); // 隐藏Toast提示和加载动画 toastContainer.style.display = "none"; loader.style.display = "none"; } catch (err) {} } }
六、快捷键打开隐藏窗口
我们可以设置快捷键快速唤起和隐藏窗口,在根目录下的main.js文件中注册快捷键,这里我设置的是alt + x
,大家也可以改成自己喜欢的快捷键,具体代码如下:
// 注册快捷键 globalShortcut.register("Alt+X", () => { if (mainWindow.isVisible()) { mainWindow.hide(); } else { mainWindow.show(); } });
工具使用
一、源码下载
直接到 gitee 上下载即可。
二、依赖安装
下载完源码之后,我们到gitImgBed目录下运行npm i
安装依赖,等待依赖安装完成。
三、程序打包
依赖安装完成之后,我们可以在gitImgBed目录下运行npm run build
进行打包
打包完成后我们可以在当前目录下看到一个叫jyeontuGitImgBed-win32-x64
文件夹,打开文件夹,找到里面一个叫jyeontuGitImgBed
的应用程序,双击启动即可
四、配置填写
将之前准备工作时间的gitee仓库相关信息填写到配置中。
输入正确信息后保存,便可以上传和查看gitee图床中的图片了。
源码
一、gitee
gitee 地址:https://gitee.com/zheng_yongtao/electron_program
二、公众号
关注公众号『前端也能这么有趣』发送 图床
即可获取源码。
说在后面
🎉 这里是 JYeontu,现在是一名前端工程师,有空会刷刷算法题,平时喜欢打羽毛球 🏸 ,平时也喜欢写些东西,既为自己记录 📋,也希望可以对大家有那么一丢丢的帮助,写的不好望多多谅解 🙇,写错的地方望指出,定会认真改进 😊,偶尔也会在自己的公众号『前端也能这么有趣』发一些比较有趣的文章,有兴趣的也可以关注下。在此谢谢大家的支持,我们下文再见 🙌。