1693636892404.jpg
微信截图_20230902144254.png
思路:
1:创建一个canvas对象
2:引入名片背景图
3:定位各个数据位置
4:保存生成的名片图片临时地址
5:创建一个新的canvas对象用来生成分享图
6:创建纯色背景,引入生成的名片临时图片地址
7:导出分享图
<view class="p20">
<view class="canvas-box">
//电子名片
<canvas type="2d" style="width:695rpx;height:370rpx;" id="myCanvas"></canvas>
</view>
<!-- <image src="{{shareImage}}"></image> -->
<view class="flex toolsBtnBox j-center a-items-c ">
<!-- <view class="toolsBtn" >
<button data-name="shareBtn" size="mini" open-type="share">
<view class="icon">
<image src="../../image/share.png"></image>
</view>
</button>
<button style="font-size: 24rpx;color: #303030;">发名片</button>
</view> -->
<view class="toolsBtn" catchtap="phoneClick">
<view class="icon">
<image src="../../image/phone.png"></image>
</view>
<button>打电话</button>
</view>
<view class="toolsBtn flex f-column " catchtap="copyBtn" data-type="email" data-str="{{employeeInfo.email}}">
<view class="icon">
<image src="../../image/email.png"></image>
</view>
<button>发邮件</button>
</view>
<view class="toolsBtn flex f-column " catchtap="copyBtn" data-type="wxNo" data-str="{{employeeInfo.wxNo}}">
<view class="icon">
<image src="../../image/email.png"></image>
</view>
<button>加微信</button>
</view>
<view class="toolsBtn flex f-column " catchtap="showEmployeeCard">
<view class="icon">
<image src="../../image/mingpian.png"></image>
</view>
<button>纸质名片</button>
</view>
<view class="toolsBtn flex f-column " catchtap="visitHandle">
<view class="icon">
<image src="../../image/loc.png"></image>
</view>
<button>去拜访</button>
</view>
</view>
<view class="basicInformation introBox">
<view class="fw mb20 title">公司简介</view>
</view>
<view class="bottomBox flex a-items-c j-center">
<view class="submit flex a-items-c j-around" >
<button class="mr20" data-name="shareBtn" size="mini" open-type="share">
分享名片
</button>
<button bindtap="editEmployeeCard">
编辑名片
</button>
</view>
</view>
//创建分享用的图片
<canvas class="shareImageCanvas" type="2d" id="myCanvas1"></canvas>
</view>
// pages/employeeCard/employeeCard.js
const util = require('../../utils/util.js');
const api = require('../../config/api.js');
const app = getApp();
var canvas=null;
var canvas1=null;
Page({
/**
* 页面的初始数据
*/
data: {
workCode:'',
employeeInfo:{},
markers:[],
windowW: 0,
windowH: 0,
scale: 1,
isToggle:false,
current:0,
cardNum:2,
addressInfo:'',
employeeImage:'',
shareImage:'',
isShowCard:true,
videoCtx:null,
pauseFlag:true,
storageMobile:''
},
/**
* 生命周期函数--监听页面加载
*/
onLoad(options) {
this.setData({
storageMobile
})
if(options){
// console.log('options',options);
let {workcode}=options
this.setData({
workCode:workcode
})
}else{
this.setData({
workCode:stoWorkCode
})
}
this.getSystemInfo();
this.getEmployeeCardInfo()
},
// 获取名片信息
getEmployeeCardInfo(){
let that=this
util.request(api.employeeCardGetInfo,
{workCode:this.data.workCode},'POST').then(function (res) {
console.log('getEmployeeCardInfo',res.data);
if (res.code == '1') {
that.setData({
employeeInfo:res.data
})
wx.setNavigationBarTitle({
title:`${res.data.name}的电子名片`,
success: (result)=>{
},
fail: ()=>{},
complete: ()=>{}
});
that.createdEmployeeCard().then(imageUrl=>{
setTimeout(() => {
//因生成分享图需依赖上面刚生成的电子名片,因为机型性能不同生成速度不同,为确保生成分享图时有数据,所以在异步后再加上一个定时器
that.createdShareImage(imageUrl)
}, 1500);
})
}
})
},
getSystemInfo () {
var that = this;
wx.getSystemInfo({
success: function (res) {
that.setData({
windowW: res.windowWidth,
windowH: res.windowHeight
})
},
})
},
//主要代码------ 生成名片
createdEmployeeCard() {
return new Promise((resolve, reject) => {
let that = this
let {employeeInfo:{name,companyName,job,phone,email}}=that.data
let canvasH = that.data.windowH
let canvasW = that.data.windowW
wx.createSelectorQuery()
.select('#myCanvas')
.fields({ node: true, size: true })
.exec((res) => {
// Canvas 对象
canvas = res[0].node
const context = canvas.getContext('2d')
// Canvas 画布的实际绘制宽高
const height = res[0].height
const width = res[0].width
console.log('height---',height);
console.log('width---',width);
// 计算像素比 初始化画布大小
const dpr = wx.getWindowInfo().pixelRatio
canvas.width = width * dpr
canvas.height = height * dpr
context.scale(dpr, dpr)
// 开始绘制
context.clearRect(0, 0, canvas.width, canvas.height)
// 若干绘制调用
context.fillStyle = 'rgb(256, 256, 256)';
context.fillRect(0, 0, canvasW, canvasH)
const bgImage = canvas.createImage()
// const logoImage = canvas.createImage()
bgImage.src = '/image/mingpian_bg.png'
bgImage.onload = () => {
context.drawImage(
bgImage,
0,
0,
360,
190,
)
context.textAlign ='left'
context.fillStyle = "#000";
context.font = 'normal bold 28px 微软雅黑' // 设置字体大小
// context.textBaseline = 'top'
context.fillText(name, 30, 40)
context.font = 'normal 500 12px 微软雅黑' // 设置字体大小
context.fillStyle = "#000";
context.fillText('某有限公司', 30,65)
context.fillText(job, 30, 85)
context.fillText(phone, 50, 131)
context.fillText(email, 50, 153)
wx.canvasToTempFilePath({
canvas: canvas,
success(res) {
that.setData({
//临时路径保存
employeeImage:res.tempFilePath
})
resolve(res.tempFilePath)
}
})
}
})
})
},
// saveEmployeeCard(){
// let {employeeImage}=this.data
// wx.saveImageToPhotosAlbum({
// filePath:employeeImage,
// success(res) {
// wx.showToast({
// title: '保存成功',
// icon: 'none',
// image: '',
// duration: 1500,
// mask: false,
// success: (result)=>{
// },
// fail: ()=>{},
// complete: ()=>{}
// });
// }
// })
// },
// 生成分享图
createdShareImage(imageUrl) {
let that = this
let canvasH = that.data.windowH
let canvasW = that.data.windowW
wx.createSelectorQuery()
.select('#myCanvas1')
.fields({ node: true, size: true })
.exec((res) => {
// Canvas 对象
canvas1 = res[0].node
const employeeImage = canvas1.createImage()
const iconImage = canvas1.createImage()
const context = canvas1.getContext('2d')
// Canvas 画布的实际绘制宽高
const width = res[0].width
const height = res[0].height
// 初始化画布大小 计算像素比
const dpr = wx.getWindowInfo().pixelRatio
canvas1.width = width * dpr
canvas1.height = height * dpr
context.scale(dpr, dpr)
context.clearRect(0, 0, canvas1.width, canvas1.height)
const grd = context.createLinearGradient(0, 0,500, 0, canvasH)
grd.addColorStop(0, '#443319')
grd.addColorStop(0.7, '#70552C')
grd.addColorStop(1, '#C89A53')
context.fillStyle = grd;
context.fillRect(0, 0, canvasW, canvasH)
employeeImage.src = imageUrl
iconImage.src = '/image/open.png'
iconImage.onload = () => {
context.drawImage(iconImage,230,30,30,30)
context.textAlign ='left'
context.fillStyle = "#fff";
context.font = 'normal bold 32px 微软雅黑' // 设置字体大小
context.textBaseline = 'top'
context.fillText('点击查看名片', 15, 30)
}
employeeImage.onload = () => {
context.drawImage(
employeeImage,
5,
90,
290,
140,
)
that.saveShareImage()
}
})
},
// 保存
saveShareImage () {
let that = this;
wx.canvasToTempFilePath({
canvas: canvas1,
success(res) {
console.log('分享的图片',res.tempFilePath);
that.setData({
shareImage:res.tempFilePath
})
// shareImage=res.tempFilePath
// wx.saveImageToPhotosAlbum({
// filePath:res.tempFilePath,
// success(res) {}
// })
}
})
},
phoneClick(e){
wx.makePhoneCall({
phoneNumber: this.data.employeeInfo.phone,
success(){},
fail(){}
})
},
copyBtn(e){
console.log('e',e);
let type=e.currentTarget.dataset.type
let str=e.currentTarget.dataset.str
wx.showModal({
title:type=='wxNo'?'微信号':'电子邮箱',
content: str,
showCancel: true,
cancelText: '取消',
cancelColor: '#ccc',
confirmText: '复制',
confirmColor: '#00a5dd',
success: (result) => {
if(result.confirm){
wx.setClipboardData({
data: str,
success: function (res) {
wx.showToast({
title:(type=='wxNo'?'微信号':'电子邮箱')+'已复制',
icon:"none",
mask:"true"
})
}})
}
},
fail: ()=>{},
complete: ()=>{}
});
},
showEmployeeCard(){
wx.previewImage({
current: this.data.employeeImage, // 图片的地址url
urls: [this.data.employeeImage] // 预览的地址url
})
},
submitHandle(){
wx.showToast({
title: '保存成功',
icon: 'none',
image: '',
duration: 1500,
mask: false,
success: (result)=>{
},
fail: ()=>{},
complete: ()=>{}
});
},
backHandle(){
wx.navigateBack({
delta: 1
});
},
/**
* 生命周期函数--监听页面初次渲染完成
*/
onReady() {
},
/**
* 生命周期函数--监听页面隐藏
*/
onHide() {
},
/**
* 生命周期函数--监听页面卸载
*/
onUnload() {
},
/**
* 页面相关事件处理函数--监听用户下拉动作
*/
onPullDownRefresh() {
},
// 拜访
visitHandle(e){
let {addressLat,addressLng}=this.data.employeeInfo
wx.openLocation({
latitude:+addressLat,
longitude:+addressLng,
scale: 17
})
},
/**
* 页面上拉触底事件的处理函数
*/
onReachBottom() {
},
/**
* 用户点击右上角分享
*/
onShareAppMessage(options) {
let that = this;
let {shareImage,employeeInfo,storageMobile}= that.data
// 设置菜单中的转发按钮触发转发事件时的转发内容
let shareObj = {
// title:storageMobile==employeeInfo.phone?"您好,这是我的名片":`这是${employeeInfo.name}的电子名片` , // 默认是小程序的名称(可以写slogan等)
title:`这是${employeeInfo.name}的电子名片` , // 默认是小程序的名称(可以写slogan等)
path: `/pages/employeeCardPreview/employeeCardPreview?workcode=${that.data.workCode}`, // 默认是当前页面,必须是以‘/'开头的完整路径
imageUrl: shareImage, //自定义图片路径,可以是本地文件路径、代码包文件路径或者网络图片路径,支持PNG及JPG,不传入 imageUrl 则使用默认截图。显示图片长宽比是 5:4
success(res){
if(res.errMsg == 'shareAppMessage:ok'){}
},
fail(){
if(res.errMsg == 'shareAppMessage:fail cancel'){
}else if(res.errMsg == 'shareAppMessage:fail'){}
},
complete(){
}
}
// 来自页面内的按钮的转发
if( options.from == 'button' ){
var eData = options.target.dataset;
console.log('---------------', eData.name );
// 此处可以修改 shareObj 中的内容
// shareObj.path = '/pages/btnname/btnname?btn_name='+eData.name;
}
return shareObj;
},
})
/* pages/employeeCard/employeeCard.wxss */
page {
background-color: #f2f2f2;
padding-bottom: 150rpx;
}
.p20 {
padding: 20rpx;
}
.employeeCardClass {
background: linear-gradient(90deg, rgba(255, 109, 85, 1) 0%, rgba(255, 31, 31, 1) 100%);
margin: 20rpx;
height: 300rpx;
padding: 20rpx;
}
.f32-ff {
font-size: 32rpx;
color: #fff;
}
.f32-5d {
font-size: 32rpx;
color: #5d5d5d;
}
.fw {
font-weight: 700;
}
.red {
color: red;
margin-left: 10rpx;
font-size: 42rpx;
position: absolute;
top: 5rpx;
}
.pr {
position: relative;
}
.title {
font-size: 32rpx;
padding-bottom: 20rpx;
border-bottom: 1px solid #f2f2f2;
}
.ml20 {
margin-left: 20rpx;
}
.mb10 {
margin-bottom: 10rpx;
}
.mb20 {
margin-bottom: 20rpx;
}
.mr100 {
margin-right: 100rpx;
}
.flex {
display: flex;
}
.basicInformation {
padding: 20rpx;
margin-top: 10rpx;
background-color: #fff;
border-radius: 10rpx;
margin-bottom: 10rpx;
}
.nonInsiderClass {
position: fixed;
background-color: #fff;
z-index: 99999;
height: 100vh;
width: 100vw;
line-height: 100vh;
top: 0rpx;
left: 0rpx;
margin: 0 auto;
text-align: center;
font-size: 36rpx;
font-weight: 700;
}
.formInput {
width: 450rpx;
padding: 0 20rpx;
}
.f-column {
flex-direction: column;
}
.a-items-c {
align-items: center;
}
.j-around {
justify-content: around;
}
.j-center {
justify-content: center;
}
.loginInput {
padding: 20rpx;
}
.loginInput_item {
height: 100rpx;
width: 80%;
margin-bottom: 20rpx;
background-color: #fff;
}
.loginInput_item text {
font-size: 28rpx;
color: #303030;
width: 150rpx;
}
.loginInput_item input {
font-size: 28rpx;
width: 200rpx;
padding: 20rpx 0;
padding-left: 20rpx;
border-bottom: 1rpx solid #F5f5f5;
}
.canvas-box {
margin-left: 10rpx;
height: 370rpx;
}
.loginButton {
height: 80rpx;
}
.login-button-custom {
margin-top: 30rpx;
width: 340rpx;
height: 70rpx;
font-size: 32rpx;
background-color: #00a5dd !important;
border-radius: 10rpx !important;
color: #fff !important;
}
.shareImageCanvas {
margin-left: 20px;
width: 300px;
height: 240px;
position: fixed;
top: -9999rpx;
}
.formInput_d {
/* background-color: #f5f5f5; */
color: #999;
}
.toolsBtnBox {
background-color: #fff;
margin-top: 10rpx;
box-sizing: border-box;
border-radius: 10rpx;
}
.toolsBtn {
width: 200rpx;
padding: 10rpx 20rpx;
color: #fff;
text-align: center;
}
button {
margin: 0 !important;
padding: 0 !important;
white-space: nowrap;
color: #fff;
font-size: 30rpx !important;
background-color: transparent;
border-radius: 0;
height: 70rpx;
line-height: 70rpx;
text-align: center;
background-color: #00a5dd;
width: 250rpx;
}
.toolsBtn button {
margin: 0 !important;
padding: 0 !important;
white-space: nowrap;
color: #333;
width: 100rpx !important;
height: 60rpx !important;
line-height: 60rpx !important;
font-size: 24rpx !important;
background-color: #fff;
}
.icon image {
height: 50rpx;
width: 50rpx;
}
button::after {
border: none;
}
.bottomBox {
box-shadow: 1rpx solid 10px 10px 5px rgba(0, 0, 0, 0.9);
background-color: #fff;
width: 100vw;
padding: 10rpx;
color: #fff;
position: fixed;
bottom: 0rpx;
left: 50%;
z-index: 9999;
transform: translateX(-50%);
}
.preview {
height: 70rpx;
line-height: 70rpx;
text-align: center;
background-color: #00a5dd;
width: 300rpx;
margin-right: 20rpx;
}
.mapClass {
width: 85vw;
overflow: hidden;
margin-left: 3vw;
transform: translateY(0);
box-sizing: border-box;
height: 280rpx;
border-radius: 10rpx;
}
.addressBox {
width: 500rpx;
padding-left: 20rpx;
padding-right: 120rpx;
}
.addressStr {
color: #00a5dd;
}
.chooseLoc {
background-color: #fff;
color: #00a5dd;
margin-left: 15rpx;
white-space: nowrap;
font-size: 26rpx;
}
map {
width: 100%;
background-color: #f6f9f9;
}
.placeholderClass {
font-size: 26rpx;
color: #ccc;
}
.introBox {
padding: 20rpx;
}
.introBox video {
width: 100%;
}
.introBox image {
width: 100vw;
height: 100%;
}
.mr20 {
margin-right: 20rpx !important;
}