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

uniapp小程序分享使用canvas自定义绘制 vue3

使用混入结合canvas做小程序的分享
在混入里面定义一个全局共享的分享样式,在遇到特殊页面需要单独处理

utils/share.js

import { ref } from 'vue';
export default {onShow() {// 创建时设置统一页面的默认值uni.$mpShare = {title: '分享的标题',path: '/pages/home/home',imageUrl: 'https:xxx',success: function (res) {// 转发成功之后的回调console.log('转发成功之后的回调', res);if (res.errMsg == 'shareAppMessage:ok') {}},fail: function () {// 转发失败之后的回调console.log('转发失败之后的回调', res);if (res.errMsg == 'shareAppMessage:fail cancel') {// 用户取消转发} else if (res.errMsg == 'shareAppMessage:fail') {// 转发失败,其中 detail message 为详细失败信息}},};},//发送给朋友onShareAppMessage(res) {console.log(' uni.$mpShare-----------', uni.$mpShare);return uni.$mpShare;},//分享到朋友圈onShareTimeline(res) {return uni.$mpShare;},
};

main.js混入

import share from '/utils/share.js';
export function createApp() {const app = createSSRApp(App);app.use(Pinia.createPinia());app.mixin(share); // 这里app.use(uviewPlus);return {app,Pinia,};
}

Canvas绘制海报
commonShare.js

/*** canvas* context* currentObj 绘制需要用到的对象* bgImg 背景图* dpr 设备分辨率* type 类型*/export async function createPoster(canvas, context, currentObj, bgImg, dpr, type) {const bgImage = await renderImg(canvas, bgImg);//绘制矩形context.drawImage(bgImage, 0, 0, canvas.width / dpr, canvas.height / dpr);context.fillStyle = '#FFF';context.strokeStyle = '#303030';context.lineWidth = 2;context.strokeRect(16, 100, 343, 180);context.fillRect(16, 100, 343, 180);switch (type) {//周边商品case 'periphery'://绘制商品图片const productPath = showPicture(currentObj.goodsPictures[0].picture);const productImg = await renderImg(canvas, productPath);context.drawImage(productImg, 28, 112, 150, 157);//绘制商品名称context.font = 'normal normal bold 19px SourceHanSansCN-Bold';context.fillStyle = '#0D1932';context.fillText(currentObj.goodsName, 189, 136);//绘制¥context.font = 'normal normal bold 25px SourceHanSansCN-Bold';context.fillStyle = '#FE2A12';context.fillText(`${currentObj.giftPrice}.${currentObj.giftPricePrefix}`, 189, 256);break;
}let path = await generatePath(context);console.log('分享图片', path);return path;
}//图片显示
function showPicture(srcPath) {if (srcPath.includes('http')) {return srcPath;} else {return 'https://xxxxxx' + srcPath; // 注意路径}
}//创建图片对象
function renderImg(canvas, url) {// url传临时路径return new Promise((resolve) => {const img = canvas.createImage();img.src = `${url}?timestamp=${new Date().getTime()}`;img.onload = () => {resolve(img);};});
}function base64src(base64data, fun) {const base64 = base64data; //base64格式图片const time = new Date().getTime();const imgPath = uni.env.USER_DATA_PATH + '/poster' + time + 'share' + '.png';//如果图片字符串不含要清空的前缀,可以不执行下行代码.const imageData = base64.replace(/^data:image\/\w+;base64,/, '');const file = uni.getFileSystemManager();file.writeFileSync(imgPath, imageData, 'base64');fun(imgPath);
}async function generatePath(context) {let base64IMG = context.canvas.toDataURL();let pathImg = '';await base64src(base64IMG, (res) => {pathImg = res;});return pathImg;
}

Canvas.createImage() 创建Image对象onload事件在安卓真机下只会触发一次,
确保每次加载的 URL 是唯一的:通过在 URL 后面添加一个时间戳或随机数来避免缓存问题。

img = `${url}?timestamp=${new Date().getTime()}`;

单独页面的处理xxxx.vue

<view id="canvas" v-show="false"><canvas id="myCanvas" type="2d" canvas-id="myCanvas" style="width: 375px; height: 300px"></canvas>
</view><script setup>
//引入分享绘制canvas
import { createPoster } from '/utils/commonShare.js';
onShow(() => {generatorCanvasUrl();
});function generatorCanvasUrl() {uni.createSelectorQuery().select('#myCanvas').node((res) => {let canvas = res.node;let context = res.node.getContext('2d');uni.getSystemInfo({success: async function (sysRes) {const dpr = sysRes.devicePixelRatio;canvas.width = 375 * dpr;canvas.height = 300 * dpr;context.clearRect(0, 0, canvas.width, canvas.height);context.scale(dpr, dpr);let path = await createPoster(canvas, context, currentObj.value, canvasBgImg.value, dpr, canvasType.value);uni.$mpShare = {title: canvasTitle.value,path: '/pagesDiscover/group/group-product-dedails?from=sharePage&data=' + encodeURIComponent(JSON.stringify(currentObj.value)),imageUrl: path,};console.log('重绘成功');},});}).exec();}
</script>

注意几个问题

  1. canvas的绘制时间,需要在拿到数据之后,dom生成之前绘制完成,onShow不可以就试试onReady,否则就会绘制失败(图片找不到,数据undefined)
  2. 图片路径后面一定要加时间戳保证图片路径是唯一的,否则就会一直走缓存
  3. 如果页面想要重置分享但是不用canvas绘制,直接用下面这个
const shareData = computed(() => {// 分享的数据return {title: '重置',desc: '重置',path: '/xxxx/xxxx/xxxx',imageUrl: 'xxxxx',};
});
onShow(() => {uni.$mpShare = shareData.value; // 修改uni.$mpShare的值
});

相关文章:

uniapp小程序分享使用canvas自定义绘制 vue3

使用混入结合canvas做小程序的分享 在混入里面定义一个全局共享的分享样式&#xff0c;在遇到特殊页面需要单独处理 utils/share.js import { ref } from vue; export default {onShow() {// 创建时设置统一页面的默认值uni.$mpShare {title: 分享的标题,path: /pages/home/…...

SpringCloud核心组件(四)

文章目录 NacosNacos 配置中心1.起源2.基本概念ProfileData IDGroup 3.基础配置a. bootstrap.ymlb. application.ymlc. nacos 中的配置 DataIDd.测试读取配置中心配置内容 4.配置隔离a.命名空间b.DataIDc.bootstrap.ymld.service 隔离 5.配置拆分a.配置拆分策略b.DataID 配置c.…...

如何把本地docker 镜像下载用到centos系统中呢?

如果需要将镜像下载到本地或在 CentOS 系统上使用该镜像&#xff0c;你可以按照以下步骤操作&#xff1a; 1. 拉取镜像 如果想将镜像从 Docker Hub 或其他镜像仓库下载到本地&#xff0c;可以使用 docker pull 命令。 如果使用的是本地构建的镜像&#xff08;如 isc:v1.0.0&…...

Godot的开发框架应当是什么样子的?

目录 前言 全局协程还是实例协程&#xff1f; 存档&#xff01; 全局管理类&#xff1f; UI框架&#xff1f; Godot中的异步&#xff08;多线程&#xff09;加载 Godot中的ScriptableObject 游戏流程思考 结语 前言 这是一篇杂谈&#xff0c;主要内容是对我…...

GitHub新手入门 - 从创建仓库到协作管理

GitHub新手入门 - 从创建仓库到协作管理 GitHub 是开发者的社交平台&#xff0c;同时也是代码托管的强大工具。无论是个人项目、开源协作&#xff0c;还是团队开发&#xff0c;GitHub 都能让你轻松管理代码、版本控制和团队协作。今天&#xff0c;我们将从基础开始&#xff0c…...

作业25 深度搜索3

作业&#xff1a; #include <iostream> using namespace std; bool b[100][100]{0}; char map[100][100]{0}; int dx[4]{0,1,0,-1}; int dy[4]{1,0,-1,0}; int n,m; int sx,sy,ex,ey; int mink2147483647; void dfs(int,int,int); int main(){cin>>n>>m;for(…...

ubuntu20.04 colmap 安装2024.11最新

很多教程都很落后了&#xff0c;需要下载压缩包解压编译的很麻烦 现在就只需要apt install就可以了 apt更新 sudo apt update && sudo apt-get upgrade安装依赖 #安装依赖 sudo apt-get install git cmake ninja-build build-essential libboost-program-options-de…...

WebRTC视频 03 - 视频采集类 VideoCaptureDS 上篇

WebRTC视频 01 - 视频采集整体架构 WebRTC视频 02 - 视频采集类 VideoCaptureModule [WebRTC视频 03 - 视频采集类 VideoCaptureDS 上篇]&#xff08;本文&#xff09; WebRTC视频 04 - 视频采集类 VideoCaptureDS 中篇 WebRTC视频 05 - 视频采集类 VideoCaptureDS 下篇 一、前…...

python os.path.basename(获取路径中的文件名部分) 详解

os.path.basename 是 Python 的 os 模块中的一个函数&#xff0c;用于获取路径中的文件名部分。它会去掉路径中的目录部分&#xff0c;只返回最后的文件名或目录名。 以下是 os.path.basename 的详细解释和使用示例&#xff1a; 语法 os.path.basename(path) 参数 path&…...

《FreeRTOS任务基础知识以及任务创建相关函数》

目录 1.FreeRTOS多任务系统与传统单片机单任务系统的区别 2.FreeRTOS中的任务&#xff08;Task&#xff09;介绍 2.1 任务特性 2.2 FreeRTOS中的任务状态 2.3 FreeRTOS中的任务优先级 2.4 在任务函数中退出 2.5 任务控制块和任务堆栈 2.5.1 任务控制块 2.5.2 任务堆栈…...

036集——查询CAD图元属性字段信息:窗体显示(CAD—C#二次开发入门)

提取CAD图元所有属性字段&#xff0c;通过窗体显示&#xff0c;效果如下&#xff1a;&#xff08;curve改为entity&#xff09; 代码如下&#xff1a; public void 属性查询() {List<Curve> ents Z.db.SelectEntities<Curve>();if (ents is null ||ents.Cou…...

Swift从0开始学习 函数和闭包 day2

一、函数 1.1函数定义 使用 func 来声明一个函数&#xff0c;使用名字和参数来调用函数。使用 -> 来指定函数返回值的类型。 示例&#xff1a;拼接字符串 //有参数和返回值的函数 func append1(name : String, description : String) -> String {return "\(name)…...

内网、公网(外网)划分

内网、公网&#xff08;外网&#xff09;划分 声明&#xff01; 学习视频来自B站up主 泷羽sec 有兴趣的师傅可以关注一下&#xff0c;如涉及侵权马上删除文章 笔记只是方便各位师傅的学习和探讨&#xff0c;文章所提到的网站以及内容&#xff0c;只做学习交流&#xff0c;其…...

【linux】centos7 换阿里云源

相关文章 【linux】CentOS 的软件源&#xff08;Repository&#xff09;学习-CSDN博客 查看yum配置文件 yum的配置文件通常位于/etc/yum.repos.d/目录下。你可以使用以下命令查看这些文件&#xff1a; ls /etc/yum.repos.d/ # 或者 ll /etc/yum.repos.d/备份当前的yum配置文…...

用OMS进行 OceanBase 租户间数据迁移的测评

基本概念 OceanBase迁移服务&#xff08;&#xff0c;简称OMS&#xff09;&#xff0c;可以让用户在同构或异构 RDBMS 与OceanBase 数据库之间进行数据交互&#xff0c;支持数据的在线迁移&#xff0c;以及实时增量同步的复制功能。 OMS 提供了可视化的集中管控平台&#xff…...

【因果分析方法】MATLAB计算Liang-Kleeman信息流

【因果分析方法】MATLAB计算Liang-Kleeman信息流 1 Liang-Kleeman信息流2 MATLAB代码2.1 函数代码2.2 案例参考Liang-Kleeman 信息流(Liang-Kleeman Information Flow)是由 Liang 和 Kleeman 提出的基于信息论的因果分析方法。该方法用于量化变量之间的因果关系,通过计算信息…...

【Java基础知识系列】之Java类的初始化顺序

前言 类的初始化顺序 简单场景 代码示例 public class Person {private String name initName();private String initName() {System.out.println("【父类】初始化实例变量name");return "【父类】史蒂夫";}private int age;private static int staticVa…...

Swift 宏(Macro)入门趣谈(二)

概述 苹果在去年 WWDC 23 中就为 Swift 语言新增了“其利断金”的重要小伙伴 Swift 宏&#xff08;Swift Macro&#xff09;。为此&#xff0c;苹果特地用 2 段视频&#xff08;入门和进阶&#xff09;颇为隆重的介绍了它。 那么到底 Swift 宏是什么&#xff1f;有什么用&…...

vue elementui el-dropdown-item设置@click无效的解决方案

如图&#xff0c;直接在el-dropdown-item上面设置click&#xff0c;相应的method并没有被触发&#xff0c;查找资料发现需要在它的上级 el-dropdown 处使用 command 方法触发。 【template】 <el-dropdown placement"bottom-end" command"handleCommand&quo…...

如何用re从第1排第2个位置中找到两个数字返回(0,1)

以下是使用 Python 的re模块从第1班第2个位置这样的字符串中提取出数字并返回类似(0, 1)这种形式的示例代码&#xff0c;假设数字都是一位数的情况&#xff08;如果是多位数可以按照后续介绍稍作调整&#xff09;&#xff1a; import redef extract_numbers(text):numbers re.…...

装饰模式(Decorator Pattern)重构java邮件发奖系统实战

前言 现在我们有个如下的需求&#xff0c;设计一个邮件发奖的小系统&#xff0c; 需求 1.数据验证 → 2. 敏感信息加密 → 3. 日志记录 → 4. 实际发送邮件 装饰器模式&#xff08;Decorator Pattern&#xff09;允许向一个现有的对象添加新的功能&#xff0c;同时又不改变其…...

零门槛NAS搭建:WinNAS如何让普通电脑秒变私有云?

一、核心优势&#xff1a;专为Windows用户设计的极简NAS WinNAS由深圳耘想存储科技开发&#xff0c;是一款收费低廉但功能全面的Windows NAS工具&#xff0c;主打“无学习成本部署” 。与其他NAS软件相比&#xff0c;其优势在于&#xff1a; 无需硬件改造&#xff1a;将任意W…...

基于FPGA的PID算法学习———实现PID比例控制算法

基于FPGA的PID算法学习 前言一、PID算法分析二、PID仿真分析1. PID代码2.PI代码3.P代码4.顶层5.测试文件6.仿真波形 总结 前言 学习内容&#xff1a;参考网站&#xff1a; PID算法控制 PID即&#xff1a;Proportional&#xff08;比例&#xff09;、Integral&#xff08;积分&…...

质量体系的重要

质量体系是为确保产品、服务或过程质量满足规定要求&#xff0c;由相互关联的要素构成的有机整体。其核心内容可归纳为以下五个方面&#xff1a; &#x1f3db;️ 一、组织架构与职责 质量体系明确组织内各部门、岗位的职责与权限&#xff0c;形成层级清晰的管理网络&#xf…...

3403. 从盒子中找出字典序最大的字符串 I

3403. 从盒子中找出字典序最大的字符串 I 题目链接&#xff1a;3403. 从盒子中找出字典序最大的字符串 I 代码如下&#xff1a; class Solution { public:string answerString(string word, int numFriends) {if (numFriends 1) {return word;}string res;for (int i 0;i &…...

SpringCloudGateway 自定义局部过滤器

场景&#xff1a; 将所有请求转化为同一路径请求&#xff08;方便穿网配置&#xff09;在请求头内标识原来路径&#xff0c;然后在将请求分发给不同服务 AllToOneGatewayFilterFactory import lombok.Getter; import lombok.Setter; import lombok.extern.slf4j.Slf4j; impor…...

今日学习:Spring线程池|并发修改异常|链路丢失|登录续期|VIP过期策略|数值类缓存

文章目录 优雅版线程池ThreadPoolTaskExecutor和ThreadPoolTaskExecutor的装饰器并发修改异常并发修改异常简介实现机制设计原因及意义 使用线程池造成的链路丢失问题线程池导致的链路丢失问题发生原因 常见解决方法更好的解决方法设计精妙之处 登录续期登录续期常见实现方式特…...

NPOI操作EXCEL文件 ——CAD C# 二次开发

缺点:dll.版本容易加载错误。CAD加载插件时&#xff0c;没有加载所有类库。插件运行过程中用到某个类库&#xff0c;会从CAD的安装目录找&#xff0c;找不到就报错了。 【方案2】让CAD在加载过程中把类库加载到内存 【方案3】是发现缺少了哪个库&#xff0c;就用插件程序加载进…...

【从零开始学习JVM | 第四篇】类加载器和双亲委派机制(高频面试题)

前言&#xff1a; 双亲委派机制对于面试这块来说非常重要&#xff0c;在实际开发中也是经常遇见需要打破双亲委派的需求&#xff0c;今天我们一起来探索一下什么是双亲委派机制&#xff0c;在此之前我们先介绍一下类的加载器。 目录 ​编辑 前言&#xff1a; 类加载器 1. …...

抽象类和接口(全)

一、抽象类 1.概念&#xff1a;如果⼀个类中没有包含⾜够的信息来描绘⼀个具体的对象&#xff0c;这样的类就是抽象类。 像是没有实际⼯作的⽅法,我们可以把它设计成⼀个抽象⽅法&#xff0c;包含抽象⽅法的类我们称为抽象类。 2.语法 在Java中&#xff0c;⼀个类如果被 abs…...