Taro 做小程序如何生成海报,以及使用全局鉴权和按钮级别的鉴权

699 阅读2分钟

1. taro使用painter做海报的生成

Taro 版本2.2.8,插件版本mina-painter": "^2.2.5

github.com/Kujiale-Mob…

其实也是基于github.com/Kujiale-Mob…

image.png

生成海报js代码片段 注意单位这里需要rpx

onImgOK=(path)=>{
    this.setState({imagePath:path},()=>{
      Taro.hideLoading()
    })
}

createPoster=async ()=>{//生成海报
  Taro.showLoading({icon:'loading',title:'海报生成中'});
  let user=getStorage(`${process.env.USERINFO}`)&&JSON.parse(getStorage(`${process.env.USERINFO}`));
    let {path,id}= await getMiNiCode({//获取小程序码
        shareDealerId:getShareDealerId(),
        activityId:`${process.env.ACTIVITYID}`})
        
    let json={
      width: `1125rpx`, // ui给的海报背景图实际的 宽
      height: `2436rpx`,// ui给的海报背景图实际的 高
      background: `${process.env.BASE_URL}/store/411activity/poster7.png`,
      views: [
        { 
          id:'avator',
          type: 'image',
          url: user&&user.wxUser.avatar,//头像
          css: {
            top: `50rpx`,
            left: `50rpx`,
            width: `120px`,
            height:`120px`,
            mode: 'aspectFill',
            borderRadius: '100%',
            borderWidth: '4rpx',
            borderColor: '#FFFFFF',
            // bottom: '0rpx',
            // right:'0rpx'
          },
        },
        {
          id:'nameTxtId',
          type: 'text',
          text:user&&user.wxUser.nick,
          // text:'我是一个名字',
          css: {
            // width:'180rpx',
            left: `calc(avator.width + 80rpx)`,
            top: `calc(avator.top + 60rpx)`,
            fontSize: `90rpx`,
            fontWeight:600,
            textAlign:'center',
            color:'#333'
          },
        },
        {
          id:'ImageId',
          type: 'image',
          url: path,
          css: {
            width: `220px`,
            height:`220px`,
            // borderRadius: '100%',
            mode: 'aspectFill',
            bottom: '140rpx',
            // borderWidth: '4rpx',
            // borderColor: '#e4393c',
            right:'220rpx',
            // left:'calc(100% / 2 - 100 )'
          }
        },
        // {
        //   type: 'text',
        //   text:'活动时间:5月1号-30号',
        //   // text:'我是一个名字',
        //   css: {
        //     // width:'180rpx',
        //     left:'calc(100% / 2 - 150)',
        //     bottom: `50rpx`,
        //     fontSize: `60rpx`,
        //     fontWeight:600,
        //     textAlign:'center',
        //     color:'#333'
        //   },
        // },
      ],
    }
    this.setState({template:json})
  }

视图部分代码片段

<Painter
      customStyle='position: absolute; left: -9999rpx;' 
      palette={template}
      // dirty={true}
      widthPixels="1000" // 同下scaleRatio一样的效果都是保证图片不失真,保证图片清晰
      // scaleRatio={2} 
      onImgOK={(e)=>this.onImgOK(e)}
  />
  {
    imagePath&&<View className='create_poster'>
                    <Poster imagePath={imagePath} onclose={()=>this.close()}/>
                </View>
  }

Poster组件

要保证生成的图片不失真,又要一屏可以显示,这里做等比缩放 我这里是设计稿的实际宽度和高度缩放0.45倍,根据自己需求

<View className='Poster'>
<Image src={imagePath} className='img' mode="widthFix" style="height:1096rpx;width:506rpx;" />
</View>

2路由的全局鉴权

通常我们有很多路由的访问需要权限的,小程序也没像vue那种路由守卫,如果全部依赖接口401就会存在多余的请求,这里用高阶函数劫持当前页面的生命周期。

1在页面中建utils文件与pages同级 utils中建isLogin.js

这里全局的分享也可以用传入不同的参数做不同的页面的分享,也是用到这种高阶去劫持生命周期

getCurrentPageUrlWithArgs的作用是保证连接上传入的回掉的参数不丢失/pages/index/index?backUrl=/pages/xxx/xxx?a=1&b=1 此种场景是我们登录完成后的回调路由依然保证参数的存在

export const needAuth=()=>{
  let url=getCurrentPageUrlWithArgs();
  Taro.reLaunch({url:`/pages/neddAuth/index?urlbackUrl=${encodeURIComponent(url)}`});
}

使用 let {backUrl}=this.$router.params; let urlbackUrl=decodeURIComponent(urlbackUrl); 这里要解码

export const getCurrentPageUrlWithArgs=()=> {
  const pages = Taro.getCurrentPages()
  const currentPage = pages[pages.length - 1]
  const url = currentPage.route
  const options = currentPage.options
  let urlWithArgs = `/${url}?`
  for (let key in options) {
    const value = options[key]
    urlWithArgs += `${key}=${value}&`
  }
   urlWithArgs = urlWithArgs.substring(0, urlWithArgs.length - 1);
   return urlWithArgs;
}
// isLogin.js
import Taro from '@tarojs/taro'
import {getStorage,getCurrentPageUrlWithArgs} from './tools'
function isLogin() {
    return function Component(Component) {
        return class extends Component {
        constructor (props){
            super(props);
        }
        //onLoad
        // componentDidShow(){
          
        // }
        componentWillMount(){
            //初始分享信息
            // initShareMenu(this.state);
        }
        
        //阻塞 didMount , 鉴权
         componentDidMount() {
            let token=getStorage(`${process.env.TOKEN}`);
            //授权成功
            if( token){
                //调用父组件的函数
                super.componentDidMount && super.componentDidMount();
            }else{
               Taro.redirectTo({url:`/pages/login/index?url=${encodeURIComponent(url)}`});
            }
        }
         
        // //重写分享
        // onShareAppMessage(){
        //     let shareOptions = super.onShareAppMessage();
        //     //如果当前页面配置分享使用配置的
        //     if( shareOptions ) return shareOptions;
        //     //默认分享
        //     return {
        //         title : '默认分享内容'
        //     }
        // }
 
    //     //重新下拉刷新
    //     onPullDownRefresh(){
    //         if(super.onPullDownRefresh){
    //             super.onPullDownRefresh();
    //             setTimeout(() => {
    //                 Taro.stopPullDownRefresh();
    //             }, 1500)
    //         }
    //     }
    }
 }
}
 
export default isLogin;

2组件中的使用

import isLogin from '@/utils/isLogin'
@isLogin() //这里面也可以传入参数
export default class Index extends Component {

}

这里和接口401都会先进入这个页面才会触发生命周期,所以看到的就会有闪一下再进到登录页,如果有好的方式也希望大佬告知

3 按钮的路由鉴权

很多时候页面有多个按钮都需要登录才能操作,taro也不能像vue提供自定义的指令做按钮的鉴权

//这里传入一个回调去做按钮鉴权的操作
export  const butNeedLogin=(callBack)=>{
  let url=getCurrentPageUrlWithArgs();
  if(!getStorage(`${process.env.TOKEN}`)){
    Taro.redirectTo({url:`/pages/login/index?url=${encodeURIComponent(url)}`});
  }else{
    if(typeof callBack === "function"){
      callBack()//这里是回调的逻辑
    }
  }
}

也可以对路由跳转方式进行重写 举2个例子

import Taro from '@tarojs/taro'
// 打开新页面并跳转
function navigateTo(url, params) {
  //这里做路由的加载
  const avtor = Taro.getStorageSync('avtor');
  const paramsStr = handleParams(params)
  url = avtor ? url + paramsStr : `/pages/login/index?backUrl=${url}`
  Taro.navigateTo({
    url
  })
}

// 关闭当前页面并跳转新的页面
function redirectTo(url, params) {
  const paramsStr = handleParams(params)
  Taro.redirectTo({
    url: url + paramsStr
  })
}