小程序uniapp利用canvas生成海报并可以保存至相册

这篇具有很好参考价值的文章主要介绍了小程序uniapp利用canvas生成海报并可以保存至相册。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

✨uniapp实现生成海报并保存至相册组件,u-popup可以根据自己所使用的组件进行替换

这里主要讲的是JS部分,css和元素相关的就不展开赘述了,下方先给大伙看看效果图,图的下方有代码讲解,最下方有完整代码,如各位大神发现问题后请友好的交流勿喷。

⏳示例图

canvas转图片 小程序,小程序,微信小程序,uni-app,javascript,前端,微信小程序,vue.js

⏳ 图片引用

想要用cavans生成海报,首先要解决的是,将图片素材引入至canvas画布中,小程序的canvas没有办法直接使用网络图片,所以首先要把网络中的图片获取到,并已文件的格式存入内存中,利用uniapp的api简单的封装了一个获取图片的函数

// 下载图片
urlToFile(url) {
  return new Promise((resolve) => {
    uni.getImageInfo({
      src: url,
      success(res) {
        resolve(res.path)
      },
      fail(res) {
        console.log('fail -> res', res)
        uni.showToast({
          title: '网络异常',
          duration: 2000,
          icon: 'none'
        })
        this.$emit('close')
      }
    })
  })
},

⏳转换rpx

拿到图片后,还有个问题要处理,那就是尺寸,在小程序中用的rpx为样式的单位。但是在canvas中却没有rpx的单位,所以我们要处理一下px转为rpx,这样就能解决不同分辨率中,样式大小不同的问题。一样的一个简单的转换函数

// rpx转px
rpxToPx(rpx) {
  return (rpx / 750) * uni.getSystemInfoSync().windowWidth
},

⏳绘制函数

图片和单位的问题解决后,就要开始绘制海报了,这里需要根据ui效果图,去自行布局,本文档中只是作为一个例子。
在开发中发现canvas生成一倍图是比较模糊的,所以这里要定义一个倍数来放大canvas画布,使生成的图片更加的清晰,也就是代码中的canvasMultiplecanvasMultiple变量在data中有定义,如果有些变量看着不明白,可以先看最下方的完整代码

async creatCanvas() {
  if (this.posterImage) return
  // 创建canvas对象
  uni.showLoading({ title: '生成专属海报' })
  this.canvas = uni.createCanvasContext('canvas', this)
  // 这里是我自己的方法下载图片
  // canvas中的插入的图片不能是网络地址只能是下载到本地的
  const qrCode = await this.urlToFile(`${this.imgUrl}poster-code.png`)
  const imgBg = await this.urlToFile(`${this.imgUrl}poster-bg.png`)
  const logoIcon = await this.urlToFile(`${this.imgUrl}poster-logo.png`)
  const fontImage = await this.urlToFile(`${this.imgUrl}poster-font.png`)
  const { canvasMultiple, rpxToPx } = this
  // 插入背景图 第2 3 4 5参数单位是px的所以我们要做适配 rpx转换为px 可以自定义方法 也可以使用uniapp中的方法
  this.canvas.drawImage(imgBg, 0, 0, rpxToPx(590 * canvasMultiple), rpxToPx(976 * canvasMultiple))
  // 将二维码插入到canvas中
  this.canvas.drawImage(qrCode, rpxToPx(460 * canvasMultiple), rpxToPx(780 * canvasMultiple), rpxToPx(100 * canvasMultiple), rpxToPx(100 * canvasMultiple))
  // 插入logo
  this.canvas.drawImage(logoIcon, rpxToPx(74 * canvasMultiple), rpxToPx(114 * canvasMultiple), rpxToPx(84 * canvasMultiple), rpxToPx(64 * canvasMultiple))
  this.canvas.drawImage(fontImage, rpxToPx(80 * canvasMultiple), rpxToPx(334 * canvasMultiple), rpxToPx(351 * canvasMultiple), rpxToPx(53 * canvasMultiple))
  this.canvas.fillStyle = '#ffffff'
  this.canvas.strokeStyle = '#ffffff'
  // this.canvas.font = `bold ${rpxToPx(40)}px`
  this.canvas.font = `normal normal 500 40px 微软雅黑`
  this.canvas.setFontSize(rpxToPx(40 * canvasMultiple))
  this.canvas.fillText(this.nickName, rpxToPx(80 * canvasMultiple), rpxToPx(274 * canvasMultiple))
  this.canvas.font = `normal normal 600 26px 微软雅黑`
  this.canvas.setFontSize(rpxToPx(26 * canvasMultiple))
  this.canvas.fillText('立即扫码', rpxToPx(80 * canvasMultiple), rpxToPx(850 * canvasMultiple))
  this.canvas.fillStyle = 'rgba(255, 255, 255, 0.43)'
  this.canvas.strokeStyle = 'rgba(255, 255, 255, 0.43)'
  this.canvas.font = `normal normal 400 26px 微软雅黑`
  this.canvas.setFontSize(rpxToPx(26 * canvasMultiple))
  this.canvas.fillText('生成的热乎的海报', rpxToPx(80 * canvasMultiple), rpxToPx(900 * canvasMultiple))
  // 成功之后
  this.canvas.draw(true, () => {
    setTimeout(() => {
      // 将canvas转换成图片
      uni.canvasToTempFilePath({
        x: 0,
        y: 0,
        canvasId: 'canvas',
        fileType: 'png',
        quality: 1,
        success: (success) => {
          console.log('success', success)
          this.posterImage = success.tempFilePath
          uni.hideLoading()
          // this.canvas.draw()
        },
        fail: (e) => {
          uni.showToast({
            title: '海报生成失败',
            icon: 'none'
          })
          this.close()
          console.log('eeee', e)
        }
      }, this)
    }, 500)
  })
},

⏳保存至相册

小程序中提供了将图片保存至相册的能力,所以这里只需要把刚刚canvas绘制的海报图片,利用uniapp的saveImageToPhotosAlbum存至相册中就可以了。

savePoster() {
  console.log('savePoster', this.posterImage)
  uni.saveImageToPhotosAlbum({
    filePath: this.posterImage,
    success: () => {
      // uni.hideLoading();
      uni.showToast({
        title: '保存成功',
        icon: 'none'
      })
      this.close()
    },
    fail: () => {
      uni.hideLoading()
      this.$toast({ title: '相册功能未授权,无法保存' })
    },
    complete: () => {

    }
  })
}

⏳至此生成海报并可以保存至相册的函数都已经完成,组装至一起既可以完成需求

完整代码

<template>
    <u-popup :show="displayPoster" mode="center"  @close="close" :overlayOpacity="0.8" :closeOnClickOverlay="true" :safeAreaInsetBottom="false">
        <view :class="posterImage ? 'poster' : 'poster-hidden'">
            <canvas v-if="posterImage === ''" canvas-id="canvas" class="poster-canvas" :style="{width:'1180rpx',height: '1952rpx'}"></canvas>
            <template v-if="posterImage">
                <image class="poster-image" :src="posterImage"></image>
                <view class="save-btn">
                    <u-button :customStyle="saveButtonStyle" type="primary" text="保存海报" @click.stop="savePoster"></u-button>
                </view>
            </template>
            <view class="close-icon" v-if="posterImage" @click.stop = "close" >
                <image class="icon" :src="imgUrl+'close-white.png'"></image>
            </view>
        </view>
    </u-popup>
</template>

<script>
export default {
  name: 'PosterDialog',
  props: {
    displayPoster: {
      type: Boolean,
      required: true
    }
  },
  data() {
    return {
      imgUrl: `${_SWF_CONFIG.TEMPLATE_URL}${_SWF_CONFIG.TEMPLATE_PATH}/images/`,
      canvasMultiple: 2,
      saveButtonStyle: {
        background: '#0C1C2B',
        border: '1px solid #0C1C2B',
        width: '280rpx',
        height: '88rpx',
        fontSize: '32rpx',
        fontWeight: '500'
      },
      posterImage: '',
      nickName: ''
    }
  },
  watch: {
    displayPoster: {
      handler(newValue) {
        console.log('newValue', newValue)
        const { displayName } = uni.getStorageSync('userInfo')
        this.nickName = displayName
        console.log('nickName', this.nickName)
        if (newValue) {
          this.creatCanvas()
        }
      },
      immediate: true
    }
  },
  methods: {
    async creatCanvas() {
      if (this.posterImage) return
      // const that = this
      // 创建canvas对象
      uni.showLoading({ title: '生成专属海报' })
      this.canvas = uni.createCanvasContext('canvas', this)
      // 这里是我自己的方法下载图片
      // canvas中的插入的图片不能是网络地址只能是下载到本地的
      const qrCode = await this.urlToFile(`${this.imgUrl}poster-code.png`)
      const imgBg = await this.urlToFile(`${this.imgUrl}poster-bg.png`)
      const logoIcon = await this.urlToFile(`${this.imgUrl}poster-logo.png`)
      const fontImage = await this.urlToFile(`${this.imgUrl}poster-font.png`)
      const { canvasMultiple, rpxToPx } = this
      // 插入背景图 第2 3 4 5参数单位是px的所以我们要做适配 rpx转换为px 可以自定义方法 也可以使用uniapp中的方法
      this.canvas.drawImage(imgBg, 0, 0, rpxToPx(590 * canvasMultiple), rpxToPx(976 * canvasMultiple))
      // 将二维码插入到canvas中
      this.canvas.drawImage(qrCode, rpxToPx(460 * canvasMultiple), rpxToPx(780 * canvasMultiple), rpxToPx(100 * canvasMultiple), rpxToPx(100 * canvasMultiple))
      // 插入logo
      this.canvas.drawImage(logoIcon, rpxToPx(74 * canvasMultiple), rpxToPx(114 * canvasMultiple), rpxToPx(84 * canvasMultiple), rpxToPx(64 * canvasMultiple))
      this.canvas.drawImage(fontImage, rpxToPx(80 * canvasMultiple), rpxToPx(334 * canvasMultiple), rpxToPx(351 * canvasMultiple), rpxToPx(53 * canvasMultiple))
      this.canvas.fillStyle = '#ffffff'
      this.canvas.strokeStyle = '#ffffff'
      // this.canvas.font = `bold ${rpxToPx(40)}px`
      this.canvas.font = `normal normal 500 40px 微软雅黑`
      this.canvas.setFontSize(rpxToPx(40 * canvasMultiple))
      this.canvas.fillText(this.nickName, rpxToPx(80 * canvasMultiple), rpxToPx(274 * canvasMultiple))
      this.canvas.font = `normal normal 600 26px 微软雅黑`
      this.canvas.setFontSize(rpxToPx(26 * canvasMultiple))
      this.canvas.fillText('立即扫码', rpxToPx(80 * canvasMultiple), rpxToPx(850 * canvasMultiple))
      this.canvas.fillStyle = 'rgba(255, 255, 255, 0.43)'
      this.canvas.strokeStyle = 'rgba(255, 255, 255, 0.43)'
      this.canvas.font = `normal normal 400 26px 微软雅黑`
      this.canvas.setFontSize(rpxToPx(26 * canvasMultiple))
      this.canvas.fillText('生成的热乎的海报', rpxToPx(80 * canvasMultiple), rpxToPx(900 * canvasMultiple))
      // 成功之后
      this.canvas.draw(true, () => {
        setTimeout(() => {
          // 讲canvas转换成图片
          uni.canvasToTempFilePath({
            x: 0,
            y: 0,
            canvasId: 'canvas',
            fileType: 'png',
            quality: 1,
            success: (success) => {
              console.log('success', success)
              this.posterImage = success.tempFilePath
              uni.hideLoading()
              // this.canvas.draw()
            },
            fail: (e) => {
              uni.showToast({
                title: '海报生成失败',
                icon: 'none'
              })
              this.close()
              console.log('eeee', e)
            }
          }, this)
        }, 500)
      })
    },
    // rpx转px
    rpxToPx(rpx) {
      return (rpx / 750) * wx.getSystemInfoSync().windowWidth
    },
    // 下载图片
    urlToFile(url) {
      return new Promise((resolve) => {
        uni.getImageInfo({
          src: url,
          success(res) {
            resolve(res.path)
          },
          fail(res) {
            console.log('fail -> res', res)
            uni.showToast({
              title: '网络异常',
              duration: 2000,
              icon: 'none'
            })
            this.$emit('close')
          }
        })
      })
    },
    close() {
      this.$emit('close')
    },
    savePoster() {
      console.log('savePoster', this.posterImage)
      uni.saveImageToPhotosAlbum({
        filePath: this.posterImage,
        success: () => {
          // uni.hideLoading();
          uni.showToast({
            title: '保存成功',
            icon: 'none'
          })
          this.close()
        },
        fail: () => {
          uni.hideLoading()
          this.$toast({ title: '相册功能未授权,无法保存' })
        },
        complete: () => {

        }
      })
    }
  }
}
</script>

<style scoped lang="scss">
.poster{
  width: 590rpx;
  height: 976rpx;
  position: relative;
}
.close-icon{
  width: 54rpx;
  height: 54rpx;
  position: absolute;
  display: flex;
  justify-content: center;
  align-items: center;
  top: 0;
  right: 0;
  background: rgba(43,47,54,.5);
  .icon{
    width: 35rpx;
    height: 35rpx;
  }
}
.poster-hidden{
  width: 0rpx;
  height: 0rpx;
  overflow: hidden;
}
.save-btn{
  position: absolute;
  left: calc(50% - 140rpx);
  bottom: -130rpx;
}
.poster-canvas{
  transform: translateY(99999999999999rpx);
}
.poster-image{
  width: 590rpx;
  height: 976rpx;
}
</style>

⏳看到上方代码,先是利用canvas生成图片,将图片用image标签展示出来,cavans元素移除屏幕外,这里可能有疑问为什么要这么做?直接用canvas元素来展示图片不好吗?为什么要用canvas生成的图片来显示呢?

⏳这么做的原因其实是因为canvas在抖音小程序,微信小程序部分真机中没有动画过渡,当弹窗关闭时比较突兀,当然如果需求中没有动画过渡的要求,就不需要多这一步。文章来源地址https://www.toymoban.com/news/detail-607980.html

🎇感谢大家阅读,如有帮助或问题欢迎给赞👍和讨论

到了这里,关于小程序uniapp利用canvas生成海报并可以保存至相册的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • 小程序生成分享海报图片并保存相册

    最近开发的小程序都有分享需求,功能大体为点击分享按钮,或主动生成海报后,用户操作保存对应海报为图片实现分享。以下是具体实现。 最终生成效果如图: 此处主要是生成工具库来生成普通二维码,如果要生成小程序码,只能通过后台接口调用开放API实现,且需要小

    2024年02月16日
    浏览(68)
  • 小程序使用canvas标签生成海报并保存图片

    先说一下做功能前的感受,简直一脸懵逼,第一次用canvas,只知道是个画布,其余什么都不知道…琢磨了一天才画出来… 开始之前百度了很久,想看看别人怎么写的,但是目前网上基本上用的都是wx.createCanvasContext这个api,但是这个api已经停止维护了,要求使用canvas代替,  

    2024年02月11日
    浏览(76)
  • uniapp小程序使用canvas绘制内容并保存到本地相册

    需求: 根据不同用户自动生成对应证书,并且可以下载该证书(下载后得到的是一张图片),故要想实现该功能,则需要借助canvas将动态生成的内容绘制到页面中,然后再实现下载功能。 1.html代码 页面很简单,只包含一个canvas和下载按钮即可。 2.js代码 3.效果图展示 注:下

    2024年02月09日
    浏览(42)
  • 微信小程序-生成canvas图片并保存到手机相册

    wxml页面 wxss页面 js代码

    2024年02月10日
    浏览(55)
  • uniapp 微信小程序 动态生成海报分享朋友圈,需先保存图片

    直接拷贝代码,不使用插件,自己纯代码实现。 从相册 或拍照 选择一个图片做海报背景。 大吉大利 今晚吃鸡。

    2024年02月11日
    浏览(90)
  • 小程序-Taro如何实现利用Canvas生成一个二维码以及保存图片

    不多说,直接看代码和文字见解: 第一步:先安装weapp-qrcode,利用一个函数触发drawQrcode的方法生成一个二维码Canvas   到这一步其实你的二维码几乎成型了,但是你还有要把它给展示出来 第二步:调用Taro.canvasToTempFilePath的Taro文档的方法,他是用来将Canvas转换为临时路径的图

    2024年02月12日
    浏览(61)
  • 微信小程序生成海报图片导出相册

    小程序内通过静态模板和样式绘制 canvas ,导出图片,可用于生成分享图等场景 https://developers.weixin.qq.com/miniprogram/dev/platform-capabilities/extended/component-plus/wxml-to-canvas.html 小程序内通过静态模板和样式绘制 canvas ,导出图片,可用于生成分享图等场景。代码片段 Step1. npm 安装,参

    2024年02月08日
    浏览(56)
  • 微信小程序canvas画布图片保存到相册官方授权、自定义授权、保存

    目录 关键步骤介绍 Component实现自定义授权弹框 wx.getSetting可以获取授权信息。 wx.authorize首次授权时会打开弹框让用户授权,若用户已选择同意或拒绝,后续不会再显示授权弹框。 如果授权信息显示未进行相册授权,则打开自定义弹框(show_auth: true)让用户选择是否自行配置

    2024年01月16日
    浏览(43)
  • uniapp 使用canvas画海报(微信小程序)

    效果展示:  项目要求:点击分享绘制海报,并实现分享到好友,朋友圈,并保存 先实现绘制海报   下面是海报下面的分享弹窗 因为分享到朋友圈实在没找到有使用自定义按钮的可能,所以还是需要点击右上角胶囊    以上就是画海报以及分享的全部过程了,另有一个点:

    2024年02月13日
    浏览(61)
  • 小程序离屏canvas(createOffscreenCanvas)生成推广海报

    离屏canvas调用wx.canvasToTempFilePath报错 Failed to execute ‘drawImage’ on ‘CanvasRenderingContext2D’: The provided value is not of type \\\'(CSSImageValue or HTMLImageElement or SVGImageElement or HTMLVideoElement or HTMLCanvasElement or ImageBitmap or OffscreenCanvas) 开发者工具版本:稳定版1.05.2204180(windows) 调试基础库版本

    2024年02月10日
    浏览(39)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包