h5新增元素,通过js脚本来绘制图形
<canvas> 对出现,默认width:300px height:150px 画布的高宽不要再css中去指定
替换内容,浏览器不支持canvas,会正常显示
需要找到它的渲染上下文,通过getContext(‘2d’)方法
canvas中画,只有矩形是原生的图形绘制。
绘制矩形
在css中不支持小数像素。
同步思维,有别于浏览器本身渲染机制
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
<style type="text/css">
*{
margin: 0;
padding: 0;
}
html,body{
height: 100%;
overflow: hidden;
}
body{
background-color:burlywood;
}
#test{
background-color: azure;
position: absolute;
left: 0;
top: 0;
bottom: 0;
right: 0;
margin: auto;
}
</style>
</head>
<body>
<canvas id="test" width="300" height="300">
<span>不支持画布元素,请您换成萌萌谷歌</span>
</canvas>
</body>
<script>
window.onload = function(){
var canvas = document.getElementById('test')
if(canvas.getContext){
var ctx = canvas.getContext("2d");//模式 2d
ctx.fillStyle = 'pink' //填充颜色
ctx.strokeStyle = 'blue'//边框色
ctx.lineWidth = 5//边框宽度
//样式
ctx.lineJoin = bevel//round miter
//获得渲染上下文和他的功能参数2d
ctx.fillRect(0,0,100,100) //填充的矩形
ctx.strokeRect(100,100,100,50)//边框矩形
//在【偏移量处往上画0.5,往下0.5
ctx.clearRect(100,100,100,100)//清楚这个区域内的矩形
//覆盖渲染
}
}
</script>
</html>
绘制路径
图形的基本元素是路径,路径是不通道额颜色和宽度的线段或曲线相连成的不同形状的点的集合
路径封闭以后就可以通过渲染和填充来操作区域
moveTo&lineTo
moveTo会抬起画笔,lineTo不会继续画
<script>
window.onload = function(){
var canvas = document.getElementById('test')
if(canvas.getContext){
var ctx = canvas.getContext("2d");//模式 2d
ctx.strokeStyle = 'green'
ctx.fillStyle = 'pink'
ctx.lineWidth = 4
ctx.moveTo(50,50)//起始点
ctx.lineTo(50,100)
ctx.lineTo(100,100)
ctx.lineTo(50,50)
ctx.closePath() //闭合路径
ctx.stroke()//线 --》不会自动合并路径closePath
// ctx.fill()//填充 会自动合并路径
ctx.beginPath()//清空路径容器
ctx.moveTo(100,100)//起始点
ctx.lineTo(150,100)
ctx.lineTo(150,150)
ctx.lineTo(100,100)
ctx.stroke()
ctx.fill()
//直接画矩形
ctx.rect(10,10,50,50)
ctx.fill()
ctx.beginPath()//清空路径容器
ctx.moveTo(300,300)//起始点
ctx.lineTo(400,400)
ctx.lineCap = 'round' //square 线段末端以不同的形状结束
}
}
</script>
save&restore
栈结构,先进后出
路径容器:每次调用路径api时,都会往路径容器里做登记,调用beginPath时,清空整个路径容器
样式容器:没戏调用样式api时,都会往样式容器中做登记,调用save时候,将容器里的状态压入样式栈,调用restore时候,将样式栈栈顶状态弹出到样式容器里,进行覆盖
样式栈:调用save时,将样式容器中的状态压入样式栈,调用restore时候,将样式栈的栈顶状态弹出到样式容器中,进行覆盖
一个save对应一个restore:成对出现
save:报尺寸当前的一个状态:strokeStyle fillstyle lineWidth lineCap lineJoin
restore:弹出栈顶相关的状态
绘制曲线
window.onload = function(){
var canvas = document.getElementById('test')
if(canvas.getContext){
var ctx = canvas.getContext("2d");//模式 2d
//圆
ctx.beginPath()
ctx.moveTo(100,100)
ctx.arc(100,100,50,0,270*Math.PI/180,true)
// x,y圆心坐标, 半径, 开始弧度,结束弧度,顺逆时针
ctx.closePath()//自动合并路径
ctx.stroke()
//圆弧
ctx.beginPath()
ctx.moveTo(50,150)
ctx.arcTo(100,100,200,200,50)//三个点确定一个圆弧
ctx.closePath()//自动合并路径
ctx.stroke()
//二次贝塞尔
ctx.beginPath()
ctx.moveTo(50,150)
ctx.quadraticCurveTo(200,0,200,200)
ctx.closePath()//自动合并路径
ctx.stroke()
//三次贝塞尔
ctx.beginPath()
ctx.moveTo(50,150)
ctx.bezierCurveTo(200,0,200,200,300,100)
ctx.closePath()//自动合并路径
ctx.stroke()
}
}
变换
放大:使画布内css像素的个数变少,单个css像素所占据的实际物理尺寸变大
缩小:使画布内css像素的个数变多,单个css像素所占据的实际物理尺寸变小
<script>
window.onload = function(){
var canvas = document.getElementById('test')
if(canvas.getContext){
var ctx = canvas.getContext("2d");//模式 2d
//translate(x,y) 移动canvas原点到不同的位置
ctx.translate(100,200)//在canvas会有累加操作,相当于写了两次原点的位置
ctx.beginPath()
ctx.fillRect(0,0,100,100)
//rotate(angle) 旋转的角度 顺时针
ctx.rotate(45*Math.PI/180)//累加的,按照原点旋转
ctx.fillRect(0,0,100,100)
//scale(x,y) 对形状,位图进行缩放
ctx.scale(.5,.2)
//css像素是一个抽像的单位
//放大:css像素的面积 区域内css像素的个数变少
//缩小:css像素的面积 区域被css像素的个数变多
}
}
</script>
变换实例
<script>
window.onload = function(){
var flag = 0
var scale = 0
var flagScale = 0
var canvas = document.getElementById('test')
if(canvas.getContext){
var ctx = canvas.getContext("2d");//模式 2d
ctx.save()
ctx.translate(150,150)//原点的位置
ctx.beginPath()
ctx.fillRect(-50,-50,100,100)
ctx.restore()
setInterval(function(){
flag++
ctx.clearRect(0,0,canvas.width,canvas.height)
ctx.save()
ctx.translate(150,150)
ctx.rotate(flag*Math.PI/180)
//放大旋转
if(scale==100){
flagScale = -1
}else if(scale==0){
flagScale = 1
}
scale+=flagScale
ctx.scale(scale/50,scale/50)
ctx.beginPath()
ctx.fillRect(-50,-50,100,100)
ctx.restore()
})
}
}
</script>
canvas使用图片
使用图片确定图片完成后才可以操作。
<script>
window.onload = function(){
var canvas = document.getElementById('test')
if(canvas.getContext){
var ctx = canvas.getContext("2d");//模式 2d
var img = new Image();
img.src = "img/企业微信截图_158428260222.png";
img.onload = function(){
draw();
}
function draw(){
//引入图片
// ctx.drawImage(img,10,10,img.width,img.height)
//图片用作背景
// var pattern = ctx.createPattern(img,'no-repeat')//repeat no-repeat repeat-x repeat-y
// ctx.fillStyle = pattern;
// ctx.fillRect(0,0,300,300)
//线性渐变
var gradient = ctx.createLinearGradient(0,0,300,300)
gradient.addColorStop(0,"red")
gradient.addColorStop(0.5,"blue")
gradient.addColorStop(1,"yellow")
ctx.fillStyle = gradient;
ctx.fillRect(0,0,300,300)
//径向渐变
var gradient = ctx.createRadialGradient(150,150,50,50,150,150)
gradient.addColorStop(0,"red")
gradient.addColorStop(0.5,"blue")
gradient.addColorStop(1,"yellow")
ctx.fillStyle = gradient;
ctx.fillRect(0,0,300,300)
}
}
}
</script>
使用图片做一个飞鸟相关的动画
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<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;
}
body{
background-color:burlywood;
}
#test{
background-color:white;
position: absolute;
left: 0;
top: 0;
bottom: 0;
right: 0;
margin: auto;
}
</style>
</head>
<body>
<canvas id="test" width="300" height="300"></canvas>
</body>
<script>
window.onload = function(){
var canvas = document.getElementById('test')
canvas.width = document.documentElement.clientWidth//设置画布大小
canvas.height = document.documentElement.clientHeight
if(canvas.getContext){
var ctx = canvas.getContext('2d')
var flag = 0//更改图片
var value = 0//刷新图片出现的位置
setInterval(function(){
ctx.clearRect(0,0,canvas.width,canvas.height)//每次清空前面的图片
value+=10
flag++;
if(flag==9){
flag=1
}
var img = new Image()//引入图片
img.src = "img/q_r"+(flag)+".jpg"
img.onload = function(){
draw(this)//加载完成以后画图
}
},100)
function draw(img){
ctx.drawImage(img,value,0)//图片和要放的位置
}
}
}
</script>
</html>
文本绘制
font属性在指定时,必须要有大小和字体(只有一种字体,sans-serif)
right center left 文本居中左对齐右对齐 center的时候文本的居中是在fillText所给的值,一般在x的右边一半在x的左边
ctx.textAlign = 'center'
文本的水平垂直居中操作 fillText设置元素的(画布尺寸-元素尺寸)/2
<script type="text/javascript">
window.onload=function(){
var canvas =document.getElementById("test");
if(canvas.getContext){
var ctx = canvas.getContext("2d");
ctx.font = "60px sans-serif"//只有一种字体
ctx.fillStyle = 'green'
//right center left 文本居中左对齐右对齐 center的时候文本的居中是在fillText所给的值,一般在x的右边一半在x的左边
ctx.textAlign = 'center'
//文本的基线 top middle bottom
ctx.textBaseline = 'top'
ctx.fillText('ss',100,111)
ctx.strokeText('ss',200,200)
var obj =ctx.measureText('ss')//返回一个包含文本尺寸的信息对象 ,必须包含一个参数
//文本的水平垂直居中
}
}
</script>
像素操作
直接通过imageDate对象操纵像素数据,直接读取或将数据数组写入该对象中
imageDate:
width:横向像素点的个数 height:纵向像素点的个数
data:数组,每一个像素点的rgba信息 --->canvas透明度0-->255
<script type="text/javascript">
window.onload=function(){
var canvas =document.getElementById("test");
if(canvas.getContext){
var ctx = canvas.getContext("2d");
ctx.fillRect(0,0,100,100)
//40000个像素点,
var imageDate = ctx.getImageDate(0,0,100,100)//拿到区域内的信息
for(var i=0;i<imageDate.data.length;i++){
imageDate.data[4*i+3] = 100//改变透明度
}
ctx.putImageDate(imageDate,0,0)
//创建一个新的ImageDate对象
ctx.createImageDate(100,100)//默认创建的是一个rgba(0,0,0,0)黑色
}
}
</script>
单像素操作
<script type="text/javascript">
window.onload=function(){
var canvas =document.getElementById("test");
if(canvas.getContext){
var ctx = canvas.getContext("2d");
ctx.save()
ctx.fillStyle = "green"
ctx.beginPath()
ctx.fillRect(0,0,100,100)
ctx.restore()
var ImageDate = ctx.getImageData(0,0,canvas.width,canvas.height)
var color = getPxInfo(ImageDate,12,12)
console.log(color)
//改变一行像素的颜色
for(var i = 0;i<ImageDate.width;i++){
setPxInfo(ImageDate,i,45,[0,0,0,255])//
}
ctx.putImageData(ImageDate,0,0)
//知道偏移量改变单个像素
}
function getPxInfo(ImageDate,x,y){
var color = [];
var data = ImageDate.data;
var w = ImageDate.width
var h = ImageDate.height
color[0] = data[(y*w+x)*4+0]
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 setPxInfo(ImageDate,x,y){
var color = [];
var data = ImageDate.data;
var w = ImageDate.width
var h = ImageDate.height
data[(y*w+x)*4+0] = 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>
全局透明度设置
globalAlpha = (0-1)
合成
ctx.globalCompositeOperation = 'source-over'
source-in只留下源于目标重叠的部分(源的那一部分)
source-out只留下源超过目标的部分
source-atop 砍掉源溢出的部分
destination-over 目标在上面
destination-in 只留下源于目标重叠的部分(目标的那一部分)
destination-out:只留下超过源的部分
destination-atop:砍掉目标溢出的部分
<script type="text/javascript">
window.onload = function(){
var canvas = document.getElementById('test')
if(canvas.getContext){
var ctx = canvas.getContext('2d')
//ctx.globalCompositeOperation = 'source-over'//源在上面
ctx.fillStyle = 'pink'
//ctx.globalAlpha = 0.5;//全局透明度设置
ctx.fillRect(0,0,100,100)
ctx.globalCompositeOperation = 'source-in'
ctx.fillStyle = 'green'
ctx.fillRect(50,50,100,100)
}
}
</script>
others
1.将画布导出为图像
canvas.toDataURL();
2.给canvas加事件
ctx.isPointInPath(x,y)
<script type="text/javascript">
window.onload=function(){
var canvas =document.getElementById("test");
//var result = canvas.toDataURL();
if(canvas.getContext){
var ctx = canvas.getContext("2d")
ctx.arc(100,100,50,0,360*Math.PI/180)
ctx.fill()
ctx.beginPath()
ctx.arc(200,200,50,0,360*Math.PI/180)
ctx.fill()
canvas.onclick = function(ev){
ev = ev||event //解决兼容问题
var x = ev.clientX - canvas.offsetLeft//获取鼠标的坐标
var y = ev.clientY - canvas.offsetTop
if(ctx.isPointInPath(x,y)){
alert(123)
}
}
}
}
</script>