详解微信小程序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 相关文章推荐
javascript下过滤数组重复值的代码
Sep 10 Javascript
文本框input聚焦失焦样式实现代码
Oct 12 Javascript
绑定回车enter事件代码
May 18 Javascript
JavaScript将字符串转换成字符编码列表的方法
Mar 19 Javascript
Javascript aop(面向切面编程)之around(环绕)分析
May 01 Javascript
JS+CSS实现经典的左侧竖向滑动菜单效果
Sep 23 Javascript
Bootstrap中CSS的使用方法
Feb 17 Javascript
如何使用jquery实现文字上下滚动效果
Oct 12 Javascript
JavaScript实现数组降维详解
Jan 05 Javascript
JavaScript实现三级联动效果
Jul 15 Javascript
js+html5实现侧滑页面效果
Jul 15 Javascript
JavaScript遍历DOM元素的常见方式示例
Feb 16 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基于php_imagick_st-Q8.dll实现JPG合成GIF图片的方法
2014/07/11 PHP
php+ajax实现无刷新分页的方法
2014/11/04 PHP
php接口数据加密、解密、验证签名
2015/03/12 PHP
PHP封装CURL扩展类实例
2015/07/28 PHP
分享一道笔试题[有n个直线最多可以把一个平面分成多少个部分]
2012/10/12 Javascript
javascript+xml实现简单图片轮换(只支持IE)
2012/12/23 Javascript
JavaScript初学者应注意的七个细节详细介绍
2012/12/27 Javascript
node.js中的http.response.end方法使用说明
2014/12/14 Javascript
javascript上下方向键控制表格行选中并高亮显示的方法
2015/02/13 Javascript
浅谈JavaScript事件的属性列表
2015/03/01 Javascript
JavaScript检测鼠标移动方向的方法
2015/05/22 Javascript
纯js代码制作的网页时钟特效【附实例】
2016/03/30 Javascript
Node使用Sequlize连接Mysql报错:Access denied for user ‘xxx’@‘localhost’
2018/01/03 Javascript
js实现一个简单的MVVM框架示例
2018/01/15 Javascript
vue.js实现标签页切换效果
2018/06/07 Javascript
NodeJS 中Stream 的基本使用
2018/07/30 NodeJs
[49:27]LGD vs OG 2018国际邀请赛小组赛BO2 第二场 8.16
2018/08/17 DOTA
python 从远程服务器下载日志文件的程序
2013/02/10 Python
python入门之语句(if语句、while语句、for语句)
2015/01/19 Python
python中set常用操作汇总
2016/06/30 Python
python访问抓取网页常用命令总结
2017/04/11 Python
Anaconda入门使用总结
2018/04/05 Python
Python解决两个整数相除只得到整数部分的实例
2018/11/10 Python
解决pycharm py文件运行后停止按钮变成了灰色的问题
2018/11/29 Python
python版本五子棋的实现代码
2018/12/11 Python
python 如何将office文件转换为PDF
2020/09/22 Python
python 30行代码实现蚂蚁森林自动偷能量
2021/02/08 Python
css3编写浏览器背景渐变背景色的方法
2018/03/05 HTML / CSS
size?德国官方网站:英国伦敦的球鞋精品店
2018/03/17 全球购物
求职简历自荐信范文
2013/10/21 职场文书
外国语学院毕业生自荐信
2013/10/28 职场文书
个人工作表现评语
2014/04/30 职场文书
法律专业求职信
2014/05/24 职场文书
拒绝黄毒毒宣传标语
2014/06/26 职场文书
列车乘务员工作不细心检讨书
2014/10/07 职场文书
2016优秀员工先进事迹材料
2016/02/25 职场文书