canvas菜鸟基于小程序实现图案在线定制功能

前言

最近在捣腾一个 袜子图案在线定制 的小程序,核心的需求大概是选择一只纯色的袜子,然后客户可以在袜子上面添加图案,
最终生成一个设计图保存后服务器。定制的图案可以旋转,缩放和拖动,当然,还可以删除。

内容比较初级, 因为我也只是一个 canvas 新手,本文仅是一次实践的记录.

实现-绘图

其实刚开始接手这个项目的时候,我是打算用小程序的 web-view 组件来嵌套 h5 的,
因为小程序的 canvas 的坑,或者说小程序的坑,我是深有体会的,不过回过头来想,
web-view 我还没再项目中用过, 还说不定会遇到什么更大的坑呢,所以最终还是选择小程序的 canvas

首先, 计算图片的大小和位置,不能让图片超过画布(我这里是不能超过画布的 80%),位置在画布的正中间.

然后, 需要将原点移动到画布的中心点 这点比较重要,等下下面的旋转如果没有这一步的话,会沿着图片的左上角旋转.

第三步,将目标图像画到画板上,找个是没啥难的,直接调用 ctx.drawImage 既可

if (!this.imgUrl) return
ctx.drawImage(this.imgUrl, x, y, this.tempImgWidth, this.tempImgHeight)

drawImage 之前需要 判断一下目标图像的路径是否可以拿到图片,如果图片路径有问题,会直接报错,并且影响接下来的代码执行,
相当于整个应用崩溃了.

我这里因为都是本地图片,所以只要判断图片存不存在即可,如果是网络图片,还要先保存成本地图片再 drawImage,
不然有可能会出现很多画不出来的可能性.

由于中心点已经偏移了,这个时候, drawImage 的 x 和 y 需要向左上角偏移回去(imgWidth / -2, imgHeight / -2),
保持图片的中心点跟canvas的原点重叠.

到此, 图片就画好了,如果有旋转,要在这个时候旋转.旋转完以后,再画外框和操作按钮,
这样可以保持外框和操作按钮不随着图片旋转(经过验证,这种方式比跟着旋转的好很多),
旋转也很简单,直接调用 ctx.rotate 即可, 旋转的角度计算方法百度上有.我是直接拷贝的

然后就是操作按钮和虚线框,参数跟 drawImage 一样,因为是画一个跟图片一样大小的框框嘛..

虚线框

ctx.setStrokeStyle(‘#fd749c‘)
ctx.setLineDash([5, 5], 10);
ctx.strokeRect(x, y, this.tempImgWidth, this.tempImgHeight)

操作按钮,这里的 r 是按钮的半径, d 是按钮的直径,无非就是在图片的四个角,画按钮.

// 画 删除 按钮
ctx.drawImage(‘/static/design/icons/delete.png‘, x - r, y - r, d, d)
// 画 旋转 按钮
ctx.drawImage(‘/static/design/icons/rotate.png‘, x + this.tempImgWidth - r, y - r, d, d)
// 画 缩放 按钮
ctx.drawImage(‘/static/design/icons/scale.png‘, x + this.tempImgWidth - r, y + this.tempImgHeight - r, d, d)

最后再调用一下 ctx.draw() 完成绘图. 所用到的 API 都很简单,不过过程要计算的东西还是很多

实现-操作

绘图已经完成了,那么如何做到点击或拖动操作按钮,做响应的操作呢?
这就需要监听 canvas 的 bindtouchstart, bindtouchmove, bindtouchend 三个事件,
然后 e.touches[0].x 和 e.touches[0].y 可以获取当前手指的位置,
在 bindtouchstart 的回调里面判断当前位置,如果跟某个操作按钮重叠,就说明是操做,如果都没有重叠,则是拖动,然后把操作记录下来,
在 bindtouchmove 的回调里面,获取手指移动的距离和角度,然后根据 bindtouchstart 里记录的操作,
调整对应的参数(拖动跟缩放,只要计算当前点的 x,y 跟 bindtouchstart 点的 x,y 的偏移量即可,旋转的上面有提过,百度有),
然后重新调用 ctx.draw() 重新绘图.

一个操作做完,可能需要复位一些东西,这个可以在 bindtouchend 的回调里面去做

tips: 这里的 e.touches[0].x 的 e 是回调函数带的参数

保存定制图

这些都画好以后,需要把定制图保存起来,指定图保存的不单单是原来那个 canvas里的图,还要连底图(也就是那张袜子图)一起保存起来,
需要一个袜子图那么大的 canvas(这个称为临时 canvas 吧),先把袜子画进去,然后再把图案画上去,画图案上去的时候,由于画布大小位置已经变了,
所以需要稍微计算一下,大概就是 x,y 要分别加上原来的 canvan 跟袜子图左上角的距离.然后还要把外框跟操作按钮去掉.
最后调用 ctx.draw 把图画出来..这里有点需要注意的是,draw 其实是个异步函数,如果你在ctx.draw() 下一行做保存操作,
那么你保存的会是一个空白的图片,draw 函数的第二个参数,是一个回调函数,想要获取画完图的 canvas,要在这个回调函数里面才能拿的到

ctx.draw(false, function () {
    // 要先保存到临时路径
    wx.canvasToTempFilePath({
      canvasId: ‘tempCanvas‘,
      success: function (res) {
        // 然后再保存到相册
        wx.saveImageToPhotosAlbum({
          filePath: res.tempFilePath,
          success () {
            wx.showToast({
              title: ‘保存成功!‘,
              icon: ‘none‘,
              duration: 2000
            })
          }
        })
      }
    })
  }
)

你感受到了微信小程序团队满满的恶意了吗? 这大概是我第一次写这么深的嵌套吧..传说中的回调地狱.虽然可以用 promise 封装解决,
不过为了几个几乎不会复用的 API 去封装似乎不太划算. 不过总算还是保存成功了.

tips: 为了保存的时候这个临时 canvas 不影响正常界面,这我的做法是对 临时 canvas 设置 position:fixed; left:100vw;这两个样式,把它隐藏起来

最后

本文用的代码都是基于 mpvue 框架的, 这个也是个比较基础的东西,就不整个项目开源浪费 github 的空间了,
我把跟 canvas 有关代码上传到这里,
仅供参考,单独运行是肯定运行不起来, 如果有需要源码,可以私下发邮件找我要.

本文的的地址 个人技术帖合集 欢迎随意 star 和 follow, 和不随意的 issue

原文地址:https://www.cnblogs.com/noahnee/p/9487044.html

时间: 2024-10-08 06:37:21

canvas菜鸟基于小程序实现图案在线定制功能的相关文章

微信小程序添加悬浮在线客服会话按钮

微信为小程序提供客服消息能力,小程序用户可以方便快捷地与小程序服务提供方进行沟通,并且已经做成了组件的形式,直接就可以调用.客服会话按钮,用于在页面上显示一个客服会话按钮,用户点击该按钮后会进入客服会话.那么如何自定义成悬浮客服会话按钮呢?随Z5Win一起来看看 1.我们可以定义contact-button的样式,加一个class.这个客服组件可以放在一个固定模板里,方便每个页面都调用到. <view> <contact-button class="img-plus-style

小程序分销系统有什么功能

今天,为大家分享一下,小程序分销系统有什么功能.各种系统开发,正品邹经理188-19172*596可微可电 一.为什么要做小程序分销软件 大多数卖货的方式都会选择分销,之所以选择分销,是因为可以实现产品直接从生产商向消费者的转移.随着电子商务发展的趋势,手机用户不断增加,移动电商越来越受到的重视,没有一套管理平台就很容易出现问题,团队的增多也会带来很多麻烦,从而小程序平台就运应而生. 小程序分销软件营销模式借助互联网的延伸性及便利性,开启各小程序爆炸式裂变分销模式,使商务过程不再受时间.空间和人

记录使用微信小程序的NFC和蓝牙功能读取15693芯片的开发历程

开发目标: (1) 对于Android手机,直接通过微信小程序调用手机的NFC功能,对15693协议的芯片进行读写操作: (2)对于苹果手机(及没有NFC模块的手机),通过微信小程序的蓝牙功能连接到蓝牙/NFC读写器,然后通过蓝牙发送指令操作读写器对15693协议的芯片进行读写操作. DAY #1 上午开了半天会,下午开始开发. 先开发简单的:直接通过Android手机的NFC模块读写芯片.开发思路如下: 1. 首先调用 wx.getHCEState(OBJECT), 判断设备是否支持NFC,如

微信小程序实现即时通信聊天功能的实例代码

项目背景:小程序中实现实时聊天功能 一.服务器域名配置 配置流程 配置参考URL:https://developers.weixin.qq.com/miniprogram/dev/api/api-network.html 二.nginx中配置反向代理加密websocket(wss) ? 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 3

微信小程序学习Course 7 定时器功能

微信小程序学习Course 7 定时器功能 微信小程序中有一个定时器API函数,其提供了四个API接口 7.1.number setTimeout(function callback, number delay, any rest) 设定一个定时器,在定时到期以后执行注册的回调函数,值得注意的是本函数只执行一次!!!! setTimeout(this.DaoJiShi, 1000);//时间到达一秒执行一次DaoJiShi函数 如果我们想实现一个不停调用的函数,怎末实现呢?以下函数利用递归实现了

超详细,用canvas在微信小程序上画时钟教程

最近开始学习canvas,看了慕课网的一个视频,开始自己动手在微信小程序上画个时钟, 首先我们可以先看以下微信小程序的官方文档:https://mp.weixin.qq.com/debug/wxadoc/dev/api/canvas/reference.html 和canvas的手册对比:http://www.w3school.com.cn/tags/html_ref_canvas.asp 我觉得其实除了删减一些内容之外没什么太大的区别 直接贴代码: wxml <!--index.wxml-->

微信小程序开发的在线影院系统

开发工具:微信开发者工具 微信小程序开发开发的在线影院系统 [详情查看](http://www.myzblog.cn:8080/blog/articles/22.html) { "pages":["pages/movie/movie","pages/recommend/recommend","pages/search/search","pages/detail/detail","pages/loc

小程序实现实时聊天IM功能

随着小程序的发展,给公司带来了不错的收益,但是有件比较苦恼的事情是,由于小程序没有即时聊天功能,这给公司的客服带来不少的麻烦,导致沟通没有时效性.通过更智能的企达第三方小程序IM,可以实现更多多维度的操作!1.主动邀请对话当用户进入小程序后,可以自动发出一个对话邀请,用户消息及时提醒客服进行接待,及时了解用户咨询信息,不错过任何一个客户.2.标签管理能力根据用户信息以及沟通中获得的信息,可设置标签对用户进行分组,区分不同类型的客户,以实现精准营销.3.富媒体沟通可群发图文.文本.音频.视频等消息

【学习ios之路:C语言】小程序:实现类似ATM取款机功能.

小程序:模拟ATM机取款的过程 1).定义两个能保存5个整形数的数组,一个用于保存5个人的卡号,一个用于保存对应卡号的密码 2).判断输入的卡号是否在数组中. 3).如果在数组中就让输入密码,判断是否和卡号对应的密码匹配. 4).判断密码,24小时内只允许输入3次错误的密码.输入错误应该提示还剩下的输入次数,3次都输入错误提示24小时内不允许操作该卡. 5).密码正确就让用户对该账户进行相应的操作. 6).注意取款的限制. 7).述功能对于一个ATM机是循环的过程,也就是说每个客户都会按照上面的