从0开始的canvas学习(二)

3 篇文章 0 订阅

本文将讲到微信小程序画布和html设置向画布中导入图片和获取视频某帧以及导出图片

向画布上面加载图片drawImage会用到这个api

首先先看看官方怎么说

image.png

image.png

一、html

首先要等把图片加载完成后再调用这个api总体还是蛮简单的

<canvas id="myCanvas"></canvas>
<script>
    var ctx = myCanvas.getContext('2d')
    var myImage = new Image()
    myImage.src = 'https://sf1-ttcdn-tos.pstatp.com/img/user-avatar/56a409021bf987376f220b475cd7a024~300x300.image'
    myImage.onload = function () {
        myCanvas.width = myImage.width
        myCanvas.height = myImage.height
        ctx.drawImage(myImage, 0, 0, myImage.width, myImage.height)
    }
</script>

效果

image.png

导出图片
var ctx = myCanvas.getContext('2d')
var myImage = new Image()
myImage.src = 'https://sf1-ttcdn-tos.pstatp.com/img/user-avatar/56a409021bf987376f220b475cd7a024~300x300.image'
myImage.onload = function () {
    myCanvas.width = myImage.width
    myCanvas.height = myImage.height
    ctx.drawImage(myImage, 0, 0, myImage.width, myImage.height)
    myCanvas.toDataURL("image/png")
}

image.png

在执行时报错告诉你画布被污染了 这个是图片跨域导致 如果来自于同一个服务的话就不会有这个问题了
如果不在同一服务器上时解决办法myImage.crossOrigin = 'Anonymous'


<canvas id="myCanvas"></canvas>
<img id="showImage" />
<script>
    var ctx = myCanvas.getContext('2d')
    var myImage = new Image()
    myImage.src = 'https://sf1-ttcdn-tos.pstatp.com/img/user-avatar/56a409021bf987376f220b475cd7a024~300x300.image'
    myImage.crossOrigin = 'Anonymous' // 新增了这一行
    myImage.onload = function () {
        myCanvas.width = myImage.width
        myCanvas.height = myImage.height
        ctx.drawImage(myImage, 0, 0, myImage.width, myImage.height)
        showImage.src = myCanvas.toDataURL("image/png")
    }
</script>

可以生成png格式的base64文件

然后通过后台上传就行

image.png

视频导canvas然后导图片
<canvas id="myCanvas"></canvas>
<video crossOrigin="anonymous" preload="auto" style="width: 300px;" autoplay muted id="myVideo"
    src="https://vd2.bdstatic.com/mda-jefnpkr5bx02gkdg/sc/mda-jefnpkr5bx02gkdg.mp4?v_from_s=hkapp-haokan-nanjing&auth_key=1626865447-0-0-c71b87d3471f605f90848dd439326fc2&bcevod_channel=searchbox_feed&pd=1&pt=3&abtest="
    controls="controls">
</video>
<img id="showImage" />
<script>
    var ctx = myCanvas.getContext("2d")
    function setCanvas() {
        ctx.drawImage(myVideo, 0, 0, myCanvas.width, myCanvas.height)
        showImage.src = myCanvas.toDataURL("image/png")
    }
    let timer = null
    myVideo.addEventListener('play', function (e) {
        var pix = 300 / e.target.videoWidth
        myCanvas.width = e.target.videoWidth * pix
        myCanvas.height = e.target.videoHeight * pix
        timer = setInterval(setCanvas, 20)
    })
    myVideo.addEventListener('pause', function (e) {
        clearInterval(timer)
    })
    myVideo.addEventListener('ended', function (e) {
        clearInterval(timer)
    })
</script>

SDGIF_Rusult_1.gif

二、微信小程序

二、图片

HTML中对跨域资源会导致画布污染需要使用这个crossOrigin="anonymous"属性

小程序中会对没有合法配置的https资源进行限制 开发时勾选不校验https就可以了正式的时候要去小程序后台添加合法域名

image.png

微信小程序 无法操作dom元素 但是官方可以通过createSelectorQuery.select()API去选中部分页面元素当作实列,目前支持VideoContextCanvasContextLivePlayerContextEditorContext和 MapContext

1、获取画布实列
 wx.createSelectorQuery()
      .select('#myCanvas')
      .fields({
        node: true,
        size: true,
      })
      .exec((e) => {
          // 获取的node节点
      })
2、获取画布实列
 wx.createSelectorQuery()
      .select('#myCanvas')
      .fields({
        node: true,
        size: true,
      })
      .exec((e) => {
          // 获取的node节点
              var canvas = res[0].node;
          // 获取画布对象
              var ctx = canvas.getContext("2d")
      })
3、创建图片并且获取图片信息
getImage(src) { return new Promise((r, j) => { wx.getImageInfo({ src: src, success: r, fail: j }) }) },
var newImage = canvas.createImage()
newImage.src = "https://sf1-ttcdn-tos.pstatp.com/img/user-avatar/56a409021bf987376f220b475cd7a024~300x300.image"
newImage.onload = async (e) => {
    var imageObject = await this.getImage(newImage.src)
}
注意获取完图片的属性之后要直接设置canvas的宽高不然图像会扭曲
this.dpr = wx.getSystemInfoSync().pixelRatio
canvas.width = imageObject.width * this.dpr
canvas.height = imageObject.height * this.dpr 

如果在使用toDataURL报错了可以看看自己的

image.png

image.png

有两种图片导出的方式一种是base64直接通过后台处理

一种是向后台上传

一种临时文件canvasToTempFilePath使用这个API

全代码

index.wxml
<canvas
  type="2d"
  id="myCanvas"
  style="width: {{canvasWidth}}px; height: {{canvasHeight}}px;"
></canvas>
<image mode="widthFix" src="{{imageSrc}}"></image>
index.js
Page({
  data: {
    canvasHeight: 200,
    canvasWidth: 200,
    imageSrc:""
  },

  onLoad: function () {
    // 通过 SelectorQuery 获取 Canvas 节点
    this.dpr = wx.getSystemInfoSync().pixelRatio
    this.windowWidth = wx.getSystemInfoSync().windowWidth
    wx.createSelectorQuery()
      .select('#myCanvas')
      .fields({
        node: true,
        size: true,
      })
      .exec(this.getCanvas.bind(this))
  },
  getImage(src) {
    return new Promise((r, j) => {
      wx.getImageInfo({
        src: src,
        success: r,
        fail: j
      })
    })
  },
  getCanvas(res) {
    var canvas = res[0].node;
    console.log(canvas)
    // 获取画布对象
    var ctx = canvas.getContext("2d")
    var newImage = canvas.createImage()
    newImage.src = "https://sf1-ttcdn-tos.pstatp.com/img/user-avatar/56a409021bf987376f220b475cd7a024~300x300.image"
    newImage.onload = async (e) => {
      var imageObject = await this.getImage(newImage.src)
      // 防止画面扭曲
      canvas.width = imageObject.width * this.dpr
      canvas.height = imageObject.height * this.dpr
      this.setData({
        canvasHeight: imageObject.height,
        canvasWidth: imageObject.width
      })
      // 或多或少可以让画面更清晰一些
      ctx.scale(0.1, 0.1)
      ctx.drawImage(newImage, 0, 0, imageObject.width * this.dpr * 10, imageObject.height * this.dpr * 10)
      this.setData({
        imageSrc:canvas.toDataURL('image/png')
      })
       wx.canvasToTempFilePath({
        x: 0,
        y: 0,
        width: imageObject.width,
        height: imageObject.height,
        destWidth: imageObject.width * this.dpr,
        destHeight: imageObject.height * this.dpr,
        canvas:canvas,
        success:(res) => {
          console.log(res)
          this.setData({
            imageSrc1:res.tempFilePath
          })
          // wx.uploadFile() 进行上传
        }
      })
    }
  }

})


二、视频

SDGIF_Rusult_1.gif
只能将临时链接或者文件本地地址放入画布
这是下面使用getVideoInfoAPI可能用到的插件
链接:https://pan.baidu.com/s/1xYr1cQA0C8ggPgpGioLN-g
提取码:tbyb
首先封装一个下载视频和获取视频信息的方法

 downloadFileVideo(url) {
    return new Promise((r, j) => {
      wx.downloadFile({
        url: url, 
        success: r,
        fail: j
      })
    })
  },
  myGetVideoInfo(url) {
    return new Promise((r, j) => {
      wx.getVideoInfo({
        src: url,
        success: r,
        fail: j
      })
    })
  },

页面结构

<canvas
  type="2d"
  id="myCanvas"
  style="width: {{canvasWidth}}px; height: {{canvasHeight}}px;"
></canvas>
<video id="myVideo" style="width:{{videoWidth}}px" bindplay="videoPlay"  bindpause="videoPause" src="{{videoSrc}}"  binderror="videoErrorCallback" ></video>
<image mode="widthFix" src="{{imageSrc}}"></image>

上面对应的参数
  data: {
    canvasHeight: 200,
    canvasWidth: 200,
    imageSrc: "",
    videoSrc: "http://wxsnsdy.tc.qq.com/105/20210/snsdyvideodownload?filekey=30280201010421301f0201690402534804102ca905ce620b1241b726bc41dcff44e00204012882540400&bizid=1023&hy=SH&fileparam=302c020101042530230204136ffd93020457e3c4ff02024ef202031e8d7f02030f42400204045a320a0201000400",
    videoWidth: 300,
    videoHeight: 225
  },

大致逻辑和之前绘制图片一样
这里直接把代码放到这里

 data: {
    canvasHeight: 200,
    canvasWidth: 200,
    imageSrc: "",
    videoSrc: "http://wxsnsdy.tc.qq.com/105/20210/snsdyvideodownload?filekey=30280201010421301f0201690402534804102ca905ce620b1241b726bc41dcff44e00204012882540400&bizid=1023&hy=SH&fileparam=302c020101042530230204136ffd93020457e3c4ff02024ef202031e8d7f02030f42400204045a320a0201000400",
    videoWidth: 300,
    videoHeight: 225
  },
  videoErrorCallback: function (e) {
    console.log(e)
  },
  videoPlay: function (e) {
    this.timer = setInterval(() => {
      this.ctx.drawImage(this.video, 0, 0, this.data.videoWidth * this.dpr, this.data.videoHeight * this.dpr)
      this.setData({
        imageSrc:this.canvas.toDataURL('image/png')
      })
    }, 20);
  },
  videoPause: function (e) {
    clearInterval(this.timer)
  },
  downloadFileVideo(url) {
    return new Promise((r, j) => {
      wx.downloadFile({
        url: url, 
        success: r,
        fail: j
      })
    })
  },
  myGetVideoInfo(url) {
    return new Promise((r, j) => {
      wx.getVideoInfo({
        src: url, 
        success: r,
        fail: j
      })
    })
  },
  onLoad: async function () {
    // 通过 SelectorQuery 获取 Video 节点
    wx.createSelectorQuery().select('#myVideo').context(async res => {
      this.video = res.context
      var videoObj = await this.downloadFileVideo(this.data.videoSrc)
      var videoInfo = await this.myGetVideoInfo(videoObj.tempFilePath)
      this.setData({
        videoHeight: videoInfo.height * (this.data.videoWidth / videoInfo.width)
      })
      this.dpr = wx.getSystemInfoSync().pixelRatio
      wx.createSelectorQuery()
        .select('#myCanvas')
        .fields({
          node: true,
          size: true,
        })
        .exec(this.getVideoCanvas.bind(this))
    }).exec()
  },
  getVideoCanvas(res) {
    var canvas = res[0].node;
    this.canvas = canvas
    canvas.width = this.data.videoWidth * this.dpr
    canvas.height = this.data.videoHeight * this.dpr
    this.setData({
      canvasHeight: this.data.videoHeight,
      canvasWidth: this.data.videoWidth
    })
    this.ctx = canvas.getContext("2d")
    this.video.play()
  },
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值