详解微信小程序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 相关文章推荐
jquery+ashx无刷新GridView数据显示插件(实现分页、排序、过滤功能)
Apr 25 Javascript
初窥JQuery(一)jquery选择符 必备知识点
Nov 25 Javascript
浅谈angular.js中实现双向绑定的方法$watch $digest $apply
Oct 14 Javascript
jquery实现的V字形显示效果代码
Oct 27 Javascript
JS留言功能的简单实现案例(推荐)
Jun 23 Javascript
读Javascript高性能编程重点笔记
Dec 21 Javascript
JS之if语句对接事件动作逻辑(详解)
Jun 28 Javascript
JS数组操作之增删改查的简单实现
Aug 21 Javascript
浅谈React Native Flexbox布局(小结)
Jan 08 Javascript
jQuery+ajax实现动态添加表格tr td功能示例
Apr 23 jQuery
vue 表单验证按钮事件交由父组件触发的方法
Dec 17 Javascript
Vue插件从封装到发布的完整步骤记录
Feb 28 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写的小东西
2006/12/06 PHP
php防注入,表单提交值转义的实现详解
2013/06/10 PHP
JS(jQuery)实现聊天接收到消息语言自动提醒功能详解【提示“您有新的消息请注意查收”】
2019/04/16 PHP
js模拟弹出效果代码修正版
2008/08/07 Javascript
javascript 数组排序函数
2009/08/20 Javascript
得到jQuery detach()后节点中的某个值实现代码
2013/02/05 Javascript
jQuery中animate动画第二次点击事件没反应
2015/05/07 Javascript
jQuery下拉美化搜索表单效果代码分享
2015/08/25 Javascript
JS实现完全语义化的网页选项卡效果代码
2015/09/15 Javascript
NodeJS连接MongoDB数据库时报错的快速解决方法
2016/05/13 NodeJs
JS中使用mailto实现将用户在网页中输入的内容传递到本地邮件客户端
2016/10/08 Javascript
jquery与ajax获取特殊字符实例详解
2017/01/08 Javascript
重学JS 系列:聊聊继承(推荐)
2019/04/11 Javascript
vue实现的多页面项目如何优化打包的步骤详解
2020/07/19 Javascript
python类和继承用法实例
2015/07/07 Python
Python循环语句中else的用法总结
2016/09/11 Python
Python实现生成随机日期字符串的方法示例
2017/12/25 Python
在Pycharm中将pyinstaller加入External Tools的方法
2019/01/16 Python
Python实现的删除重复文件或图片功能示例【去重】
2019/04/23 Python
python实现在cmd窗口显示彩色文字
2019/06/24 Python
Python文件操作中进行字符串替换的方法(保存到新文件/当前文件)
2019/06/28 Python
vscode 配置 python3开发环境的方法
2019/09/19 Python
python实现翻译word表格小程序
2020/02/27 Python
关于HTML5 Placeholder新标签低版本浏览器下不兼容的问题分析及解决办法
2016/01/27 HTML / CSS
HTML5实现页面切换激活的PageVisibility API使用初探
2016/05/13 HTML / CSS
Jabra捷波朗美国官网:用于办公、车载和运动的无线蓝牙耳麦
2017/02/01 全球购物
护理专业应届毕业生推荐信
2013/11/15 职场文书
社区网格化管理实施方案
2014/03/21 职场文书
计算机相关专业自荐信
2014/07/02 职场文书
学校百日安全生产活动总结
2014/07/05 职场文书
“四风”问题自我剖析材料思想汇报
2014/09/23 职场文书
企业整改报告范文
2014/11/08 职场文书
2015年财政局工作总结
2015/05/21 职场文书
工作会议简报
2015/07/20 职场文书
未来,这5大方向都很适合创业
2019/07/22 职场文书
python自动化调用百度api解决验证码
2021/04/13 Python