canvas 文字颜色_canvas 中普通动效与粒子动效的实现
(给前端大全加星标,提升前端技能)
作者:薄荷前端
https://github.com/BooheeFE/weekly/issues/26
canvas 用于在网页上绘制图像、动画,可以将其理解为画布,在这个画布上构建想要的效果。
canvas 可以绘制动态效果,除了常用的规则动画之外,还可以采用粒子的概念来实现较复杂的动效,本文分别采用普通动效与粒子特效实现了一个简单的时钟。
普通时钟
普通动效即利用 canvas 的 api,实现有规则的图案、动画。
效果
该效果实现比较简单,主要分析一下刻度与指针角度偏移的实现。
绘制刻度
此例为小时刻度的绘制:表盘上共有 12 个小时,Math.PI 为 180°,每小时占据 30°。
.save()表示保存 canvas 当前环境的状态,在此基础上进行绘制。绘制完成之后,返回之前保存过的路径状态和属性。
分钟刻度同理,改变角度与样式即可。
// 小时时间刻度offscreenCanvasCtx.save();for (var i = 0; i 12; i++) { offscreenCanvasCtx.beginPath(); // 刻度颜色 offscreenCanvasCtx.strokeStyle = "#fff"; // 刻度宽度 offscreenCanvasCtx.lineWidth = 3; // 每小时占据30° offscreenCanvasCtx.rotate(Math.PI / 6); // 开始绘制的位置 offscreenCanvasCtx.lineTo(140, 0); // 结束绘制的位置; offscreenCanvasCtx.lineTo(120, 0); // 绘制路径 offscreenCanvasCtx.stroke();}offscreenCanvasCtx.restore();
指针指向
以秒针为例:获取当前时间的秒数,并计算对应的偏移角度
var now = new Date(), sec = now.getSeconds(), min = now.getMinutes(), hr = now.getHours(); hr = hr 12 ? hr - 12 : hr;
//秒针 offscreenCanvasCtx.save(); offscreenCanvasCtx.rotate(sec * (Math.PI / 30)); ...... offscreenCanvasCtx.stroke();
粒子动效
canvas 可以用来绘制复杂,不规则的动画。粒子特效可以用来实现复杂、随机的动态效果。
粒子,指图像数据imageData中的每一个像素点,获取到每个像素点之后,添加属性或事件对区域内的粒子进行交互,达到动态效果。
效果
粒子获取
以下图的图片转化为例,该效果是先在 canvas 上渲染图片,然后获取文字所在区域的每个像素点。
let image = new Image();image.src = "../image/logo.png";let pixels = []; //存储像素数据let imageData;image.width = 300;image.height = 300;// 渲染图片,并获取该区域内像素信息image.onload = function() { ctx.drawImage( image, (canvas.width - image.width) / 2, (canvas.height - image.height) / 2, image.width, image.height ); imageData = ctx.getImageData( (canvas.width - image.width) / 2, (canvas.height - image.height) / 2, image.width, image.height ); //获取图表像素信息 //绘制图像};
像素信息
图片的大小为 300*300,共有 90000 个像素,每个像素占 4 位,存放 rgba 数据。
粒子绘制
function getPixels() { var pos = 0; var data = imageData.data; //RGBA的一维数组数据 //源图像的高度和宽度为300px for (var i = 1; i <= image.width; i++) { for (var j = 1; j <= image.height; j++) { pos = [(i - 1) * image.width + (j - 1)] * 4; //取得像素位置 if (data[pos] >= 0) { var pixel = { x: (canvas.width - image.width) / 2 + j + Math.random() * 20, //重新设置每个像素的位置信息 y: (canvas.height - image.height) / 2 + i + Math.random() * 20, //重新设置每个像素的位置信息 fillStyle: "rgba(" + data[pos] + "," + data[pos + 1] + "," + data[pos + 2] + "," + data[pos + 3] + ")" }; pixels.push(pixel); } } }}function drawPixels() { var canvas = document.getElementById("myCanvas"); var ctx = canvas.getContext("2d"); ctx.clearRect(0, 0, canvas.width, canvas.height); var len = pixels.length, curr_pixel = null; for (var i = 0; i curr_pixel = pixels[i]; ctx.fillStyle = curr_pixel.fillStyle; ctx.fillRect(curr_pixel.x, curr_pixel.y, 1, 1); }}
粒子时钟
渲染文字时钟
function time() { ctx.clearRect(0, 0, canvas.width, canvas.height); ctx.font = "150px 黑体"; ctx.textBaseline = "top"; ctx.fillStyle = "rgba(245,245,245,0.2)"; ctx.fillText( new Date().format("hh:mm:ss"), (canvas.width - textWidth) / 2, (canvas.height - textHeight) / 2, textWidth, textHeight );}
效果
获取粒子
文字转换粒子概念同上,获取选定区域的像素,根据筛选条件进行选择并存入数组。经过遍历后重新绘制。
function getPixels() { let imgData = ctx.getImageData( (canvas.width - textWidth) / 2, (canvas.height - textHeight) / 2, textWidth, textHeight ); let data = imgData.data; pixelsArr = []; for (let i = 1; i <= textHeight; i++) { for (let j = 1; j <= textWidth; j++) { pos = [(i - 1) * textWidth + (j - 1)] * 4; //取得像素位置 if (data[pos] >= 0) { var pixel = { x: j + Math.random() * 20, //重新设置每个像素的位置信息 y: i + Math.random() * 20, //重新设置每个像素的位置信息 fillStyle: "rgba(" + data[pos] + "," + data[pos + 1] + "," + data[pos + 2] + "," + data[pos + 3] + ")" }; pixelsArr.push(pixel); } } }}
imgData保存了所选区域内的像素信息,每个像素点占据 4 位,保存了 RGBA 四位信息。筛选每个像素的第四位,这段代码中将所有透明度不为 0 的像素都保存到了数组pixelsArr中。
x、y记载了该粒子的位置信息,为了产生效果图中的运动效果,给每个粒子添加了 0-20 个像素的偏移位置,每次重绘时,偏移位置随机生成,产生运动效果。
粒子重绘
获取粒子之后,需要清除画布中原有的文字,将获取到的粒子重新绘制到画布上去。
function drawPixels() { // 清除画布内容,进行重绘 ctx.clearRect(0, 0, canvas.width, canvas.height); for (let i in pixelsArr) { ctx.fillStyle = pixelsArr[i].fillStyle; let r = Math.random() * 4; ctx.fillRect(pixelsArr[i].x, pixelsArr[i].y, r, r); }}
粒子重绘时的样式为筛选像素时原本的颜色与透明度,并且每个在画布上绘制每个粒子时,定义大小参数 r,r 取值为 0-4 中随机的数字。最终生成的粒子大小随机。
实时刷新
获取粒子并成功重绘之后,需要页面实时刷新时间。这里采用window.requestAnimationFrame(callback)方法。
function time() { ...... getpixels(); //获取粒子 drawPixels(); // 重绘粒子 requestAnimationFrame(time); }
window.requestAnimationFrame(callback) 方法告诉浏览器您希望执行动画并请求浏览器在下一次重绘之前调用指定的函数来更新动画。该方法使用一个回调函数作为参数,这个回调函数会在浏览器重绘之前调用。
该方法不需要设置时间间隔,调用频率采用系统时间间隔(1s)。
文档解释戳这里
效果
总结
本文主要通过两种不同的方式实现了时钟的动态效果,其中粒子时钟具有更多的可操作性。在以后的 canvas 系列中会针对粒子系统实现更多的动态效果。
推荐阅读
(点击标题可跳转阅读)
canvas 入门实战--邀请卡生成与下载
基于 HTML5 Canvas 的交互式地铁线路图
Canvas 动画之支付宝价格拖动选择
觉得本文对你有帮助?请分享给更多人
关注「前端大全」加星标,提升前端技能
喜欢就点一下「好看」呗~
canvas 文字颜色_canvas 中普通动效与粒子动效的实现相关推荐
- canvas 文字颜色_Canvas 超全教程
一.简介 <canvas>是一个可以使用脚本(通常为JavaScript)来绘制图形的 HTML 元素.例如,它可以用于绘制图表.制作图片构图或者制作简单的(以及不那么简单的)动画. &l ...
- canvas 文字颜色_Canvas技术概述
Canvas简介 在学习一项新技术之前,先了解这项技术的历史发展及成因会帮助我们更深刻的理解这项技术. 历史上,canvas最早是由Apple Inc. 提出的,在Mac OS X webkit中创建 ...
- canvas 文字颜色_Canvas基本功能Canvas标签
Canvas基本功能 在所有的桌面应用程序的开发平台中几乎都有 Canvas 组件. Canvas组件已经成为绘图组件的代名词. Canvas元素本制裁上是在浏览器中提供一块儿可绘制的区域,JavaS ...
- html5 canvas文字颜色,我可以通过HTML5 Canvas中的字符文本颜色来做吗?
我告诉你这个解决方法.基本上你一次输出一个字符,并使用内置的measureText()函数来确定每个字母的宽度.然后我们将我们想要绘制的位置偏移相同的数量.您可以修改此代码段,以产生所需的效果. 假设 ...
- canvas 文字颜色_实现一个canvas小画板
<canvas>是HTML5新增的元素,可用于通过使用JavaScript中的脚本来绘制图形.例如,它可以用于绘制图形,制作照片,创建动画,甚至可以进行实时视频处理或渲染. --摘自MDN ...
- canvas 文字颜色_一篇图文学会HTML5的canvas标签,直线曲线文字渐变,统统可以有...
什么是 canvas? 通常情况下,我们可以认为和 是同一个效果的html元素,他们都是在浏览器显示区域绘制一个矩形的"区域".这个区域我们可以附以选择器进行丰富的显示效果. 但是 ...
- Android自定义View高级动效---粒子动效实现|音乐播放器粒子动效|实现酷我网易云粒子动效
篇章目标介绍 之前看到网易云,酷我音乐都发布过用于播放器页面粒子动效的效果,于是打算自己也动手做一个,产品目标是对标酷我手机app的动效设计,实现过程完全基于自身的推测理解予以实现.计划通过两次完全完 ...
- Canvas实现网页星空背景粒子动效跟随光标
目 录 1. 设计思路 2. 星空背景图片 3. 页面代码 4. 效果图 1. 设计思路 1. 利用样式插入星空背景图片: 2.设置窗口改变时自动修改画布大小(自适应): 3. 编写随机函数(随机数 ...
- Viewpager中改变PagerTabStrip的颜色(背景色,指示条颜色,文字颜色)
Viewpager中改变PagerTabStrip的颜色(背景色,指示条颜色,文字颜色) 效果图: 改变指示条颜色: pagerTabStrip为PagerTabStrip的实例: pagerTabS ...
最新文章
- 超越EfficientNet,GPU上加速5倍,何恺明组CVPR 2020论文提出新型网络设计范式
- UA MATH524 复变函数9 柯西公式与幂级数展开
- Android使用腾讯浏览服务X5内核
- 初一模拟赛总结(6.6 my brother高考前一天,加油!(。・`ω´・。))
- 漫步微积分十九——牛顿法解方程
- 互联网架构,如何进行容量设计?
- Windows ESXI 5.5 升級到 VCSA 6.5
- Ubuntu18.04之微信中文乱码解决
- HTML5新表单新功能解析
- Cairo-Dock 系统关机无效
- 基于安卓Android银行排队叫号系统设计与实现
- BIG5, GB(GB2312, GBK, ...), Unicode编码, UTF8, WideChar, MultiByte, Char说明与区别
- 程序员真的需要一台 Mac 吗?
- 云业务“探路” 中国联通成立产业互联网子公司
- 开热点给电脑消耗大吗_用手机热点上电脑是不是比手机用流量更费一些?
- 微信营销与博客营销的区别
- 上亿会员 为b站会员购众筹项目打下消费基础
- Qt之自定义QLineEdit
- 测试路由和设备连接速度的软件,如何简单,快速地在家中测试无线路由器的速度和性能?...
- erLang中的标点符号
热门文章
- Psych101(part6)--Day6
- 利用python爬虫(part12)--随机获取UserAgent
- mysql 数据库 额外_mysql – 拥有“额外”数据库查询有多糟糕?
- 显著性目标检测matlab代码_显著性目标检测代码全汇总!(包含2D、3D、4D以及Video)...
- 基类使用私有数据_C++作业之多继承与虚基类
- python怎么调用另一个文件的函数_python如何调用另一个py文件的所有函数?
- 数据链路层介质访问控制——信道划分、随机访问和轮询访问
- 为什么 SAP 电商云 Spartacus UI SSR 模式下的客户端应用,不会发起 product 请求
- SAP 电商云 Spartacus UI CheckoutDeliveryService 的单元测试设计
- Rxjs 里 Subject 和 BehaviorSubject 的区别