文章目录
Canvas特效页面分享
canvas是一个可以使用脚本(通常为JavaScript)来绘制图形的 HTML 元素.例如,它可用于绘制图表、制作图片构图或者制作简单的(以及不那么简单的)动画。
Canvas 的默认大小为300像素×150像素(宽×高,像素的单位是px)。但是,可以使用HTML的高度和宽度属性来自定义Canvas 的尺寸。为了在 Canvas 上绘制图形,我们使用一个JavaScript上下文对象,它能动态创建图像( creates graphics on the fly)。
canvas>看起来和 img 元素很相像,唯一的不同就是它并没有 src 和 alt 属性。实际上, 标签只有两个属性—— width和height。这些都是可选的,并且同样利用 DOMproperties 来设置。当没有设置宽度和高度的时候,canvas会初始化宽度为300像素和高度为150像素。该元素可以使用CSS来定义大小,但在绘制时图像会伸缩以适应它的框架尺寸:如果CSS的尺寸与初始画布的比例不一致,它会出现扭曲。
getContext():
getContext() 方法返回一个用于在画布上绘图的环境。
参数 contextID 指定了您想要在画布上绘制的类型。当前唯一的合法值是 “2d”,它指定了二维绘图,并且导致这个方法返回一个环境对象,该对象导出一个二维绘图 API。
lineWidth:
绘制线条宽度
strokeStyle:
trokeStyle 属性设置或返回用于笔触的颜色、渐变。
createLinearGradient():
createLinearGradient() 方法创建线性的渐变对象。
渐变可用于填充矩形、圆形、线条、文本等等context.createLinearGradient(x0,y0,x1,y1)
beginPath:
开始绘画
lineCap:
lineCap 属性设置或返回线条末端线帽的样式。
Butt:默认。向线条的每个末端添加平直的边缘。
Round:向线条的每个末端添加圆形线帽。
Square:向线条的每个末端添加正方形线帽。
arc():
arc() 方法创建弧/曲线(用于创建圆或部分圆)。
context.arc(x,y,r,sAngle,eAngle,counterclockwise)
补充(弧度):弧长等于半径的弧,其所对的圆心角为1弧度;
根据定义,一周的弧度数为2πr/r=2π,360°角=2π弧度,因此,1弧度约为57.3°,即57°17’44.806’’,1°为π/180弧度,近似值为0.01745弧度,周角为2π弧度,平角(即180°角)为π弧度,直角为π/2弧度。
Stroke:
stroke() 方法会实际地绘制出通过 moveTo() 和 lineTo() 等方法定义的路径
requestAnimationFrame:
为什么不使用setTimeout和setInterval方法:
1、即使向其传递毫秒为单位的参数,它们也不能达到ms的准确性。这是因为javascript是单线程的,可能会发生阻塞。
2、没有对调用动画的循环机制进行优化。
3、没有考虑到绘制动画的最佳时机,只是一味地以某个大致的事件间隔来调用循环。
其实,使用setInterval或setTimeout来实现主循环,根本错误就在于它们抽象等级不符合要求。我们想让浏览器执行的是一套可以控制各种细节的api,实现如“最优帧速率”、“选择绘制下一帧的最佳时机”等功能。但是如果使用它们的话,这些具体的细节就必须由开发者自己来完成。
requestAnimationFrame不需要使用者指定循环间隔时间,浏览器会基于当前页面是否可见、CPU的负荷情况等来自行决定最佳的帧速率,从而更合理地使用CPU。
详细解释请跳转另一个大佬的笔记
clearRect:
清空画布
cancelAnimationFrame:
此方法可以停止函数动画的执行
save:用来保存Canvas的状态。save之后,可以调用Canvas的平移、放缩、旋转、错切、裁剪等操作。 restore:用来恢复Canvas之前保存的状态。防止save后对Canvas执行的操作对后续的绘制有影响
Rotate:
rotate() 方法旋转当前的绘图。
globalCompositeOperation :
globalCompositeOperation 属性设置或返回如何将一个源(新的)图像绘制到目标(已有)的图像上
(destination-out):在源图像外显示目标图像。只有源图像外的目标图像部分会被显示,源图像是透明的
大家如果认真看完的话应该已经可自己写canvas动画了,但是这里还是给大家附上我自己写的一个刮刮乐小demo,
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title>audio</title>
<style type="text/css">
canvas {
/* canvas 默认宽高 300*150
css设置的宽高,只能设置canvas对象在页面显示的大小。
并不能增加画布内部的像素数
*/
border: 1px solid black;
/* width: 500px;
height: 500px; */
margin: 0 auto;
position: absolute;
left: 0;
top: 0;
}
div {
width: 500px;
height: 500px;
background: url("https://ss1.bdstatic.com/70cFvXSh_Q1YnxGkpoWK1HF6hhy/it/u=4210473879,3554842544&fm=27&gp=0.jpg") no-repeat;
background-size: 100% 100%;
position: relative;
}
div p {
font-size: 50px;
line-height: 500px;
text-align: center;
width: 100%;
}
</style>
</head>
<body>
<!-- 在标签上添加canvas像素值 -->
<div>
<p>一等奖</p>
<canvas id="canvasId" width="500" height="500">您的浏览器不支持canvas!</canvas>
</div>
<script type="text/javascript">
var cv = document.getElementById("canvasId"),
p = document.getElementsByTagName("p")[0];
//设置中奖几率
var num = 10000 * Math.random(),
result = "谢谢惠顾";
if (num < 1000) {
result = "三等奖";
}
if (num < 50) {
result = "二等奖";
}
if (num < 5) {
result = "一等奖";
}
p.innerText = result;
try {
var ct = cv.getContext("2d");
//绘制背景色
ct.fillStyle = "#aaa";
ct.fillRect(0, 0, 500, 500);
//设置绘制状态
ct.lineCap = "round"; //设置线条两端为圆弧
ct.lineJoin = "round"; //设置线条转折为圆弧
ct.lineWidth = 60;
/*设置新绘制清除新绘制内容和原内容的重叠区域*/
ct.globalCompositeOperation = "destination-out";
} catch (e) {
console.log(e);
}
//绘制曲线
// var flag = false,
// lx, ly;
// cv.onmousedown = function (e) {
// flag = true;
// lx = e.offsetX;
// ly = e.offsetY;
// }
//
// cv.onmousemove = function (e) {
// if (flag) {
// ct.beginPath();
// ct.moveTo(lx, ly);
// ct.lineTo(e.offsetX, e.offsetY);
// ct.stroke();
// ct.closePath();
//
// //更新坐标
// lx = e.offsetX;
// ly = e.offsetY;
// }
// }
//
// cv.onmouseup = function (e) {
// flag = false;
// }
var lx ;
var ly ;
function touchMove(event) {
console.log(1)
event.preventDefault(); //阻止事件默认动作
var completed = 0;
var data = ct.getImageData(0, 0, 500, 500).data;
var total = data.length / 4;
var touch = event.touches[0];
var x = touch.pageX;
var y = touch.pageY;
console.log(lx)
console.log(ly)
ct.beginPath();
ct.moveTo(lx, ly); //线条开始位置
ct.lineTo(x, y);//线条结束位置
ct.stroke();
ct.closePath();
//更新坐标
lx = x;
ly = y;
// ct.beginPath();
// ct.arc(x, y, 20, 0, Math.PI * 2, false);
// ct.fill();
for (var i = 3; i < data.length; i += 4) {
if (data[i] === 0) {
completed += 1;
}
}
if (completed > total / 1.4) {//根据自己要刮开的面积大小改变数值
console.log("已完成刮奖");
ct.clearRect(0, 0, 500, 500);//完成刮奖后清除剩余没有刮开的地方
}
};
function touchStart(event) {
var touch = event.touches[0];
lx = touch.pageX;
ly = touch.pageY;
console.log(lx)
console.log(ly)
}
cv.addEventListener("touchmove", touchMove, false);//注册事件
cv.addEventListener("touchstart", touchStart, false);//注册事件
</script>
</html>
PS:在这个demo中我使用的事件是移动端的触摸事件,想要在PC端实现的同学把事件改为鼠标触发即可。
同时在这个demo里还有一个设计思路,我们消除黑幕的时候是不是可以考虑重复话圆点来完成呢?或者使用锯齿波浪线?