详解微信小程序canvas圆角矩形的绘制的方法


Posted in Javascript onAugust 22, 2018

微信小程序允许对普通元素通过 border-radius 的设置来进行圆角的绘制,但有时候在使用 canvas 绘图的时候,也需要圆角,例如需要将页面上某块区域导出为图片下载到本地的时候,常用的解决方法就是使用 canvas 将这块区域绘制出来,最后导出 canvas 即可,但是 canvas 没有直接提供圆角的绘制 api ,所以需要 曲线救国

圆角矩形与一般矩形的区别在于,前者的四个角都是圆弧,所以只需要将一般矩形的四个角切掉,换成圆弧即可,如下图就是一个一般矩形被切掉了四个角的样子:

详解微信小程序canvas圆角矩形的绘制的方法

很明显,切掉了四个角的矩形,剩下其实就是四条 line ,既然如此,完全可以跳过绘制矩形然后切角这一步,因为切角的结果就是四条边( line ),直接绘制四条边即可。 然后在每两条边的缺角处绘制弧度为 0.5 * Math.PI 的圆弧,最后这四条边与四个圆弧所封闭的图形就是圆角矩形:

详解微信小程序canvas圆角矩形的绘制的方法

原理知道了,代码就很好写了,这里只说几个注意点:

封闭图形的 fillStyle 颜色设置为 transparent

想将封闭路径的图形绘制下来,需要调用 strokefill 方法,默认 strokefill 的颜色是 black ,但是这里有个问题, 圆弧的绘制可能会出现锯齿或者糊边,如果 strokefill 的颜色,与你所需要绘制的圆角矩形的边缘色调不一致,这种糊边的感觉会比二者色调一致的更明显, 下图第一个为色调一致,第二个为色调不一致的情况:

详解微信小程序canvas圆角矩形的绘制的方法

详解微信小程序canvas圆角矩形的绘制的方法

不过据我观测,只要不是特意放大仔细看,无论是色调是否一致,其实一般人很难注意到糊边的事情

clip

绘制好了圆角选区之后,还需要调用 ctx.clip 方法来裁剪选区

saverestore

如果这个矩形选区只是 canvas 画布的一部分,为了避免对后续的影响,最好在 beginPath 之前,将之前的动作 save ,然后画完后再 restore

一个关于 canvas 上绘制圆角图片,并下载到本地 的可运行示例代码已经放到 github 上了,注释也比较详细,需要的可自取

其中关键代码如下:

/**
 * 
 * @param {CanvasContext} ctx canvas上下文
 * @param {number} x 圆角矩形选区的左上角 x坐标
 * @param {number} y 圆角矩形选区的左上角 y坐标
 * @param {number} w 圆角矩形选区的宽度
 * @param {number} h 圆角矩形选区的高度
 * @param {number} r 圆角的半径
 */
function roundRect(ctx, x, y, w, h, r) {
 // 开始绘制
 ctx.beginPath()
 // 因为边缘描边存在锯齿,最好指定使用 transparent 填充
 // 这里是使用 fill 还是 stroke都可以,二选一即可
 ctx.setFillStyle('transparent')
 // ctx.setStrokeStyle('transparent')
 // 左上角
 ctx.arc(x + r, y + r, r, Math.PI, Math.PI * 1.5)

 // border-top
 ctx.moveTo(x + r, y)
 ctx.lineTo(x + w - r, y)
 ctx.lineTo(x + w, y + r)
 // 右上角
 ctx.arc(x + w - r, y + r, r, Math.PI * 1.5, Math.PI * 2)

 // border-right
 ctx.lineTo(x + w, y + h - r)
 ctx.lineTo(x + w - r, y + h)
 // 右下角
 ctx.arc(x + w - r, y + h - r, r, 0, Math.PI * 0.5)

 // border-bottom
 ctx.lineTo(x + r, y + h)
 ctx.lineTo(x, y + h - r)
 // 左下角
 ctx.arc(x + r, y + h - r, r, Math.PI * 0.5, Math.PI)

 // border-left
 ctx.lineTo(x, y + r)
 ctx.lineTo(x + r, y)

 // 这里是使用 fill 还是 stroke都可以,二选一即可,但是需要与上面对应
 ctx.fill()
 // ctx.stroke()
 ctx.closePath()
 // 剪切
 ctx.clip()
}

ps:微信小程序canvas把正方形图片绘制成圆形

<canvas style="width: 400px; height: 400px;border:1px solid red" canvas-id="firstCanvas"></canvas>
//index.js
Page({
 data: {
  image: {
   src: "/1.png",
   width: 200,
   heigth: 200
  }
 },
 onLoad: function () {
  let that = this;
  var contex = wx.createCanvasContext('firstCanvas')
  contex.save(); // 先保存状态 已便于画完圆再用
  contex.beginPath(); //开始绘制
  //先画个圆
  contex.arc(100, 100, 100, 0, Math.PI * 2, false);
  contex.clip();//画了圆 再剪切 原始画布中剪切任意形状和尺寸。一旦剪切了某个区域,则所有之后的绘图都会被限制在被剪切的区域内
  contex.drawImage(that.data.image.src, 0, 0, that.data.image.width, that.data.image.heigth); // 推进去图片
  contex.restore(); //恢复之前保存的绘图上下文 恢复之前保存的绘图上下午即状态 可以继续绘制
  contex.draw();
 }
})

以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持三水点靠木。

Javascript 相关文章推荐
Prototype 工具函数 学习
Jul 23 Javascript
jquery 关键字“拖曳搜索”之“拖曳”以及 图片“提示自适应放大”效果 的实现
Apr 18 Javascript
为JavaScript提供睡眠功能(sleep) 自编译JS引擎
Aug 16 Javascript
js/ajax跨越访问-jsonp的原理和实例(javascript和jquery实现代码)
Dec 27 Javascript
JS获取随机数函数可自定义最小值最大值
May 08 Javascript
js 文字超出长度用省略号代替,鼠标悬停并以悬浮框显示实例
Dec 06 Javascript
JavaScript 实现 Tab 点击切换实例代码
Mar 25 Javascript
vue父组件异步获取数据传给子组件的方法
Jul 26 Javascript
vue动画效果实现方法示例
Mar 18 Javascript
vue watch关于对象内的属性监听
Apr 22 Javascript
微信小程序表单验证WxValidate的使用
Nov 27 Javascript
非常漂亮的js烟花效果
Mar 10 Javascript
解决element UI 自定义传参的问题
Aug 22 #Javascript
微信小程序chooseImage的用法(从本地相册选择图片或使用相机拍照)
Aug 22 #Javascript
解决element-ui中下拉菜单子选项click事件不触发的问题
Aug 22 #Javascript
微信小程序 Animation实现图片旋转动画示例
Aug 22 #Javascript
Vue动态获取width的方法
Aug 22 #Javascript
微信小程序调用摄像头隐藏式拍照功能
Aug 22 #Javascript
Vue2.2.0+新特性整理及注意事项
Aug 22 #Javascript
You might like
php设计模式之单例、多例设计模式的应用分析
2013/06/30 PHP
PHP实现根据时间戳获取周几的方法
2016/02/26 PHP
Laravel实现自定义错误输出内容的方法
2016/10/10 PHP
PHP验证终端类型是否为手机的简单实例
2017/02/07 PHP
PHP魔术方法之__call与__callStatic使用方法
2017/07/23 PHP
jquery ajax 登录验证实现代码
2009/09/23 Javascript
JavaScript 编写匿名函数的几种方法
2010/02/21 Javascript
js动态切换图片的方法
2015/01/20 Javascript
JS模式之简单的订阅者和发布者模式完整实例
2015/06/30 Javascript
javascript断点调试心得分享
2016/04/23 Javascript
jQuery仿京东商城楼梯式导航定位菜单
2016/07/25 Javascript
angularJs关于指令的一些冷门属性详解
2016/10/24 Javascript
关于angularJs指令的Scope(作用域)介绍
2016/10/25 Javascript
BootStrap3使用错误记录及解决办法
2016/12/22 Javascript
javascript 中设置window.location.href跳转无效问题解决办法
2017/02/09 Javascript
vue拦截器Vue.http.interceptors.push使用详解
2017/04/22 Javascript
微信小程序实现滴滴导航tab切换效果
2018/07/24 Javascript
[02:43]中国五虎出征TI3视频
2013/08/02 DOTA
[01:21]2018DOTA2亚洲邀请赛4.5采访 打DOTA2也能有女朋友?
2018/04/06 DOTA
python实现从一组颜色中找出与给定颜色最接近颜色的方法
2015/03/19 Python
分享给Python新手们的几道简单练习题
2017/09/21 Python
python网络爬虫学习笔记(1)
2018/04/09 Python
Python使用修饰器进行异常日志记录操作示例
2019/03/19 Python
Python简直是万能的,这5大主要用途你一定要知道!(推荐)
2019/04/03 Python
Python3.5面向对象编程图文与实例详解
2019/04/24 Python
python连接mongodb数据库操作数据示例
2020/11/30 Python
pandas数据分组groupby()和统计函数agg()的使用
2021/03/04 Python
Pop In A Box英国:Funko POP搪胶公仔
2019/05/27 全球购物
早读迟到检讨书
2014/01/24 职场文书
初二生物教学反思
2014/02/03 职场文书
初中三年毕业生的自我评价分享
2014/02/14 职场文书
社区扶贫帮困工作总结
2015/05/20 职场文书
郭明义电影观后感
2015/06/08 职场文书
幼儿园毕业致辞
2015/07/29 职场文书
作文之亲情600字
2019/09/23 职场文书
python实现进度条的多种实现
2021/04/29 Python