小程序保存图片分享朋友圈

最近写的小程序分享,和小伙伴们分享交流一下.小程序分享分为两种:一种是直接分享给好友或群;一种是生成带有小程序码的图片保存本地,然后将图片分享给好友或者朋友圈,其他人通过扫码进入你要分享的页面.好了废话不多说,直接上码!!!里面有些数据和接口调用如果不懂的可以关注我前几篇文章哦!

这里先给大家展示一下效果图

 这里是分享逻辑

// pages/bargain/bargain.js
const app = getApp();
import { Bargain } from 'bargain-model.js';
var bargain = new Bargain(); //实例化 对象
var util = require('../../utils/util.js');

Page({

  /**
   * 页面的初始数据
   */
  data: {
    imgwidth: 750,
    imgheights: [],
    msgList: [],
    isShow: false,//控制emoji表情是否显示
    isShowModel: false,
  },
  bindchange: function (e) {
    this.setData({
      current: e.detail.current
    })
  },
  imgHeight: function (e) {
    //获取图片真实宽度
    var imgwidth = e.detail.width,
      imgheight = e.detail.height,
      //宽高比
      ratio = imgwidth / imgheight;
    var first = e.target.dataset['index'];
    //计算的高度值
    var viewHeight = 750 / ratio;
    var imgheight = viewHeight
    var imgheights = this.data.imgheights
    //把每一张图片的高度记录到数组里
    imgheights[first] = imgheight;// 改了这里 赋值给当前 index
    this.setData({
      imgheights: imgheights,
    })
    if (first == 0) {
      var canvasheight = 420 * imgheight / 750;
      if (canvasheight > 420) {
        canvasheight = 420;
        var canvaswidth = 420 * 750 / imgheight;
      } else {
        canvaswidth = 420;
      }

      this.setData({
        canvaswidth: canvaswidth,
        canvasheight: canvasheight,
      })
    }
  },
 

  /**
   * 用户点击右上角分享
   */
  onShareAppMessage: function () {
    var that = this;
    var goodid = that.data.goodid;
    var scheduleId = that.data.scheduleId;
    return {
      title: '砍价',
      path: '/pages/bargain/bargain?goodid=' + goodid + '&scheduleId=' + scheduleId,
      success: function (res) {
        
      }
    }
  },

  /**邀请好友帮砍 */
  onForward:function(e){
    this.setData({
      isShow: !this.data.isShow,
    })
  },

  //分享给个人
  sharetoperson: function (e) {
    this.onShareAppMessage;
  },

  //分享到朋友圈
  sharetogroup: function (e) {
    var that = this;
    that.setData({
      isShow: false,
      isShowModel: true
    })
    
    //获取发起者头像和昵称
    var user = that.data.user;
  
    wx.showLoading({
      title: '绘制分享图片中',
      mask: true
    });
    var sid = app.globalData.sid;//发型师sid
    var goodid = that.data.goodid;//商品id
    var scheduleId = that.data.scheduleId;//用户发起砍价表id
    var pid = user.pid;//活动id
    bargain.getSpecialMData(sid, goodid, scheduleId,pid, (callbackdata) => {
      this.setData({
        painting: {
          width: 520,
          height: 800,
          clear: true,
          views: [
            {
              type: 'rect',
              background: '#fff',
              top: 0,
              left: 0,
              width: 520,
              height: 800
            },
            {
              type: 'text',
              content: that.data.bargain.activity_name,
              fontSize: 40,
              color: '#000',
              textAlign: 'left',
              top: 68,
              left: 54,
              bolder: true
            },
            {
              type: 'image',
              url: that.data.bargain.img[0],
              top: 158,
              left: 54,
              width: that.data.canvaswidth,
              height: that.data.canvasheight
            },
            {
              type: 'text',
              content: that.data.bargain.product_name,
              fontSize: 25,
              lineHeight: 30,
              color: '#000',
              textAlign: 'left',
              MaxLineNumber: 2,
              breakWord: true,
              top: 606,
              left: 55,
              width: 245
            },
            {
              type: 'text',
              content: util.formatMonth(new Date()),
              fontSize: 20,
              color: '#999',
              top: 685,
              left: 54
            },
            {
              type: 'text',
              content:  that.data.user.nickname + "需要你帮Ta砍价",
              fontSize: 20,
              color: '#999',
              top: 717,
              left: 54
            },
            {
              type: 'image',
              url: callbackdata,
              top: 605,
              left: 373,
              width: 106,
              height: 106
            },
            {
              type: 'text',
              content: '长按识别小程序码',
              fontSize: 20,
              color: '#666',
              top: 717,
              left: 337,
            }
          ]
        }
      })
    });
  },
  eventSave: function () {
    wx.saveImageToPhotosAlbum({
      filePath: this.data.shareImage,
      success(res) {
        wx.showToast({
          title: '保存图片成功',
          icon: 'success',
          duration: 2000
        })
      }
    })
  },
  eventGetImage: function (event) {
    wx.hideLoading()
    const { tempFilePath, errMsg } = event.detail
    if (errMsg === 'canvasdrawer:ok') {
      this.setData({
        shareImage: tempFilePath
      })
    }
  },

  hideImgModel: function () {
    var that = this;
    that.setData({
      isShowModel: false
    })
  },


})

这里是wxml

<!--分享弹出层{{shareImage}}-->
<view class="bottomshare">
  <view class="showimportant {{isShow ? 'showmodel' : 'hidemodel'}}"></view>
  <view class="emoji-box {{isShow ? 'emoji-move-in' : 'emoji-move-out'}}">
    <view class="deleteTag" bindtap='onForward'>×</view>
    <button  class="toperson" open-type="share" bindtap='sharetoperson'>
      <image src='https://img.nmsmt.cn/public/youxuan_xcx/toperson.png' class="shareimg" mode="widthFix" ></image>
      <view>分享给好友</view>
    </button>
    <button class="togroup" bindtap='sharetogroup'>
      <image src='https://img.nmsmt.cn/public/youxuan_xcx/groups.png'  class="shareimg" mode="widthFix" ></image>
      <view>分享到朋友圈</view>
    </button>
  </view>
</view>

<!-- 保存图片到本地 -->
<view class="model {{isShowModel ? 'showmodel' : 'hidemodel'}}" >
  <view class="deleteTagShare" bindtap='hideImgModel'>×</view>
  <image src="{{shareImage}}" class="share-image" model="widthFix"></image>
  <canvasdrawer painting="{{painting}}" class="canvasdrawer" bind:getImage="eventGetImage"/>
  <button bind:tap="eventSave" class="savetolocal">保存到本地</button>
</view>

这里是wxss

/*分享弹出层*/
.bottomshare{
  position: fixed;
  bottom:0;
  width:100%;
  z-index:2;
}
.showimportant{
  height:100%;
  background: rgba(0,0,0,0.4);
  position: fixed;
  bottom:0%;
  width:100%;
}

.emoji-box {
  position: relative;
  /* height: 200rpx; */
  padding: 5px 0;
  box-sizing: border-box;
  margin-bottom: -300rpx;
  height:300rpx;
  width:100%;
  background-color:white;
  text-align:center;
  z-index:3;

}

.emoji-move-in {
  -webkit-animation: emoji-move-in 0.3s forwards;
  animation: emoji-move-in 0.3s forwards;
}

.emoji-move-out {
  -webkit-animation: emoji-move-out 0.3s forwards;
  animation: emoji-move-out 0.3s forwards;
}

.no-emoji-move {
  -webkit-animation: none;
  animation: none;
}

@-webkit-keyframes emoji-move-in {
  0% {
    margin-bottom: -300rpx;
  }

  100% {
    margin-bottom: 0;
  }
}

@keyframes emoji-move-in {
  0% {
    margin-bottom: -300rpx;
  }

  100% {
    margin-bottom: 0;
  }
}

@-webkit-keyframes emoji-move-out {
  0% {
    margin-bottom: 0;
  }

  100% {
    margin-bottom: -300rpx;
  }
}

@keyframes emoji-move-out {
  0% {
    margin-bottom: 0;
  }

  100% {
    margin-bottom: -300rpx;
  }
}



.toperson{
  display: inline-block;
  width:50%;
  margin-top:50rpx;
  border:none;
  background:#fff;

}

.toperson:after{
  border:none;
}

.togroup{
  display: inline-block;
  width:50%;
  margin-top:50rpx;
  border:none;
  background:#fff;
}
.togroup:after{
  border:none;
}

.shareimg{
  width:30%;
}
.deleteTag{
  position:absolute;
  top:0;
  line-height:60rpx;
  font-size:60rpx;
  width:60rpx;
  height:60rpx;
  right:0rpx;
  color:#666;
}
.model{
  position:fixed;
  top:0;
  left:0;
  width:100%;
  height:100%;
  background:rgba(0,0,0,0.4);
  overflow:hidden;
  z-index:2;

}
.showmodel{
  display: block;
}
.hidemodel{
  display: none;
}
.share-image{
  width:520rpx;
  position:absolute;
  text-align:center;
  margin:auto;
  top:0;
  bottom:0;
  left:0;
  right:0;
  height:800rpx

}
.savetolocal{
  bottom:50rpx;
  position:absolute;
  background-color:#ff8134;
  color:white;
  width:80%;
  margin:auto;
  left:0;
  right:0;

}
.deleteTagShare{
  position:absolute;
  top:127rpx;
  line-height:40rpx;
  font-size:105rpx;
  width:113rpx;
  height:60rpx;
  right:35rpx;
  color:white;
  z-index:100;

}
.showimportant{
  position:fixed;
  top:0;
  left:0;
  width:100%;
  height:100%;
  background:rgba(0,0,0,0.4);
  overflow:hidden;
  z-index:2;
}

小伙伴们写到这一步,相信你们已经知道,保存图片需要用到canvas画图,不要慌,我这里给你准备好了已经封装好的代码,你只需要引入文件就可以了,接下来是划水时间!!!

这里引入文件我是在小程序页面配置文件json里面写的,只需要一句话搞定!

{
  "navigationBarTitleText": "砍价",
  "usingComponents": {
    "canvasdrawer": "/components/canvasdrawer/canvasdrawer"
  }
}

这里是components文件

//这里是js

/* global Component wx */

Component({
  properties: {
    painting: {
      type: Object,
      value: {view: []},
      observer (newVal, oldVal) {
        if (!this.data.isPainting) {
          if (JSON.stringify(newVal) !== JSON.stringify(oldVal)) {
            if (newVal && newVal.width && newVal.height) {
              this.setData({
                showCanvas: true,
                isPainting: true
              })
              this.readyPigment()
            }
          } else {
            if (newVal && newVal.mode !== 'same') {
              this.triggerEvent('getImage', {errMsg: 'canvasdrawer:samme params'})
            }
          }
        }
      }
    }
  },
  data: {
    showCanvas: false,

    width: 100,
    height: 100,

    index: 0,
    imageList: [],
    tempFileList: [],

    isPainting: false
  },
  ctx: null,
  cache: {},
  ready () {
    wx.removeStorageSync('canvasdrawer_pic_cache')
    this.cache = wx.getStorageSync('canvasdrawer_pic_cache') || {}
    this.ctx = wx.createCanvasContext('canvasdrawer', this)
  },
  methods: {
    readyPigment () {
      const { width, height, views } = this.data.painting
      this.setData({
        width,
        height
      })

      const inter = setInterval(() => {
        if (this.ctx) {
          clearInterval(inter)
          this.ctx.clearActions()
          this.ctx.save()
          this.getImageList(views)
          this.downLoadImages(0)
        }
      }, 100)
    },
    getImageList (views) {
      const imageList = []
      for (let i = 0; i < views.length; i++) {
        if (views[i].type === 'image') {
          imageList.push(views[i].url)
        }
      }
      this.setData({
        imageList
      })
    },
    downLoadImages (index) {
      const { imageList, tempFileList } = this.data
      if (index < imageList.length) {
        // console.log(imageList[index])
        this.getImageInfo(imageList[index]).then(file => {
          tempFileList.push(file)
          this.setData({
            tempFileList
          })
          this.downLoadImages(index + 1)
        })
      } else {
        this.startPainting()
      }
    },
    startPainting () {
      const { tempFileList, painting: { views } } = this.data
      for (let i = 0, imageIndex = 0; i < views.length; i++) {
        if (views[i].type === 'image') {
          this.drawImage({
            ...views[i],
            url: tempFileList[imageIndex]
          })
          imageIndex++
        } else if (views[i].type === 'text') {
          if (!this.ctx.measureText) {
            wx.showModal({
              title: '提示',
              content: '当前微信版本过低,无法使用 measureText 功能,请升级到最新微信版本后重试。'
            })
            this.triggerEvent('getImage', {errMsg: 'canvasdrawer:version too low'})
            return
          } else {
            this.drawText(views[i])
          }
        } else if (views[i].type === 'rect') {
          this.drawRect(views[i])
        }
      }
      this.ctx.draw(false, () => {
        wx.setStorageSync('canvasdrawer_pic_cache', this.cache)
        this.saveImageToLocal()
      })
    },
    drawImage (params) {
      this.ctx.save()
      const { url, top = 0, left = 0, width = 0, height = 0, borderRadius = 0 } = params
      // if (borderRadius) {
      //   this.ctx.beginPath()
      //   this.ctx.arc(left + borderRadius, top + borderRadius, borderRadius, 0, 2 * Math.PI)
      //   this.ctx.clip()
      //   this.ctx.drawImage(url, left, top, width, height)
      // } else {
      this.ctx.drawImage(url, left, top, width, height)
      // }
      this.ctx.restore()
    },
    drawText (params) {
      this.ctx.save()
      const {
        MaxLineNumber = 2,
        breakWord = false,
        color = 'black',
        content = '',
        fontSize = 16,
        top = 0,
        left = 0,
        lineHeight = 20,
        textAlign = 'left',
        width,
        bolder = false,
        textDecoration = 'none'
      } = params
      
      this.ctx.beginPath()
      this.ctx.setTextBaseline('top')
      this.ctx.setTextAlign(textAlign)
      this.ctx.setFillStyle(color)
      this.ctx.setFontSize(fontSize)

      if (!breakWord) {
        this.ctx.fillText(content, left, top)
        this.drawTextLine(left, top, textDecoration, color, fontSize, content)
      } else {
        let fillText = ''
        let fillTop = top
        let lineNum = 1
        for (let i = 0; i < content.length; i++) {
          fillText += [content[i]]
          if (this.ctx.measureText(fillText).width > width) {
            if (lineNum === MaxLineNumber) {
              if (i !== content.length) {
                fillText = fillText.substring(0, fillText.length - 1) + '...'
                this.ctx.fillText(fillText, left, fillTop)
                this.drawTextLine(left, fillTop, textDecoration, color, fontSize, fillText)
                fillText = ''
                break
              }
            }
            this.ctx.fillText(fillText, left, fillTop)
            this.drawTextLine(left, fillTop, textDecoration, color, fontSize, fillText)
            fillText = ''
            fillTop += lineHeight
            lineNum ++
          }
        }
        this.ctx.fillText(fillText, left, fillTop)
        this.drawTextLine(left, fillTop, textDecoration, color, fontSize, fillText)
      }
      
      this.ctx.restore()

      if (bolder) {
        this.drawText({
          ...params,
          left: left + 0.3,
          top: top + 0.3,
          bolder: false,
          textDecoration: 'none' 
        })
      }
    },
    drawTextLine (left, top, textDecoration, color, fontSize, content) {
      if (textDecoration === 'underline') {
        this.drawRect({
          background: color,
          top: top + fontSize * 1.2,
          left: left - 1,
          width: this.ctx.measureText(content).width + 3,
          height: 1
        })
      } else if (textDecoration === 'line-through') {
        this.drawRect({
          background: color,
          top: top + fontSize * 0.6,
          left: left - 1,
          width: this.ctx.measureText(content).width + 3,
          height: 1
        })
      }
    },
    drawRect (params) {
      this.ctx.save()
      const { background, top = 0, left = 0, width = 0, height = 0 } = params
      this.ctx.setFillStyle(background)
      this.ctx.fillRect(left, top, width, height)
      this.ctx.restore()
    },
    getImageInfo (url) {
      return new Promise((resolve, reject) => {
        if (this.cache[url]) {
          resolve(this.cache[url])
        } else {
          const objExp = new RegExp(/^http(s)?:\/\/([\w-]+\.)+[\w-]+(\/[\w- .\/?%&=]*)?/)
          if (objExp.test(url)) {
            wx.getImageInfo({
              src: url,
              complete: res => {
                if (res.errMsg === 'getImageInfo:ok') {
                  this.cache[url] = res.path
                  resolve(res.path)
                } else {
                  this.triggerEvent('getImage', {errMsg: 'canvasdrawer:download fail'})
                  reject(new Error('getImageInfo fail'))
                }
              }
            })
          } else {
            this.cache[url] = url
            resolve(url)
          }
        }
      })
    },
    saveImageToLocal () {
      const { width, height } = this.data
      wx.canvasToTempFilePath({
        x: 0,
        y: 0,
        width,
        height,
        canvasId: 'canvasdrawer',
        complete: res => {
          if (res.errMsg === 'canvasToTempFilePath:ok') {
            this.setData({
              showCanvas: false,
              isPainting: false,
              imageList: [],
              tempFileList: []
            })
            this.triggerEvent('getImage', {tempFilePath: res.tempFilePath, errMsg: 'canvasdrawer:ok'})
          } else {
            this.triggerEvent('getImage', {errMsg: 'canvasdrawer:fail'})
          }
        }
      }, this)
    }
  }
})

这里是json

{
  "component": true
}

 这里是wxml

<canvas canvas-id="canvasdrawer" style="width:{{width}}px;height:{{height}}px;" class="board" wx:if="{{showCanvas}}"></canvas>

//这里是wxss

.board {

position: fixed;

top: 2000rpx;

background-color: #fff;

}

好了,新鲜的两种分享就完成了,希望对你们有所帮助,欢迎dalao批评指正!!!整理不易,转发请附地址.

欢迎加微信object_1995交流哦!!!

猜你喜欢

转载自blog.csdn.net/weixin_42593599/article/details/84998717