目录
canvas像素操作
事实上,直接通过ImageData对象操作像素数据,直接读取或将数据数组写入该对象中。
getImageData()
该方法可以获取一个包含画布场景像素数据的ImageData对象,它代表了画布区域的对象数据
ctx.getImageData(sx,sy,width,height)
sx:将要被提取的图像数据矩形区域的左上角x坐标
sy:将要被提取的图像数据矩形区域的左上角y坐标
width:将要被提取的图像数据矩形区域的宽度
height:将要被提取的图像数据矩形区域的高度
ImageData对象
ImageData对象中存储着canvas对象实际的像素数据,它包含以下几个只读属性:
width:图像的宽度,单位是像素
height:图像的高度,单位是像素
data:Unit8ClampedArray类型的一维数组,
包含着RGBA格式的整型数据,范围在0~255之间
ctx.createImageData(width,height)
该方法可以创建一个ImageData对象(默认是透明的)
putImageData()
该方法可以对场景进行像素数据的写入
putImageData(myImageData,dx,dy)
dx和dy参数表示你希望在场景的哪个位置绘制像素数据
单像素操作
获取单像素数据
function getinfo(imageData,x,y){
var color=[];
var data=imageData.data;
var w=imageData.width;
var h=imageData.height;
//(x,y) y*w+x
color[0]=data[(y*w+x)*4];
color[1]=data[(y*w+x)*4+1];
color[2]=data[(y*w+x)*4+2];
color[3]=data[(y*w+x)*4+3];
return color;
}
设置单像素数据
function setinfo(imageData,x,y,color){
var data=imageData.data;
var w=imageData.width;
var h=imageData.height;
//(x,y) y*w+x
data[(y*w+x)*4]=color[0];
data[(y*w+x)*4+1]=color[1];
data[(y*w+x)*4+2]=color[2];
data[(y*w+x)*4+3]=color[3];
}
马赛克效果
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
<style>
body{
background-color: gray;
}
.test{
position: absolute;
top: 0;
bottom: 0;
left: 0;
right: 0;
margin:auto;
background-color: white;
}
</style>
<script>
window.onload=function(){
var canvas=document.getElementsByTagName("canvas")[0];
if(canvas.getContext){
var ctx=canvas.getContext("2d");
var img=new Image();
img.src="/New/img/5.jpg";
img.onload=function(){
canvas.width=img.width*2;
canvas.height=img.height;
draw();
}
}
function draw(){
ctx.drawImage(img,0,0);
var oldimage=ctx.getImageData(0,0,img.width,img.height);
var newimage=ctx.createImageData(img.width,img.height);
//马赛克
var size=5;
for(var i=0;i<oldimage.height/size;i++){
for(var j=0;j<oldimage.width/size;j++){
var color=getinfo(oldimage,Math.floor(Math.random(0,size))+j*size,Math.floor(Math.random(0,size))+i*size);
for(var k=0;k<size;k++){
for(var g=0;g<size;g++){
setinfo(newimage,j*size+k,i*size+g,color);
}
}
}
}
ctx.putImageData(newimage,img.width,0);
}
function getinfo(imageData,x,y){
var color=[];
var data=imageData.data;
var w=imageData.width;
var h=imageData.height;
color[0]=data[(y*w+x)*4];
color[1]=data[(y*w+x)*4+1];
color[2]=data[(y*w+x)*4+2];
color[3]=data[(y*w+x)*4+3];
return color;
}
function setinfo(imageData,x,y,color){
var data=imageData.data;
var w=imageData.width;
var h=imageData.height;
//(x,y) y*w+x
data[(y*w+x)*4]=color[0];
data[(y*w+x)*4+1]=color[1];
data[(y*w+x)*4+2]=color[2];
data[(y*w+x)*4+3]=color[3];
}
}
</script>
</head>
<body>
<canvas class="test" width="500px" height="500px"></canvas>
</body>
</html>
合成
全局透明度的设置
globalAlpha=value
该属性影响倒canvas里所有图形的透明度,有效范围为0.0~1.0(默认为1.0)
覆盖合成
source:新的图像(源)
destination:已经绘制过的图像(目标)
globalCompositeOperation
- source-over(默认值):源在上面,新的图像层级比较高
- source-in:只留下源与目标的重叠部分(源的部分)
- source-out:只留下源超过目标的部分
- source-atop:砍掉源溢出的部分
- destination-over:目标在上面,旧的图像的层级比较高
- destination-in:只留下源与目标的重叠部分(目标的部分)
- destination-out:只留下目标超过源的部分
- destination-atop:砍掉目标溢出的部分
刮刮卡案例
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
<style>
*{
margin: 0;
padding: 0;
}
html,body{
height: 100%;
overflow: hidden;
}
.wrap,ul,ul>li{
height: 100%;
}
ul>li{
background-image: url(b.png);
background-size: 100% 100%;
}
canvas{
position: absolute;
top: 0;
left: 0;
transition: 2s;
}
</style>
<script>
window.onload=function(){
canvas=document.getElementsByTagName("canvas")[0];
canvas.width=document.documentElement.clientWidth;
canvas.height=document.documentElement.clientHeight;
if(canvas.getContext){
var ctx=canvas.getContext("2d");
var img=new Image();
img.src="a.png";
img.onload=function(){
draw();
}
}
function draw(){
var flag=0;
ctx.drawImage(img,0,0,canvas.width,canvas.height);
canvas.addEventListener("touchstart",function(ev){
ev=ev||event;
var touchC=ev.changedTouches[0];
var x=touchC.clientX-canvas.offsetLeft;
var y=touchC.clientY-canvas.offsetTop;
ctx.lineCap="round";
ctx.globalCompositeOperation="destination-out";
ctx.lineWidth=40;
ctx.lineJoin="round";
ctx.save();
ctx.beginPath();
ctx.moveTo(x,y);
ctx.lineTo(x+1,y+1);
ctx.stroke();
ctx.restore();
})
canvas.addEventListener("touchmove",function(ev){
ev=ev||event;
var touchC=ev.changedTouches[0];
var x=touchC.clientX-canvas.offsetLeft;
var y=touchC.clientY-canvas.offsetTop;
ctx.save();
ctx.lineTo(x,y);
ctx.stroke();
ctx.restore();
})
var flag=0;
canvas.addEventListener("touchend",function(ev){
var imageData=ctx.getImageData(0,0,canvas.width,canvas.height);
var allpx=imageData.width*imageData.height;
for(var i=0;i<allpx;i++){
if(imageData.data[4*i+3]==0){
flag++;
}
}
if(flag>=allpx/2){
canvas.style.opacity=0;
}
})
}
}
</script>
</head>
<body>
<div class="wrap">
<canvas></canvas>
<ul>
<li></li>
</ul>
</div>
</body>
</html>
others
将画布导出为图像
toDataURL(canvas上的方法)
事件操作
isPointInPath(x,y)
判断在当前路径中是否包含检测点
注意:此方法只作用于最新画出的canvas图像
音视频标签
video标签的属性
- width:视频显示区域的宽度
- height:视频显示区域的高度
- poster:一个海报帧的URL,用于用户播放或跳帧之前展示
- src:要嵌到页面的视频的URL
- controls:显示或隐藏控制界面
- autoplay:媒体是否自动播放
- loop:媒体是否循环播放
- muted:是否静音
- preload:是否缓存
audio标签的属性
- src
- controls
- autoplay
- loop
- muted
- preload
音视频js相关属性
- currentTime:开始到播放现在所用时间(可读写)
- duration:媒体总时间(只读)
- muted:是否静音(可读写,相比于volume优先级更高)
- volume:0.0~1.0的音量相对值(可读写)
- paused:媒体是否暂停(可读)
- ended:媒体是否播放完(只读)
- error:媒体发生错误的时候,返回错误代码(只读)
- currentSrc:以字符串的形式返回媒体地址(只读)
除此之外,视频还有:
- poster:视频播放前的预览图片(可读写)
- width、height:高宽(可读写)
- videoWidth、videoHeight:视频的实际高宽(只读)
音视频标签的函数
- play():媒体播放
- pause():媒体暂停
- load():重新加载媒体
音阶导航实例
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
<style>
*{
margin: 0;
padding: 0;
}
html,body{
height: 100%;
overflow: hidden;
}
ul{
margin: 100px auto;
background-color: antiquewhite;
width: 605px;
height: 40px;
text-align: center;
line-height: 40px;
list-style: none;
border: 1px solid;
}
ul>li{
width: 100px;
height: 100%;
float: left;
overflow: hidden;
transition: 0.5s;
}
ul>li:not(:last-child){
border-right: 1px solid;
}
a{
text-decoration: none;
color: black;
display: block;
}
.bottom{
height: 40px;
background-color: gray;
transition: 0.5s;
}
ul>li:hover .bottom{
transform: translateY(-40px);
}
</style>
<script>
window.onload=function(){
var liNodes = document.querySelectorAll("ul>li");
var audio = document.querySelector("audio");
for(var i=0;i<liNodes.length;i++){
liNodes[i].addEventListener("mouseenter",function(){
var flag = this.getAttribute("data-flag");
if(flag){
audio.src="http://s8.qhimg.com/share/audio/piano1/"+flag+"4.mp3";
audio.play();
}
})
}
}
</script>
</head>
<body>
<audio src=""></audio>
<div class="wrap">
<ul>
<li data-flag="a">
<a href="javascrpit:;">我的主页</a>
<div class="bottom"></div>
</li>
<li >
<a href="javascrpit:;">新闻</a>
<div class="bottom"></div>
</li>
<li data-flag="b">
<a href="javascrpit:;">游戏</a>
<div class="bottom"></div>
</li>
<li>
<a href="javascrpit:;">音乐</a>
<div class="bottom"></div>
</li>
<li data-flag="c">
<a href="javascrpit:;">电影</a>
<div class="bottom"></div>
</li>
<li>
<a href="javascrpit:;">电视剧</a>
<div class="bottom"></div>
</li>
</ul>
</div>
</body>
</html>