uniapp使用Canvas生成电子名片

uniapp使用Canvas生成电子名片

工作中有生成电子名片的一个需求,刚刚好弄了发一下分享分享


文章目录

  • uniapp使用Canvas生成电子名片
  • 前言
  • 一、上代码?
  • 总结


前言

先看效果
在这里插入图片描述


一、上代码?

不对不对应该是上才艺,哈哈哈

	<template><view class="container"><view class="head" style="height: 7rem;"><view style="color:#fff;position: fixed;top: 4rem;left: 1rem;"><br><text style="font-size: 11px;"></text></view></view><view style="width: 100%; height: 7.5rem;"></view><scroll-view scroll-y style="height: 100vh;" class="content"><view style="padding-top: 30rpx;"><!-- 立体名片卡片 --><view class="card-container" id="cardContainer"><view class="business-card"><!-- 顶部彩色边缘标签 --><view class="card-edge"></view><view class="card-content"><view class="card-title">裤架工厂</view><view class="card-subtitle">专做软体沙发</view><view class="card-details"><view class="detail-item"><view>高级产品设计师</view></view><view class="detail-item"><view>创新事业部 | ABC科技</view></view><view class="detail-item"><view>工厂地址:上海浦东新区三林东地铁左边大厦23</view></view></view></view><!-- 双二维码容器 --><view class="qrcode-column"><view class="qrcode-item"><view class="card-image-container"><image class="card-image"src="https://linda-uni.oss-cn-guangzhou.aliyuncs.com/images/and/app_20230925_20250529092745.png"mode="aspectFit"></image></view><view class="qrcode-label">微信联系</view></view><view class="qrcode-item"><view class="card-image-container"><image class="card-image"src="https://linda-uni.oss-cn-guangzhou.aliyuncs.com/images/and/app_20230925_20250529092745.png"mode="aspectFit"></image></view><view class="qrcode-label">官方网站</view></view></view><!-- 角落装饰 --><view class="card-corner corner-tl"></view><view class="card-corner corner-br"></view></view></view><view class="save-btn" @click="saveCardImage"><text>保存名片图片</text></view></view></scroll-view><canvas canvas-id="cardCanvas":style="{ position: 'absolute', left: '-9999px', width: canvasWidth + 'px', height: canvasHeight + 'px' }"></canvas></view></template><script>export default {data() {return {canvasWidth: 1100,canvasHeight: 630,dpr: 1,qrcode1: 'https://linda-uni.oss-cn-guangzhou.aliyuncs.com/images/and/app_20230925_20250529092745.png',qrcode2: 'https://linda-uni.oss-cn-guangzhou.aliyuncs.com/images/and/app_20230925_20250529092745.png',backgroundImage: 'https://linda-uni.oss-cn-guangzhou.aliyuncs.com/images/and/550e8a1a-e450-4880-9441-33608476b32a.jpg'}},mounted() {},methods: {// 保存名片为图片   async saveCardImage() {uni.showLoading({title: '生成中...',mask: true});try {// 1. 绘制Canvasawait this.drawCardCanvas();// 2. 生成临时图片路径const tempPath = await new Promise((resolve, reject) => {uni.canvasToTempFilePath({canvasId: 'cardCanvas',quality: 1,fileType: 'png',width: this.canvasWidth * this.dpr,height: this.canvasHeight * this.dpr,destWidth: this.canvasWidth * this.dpr,destHeight: this.canvasHeight * this.dpr,success: res => resolve(res.tempFilePath),fail: err => reject(err)});});// 3. 保存到相册await new Promise((resolve, reject) => {uni.saveImageToPhotosAlbum({filePath: tempPath,success: () => resolve(),fail: err => reject(err)});});uni.hideLoading();uni.showToast({title: '保存成功',icon: 'success'});} catch (err) {uni.hideLoading();uni.showToast({title: '保存失败: ' + (err.errMsg || err),icon: 'none'});console.error('保存失败:', err);}},// 绘制名片到Canvasasync drawCardCanvas() {const ctx = uni.createCanvasContext('cardCanvas', this);const dpr = this.dpr;const width = this.canvasWidth;const height = this.canvasHeight;const padding = 30 * dpr;// 清除画布ctx.clearRect(0, 0, width, height);// 1. 绘制背景// ctx.setFillStyle('#1F1F1F');// ctx.fillRect(0, 0, width, height);// 2. 绘制名片背景const cardWidth = width - padding * 2;const cardHeight = height - padding * 2;// 绘制名片背景if (this.backgroundImage) {// 使用图片背景try {await this.drawRoundedImage(ctx,this.backgroundImage,padding,padding,cardWidth,cardHeight,20 * dpr);} catch (e) {console.error('背景图片加载失败:', e);// 回退到默认背景this.drawDefaultBackground(ctx, padding, cardWidth, cardHeight);}} else {// 使用颜色背景this.drawDefaultBackground(ctx, padding, cardWidth, cardHeight);}// // 渐变背景// const gradient = ctx.createLinearGradient(0, 0, cardWidth, cardHeight);   // gradient.addColorStop(0, '#302f30');// gradient.addColorStop(1, '#282728');// ctx.setFillStyle(gradient);// // 圆角矩形// this.drawRoundedRect(ctx, padding, padding, cardWidth, cardHeight, 20 * dpr);// ctx.fill();// 3. 顶部彩色边缘(带圆角)const topHeight = 16 * dpr; // 边缘高度const topRadius = 20 * dpr; // 圆角半径// 创建渐变const edgeGradient = ctx.createLinearGradient(padding, padding, padding + cardWidth, padding);edgeGradient.addColorStop(0, '#ff9a9e');edgeGradient.addColorStop(0.3, '#fad0c4');edgeGradient.addColorStop(0.6, '#a18cd1');edgeGradient.addColorStop(1, '#fbc2eb');ctx.setFillStyle(edgeGradient);// 绘制带圆角的顶部边缘(仅左上和右上圆角)ctx.beginPath();// 从左上圆角结束点开始ctx.moveTo(padding + topRadius, padding);// 绘制上边缘线ctx.lineTo(padding + cardWidth - topRadius, padding);// 绘制右上圆角ctx.arcTo(padding + cardWidth, padding,padding + cardWidth, padding + topHeight,topRadius);// 绘制右边缘ctx.lineTo(padding + cardWidth, padding + topHeight);// 绘制下边缘(向左)ctx.lineTo(padding, padding + topHeight);// 绘制左边缘(向上)ctx.lineTo(padding, padding + topRadius);// 绘制左上圆角ctx.arcTo(padding, padding,padding + topRadius, padding,topRadius);ctx.closePath();ctx.fill();// 4. 设置字体  ctx.setFontSize(40 * dpr);ctx.setFillStyle('#f0f0f0');ctx.fillText('裤架工厂', padding + 40 * dpr, padding + 80 * dpr);ctx.setFontSize(28 * dpr);ctx.setFillStyle('#CCCCCC');ctx.fillText('专做软体沙发', padding + 40 * dpr, padding + 130 * dpr);// 绘制下划线ctx.setStrokeStyle('#ff9a9e');ctx.setLineWidth(6 * dpr);ctx.beginPath();ctx.moveTo(padding + 40 * dpr, padding + 90 * dpr);ctx.lineTo(padding + 120 * dpr, padding + 90 * dpr);ctx.stroke();// 5. 绘制详情信息const details = ['高级产品设计师','创新事业部 | ABC科技','工厂地址:上海浦东新区三林东地铁左边大厦23'];ctx.setFontSize(28 * dpr);ctx.setFillStyle('#b0b0b0');details.forEach((text, i) => {ctx.fillText(text, padding + 40 * dpr, padding + 200 * dpr + i * 50 * dpr);});// 6. 绘制二维码 (修改部分开始)const qrSize = cardWidth * 0.12; // 缩小二维码尺寸const qrY = padding + 350 * dpr;const qrSpacing = 30 * dpr; // 二维码间距const qrRadius = 20 * dpr; // 圆角半径const wxX = padding + 40 * dpr;await this.drawRoundedImage(ctx,this.qrcode1,wxX,qrY,qrSize,qrSize,qrRadius);// 官网二维码 (靠左,在微信二维码右侧)const webX = wxX + qrSize + qrSpacing;await this.drawRoundedImage(ctx,this.qrcode2,webX,qrY,qrSize,qrSize,qrRadius);ctx.setFontSize(24 * dpr);ctx.setFillStyle('#e0e0e0');// 微信文字居中ctx.setTextAlign('center');ctx.fillText('客户群', wxX + qrSize / 2, qrY + qrSize + 30 * dpr);// 官网文字居中ctx.setTextAlign('center');ctx.fillText('国内站', webX + qrSize / 2, qrY + qrSize + 30 * dpr);// 恢复对齐方式ctx.setTextAlign('left');// 执行绘制ctx.draw();// 返回绘制完成的Promisereturn new Promise(resolve => {setTimeout(resolve, 500);});},// 新增方法:绘制圆角图片async drawRoundedImage(ctx, src, x, y, width, height, radius) {return new Promise((resolve, reject) => {uni.getImageInfo({src: src,success: (res) => {// 保存当前状态ctx.save();// 创建圆角矩形路径   this.drawRoundedRect(ctx, x, y, width, height, radius);ctx.clip(); // 裁剪为圆角矩形// 绘制图片ctx.drawImage(res.path, x, y, width, height);// 恢复状态ctx.restore();resolve();},fail: reject});});},// 工具方法:绘制圆角矩形drawRoundedRect(ctx, x, y, width, height, radius) {ctx.beginPath();ctx.moveTo(x + radius, y);ctx.lineTo(x + width - radius, y);ctx.arcTo(x + width, y, x + width, y + radius, radius);ctx.lineTo(x + width, y + height - radius);ctx.arcTo(x + width, y + height, x + width - radius, y + height, radius);ctx.lineTo(x + radius, y + height);ctx.arcTo(x, y + height, x, y + height - radius, radius);ctx.lineTo(x, y + radius);ctx.arcTo(x, y, x + radius, y, radius);ctx.closePath();},drawDefaultBackground(ctx, padding, cardWidth, cardHeight) {const gradient = ctx.createLinearGradient(0, 0, cardWidth, cardHeight);gradient.addColorStop(0, '#302f30');gradient.addColorStop(1, '#282728');ctx.setFillStyle(gradient);this.drawRoundedRect(ctx, padding, padding, cardWidth, cardHeight, 20);ctx.fill();},// 工具方法:绘制装饰角drawCorner(ctx, x, y, size, position) {ctx.setStrokeStyle('#ff9a9e');ctx.setLineWidth(3 * this.dpr);ctx.beginPath();// 圆角半径const radius = 12 * this.dpr;if (position === 'tl') {// 左上角 - 包围式圆角ctx.moveTo(x - size, y);ctx.lineTo(x, y);ctx.lineTo(x, y - size);// 添加圆角效果ctx.moveTo(x, y - radius);ctx.arc(x + radius, y - radius, radius, Math.PI, 1.5 * Math.PI);} else if (position === 'br') {// 右下角 - 包围式圆角ctx.moveTo(x + size, y);ctx.lineTo(x, y);ctx.lineTo(x, y + size);// 添加圆角效果ctx.moveTo(x, y + radius);ctx.arc(x - radius, y + radius, radius, 0.5 * Math.PI, Math.PI);}ctx.stroke();},// 工具方法:绘制图片(支持网络图片)drawImage(ctx, src, x, y, width, height) {return new Promise((resolve, reject) => {uni.getImageInfo({src: src,success: res => {ctx.drawImage(res.path, x, y, width, height);resolve();},fail: (err) => {console.error('图片加载失败:', err);reject(err);}});});}},}</script><style>page {background-color: #1F1F1F;}.container {position: relative;height: 100vh;width: 100vw;overflow: hidden;}.head {width: 100%;position: fixed;top: 0px;left: 0%;z-index: 99999;}/* 新增样式 */.card-container {position: relative;width: 88%;margin: 0 auto 40rpx;perspective: 1000px;}.business-card {background: linear-gradient(145deg, #302f30, #282728);border-radius: 20rpx;padding: 30rpx;/* display: flex; */justify-content: space-between;box-shadow: 0 10rpx 30rpx rgba(0, 0, 0, 0.4);position: relative;overflow: hidden;transform: translateY(0);transition: all 0.4s cubic-bezier(0.175, 0.885, 0.32, 1.275);}.business-card:active {transform: translateY(-10rpx);box-shadow: 0 15rpx 40rpx rgba(0, 0, 0, 0.6);}/* 边缘装饰效果 */.card-edge {position: absolute;top: 0;left: 0;width: 100%;height: 16rpx;background: linear-gradient(90deg, #ff9a9e, #fad0c4, #a18cd1, #fbc2eb);border-radius: 20rpx 20rpx 0 0;}.card-corner {position: absolute;width: 40rpx;height: 40rpx;border: 3rpx solid #ff9a9e;}.corner-tl {top: 20rpx;left: 20rpx;border-right: none;border-bottom: none;border-top-left-radius: 12rpx;}.corner-br {bottom: 20rpx;right: 20rpx;border-left: none;border-top: none;border-bottom-right-radius: 12rpx;}.card-content {flex: 1;padding-right: 20rpx;}.card-title {font-size: 40rpx;font-weight: bold;color: #f0f0f0;margin-bottom: 16rpx;position: relative;display: inline-block;}.card-title::after {content: '';position: absolute;bottom: -8rpx;left: 0;width: 80rpx;height: 6rpx;background: linear-gradient(90deg, #ff9a9e, #fad0c4);border-radius: 4rpx;}.card-subtitle {font-size: 28rpx;color: #CCCCCC;margin: 30rpx 0 20rpx;line-height: 1.5;}.card-details {display: flex;flex-direction: column;gap: 20rpx;margin-top: 30rpx;}.detail-item {display: flex;align-items: center;font-size: 28rpx;color: #b0b0b0;}.detail-icon {width: 50rpx;color: #ff9a9e;font-size: 32rpx;margin-right: 15rpx;}.card-image-container {flex-shrink: 0;width: 180rpx;height: 180rpx;border-radius: 15rpx;overflow: hidden;box-shadow: 0 8rpx 20rpx rgba(0, 0, 0, 0.3);border: 2rpx solid rgba(255, 255, 255, 0.1);position: relative;background: #fff;display: flex;align-items: center;justify-content: center;transition: all 0.3s ease;}.card-image-container:active {transform: scale(1.05);box-shadow: 0 12rpx 25rpx rgba(0, 0, 0, 0.5);}.card-image {width: 90%;height: 90%;display: block;}/* 双二维码样式 */.qrcode-column {display: flex;/* flex-direction: column; *//* align-items: center; *//* justify-content: center; */flex-shrink: 0;width: 100%;gap: 25rpx;margin-top: 20rpx;}.qrcode-item {display: flex;flex-direction: column;align-items: center;}.qrcode-label {color: #e0e0e0;font-size: 24rpx;text-align: center;margin-top: 10rpx;font-weight: 500;}.save-btn {margin: 40rpx auto;padding: 20rpx 40rpx;background: linear-gradient(90deg, #ff9a9e, #a18cd1);color: white;border-radius: 50rpx;width: 60%;text-align: center;font-weight: bold;box-shadow: 0 8rpx 20rpx rgba(161, 140, 209, 0.4);}</style>

总结

这里面就js 里面的有用,其他的我也没有删除,要用的可以自己删除就可以了,go,卷起来

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.pswp.cn/web/81868.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

PostgreSQL ALTER TABLE 命令详解

PostgreSQL ALTER TABLE 命令详解 引言 PostgreSQL 是一款功能强大的开源关系型数据库管理系统&#xff0c;它提供了丰富的命令来帮助数据库管理员和开发者管理数据库中的表。其中&#xff0c;ALTER TABLE 命令是 PostgreSQL 中最常用的命令之一&#xff0c;用于修改表的结构…

Kafka KRaft + SSL + SASL/PLAIN 部署文档

本文档介绍如何在 Windows 环境下部署 Kafka 4.x&#xff0c;使用 KRaft 模式、SSL 加密和 SASL/PLAIN 认证。stevensu1/kafka_2.13-4.0.0 1. 环境准备 JDK 17 或更高版本Kafka 4.x 版本&#xff08;本文档基于 kafka_2.13-4.0.0&#xff09; 2. 目录结构 D:\kafka_2.13-4.…

MQTT协议,EMQX部署,MQTTX安装学习

一、MQTT概述 1.什么是MQTT MQTT是一种基于“发布订阅“”模式的消息传输协议。 消息&#xff1a;设备和设备之间传输的数据&#xff0c;或者服务和服务之间要传输的数据。 协议&#xff1a;传输数据时所遵循的规范。 2.常见的通讯模式 &#xff08;1&#xff09;客户端-服…

Java Web 开发详细流程

&#x1f9ed; 一、项目立项与需求分析阶段&#xff08;0%&#xff09; 1.1 商业需求确认 与产品经理沟通核心业务目标 目标&#xff1a;构建一个图书管理系统用户&#xff1a;图书管理员、普通用户功能&#xff1a;登录、查看、增删改图书、权限控制、分页、搜索 1.2 输出文…

学习路之PHP--easyswoole_panel安装使用

学习路之PHP--easyswoole_panel安装使用 一、新建文件夹二、安装三、改配置地址四、访问 IP:Port 自动进入index.html页面 一、新建文件夹 /www/wwwroot/easyswoole_panel 及配置ftp 解压easyswoole_panel源码 https://github.com/easyswoole-panel/easyswoole_panel 二、安…

软件设计综合知识

software-design 软考中级-软件设计师-综合知识&#xff1a;计算机系统基础、操作系统、计算机网络与信息安全、程序语言基础、数据库基础、数据结构与算法、软件工程基础知识、标准与知识产权等。 —— 2025 年 3 月 5 日 甲辰年二月初六 惊蛰 目录 software-design1、计算机基…

海思 35XX MIPI读取YUV422

1.项目背景&#xff1a; 使用海思芯片&#xff0c;接收FPGA发送的MIPI数据&#xff0c;不需要ISP处理&#xff0c;YUV图像格式为YUV422。 2.移植MIPI驱动 修改IMX347的驱动远吗&#xff0c;将I2C读写的部分注释&#xff0c;其他的不用再做修改。 int imx347_slave_i2c_init(ot…

算力租赁革命:弹性模式如何重构数字时代的创新门槛​

一、算力革命&#xff1a;第四次工业革命的核心驱动力​ 在科技飞速发展的当下&#xff0c;我们正悄然迎来第四次工业革命。华为创始人任正非在一场程序设计竞赛中曾深刻指出&#xff0c;这场革命的基础便是大算力。随着 5G、人工智能、大数据、物联网等信息技术的迅猛发展&am…

改写自己的浏览器插件工具 myChromeTools

1. 起因&#xff0c; 目的: 前面我写过&#xff0c; 自己的一个浏览器插件小工具 最近又增加一个小功能&#xff0c;可以自动滚动页面&#xff0c;尤其是对于那些瀑布流加载的网页。最新的代码都在这里 2. 先看效果 3. 过程: 代码 1, 模拟鼠标自然滚动 // 处理滚动控制逻辑…

深度学习篇---OC-SORT简介

OC-SORT&#xff08;Observation-Centric SORT&#xff09;是一种以观测为中心的多目标跟踪算法&#xff0c;旨在解决传统 SORT 算法在目标遮挡、外观变化和复杂交互场景下关联准确性不足的问题。以下是其详细介绍&#xff1a; 核心创新点 以观测为中心的在线平滑&#xff08…

硬件工程师笔记——二极管Multisim电路仿真实验汇总

目录 1 二极管基础知识 1.1 工作原理 1.2 二极管的结构 1.3 PN结的形成 1.4 二极管的工作原理详解 正向偏置 反向偏置 multisim使用说明链接 2 二极管特性实验 2.1 二极管加正向电压 2.2 二极管加反向电压 2.3 二极管两端的电阻 2.4 交流电下二级管工作 2.5 二极…

vscode中让文件夹一直保持展开不折叠

vscode中让文件夹一直保持展开不折叠 问题 很多小伙伴使用vscode发现空文件夹会折叠显示, 让人看起来非常难受, 如下图 解决办法 首先打开设置->setting, 搜索compact Folders, 去掉勾选即可, 如下图所示 效果如下 看起来非常爽 ! ! !

设计模式学习笔记

设计模式 一&#xff1a;分类&#xff1a; 创建型模式 用于描述“怎样创建对象”&#xff0c;它的主要特点是“将对象的创建与使用分离”。GoF&#xff08;四人组&#xff09;书中提供了单例、原型、工厂方法、抽象工厂、建造者等 5 种创建型模式。 结构型模式 用于描述如何将…

Kaggle-Predict Calorie Expenditure-(回归+xgb+cat+lgb+模型融合+预测结果)

Predict Calorie Expenditure 题意&#xff1a; 给出每个人的基本信息&#xff0c;预测运动后的卡路里消耗值。 数据处理&#xff1a; 1.构造出人体机能、运动相关的特征值。 2.所有特征值进行从新组合&#xff0c;注意唯独爆炸 3.对连续信息分箱变成离散 建立模型&#x…

第十二篇:MySQL 分布式架构演进与云原生数据库探索

本篇聚焦 MySQL 在互联网架构演进过程中的角色变化&#xff0c;探讨其从单体向分布式、再向云原生架构转型的关键技术路径与实践建议。 一、传统单体架构下的 MySQL 应用模式 在早期项目中&#xff0c;MySQL 多用于中小型应用&#xff1a; 单节点部署&#xff1b; 水平扩展难…

JVM——回顾:JVM的起源、特性与系统构成

引入 在当今数字化时代&#xff0c;Java语言及其运行环境Java虚拟机&#xff08;JVM&#xff09;在软件开发领域占据着举足轻重的地位。从大型企业级应用到各类移动应用&#xff0c;JVM凭借其独特的特性和强大的功能&#xff0c;为开发者提供了高效且稳定的运行环境。 JVM的起…

大疆上云API+流媒体服务器部署实现直播功能

根据官网文档上云API&#xff0c;先将官方提供的Demo部署起来&#xff0c;后端和前端服务环境搭建请参考官方文档。因为官方文档没有对直播这块的环境搭建进行说明&#xff0c;所以下面主要对直播功能环境搭建做一个记录&#xff0c;仅供参考&#xff0c;如有不足之处&#xff…

计算机网络 HTTP篇常见面试题总结

HTTP各版本区别 HTTP 1.0 无状态、无连接&#xff1a;每次请求都需要建立新的 TCP&#xff0c;处理完后立即关闭&#xff0c;导致开销较大。队头阻塞&#xff1a;每个请求必须按照顺序依次处理&#xff0c;前面的请求未完成&#xff0c;后面的请求只能等待&#xff0c;减低了…

目标检测:YOLO 模型详解

目录 一、YOLO&#xff08;You Only Look Once&#xff09;模型讲解 YOLOv1 YOLOv2 (YOLO9000) YOLOv3 YOLOv4 YOLOv5 YOLOv6 YOLOv7 YOLOv8 YOLOv9 YOLOv10 YOLOv11 YOLOv12 其他变体&#xff1a;PP-YOLO 二、YOLO 模型的 Backbone&#xff1a;Focus 结构 三、…

开源 FcDesigner 表单设计器组件事件详解

FcDesigner 是一款基于Vue的开源低代码可视化表单设计器工具&#xff0c;通过数据驱动表单渲染。可以通过拖拽的方式快速创建表单&#xff0c;提高开发者对表单的开发效率&#xff0c;节省开发者的时间。并广泛应用于在政务系统、OA系统、ERP系统、电商系统、流程管理等领域。 …