『uniapp』uni-share 分享功能 使用例子(保姆级图文)

目录


欢迎关注 『uniapp』 专栏,持续更新中
欢迎关注 『uniapp』 专栏,持续更新中

打包自定义基座后的预览效果

  • 分享内容

  • 点击更多后调用系统的分享

  • 取消分享的回调

  • 分享给QQ

启用share模块

启用后会自动给你加入对应的分享权限

这里面的个汇总appid或是key可以随便填,如果你没有申请的话,不影响功能测试


准备好分享按钮图标文件

你可以用自己的图片


具体功能实现

新建utils文件夹

uni-image-menu.js

javascript 复制代码
var nvMask, nvImageMenu;
class NvImageMenu {
	constructor(arg) {
		this.isShow = false
	}
	show({
		list,
		cancelText
	}, callback) {
		if (!list) {
			list = [{
				"img": "/static/sharemenu/wechatfriend.png",
				"text": "图标文字"
			}]
		}
		//以下为计算菜单的nview绘制布局,为固定算法,使用者无关关心
		var screenWidth = plus.screen.resolutionWidth
		//以360px宽度屏幕为例,上下左右边距及2排按钮边距留25像素,图标宽度55像素,同行图标间的间距在360宽的屏幕是30px,但需要动态计算,以此原则计算4列图标分别的left位置
		//图标下的按钮文字距离图标5像素,文字大小12像素
		//底部取消按钮高度固定为44px
		//TODO 未处理横屏和pad,这些情况6个图标应该一排即可
		var margin = 20,
			iconWidth = 60,
			icontextSpace = 5,
			textHeight = 12
		var left1 = margin / 360 * screenWidth
		var iconSpace = (screenWidth - (left1 * 2) - (iconWidth * 4)) / 3 //屏幕宽度减去左右留白间距,再减去4个图标的宽度,就是3个同行图标的间距
		if (iconSpace <= 5) { //屏幕过窄时,缩小边距和图标大小,再算一次
			margin = 15
			iconWidth = 40
			left1 = margin / 360 * screenWidth
			iconSpace = (screenWidth - (left1 * 2) - (iconWidth * 4)) / 3 //屏幕宽度减去左右留白间距,再减去4个图标的宽度,就是3个同行图标的间距
		}
		var left2 = left1 + iconWidth + iconSpace
		var left3 = left1 + (iconWidth + iconSpace) * 2
		var left4 = left1 + (iconWidth + iconSpace) * 3
		var top1 = left1
		var top2 = top1 + iconWidth + icontextSpace + textHeight + left1

		const TOP = {
				top1,
				top2
			},
			LEFT = {
				left1,
				left2,
				left3,
				left4
			};

		nvMask = new plus.nativeObj.View("nvMask", { //先创建遮罩层
			top: '0px',
			left: '0px',
			height: '100%',
			width: '100%',
			backgroundColor: 'rgba(0,0,0,0.2)'
		});
		nvImageMenu = new plus.nativeObj.View("nvImageMenu", { //创建底部图标菜单
			bottom: '0px',
			left: '0px',
			height: (iconWidth + textHeight + 2 * margin) * Math.ceil(list.length / 4) + 44 +
			'px', //'264px',
			width: '100%',
			backgroundColor: 'rgb(255,255,255)'
		});
		nvMask.addEventListener("click", () => { //处理遮罩层点击
			// console.log('处理遮罩层点击');
			this.hide()
			callback({
				event: "clickMask"
			})
		})
		let myList = []
		list.forEach((item, i) => {
			myList.push({
				tag: 'img',
				src: item.img,
				position: {
					top: TOP['top' + (parseInt(i / 4) + 1)],
					left: LEFT['left' + (1 + i % 4)],
					width: iconWidth,
					height: iconWidth
				}
			})
			myList.push({
				tag: 'font',
				text: item.text,
				textStyles: {
					size: textHeight
				},
				position: {
					top: TOP['top' + (parseInt(i / 4) + 1)] + iconWidth + icontextSpace,
					left: LEFT['left' + (1 + i % 4)],
					width: iconWidth,
					height: textHeight
				}
			})
		})

		//绘制底部图标菜单的内容
		nvImageMenu.draw([{
				tag: 'rect', //菜单顶部的分割灰线
				color: '#e7e7e7',
				position: {
					top: '0px',
					height: '1px'
				}
			},
			{
				tag: 'font',
				text: cancelText, //底部取消按钮的文字
				textStyles: {
					size: '14px'
				},
				position: {
					bottom: '0px',
					height: '44px'
				}
			},
			{
				tag: 'rect', //底部取消按钮的顶部边线
				color: '#e7e7e7',
				position: {
					bottom: '45px',
					height: '1px'
				}
			},
			...myList
		])
		nvMask.show()
		nvImageMenu.show()
		// 开始动画
		/*
			plus.nativeObj.View.startAnimation({
				type: 'slide-in-bottom',
				duration: 300
			}, nvImageMenu, {}, function() {
				console.log('plus.nativeObj.View.startAnimation动画结束');
				// 关闭原生动画
				plus.nativeObj.View.clearAnimation();
				nvImageMenu.show()
			});
		*/


		this.isShow = true
		nvImageMenu.addEventListener("click", e => { //处理底部图标菜单的点击事件,根据点击位置触发不同的逻辑
			// console.log("click menu"+JSON.stringify(e));
			if (e.screenY > plus.screen.resolutionHeight - 44) { //点击了底部取消按钮
				// callback({event:"clickCancelButton"})
				this.hide()
			} else if (e.clientX < 5 || e.clientX > screenWidth - 5 || e.clientY < 5) {
				//屏幕左右边缘5像素及菜单顶部5像素不处理点击
			} else { //点击了图标按钮
				var iClickIndex = -1 //点击的图标按钮序号,第一个图标按钮的index为0
				var iRow = e.clientY < (top2 - (left1 / 2)) ? 0 : 1
				var iCol = -1
				if (e.clientX < (left2 - (iconSpace / 2))) {
					iCol = 0
				} else if (e.clientX < (left3 - (iconSpace / 2))) {
					iCol = 1
				} else if (e.clientX < (left4 - (iconSpace / 2))) {
					iCol = 2
				} else {
					iCol = 3
				}
				if (iRow == 0) {
					iClickIndex = iCol
				} else {
					iClickIndex = iCol + 4
				}
				// console.log("点击按钮的序号: " + iClickIndex);
				// if (iClickIndex >= 0 && iClickIndex <= 5) { //处理具体的点击逻辑,此处也可以自行定义逻辑。如果增减了按钮,此处也需要跟着修改
				// }
				callback({
					event: "clickMenu",
					index: iClickIndex
				})
			}
		})
		/* nvImageMenu.addEventListener("touchstart", function(e) {
			if (e.screenY > (plus.screen.resolutionHeight - 44)) {
				//TODO 这里可以处理按下背景变灰的效果
			}
		})
		nvImageMenu.addEventListener("touchmove", function(e) {
			//TODO 这里可以处理按下背景变灰的效果
			if (e.screenY > plus.screen.resolutionHeight - 44) {}
		})
		nvImageMenu.addEventListener("touchend", function(e) {
			//TODO 这里可以处理释放背景恢复的效果
		})
		*/
	}

	hide() {
		nvMask.hide()
		nvImageMenu.hide()
		this.isShow = false
	}
}

export default NvImageMenu

uni-share.js

javascript 复制代码
import UniImageMenu from './uni-image-menu.js';
class UniShare extends UniImageMenu{
	constructor(arg) {
		super()
		this.isShow = super.isShow
	}
	async show(param, callback){
		var menus = []
		plus.share.getServices(services => { //只显示有服务的项目
			services = services.filter(item => item.nativeClient)
			let servicesList = services.map(e => e.id)
			param.menus.forEach(item => {
				if (servicesList.includes(item.share.provider) || typeof(item.share) == 'string') {
					menus.push(item)
				}
			})
			super.show({
				list: menus,
				cancelText: param.cancelText
			}, e => {
				callback(e)
				if(e.event == 'clickMenu'){
					if (typeof(menus[e.index]['share']) == 'string') {
						this[menus[e.index]['share']](param)
					} else {
						uni.share({
							...param.content,
							...menus[e.index].share,
							success: res=> {
								console.log("success:" + JSON.stringify(res));
								super.hide()
							},
							fail: function(err) {
								console.log("fail:" + JSON.stringify(err));
								uni.showModal({
									content: JSON.stringify(err),
									showCancel: false,
									confirmText: "知道了"
								});
							}
						})
					}
				}
			})
		}, err => {
			uni.showModal({
				title: '获取服务供应商失败:' + JSON.stringify(err),
				showCancel: false,
				confirmText: '知道了'
			});
			console.error('获取服务供应商失败:' + JSON.stringify(err));
		})
	}
	hide(){
		super.hide()
	}
	copyurl(param) {
		console.log('copyurl',param);
		uni.setClipboardData({
			data: param.content.href,
			success: ()=>{
				console.log('success');
				uni.hideToast() //关闭自带的toast
				uni.showToast({
					title: '复制成功',
					icon: 'none'
				});
				super.hide();
			},
			fail: (err) => {
				uni.showModal({
					content: JSON.stringify(err),
					showCancel: false
				});
			}
		});
	}
	// 使用系统分享发送分享消息 
	shareSystem(param) {
		console.log('shareSystem',param);
		plus.share.sendWithSystem({
			type: 'text',
			content: param.content.title + param.content.summary || '',
			href: param.content.href,
		}, (e)=> {
			console.log('分享成功');
			super.hide()
		}, (err)=> {
			console.log('分享失败:' + JSON.stringify(err));
			uni.showModal({
				title: '获取服务供应商失败:' + JSON.stringify(err),
				showCancel: false,
				confirmText: '知道了'
			});
		});
	}
}
export default UniShare

功能演示页面

导入依赖

  • 通过 import 语句从 utils/uni-share.js 文件导入了一个名为 UniShare 的类。
  • 然后创建了一个 UniShare 的实例 uniShare,通过这个实例来调用分享功能。
javascript 复制代码
import UniShare from 'utils/uni-share.js';
const uniShare = new UniShare();

onBackPress 方法

  • onBackPress 是一个自定义方法,可能用来处理用户按下返回按钮时的行为。
  • from 是一个参数,表示返回操作的来源(比如是否是系统的返回按钮)。
  • 如果 from 等于 'backbutton',表示是从设备的返回按钮触发的返回事件。
  • 通过 this.$nextTick() 延迟执行 uniShare.hide(),隐藏分享界面(这是在返回时进行的UI更新)。
  • 最后返回 uniShare.isShow,这是一个布尔值,表示分享界面是否可见。
javascript 复制代码
onBackPress({ from }) {
  console.log(from);
  if (from == 'backbutton') {
    this.$nextTick(function() {
      uniShare.hide()
    })
    return uniShare.isShow;
  }
}

uniShare.show 配置说明

content: 定义了分享的基本内容,包括:
  • type : 分享类型,0 可能表示常规的链接分享。
  • href: 分享的目标链接。
  • title: 分享内容的标题。
  • summary: 分享内容的描述。
  • imageUrl: 分享的缩略图,要求是在线的图片URL。
  • img: 该平台的图标(路径)。
  • text: 平台名称(显示的文字)。
  • share : 配置该平台的具体分享参数:
    • provider : 平台提供者,比如 weixinsinaweiboqq 等。
    • scene : 分享的场景(如 WXSceneSession 表示微信好友,WXSceneTimeline 表示微信朋友圈)。

对于微信小程序的分享,配置了 type: 5 以及 miniProgram 的详细信息,如小程序ID、路径、Web URL等。

cancelText: 设置分享取消按钮的文字。

回调函数:
javascript 复制代码
e => { 
  console.log(uniShare.isShow); 
  console.log(e); 
}

完整代码

pages/index/index.vue

javascript 复制代码
<template>
	<button type="default" @click="uniShare">分享给好友</button>
</template>
<script>
	import UniShare from 'utils/uni-share.js';
	const uniShare = new UniShare();
	export default {
		onBackPress({ from }) {
			console.log(from);
			if (from == 'backbutton') {
				this.$nextTick(function() {
					uniShare.hide()
				})
				return uniShare.isShow;
			}
		},
		methods: {
			uniShare() {
				uniShare.show({
						content: { //公共的分享参数配置  类型(type)、链接(herf)、标题(title)、summary(描述)、imageUrl(缩略图)
							type: 0,
							href: 'https://blog.csdn.net/u011027547',
							title: '分享内容标题',
							summary: '分享内容~~~~~',
							// imageUrl: 必须是在线的url  本地文件没有成功
							imageUrl: 'https://img-cdn-aliyun.dcloud.net.cn/stream/icon/__UNI__HelloUniApp.png'
						},
						menus: [{
								"img": "/static/app-plus/sharemenu/wechatfriend.png",
								"text": "微信好友",
								"share": { //当前项的分享参数配置。可覆盖公共的配置如下:分享到微信小程序,配置了type=5
									"provider": "weixin",
									"scene": "WXSceneSession"
								}
							},
							{
								"img": "/static/app-plus/sharemenu/wechatmoments.png",
								"text": "微信朋友圈",
								"share": {
									"provider": "weixin",
									"scene": "WXSceneTimeline"
								}
							},
							{
								"img": "/static/app-plus/sharemenu/mp_weixin.png",
								"text": "微信小程序",
								"share": {
									provider: "weixin",
									scene: "WXSceneSession",
									type: 5,
									miniProgram: {
										id: '123',
										path: '/pages/list/detail',
										webUrl: '/#/pages/list/detail',
										type: 0
									},
								}
							},
							{
								"img": "/static/app-plus/sharemenu/weibo.png",
								"text": "微博",
								"share": {
									"provider": "sinaweibo"
								}
							},
							{
								"img": "/static/app-plus/sharemenu/qq.png",
								"text": "QQ",
								"share": {
									"provider": "qq"
								}
							},
							{
								"img": "/static/app-plus/sharemenu/copyurl.png",
								"text": "复制",
								"share": "copyurl"
							},
							{
								"img": "/static/app-plus/sharemenu/more.png",
								"text": "更多",
								"share": "shareSystem"
							}
						],
						cancelText: "取消分享",
					},
					e => { //callback
						console.log(uniShare.isShow);
						console.log(e);
					})
			}
		}
	}
</script>

总结

大家喜欢的话,给个👍,点个关注!给大家分享更多计算机专业学生的求学之路!

版权声明:

发现你走远了@mzh原创作品,转载必须标注原文链接

Copyright 2024 mzh

Crated:2024-4-1

欢迎关注 『uniapp』 专栏,持续更新中
欢迎关注 『uniapp』 专栏,持续更新中
『未完待续』


相关推荐
跟着阿龙学编程5 小时前
vue-table-print 一个强大的Vue 3表格打印工具,支持ElementPlus、Ant Design Vue等主流UI组件库。
vue·print
_龙衣8 小时前
uni-app/vue2:微信小程序实现文件流的下载及预览
微信小程序·uni-app·notepad++
游王子12 小时前
uni-app(3):互相引用
uni-app
游王子1 天前
uni-app(4):js语法、css语法
uni-app
晓晓莺歌1 天前
uniapp图片下载(微信H5可用、小程序应该也通用)
uni-app
Vue10241 天前
uniapp 嵌入鸿蒙原生组件 具体步骤
华为·uni-app·harmonyos
耶啵奶膘1 天前
uniapp+vue3 随机、换一批
uni-app
.生产的驴1 天前
Vue3 数据可视化屏幕大屏适配 页面自适应 响应式 数据大屏 大屏适配
java·c++·vue.js·后端·信息可视化·前端框架·vue
Li_Ning212 天前
【uniapp】 iosApp开发xcode原生配置项(iOS平台Capabilities配置)
ios·uni-app·xcode