实现一个小程序电子名片功能

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;
}
最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
【社区内容提示】社区部分内容疑似由AI辅助生成,浏览时请结合常识与多方信息审慎甄别。
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。

相关阅读更多精彩内容

友情链接更多精彩内容