美文网首页
小程序初体验

小程序初体验

作者: 好奇的猫猫猫 | 来源:发表于2018-08-21 15:55 被阅读0次

    要求实现一个日签功能,提供一个背景图片集合,文案集合,点击按钮可随机组合,形成一张海报,可支持下载。

    功能点:

    1. 点击换个背景按钮,随机替换图片
    2. 点击换个灵感按钮,随机替换文案
    3. 右下角logo可以由用户选择上传,并需要裁剪,裁剪宽高比1:1
    4. 点击下载海报,将图片生成保存到相册

    第一次接触小程序,花了将近一周的时间写出了两个页面,一个是首页,一个是预览海报页面,如下图。还包括上面提到的一些功能实现。

    首页
    点击预览,跳转到预览页面
    预览页
    页面搭建没太多要说的,只要能够灵活使用定位,浮动和层级这些,很快就能把样式搭出来。我们来着重说下功能。
    功能描述
    当点击换个背景时,中间区域的图片会随机更换,点击换个背景时,图片下方的文字也会随机更换,这两个功能其实是一个功能,实现方式一样,就是随机获取data中的图片数组和文字数组的下标,再渲染到页面上,我是这么实现的
    data:
    imgUrls: [
    
          'http://img02.tooopen.com/images/20150928/tooopen_sy_143912755726.jpg',
          'http://img06.tooopen.com/images/20160818/tooopen_sy_175866434296.jpg',
          'http://img06.tooopen.com/images/20160818/tooopen_sy_175833047715.jpg'],
        imgIndex:0,   
        texts:[
            '早上叫我起床的不是贫穷而是闹钟',
            '人所缺乏的不是才干而是志向。',
            '勇敢坚毅真正之才智乃刚毅之志向。',
          ],
        textIndex:0,
    

    函数实现

    //实现换个背景功能
      changeBg:function(e){
      
        var imgIndex=Math.floor(Math.random() * this.data.imgUrls.length)
        
        console.log('图片选择改变,携带值为',this.data.imgIndex=imgIndex,this.data.imgUrls[imgIndex])
        this.setData({
          imgIndex:imgIndex
        })
        console.log(this.data.imgIndex);
      },
    //实现换个灵感功能
      changeMind:function(e){
        
        var textIndex=Math.floor(Math.random() * 3)
        
        console.log('文字选择改变,携带值为',this.data.textIndex=textIndex)
        this.setData({
          textIndex:this.data.textIndex
        })
      },
    

    在index.wxml页面通过bindtap='函数名'来调用函数
    在前端页面是这样取到js获得的数据

    <view class="bgImg">
                          <block range= "{{imgUrls}}" value = "{{imgIndex}}">
                              
                                 <image src="{{imgUrls[imgIndex]}}" class="slide-image"/>
                               
                          </block>
                                   
                </view>
                <view class="text">
                        <block range= "{{texts}}" value = "{{textIndex}}">
                              
                               {{texts[textIndex]}}
                              
                         </block>
                </view>
    

    好啦,这样就实现了两个功能!
    在开始第三个功能时,我发现文字左下角还要获取当天的日期,毕竟是日签嘛。
    在小程序中,新建项目时,就会有一个utils.js文件,就是获取日期和时间的
    但这里只要日期,于是我修改了一下
    util.js

    const formatTime = date => {
      const year = date.getFullYear()
      const month = date.getMonth() + 1
      const day = date.getDate()
      const hour = date.getHours()
      const minute = date.getMinutes()
      const second = date.getSeconds()
    
      return [month, day].map(formatNumber).join('-')
    }
    
    const formatNumber = n => {
      n = n.toString()
      return n[1] ? n : '0' + n
    }
    
    module.exports = {
      formatTime: formatTime
    }
    
    

    在index.js的onload函数里

     var time = util.formatTime(new Date());
        this.setData({
          time:time
        });
    

    index.wxml

    <view class="time">{{time}}</view>
    

    改一改样式,就可以在自己想要的位置显示日期啦~
    实现第三个函数时,在右下角logo那里绑定一个点击事件,调用上传函数
    index.wxml

    <image class="camera" src="{{smallImg}}" bindtap='upload'></image>
    

    index.js

    //从本地上传图片
      upload () {
        wx.chooseImage({
          count: 1, // 默认9
          sizeType: ['original', 'compressed'], // 可以指定是原图还是压缩图,默认二者都有
          sourceType: ['album', 'camera'], // 可以指定来源是相册还是相机,默认二者都有
          success (res) {
            const src = res.tempFilePaths[0]
    
            wx.redirectTo({
              url: `../upload/upload?src=${src}`//将该图片的临时路径传到upload.js里
            })
          }
        })
      },
    

    利用wx.redirectTo重定向到upload页面


    upload.png

    upload.wxml

    <import src="../../we-cropper/we-cropper.wxml"/>
    
    <view class="cropper-wrapper">
        <template is="we-cropper" data="{{...cropperOpt}}"/>
        <view class="cropper-buttons">
            <view
                    class="upload"
                    bindtap="uploadTap">
                重新选择
            </view>
            <view
                    class="getCropperImage"
                    bindtap="getCropperImage">
                确定
            </view>
        </view>
    </view>
    

    upload.js

    import WeCropper from '../../we-cropper/we-cropper.js'
    
    const device = wx.getSystemInfoSync()
    const width = device.windowWidth
    const height = device.windowHeight - 50
    
    Page({
      data: {
        cropperOpt: {
          id: 'cropper',
          width,
          height,
          scale: 2.5,
          zoom: 8,
          cut: {
            x: (width - 100) / 2,
            y: (height - 100) / 2,
            width: 100,
            height: 100
          }
        }
      },
      touchStart (e) {
        this.wecropper.touchStart(e)
      },
      touchMove (e) {
        this.wecropper.touchMove(e)
      },
      touchEnd (e) {
        this.wecropper.touchEnd(e)
      },
      getCropperImage () {
        this.wecropper.getCropperImage((avatar) => {
          if (avatar) {
            //  获取到裁剪后的图片
            wx.redirectTo({
              url: `../index/index?imgSrc=${avatar}`
            })
          } else {
            console.log('获取图片失败,请稍后重试')
          }
        })
      },
      uploadTap () {
        const self = this
    
        wx.chooseImage({
          count: 1, // 默认9
          sizeType: ['original', 'compressed'], // 可以指定是原图还是压缩图,默认二者都有
          sourceType: ['album', 'camera'], // 可以指定来源是相册还是相机,默认二者都有
          success (res) {
            const src = res.tempFilePaths[0]
            //  获取裁剪图片资源后,给data添加src属性及其值
    
            self.wecropper.pushOrign(src)
          }
        })
      },
      onLoad (option) {
        const { cropperOpt } = this.data
    
        if (option.src) {
          cropperOpt.src = option.src
          new WeCropper(cropperOpt)
            .on('ready', (ctx) => {
              console.log(`wecropper is ready for work!`)
            })
            .on('beforeImageLoad', (ctx) => {
              console.log(`before picture loaded, i can do something`)
              console.log(`current canvas context:`, ctx)
              wx.showToast({
                title: '上传中',
                icon: 'loading',
                duration: 20000
              })
            })
            .on('imageLoad', (ctx) => {
              console.log(`picture loaded`)
              console.log(`current canvas context:`, ctx)
              wx.hideToast()
            })
            .on('beforeDraw', (ctx, instance) => {
              console.log(`before canvas draw,i can do something`)
              console.log(`current canvas context:`, ctx)
            })
            .updateCanvas()
        }
      }
    })
    

    这里用到了cropper裁剪插件

    cropper
    具体代码就不放上来了,你们可以自己看
    we-cropper插件是网上GitHub大神写的,
    项目地址:
    到这里就完成了前三个功能,最后一个绘图并下载海报花了我两天的时间才做好,有些麻烦。
    要画中间区域的部分,有三张图片和3段文字
    index.js
        //得到三张图片的信息
      let promise1 = new Promise(function (resolve,reject)
      {
        console.log('00000');
        wx.getImageInfo({
          src:'../../images/招生赢家2@2x.png',
          success:function(res){
            console.log(res)
            resolve(res);
          }
        })
      });
        let promise2 = new Promise(function(resolve,reject){
          console.log(that.data.imgIndex);
          
          wx.getImageInfo({
            src:that.data.imgUrls[that.data.imgIndex],
            success:function(res){
              console.log(res)
              resolve(res);
            }
          })
        });
        let promise3 = new Promise(function(resolve,reject){
          wx.getImageInfo({
            src:that.data.smallImg,
            success:function(res){
              console.log(res)
              resolve(res);
            }
          })
        });
        //成功得到图片信息后,开始绘图
        Promise.all([
          promise1,promise2,promise3
        ]).then(res => {
          // console.log('11111');
        //如果为网络图片,最好先执行下载操作
          wx.downloadFile({
            
            url: that.data.imgUrls[that.data.imgIndex],
            success: function (res) {
              that.setData({
                canvasimgbg: res.tempFilePath
              })
       
            }
          })
      
          console.log(res)
          const ctx = wx.createCanvasContext('shareImg')
          console.log('ctx'+ctx)
          ctx.setFillStyle('white')
          ctx.fillRect(0, 0, 600, 732);
          ctx.drawImage('../../images/招生赢家2@2x.png',8,5,243,21)//相对于canvas
          ctx.drawImage(that.data.imgUrls[that.data.imgIndex],15,65,228,152)
          ctx.drawImage(that.data.smallImg,197,270,37,37)//相对于父容器
          
          ctx.setTextAlign('left')
          // ctx.setFillStyle('white')
          ctx.setFontSize(16)
          
          // console.log('222222');
          ctx.setFillStyle('black')
          ctx.fillText('——  满天星教育培训机构  ——',18,55)
          //使文字换行显示
          const textHeight = that.fillTextWrap(ctx,that.data.texts[that.data.textIndex],15,240,200)
               
          ctx.setFillStyle('red');
          ctx.fillText(that.data.time,14,300)
                
          ctx.stroke()
          ctx.draw()
        })
    

    在canvas里是不支持对文本的换行的,所以要自己写方法来实现换行,下面的方法实现是我借鉴的大神的方法,你们自己也可以在网上找到,懒得找可以把我这个直接拿过去,就可以实现

    // 文字换行
    fillTextWrap(ctx, text, x, y, maxWidth, lineHeight) {
      // 设定默认最大宽度
      const systemInfo = wx.getSystemInfoSync();
      const deciveWidth = systemInfo.screenWidth;
      // 默认参数
      maxWidth = maxWidth || deciveWidth;
      lineHeight = lineHeight || 20;
      // 校验参数
      if (typeof text !== 'string' || typeof x !== 'number' || typeof y !== 'number') {
        return;
      }
      // 字符串分割为数组
      const arrText = text.split('');
      // 当前字符串及宽度
      let currentText = '';
      let currentWidth;
      for (let letter of arrText) {
        currentText += letter;
        currentWidth = ctx.measureText(currentText).width;
        if (currentWidth > maxWidth) {
          ctx.fillText(currentText, x, y);
          currentText = '';
          y += lineHeight;
        }
      }
      if (currentText) {
        ctx.fillText(currentText, x, y);
      }
    }
    

    canvas里有很多方法可以用,比如drawImage,setFillStyle等,用到的时候可以自行去小程序官方文档
    下面是下载和分享功能的实现
    index.js

      //将绘图结果显示出来
    share:function(){
      var that = this;
      // console.log(that.data.imgIndex);
      
      wx.showLoading({
        title:'努力生成中...'
      })
      
      
      wx.canvasToTempFilePath({
        x:0,
        y:0,
        width:600,
        height:732,
        destWidth: 600,
        destHeight: 732,
        canvasId:'shareImg',
        success:function(res){
          // console.log('res.tempFilePath'+res.tempFilePath);
          that.setData({
            preurl:res.tempFilePath,
            previewHidden:false,
            
         
          })
          wx.hideLoading()
        },
        fail:function(res){
          console.log(res)
        }
      })
    },
    
    /**
       * 保存到相册
      */
     save: function () {
      var that = this
      // 生产环境时 记得这里要加入获取相册授权的代码
      // 可以通过 wx.getSetting 先查询一下用户是否授权了 "scope.writePhotosAlbum" 这个 scope
      wx.getSetting({
        success(res) {
          if (!res.authSetting['scope.writePhotosAlbum']) {
            wx.authorize({
              scope: 'scope.writePhotosAlbum',
              success() {
                // 用户已经同意小程序相册功能,后续调用 wx.saveImageToPhotosAlbum 接口不会弹窗询问
                that.startSaveImage()
              }
            })
          }else{
            that.startSaveImage()
          }
        }
      })
    
    },
    
    startSaveImage: function () {
      let that = this; 
      wx.saveImageToPhotosAlbum({
        filePath: that.data.preurl,
        success(res) {
          wx.showModal({
            content: '图片已保存到相册,赶紧晒一下吧~',
            showCancel: false,
            confirmText: '好哒',
            confirmColor: '#72B9C3',
            success: function (res) {
              if (res.confirm) {
                console.log('用户点击确定');
                that.setData({
                  previewHidden: true
                })
              }
            }
          })
        }
      })
    },
    

    index.wxml

      <!-- 画布大小按需定制  -->
                <canvas canvas-id="shareImg" style="width:600rpx;height:732rpx"></canvas>
      
          <!-- 预览区域  -->
                <view hidden='{{previewHidden}}' class='preview'>
                <image src='{{preurl}}' mode='widthFix' class='previewImg'></image>
                <button type='primary' bindtap='save'>保存分享图</button>
                </view>
        <!-- 预览与下载start -->
          <view class="fore_down">
           
                <button class="foresee" bindtap='foreseePage'>预览海报</button>
                <button class="download" bindtap='share'>下载海报</button>
           
          </view>
    

    到这里,全部功能都实现啦!!!
    希望大家指正~~~

    相关文章

      网友评论

          本文标题:小程序初体验

          本文链接:https://www.haomeiwen.com/subject/uqdjiftx.html