小程序初体验

2018-08-21  本文已影响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>

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

上一篇下一篇

猜你喜欢

热点阅读