微信小程序canvas画布实现矩形元素自由缩放、移动功能

获取画布信息并绘制背景

.whml

.wxss

.canvas{
  background-color: white;
  height: 65vh;
  width: 100%;
  margin-top: 5px;
  margin-bottom: 5px;  
}

 .js

获取画布对象并设置背景图

onReady() {
    const query = wx.createSelectorQuery()
    query.select('#myCanvas')
      .fields({ node: true, size: true })
      .exec((res) => {
        const canvas = res[0].node
        const ctx = canvas.getContext('2d')
        const dpr = wx.getSystemInfoSync().pixelRatio
        this.setData({
          pixelRatio: dpr
        })
        canvas.width = res[0].width * dpr
        canvas.height = res[0].height * dpr      
        var bg = canvas.createImage()
        var bg_info = {
          img: bg,
          width: canvas.width,
          height: canvas.height
        }
        bg.src = "../../image/白屏竖.png"
        bg.onload = () =>{
            ctx.drawImage(bg,0,0,canvas.width,canvas.height)
        }
        this.setData({
          canvas: canvas,
          ctx: ctx,
          bg_info: bg_info
        })
        
      })
  },

绘制矩形

可在whml添加按钮或图表,点击后调用绘制矩形函数,作为测试,也可在以上onReady函数获取画布对象后调用绘制矩形函数。

data:{
    edit_rect:{}
},
draw_basic_rect(){
    ctx.strokeRect(100,100,100,100)
    var t_edit = {
        left_top_x: 100,
        left_top_y: 100,
        width: 100,
        height: 100
    }
    this.setData({
        edit_rect: t_edit,
        current_edit_element: e.currentTarget.dataset.info
    })
    this.draw_rect_edit_icon() //绘制矩形编辑按钮,见下文
},

 绘制矩形编辑按钮

draw_rect_edit_icon(e){
    var lt_x = this.data.edit_rect.left_top_x
    var lt_y = this.data.edit_rect.left_top_y
    var width = this.data.edit_rect.width
    var height = this.data.edit_rect.height
    var color = 'red' //编辑按钮颜色
    var rt_x = lt_x + width
    var rt_y = lt_y
    var lb_x = lt_x
    var lb_y = lt_y + height
    var rb_x = lt_x + width
    var rb_y = lt_y + height
    //在矩形四个顶点绘制四个编辑按钮
    this.data.ctx.beginPath()
    this.data.ctx.arc(lt_x,lt_y,10,0,Math.PI*2)
    this.data.ctx.fillStyle = color
    this.data.ctx.fill()
    this.data.ctx.beginPath()
    this.data.ctx.arc(rt_x,rt_y,10,0,Math.PI*2)
    this.data.ctx.fillStyle = color
    this.data.ctx.fill()
    this.data.ctx.beginPath()
    this.data.ctx.arc(lb_x,lb_y,10,0,Math.PI*2)
    this.data.ctx.fillStyle = color
    this.data.ctx.fill()
    this.data.ctx.beginPath()
    this.data.ctx.arc(rb_x,rb_y,10,0,Math.PI*2)
    this.data.ctx.fillStyle = color
    this.data.ctx.fill()
  },

用户触摸画布,获取并更新触摸位置

data:{
  touch_radius: 10  
},
get_rect_touch_position(e){
    if(e.type=='touchstart'){
      var x = e.touches[0].x*this.data.pixelRatio
      var y = e.touches[0].y*this.data.pixelRatio
    }else if(e.type=='tap'){
      var x = (e.detail.x-e.currentTarget.offsetLeft)*this.data.pixelRatio
      var y = (e.detail.y-e.currentTarget.offsetTop)*this.data.pixelRatio      
    }
    var touch_radius = this.data.touch_radius*this.data.pixelRatio //设置触摸检测半径
    var lt_x = this.data.edit_rect.left_top_x
    var lt_y = this.data.edit_rect.left_top_y
    var width = this.data.edit_rect.width
    var height = this.data.edit_rect.height
    var rt_x = lt_x + width
    var rt_y = lt_y
    var lb_x = lt_x
    var lb_y = lt_y + height
    var rb_x = lt_x + width
    var rb_y = lt_y + height
    var position = ''
    if(Math.pow(x-lt_x,2)+Math.pow(y-lt_y,2)

划动画布时,判断是否是缩放操作或移动操作

move_or_scale(e){
    var c_ele = this.data.current_edit_element
    var position = this.data.current_edit_position  
    var scale_po = ['left-top','right-top','left-bottom','right-bottom']
    if(position=='outside') this.finish_edit_check()
    else if(position == 'inside') this.move_rectangle(e)
    else if(scale_po.indexOf(position)>=0) this.scale_rectangle(e,position)
    break 
},

移动编辑框圆点,对矩形进行缩放

scale_rectangle(e,position){
    var ctx = this.data.ctx
    var x = e.touches[0].x*this.data.pixelRatio
    var y = e.touches[0].y*this.data.pixelRatio
    var lt_x = this.data.edit_rect.left_top_x
    var lt_y = this.data.edit_rect.left_top_y
    var width = this.data.edit_rect.width
    var height = this.data.edit_rect.height
    var rb_x = lt_x + width
    var rb_y = lt_y + height
    switch(position){
      case 'left-top':
        this.data.ctx.drawImage(this.data.bg_info.img,0,0,
                                this.data.canvas.width,this.data.canvas.height)
        ctx.strokeRect(x,y,rb_x-x,rb_y-y)
        this.setData({
          'edit_rect.left_top_x':x,
          'edit_rect.left_top_y':y,
          'edit_rect.width': rb_x-x,
          'edit_rect.height': rb_y-y
        })
        this.draw_rect_edit_icon()
        break
      case 'right-top':
        this.data.ctx.drawImage(this.data.bg_info.img,0,0,
                                this.data.canvas.width,this.data.canvas.height)
        ctx.strokeRect(lt_x,y,x-lt_x,rb_y-y)
        this.setData({
          'edit_rect.left_top_y':y,
          'edit_rect.width': x-lt_x,
          'edit_rect.height': rb_y-y
        })
        this.draw_rect_edit_icon()
        break
      case 'right-bottom': 
        this.data.ctx.drawImage(this.data.bg_info.img,0,0,
                                this.data.canvas.width,this.data.canvas.height)
        ctx.strokeRect(lt_x,lt_y,x-lt_x,y-lt_y)
        this.setData({
          'edit_rect.width': x-lt_x,
          'edit_rect.height': y-lt_y
        })
        this.draw_rect_edit_icon()
        break
      case 'left-bottom':
        this.data.ctx.drawImage(this.data.bg_info.img,0,0,
                                this.data.canvas.width,this.data.canvas.height)
        ctx.strokeRect(x,lt_y,rb_x-x,y-lt_y)
        this.setData({
          'edit_rect.left_top_x':x,
          'edit_rect.width': rb_x-x,
          'edit_rect.height': y-lt_y
        })
        this.draw_rect_edit_icon()
        break
      default:
        console.log('error')
    }

触摸矩形内部,移动矩形

move_rectangle(e){
    var ctx = this.data.ctx
    var x = e.touches[0].x*this.data.pixelRatio
    var y = e.touches[0].y*this.data.pixelRatio
    var width = this.data.edit_rect.width
    var height = this.data.edit_rect.height
    this.data.ctx.drawImage(this.data.bg_info.img,0,0,
                            this.data.canvas.width,this.data.canvas.height)
    ctx.strokeRect(x-width/2,y-height/2,width,height)
    this.setData({
      'edit_rect.left_top_x':x-width/2,
      'edit_rect.left_top_y':y-height/2
    })
    this.draw_rect_edit_icon()
  },

触摸矩形外部,结束编辑

finish_edit_check(){
    this.data.ctx.drawImage(this.data.bg_info.img,0,0,
                                this.data.canvas.width,this.data.canvas.height)
    var lt_x = this.data.edit_rect.left_top_x
    var lt_y = this.data.edit_rect.left_top_y
    var width = this.data.edit_rect.width
    var height = this.data.edit_rect.height
    ctx.strokeRect(lt_x,lt_y,width,height)
    this.clear_edit_state()
    this.save_canvas()
},
clear_edit_state(){
    this.setData({
        edit_rect: {},
        current_edit_element: "",
        current_edit_position: ""
    })    
},
save_canvas(){
    wx.canvasToTempFilePath({
      x: 0,
      y: 0,
      width: this.data.canvas.width,
      height: this.data.canvas.height,
      destWidth: this.data.canvas.width,
      destHeight: this.data.canvas.height,
      canvas: this.data.canvas,
      canvasId: 'myCanvas',
    })
    .then(res=>{
      this.setData({
        'bg_info.img.src':res.tempFilePath
      })
      this.data.ctx.drawImage(this.data.bg_info.img,0,0,
                             this.data.canvas.width,this.data.canvas.height)
    })
    .catch(res=>{
      console.log('error',res)
    })
},

更多内容欢迎关注博主,小程序功能定制或咨询请私信博主。

其他元素缩放和移动功能欢迎私信咨询,也可先关注博主,等候后续博文。

你可能感兴趣的:(微信小程序,微信小程序,小程序,canva可画,画布)