前端實戰:基于 Vue 與 QRCode 庫實現動態二維碼合成與下載功能

在現代 Web 應用開發中,二維碼的應用越來越廣泛,從電子票務到信息傳遞,它都扮演著重要角色。本文將分享如何在 Vue 項目中,結合QRCode庫實現動態二維碼的生成、與背景圖合成以及圖片下載功能,打造一個完整且實用的二維碼展示模塊,最終效果兼顧美觀與交互性。

項目背景與需求分析

在我們的五龍山野生動物園票務項目中,需要為用戶提供電子門票二維碼展示頁面。該頁面不僅要展示清晰的門票二維碼,還需結合動物園特色背景圖,增強視覺體驗。同時,為方便用戶保存門票,需實現長按二維碼保存合成圖片的功能。這就涉及到二維碼生成、圖片合成以及用戶交互邏輯的實現。

技術棧選擇

本項目基于 Vue.js 框架進行開發,結合QRCode庫用于二維碼的生成,利用原生 JavaScript 的 Canvas API 完成圖片合成與繪制,確保功能的高效與穩定。

代碼實現詳解

1. 樣式設計(<style>部分)

* {margin: 0;padding: 0;
}.yard_box {width: 100%;height: 100vh;background-image: url('../assets/yard_back.png');background-size: cover;background-repeat: no-repeat;background-position: center;position: relative;
}.top_title {width: 100%;height: 50px;display: flex;
}.return_icon {width: 40px;height: 40px;
}.return_box {width: 40px;height: 40px;background-color: rgb(70, 58, 58);border-radius: 50%;opacity: 0.7;margin-left: 2%;margin-top: 2%;
}.qr-canvas {width: 200px;height: 200px;position: absolute;left: 51%;bottom: 180px;/* 調整二維碼在頁面中的位置 */transform: translateX(-50%);cursor: pointer;transition: transform 0.1s;
}.qr-canvas:active {transform: translateX(-50%) scale(0.98);
}.save-hint {position: absolute;bottom: 50px;left: 0;right: 0;text-align: center;color: white;font-size: 14px;text-shadow: 0 0 5px rgba(0, 0, 0, 0.5);
}

?

樣式部分首先通過*選擇器重置默認樣式,消除內外邊距。yard_box類為整個頁面設置了全屏背景圖,營造沉浸式視覺效果。top_titlereturn_box實現了返回按鈕的布局與樣式,qr-canvas類定義了二維碼畫布的初始位置、大小及交互效果,通過active偽類實現按壓時的縮放動效,提升交互體驗。

2. 模板搭建(<template>部分)

<template><div class="yard_box"><div class="top_title" @click="$router.go(-1)"><div class="return_box"><img src="../assets/left.svg" alt="" class="return_icon"></div></div><!-- 顯示二維碼的畫布 --><canvas ref="qrCanvas" @mousedown="startLongPress" @mouseup="cancelLongPress" @mouseleave="cancelLongPress"@touchstart="startLongPress" @touchend="cancelLongPress" @touchcancel="cancelLongPress"class="qr-canvas"></canvas></div>
</template>

模板中,外層yard_box包裹頁面所有元素,top_title綁定點擊事件實現返回上一頁功能。<canvas>標簽用于繪制二維碼,同時綁定了鼠標和觸摸事件,以兼容 PC 端與移動端的長按操作,為后續的保存功能提供交互基礎。

3. 邏輯實現(<script>部分)

import QRCode from 'qrcode';
import yardBack from '@/assets/yard_back.png'; // 使用ES模塊導入export default {data() {return {ticketId: '35',longPressTimer: null,longPressDuration: 1000, // 長按時間閾值(1秒)backgroundImage: new Image() // 用于合成圖片的背景圖};},methods: {async loadBackgroundImage() {return new Promise((resolve) => {this.backgroundImage.src = yardBack; // 使用導入的圖片路徑this.backgroundImage.onload = resolve;});},// 生成二維碼generateQRCode() {const canvas = this.$refs.qrCanvas;QRCode.toCanvas(canvas, this.ticketId, {width: 200,margin: 2}, (error) => {if (error) console.error('二維碼生成失敗:', error);});},// 開始長按startLongPress() {this.longPressTimer = setTimeout(() => {this.saveMergedImage();}, this.longPressDuration);},// 取消長按cancelLongPress() {if (this.longPressTimer) {clearTimeout(this.longPressTimer);this.longPressTimer = null;}},// 創建并保存合并后的圖片async saveMergedImage() {// 創建臨時Canvas用于合成const mergedCanvas = document.createElement('canvas');const ctx = mergedCanvas.getContext('2d');// 設置Canvas尺寸與背景圖一致mergedCanvas.width = this.backgroundImage.width;mergedCanvas.height = this.backgroundImage.height;// 1. 繪制背景圖ctx.drawImage(this.backgroundImage, 0, 0, mergedCanvas.width, mergedCanvas.height);// 2. 計算白色區域的位置和大小(需要根據實際背景圖調整)const whiteArea = {x: mergedCanvas.width * 0.2,    // 白色區域左側位置(20%寬度處)y: mergedCanvas.height * 0.45,   // 白色區域頂部位置(60%高度處)width: mergedCanvas.width * 0.6, // 白色區域寬度(60%寬度)height: mergedCanvas.height * 0.3 // 白色區域高度(30%高度)};// 3. 計算二維碼在白色區域中的合適大小和位置const qrCanvas = this.$refs.qrCanvas;const qrMaxSize = Math.min(whiteArea.width, whiteArea.height) * 0.8; // 二維碼最大尺寸(白色區域的80%)const qrSize = Math.min(420, qrMaxSize); // 不超過200px// 計算居中位置const qrX = whiteArea.x + (whiteArea.width - qrSize) / 2;const qrY = whiteArea.y + (whiteArea.height - qrSize) / 2;// 繪制二維碼ctx.drawImage(qrCanvas, qrX, qrY, qrSize, qrSize);// 4. 添加文字(調整到二維碼上方)const textY = qrY - 30;ctx.font = 'bold 40px Arial';ctx.fillStyle = 'white';ctx.textAlign = 'center';ctx.fillText('', mergedCanvas.width / 2, textY);// 保存圖片const link = document.createElement('a');link.download = `五龍山野生動物園門票-${this.ticketId}.png`;link.href = mergedCanvas.toDataURL('image/png');document.body.appendChild(link);link.click();document.body.removeChild(link);}},async mounted() {await this.loadBackgroundImage();await this.generateQRCode();}
};

JavaScript邏輯部分,首先導入QRCode庫和背景圖片資源。data中定義了門票 ID、長按計時器、長按閾值以及背景圖片對象。

loadBackgroundImage方法通過 Promise 封裝圖片加載過程,確保圖片加載完成后再進行后續操作。generateQRCode方法利用QRCode庫將門票 ID 生成到指定的<canvas>上。

長按相關方法startLongPresscancelLongPress分別用于啟動長按計時和取消計時,當長按達到設定閾值時,觸發saveMergedImage方法。

saveMergedImage方法是核心邏輯,創建新的<canvas>用于合成圖片,先繪制背景圖,再計算并繪制白色區域、二維碼,最后添加文字。通過創建<a>標簽,利用toDataURL方法將合成后的圖片轉換為 URL,實現圖片下載功能。mounted鉤子函數確保頁面加載時完成背景圖加載和二維碼生成。

效果展示與優化方向

最終實現的頁面,背景圖與二維碼完美融合,用戶長按二維碼即可保存包含背景、二維碼和文字信息的合成圖片。后續優化可以考慮:

  1. 動態數據綁定:將ticketId改為動態獲取,實現不同門票二維碼的展示。
  2. 樣式優化:根據實際背景圖調整白色區域和文字樣式,增強視覺美感。
  3. 錯誤處理:完善二維碼生成和圖片合成過程中的錯誤提示,提升用戶體驗。

通過以上步驟,我們成功在 Vue 項目中實現了一個功能完整、交互良好的二維碼合成與下載模塊。希望本文能為你的前端開發實踐帶來啟發,在實際項目中靈活運用相關技術!

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/news/901891.shtml
繁體地址,請注明出處:http://hk.pswp.cn/news/901891.shtml
英文地址,請注明出處:http://en.pswp.cn/news/901891.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

HAL詳解

一、直通式HAL 這里使用一個案例來介紹直通式HAL&#xff0c;選擇MTK的NFC HIDL 1.0為例&#xff0c;因為比較簡單&#xff0c;代碼量也比較小&#xff0c;其源碼路徑&#xff1a;vendor/hardware/interfaces/nfc/1.0/ 1、NFC HAL的定義 1&#xff09;NFC HAL數據類型 通常定…

Vue自定義指令-防抖節流

Vue2版本 // 防抖 // <el-button v-debounce"[reset,click,300]" ></el-button> // <el-button v-debounce"[reset]" ></el-button> Vue.directive(debounce, { inserted: function (el, binding) { let [fn, event "cl…

AI知識補全(十六):A2A - 谷歌開源的agent通信協議是什么?

名人說&#xff1a;一笑出門去&#xff0c;千里落花風。——辛棄疾《水調歌頭我飲不須勸》 創作者&#xff1a;Code_流蘇(CSDN)&#xff08;一個喜歡古詩詞和編程的Coder&#x1f60a;&#xff09; 上一篇&#xff1a;AI知識補全&#xff08;十五&#xff09;&#xff1a;AI可解…

【機器人創新創業應需明確產品定位與方向指南】

機器人領域的創新創業, 需要對公司和產品的定位和生態進行深入思考, 明確其定位與發展目標, 明確產品在是為G、為B還是為C進行服務。 本文引用地址&#xff1a;https://www.eepw.com.cn/article/202504/469401.htm 超前的、探索性的創新技術一般是面向G端, 而不是面向B端或者C…

網安加·百家講壇 | 劉志誠:AI安全風險與未來展望

作者簡介&#xff1a;劉志誠&#xff0c;樂信集團信息安全中心總監、OWASP廣東區域負責人、網安加社區特聘專家。專注于企業數字化過程中網絡空間安全風險治理&#xff0c;對大數據、人工智能、區塊鏈等新技術在金融風險治理領域的應用&#xff0c;以及新技術帶來的技術風險治理…

TOA與AOA聯合定位的高精度算法,三維、4個基站的情況,MATLAB例程,附完整代碼

本代碼實現了三維空間內目標的高精度定位,結合到達角(AOA) 和到達時間(TOA) 兩種測量方法,通過4個基站的協同觀測,利用最小二乘法解算目標位置。代碼支持噪聲模擬、誤差分析及三維可視化,適用于無人機導航、室內定位等場景。訂閱專欄后可獲得完整代碼 文章目錄 運行結果…

2025MathorcupC題 音頻文件的高質量讀寫與去噪優化 保姆級教程講解|模型講解

2025Mathorcup數學建模挑戰賽&#xff08;媽媽杯&#xff09;C題保姆級分析完整思路代碼數據教學 C題&#xff1a;音頻文件的高質量讀寫與去噪優化 隨著數字媒體技術的迅速發展&#xff0c;音頻處理成為信息時代的關鍵技術之一。在日常生活中&#xff0c;從錄音設備捕捉的原始…

Deno Dep:顛覆傳統的模塊化未來

一、重新定義依賴管理&#xff1a;Deno Dep 的革新哲學 Deno Dep&#xff08;原Deno包管理器&#xff09;徹底重構了JavaScript/TypeScript的依賴管理方式&#xff0c;其核心突破體現在&#xff1a; 1. 瀏覽器優先的模塊化&#xff08;URL-Centric Modules&#xff09; // 直…

歐拉系統升級openssh 9.7p1

開發的系統準備上線&#xff0c;甲方對歐拉服務器進行了掃描&#xff0c;發現openssh版本為8.2p1&#xff0c;存在漏洞&#xff0c;因此需要升級openssh至9.7p1。歐拉系統版本為20.03 SP3。 1、下載openssh 9.7p1 https://www.openssh.com/releasenotes.html&#xff0c; 將下…

如何精通C++編程?

如果從學生時代算起的話&#xff0c;我學習和使用C已經差不多快十年了&#xff0c;仍然不敢說自己已經掌握了C的全部特性&#xff0c;但或許能夠給出一些有用的建議吧。 我學習C全靠自學&#xff0c;花費了不少的功夫&#xff0c;在這里分享一些學習心得&#xff0c;希望對大家…

提高Qt工作線程的運行速度

1. 使用線程池&#xff08;QThreadPool&#xff09;替代單一線程 做過&#xff0c;但是當時沒想到。。。 目的&#xff1a;減少線程創建和銷毀的開銷&#xff0c;復用線程資源。 實現步驟&#xff1a; 創建自定義任務類&#xff1a;繼承QRunnable&#xff0c;實現run()方法。…

Solon AI MCP Server 入門:Helloworld (支持 java8 到 java24。國產解決方案)

目前網上能看到的 MCP Server 基本上都是基于 Python 或者 nodejs &#xff0c;雖然也有 Java 版本的 MCP SDK&#xff0c;但是鮮有基于 Java 開發的。 作為Java 開發中的國產頂級框架 Solon 已經基于 MCP SDK 在進行 Solon AI MCP 框架開發了&#xff0c;本文將使用 Solon AI …

STL之迭代器(iterator)

迭代器的基本概念 迭代器(iterator)模式又稱為游標(Cursor)模式&#xff0c;用于提供一種方法順序訪問一個聚合對象中各個元素, 而又不需暴露該對象的內部表示。或者這樣說可能更容易理解&#xff1a;Iterator模式是運用于聚合對象的一種模式&#xff0c;通過運用該模式&#…

Android系統通知機制深度解析:Framework至SystemUI全鏈路剖析

1. 前言 在Android 13的ROM定制化開發中&#xff0c;系統通知機制作為用戶交互的核心組件&#xff0c;其實現涉及Framework層到SystemUI的復雜協作。本文將深入剖析從Notification發送到呈現的全鏈路流程&#xff0c;重點解析關鍵類的作用機制及系統服務間的交互邏輯&#xff…

UE5角色狀態機中跳躍落地移動銜接問題

UE5系列文章目錄 文章目錄 UE5系列文章目錄前言一、狀態機設置二、主要藍圖 前言 先說說遇到的問題&#xff0c;在我按空格鍵跳躍落地以后&#xff0c;角色落地再按WSAD鍵移動就出現了畫面中角色抽搐的情況 一、狀態機設置 在Unreal Engine 5中創建角色時&#xff0c;處理跳…

使用SVM對心臟數據是否患病進行分類預測

作者簡介 杜嘉寶&#xff0c;男&#xff0c;西安工程大學電子信息學院&#xff0c;2024級研究生 研究方向&#xff1a;變壓器故障預警與檢測 電子郵件&#xff1a;djb857497378gmail.com 王子謙&#xff0c;男&#xff0c;西安工程大學電子信息學院&#xff0c;2024級研究生&a…

Node做BFF中間層架構優化前端開發體驗并提升系統整體性能。

文章目錄 1. BFF 層的定位2. 技術選型3. 架構設計3.1 分層設計3.2 示例架構 4. 核心功能實現4.1 數據聚合4.2 權限校驗4.3 緩存優化 5、實戰示例1. 場景說明2. ECharts 數據格式要求3. BFF 層實現步驟3.1 接收前端參數3.2 調用后端服務獲取數據 4. 前端使用 總結 在使用 Node.j…

文件系統 軟硬連接

&#x1f33b;個人主頁&#xff1a;路飛雪吖~ &#x1f320;專欄&#xff1a;Linux 目錄 一、理解文件系統 &#x1f320;磁盤結構 二、軟硬連接 &#x1f31f;軟硬鏈接 &#x1f320;軟鏈接&#xff1a; &#x1f320;硬鏈接&#xff1a; &#x1f31f;理解軟硬鏈接的應…

單片機 | 基于51單片機的自動循跡小車設計

以下是一個基于51單片機的自動循跡小車設計詳解,包含原理、公式和完整代碼: 一、系統原理 核心模塊: 傳感器:紅外對管(TCRT5000)x4主控芯片:STC89C52RC(51單片機)電機驅動:L298N驅動模塊電源:7.4V鋰電池(電機) + 5V穩壓(單片機)工作原理: 紅外對管發射紅外線,…

2025.04.17【Stacked area】| 生信數據可視化:堆疊區域圖深度解析

文章目錄 生信數據可視化&#xff1a;堆疊區域圖深度解析堆疊面積圖簡介為什么使用堆疊面積圖如何使用R語言創建堆疊面積圖安裝和加載ggplot2包創建堆疊面積圖的基本步驟示例代碼 解讀堆疊面積圖堆疊面積圖的局限性實際應用案例示例&#xff1a;基因表達量隨時間變化 結論 生信…