canvas常用API 总结

getContext 获取canvas绘图的上下文环境
之后在绘图环境上有以下API
lineJoin 线头线尾的形状 round为圆角
lineWidth 线的宽度
font 设置字体
fillText 填充文字 第一个参数是文本 第二个参数是X坐标,第三个参数是Y坐标
strokeRect 空心矩形,接收四个参数
fillStyle 填充样式 可以接受rgba或渐变
渐变例子

var gradient=can2_context.createLinearGradient(0,500,0,700);
gradient.addColorStop(0,'blue')
gradient.addColorStop(0.25,'white')
gradient.addColorStop(1,'blue')
can2_context.fillStyle=gradient;
can2_context.fillRect(0,500,canvas_2.width,700)

createLinearGradient的四个参数表示渐变的方向 0,500,0,700表示的是垂直方向渐变
addColorStop 第一个参数填0~1之间的数 第二个参数添颜色
fillRect 实心矩形


放射性渐变
这里用到了createRadialGradient这个API 这个API接收6个参数,前三个表示底下的圆,后三个表示上面的圆,返回的实例依然可以用addColorStop

function Radia(bottom_x,bottom_y,bottom_r,top_x,top_y,top_r){
  this.bottom_x=bottom_x;
  this.bottom_y=bottom_y;
  this.bottom_r=bottom_r;
  this.top_x=top_x;
  this.top_y=top_y;
  this.top_r=top_r;
  this.gradient=can2_context.createRadialGradient(this.bottom_x,this.bottom_y,this.bottom_r,this.top_x,this.top_y,this.top_r)
}
Radia.prototype.addColor=function(){
  
  for(var i=0;i

图像填充 createPattern
图像填充也是一种fillStyle
该方法的第一个参数指定了图案所用图像,它可以是images元素,canvas元素或者video元素.第2个参数告诉浏览器,对图形进行扫描或填充时,应该如何重复该图案,这个参数的有效值是repeat,repeat-x,repeat-y,no-repeat

var canvas_2=document.getElementById("canvas_2");
var can2_context=canvas_2.getContext("2d");
var img=new Image();
img.src='./images/hover2.png'

function fillimage(){
    var pattern=can2_context.createPattern(img,'no-repeat')
    can2_context.fillStyle=pattern;
    can2_context.fillRect(0,0,canvas_2.width,canvas_2.height)
    

}
img.onload=function(e){
  fillimage()
}

canvas阴影
尽量不要用canvas做出阴影 因为效率并不是那么高

shadowBlur表示阴影效果如何延伸double值。浏览器在阴影智商运用高斯模糊时,将会用到该值,它与像素无关,只会被用到高斯模糊方程之中,其默认值为0
shadowColor CSS格式的颜色字符串,默认值是rgba(0,0,0,0)
shadowOffsetX 阴影在X轴方向的偏移量,以像素为单位,默认值为0
shadowOffsetY 阴影在Y轴方向的偏移量,以像素为单位,默认值是0

var canvas_2=document.getElementById("canvas_2");
var can2_context=canvas_2.getContext("2d");

var SHADOW_COLOR='rgba(0,0,0,0.7)'
function setShadow(){
  can2_context.shadowColor=SHADOW_COLOR;
  can2_context.shadowOffsetX=3;
  can2_context.shadowOffsetY=3; 
  can2_context.shadowBlur=5
}
setShadow();
can2_context.fillStyle="blue"
can2_context.fillRect(0,0,100,100)

关于beginPath

can2_context.beginPath();
 can2_context.rect(10,10,100,100)
 can2_context.stroke();

//  can2_context.beginPath()
 can2_context.rect(50,50,100,100)
 can2_context.stroke()

先调用beginPath()来清楚当前路径中的所有子路径,然后调用rect()来创建一条包含矩形4个点的子路径,再调用stroke()方法使得这个矩形出现在canvas上。
接下来这段代码再次调用rect()方法,不过这一次,由于没有调用beginPath()方法清除原有的路径,所以第二次对rect()的方法的调用,会向当前中增加一条子路径。最后该段代码再一次调用stroke()方法。这次stroke()方法的调用,将会使得当前路径中的两条子路径都被描边,这意味着它会重绘第一个矩形


关于非零环绕原则

“非零环绕规则”是这么来判断有自我交叉情况的路径的:
对于路径中的任意给定区域,从该区域内部画一条足够长的线段
使此线段的终点完全落在路径范围之外。
接下来,将计数器初始化为0,然后,每当这条线段与路径上的直线或曲线相交时,就
改变计数器的值。如果是与路径顺时针部分相交,则加1,如果是与路径逆时针部分相交就
减一。若计数器的最终值不是0,那么此区域就在路径里面,在调用fill()方法时,浏览器就会对其进行填充。如果最终值是0,那么此区域就不在路径内部,浏览器也就不会对其进行填充


剪纸漏洞效果主要是利用了canvas的非零环绕规则
简单来说就是canvas fill填充的是同一路径顺时针和逆时针中间的部分,简称
非零环绕

var canvas_2=document.getElementById("canvas_2");
var can2_context=canvas_2.getContext("2d");
var width_2=canvas_2.width
var height_2=canvas_2.height
var testx=300
var testy=300
function drawCutouts(){

    can2_context.beginPath();
    addOurterRectanglePath()
    addrect()
    addTrianglePath()
    addarc()
    can2_context.fill()
}

function addOurterRectanglePath(){
     can2_context.rect(110,25,370,335)
     can2_context.closePath()
}


function rect(x,y,w,h,direction){

    if(direction){
        can2_context.moveTo(x,y);
        can2_context.lineTo(x,y+h)
        can2_context.lineTo(x+w,y+h)
        can2_context.lineTo(x+w,y)
    }else{
        can2_context.moveTo(x,y)
        can2_context.lineTo(x+w,y)
        can2_context.lineTo(x+w,y+h)
        can2_context.lineTo(x,y+h)

    }
    can2_context.closePath()
}
function addrect(){
    rect(310,55,70,35,true)  //true为逆时针
}
function addTrianglePath(){
   
   can2_context.moveTo(400,200)
   can2_context.lineTo(250,115)
   can2_context.lineTo(200,200)
   can2_context.closePath()

}



function addarc(){
    if(testy>335){testy=25}
    testy=testy+1
    
    can2_context.arc(testx,testy,40,0,Math.PI*2,true)
   
}

function hi(){
   can2_context.clearRect(0,0,width_2,height_2)
   drawCutouts()

   requestAnimationFrame(hi)

}
hi()

getBoundingClientRect,getImageData,putImageData
//getBoundingClientRect 返回元素的6个值 left top right bottom width height
注意这里的left top right bottom 都是相对于可视窗口的左上角的
width是元素的宽度
height是元素的高度
var bbox=canvas.getBoundingClientRect()
bbox.left

bbox.right

//getImageData() 方法返回 ImageData 对象,该对象拷贝了画布指定矩形的像素数据。
//context.getImageData(0,0,canvas.width,canvas.height)

//putImageData() 方法将图像数据(从指定的 ImageData 对象)放回画布上。
//context.putImageData(drawingSurfaceImageData,0,0)


canvas橡皮筋式线段绘制

context.save() 设置绘图环境存档
context.restore() 读取绘图环境存档
Math.abs()求绝对值

var canvas=document.getElementById("canvas"),
   context=canvas.getContext("2d"),
   eraseAllButton=document.getElementById("eraseAllButton"),
   strokeStyleSelect=document.getElementById("strokeStyleSelect"),
   guidewireCheckbox=document.getElementById("guidewireCheckbox"),
   drawingSurfaceImageData,
   mousedown={},
   rubberbandRect={},
   dragging=false,
   guidewires=guidewireCheckbox.checked;


    function windowToCanvas(x,y){
        var bbox=canvas.getBoundingClientRect()//getBoundingClientRect 返回元素的6个值 left top right bottom width height
     
        return {
            x:x-bbox.left*(canvas.width/bbox.width),
            y:y-bbox.top*(canvas.height/bbox.height)
        }
    }

    function saveDrawingSurface(){
        drawingSurfaceImageData=context.getImageData(0,0,canvas.width,canvas.height) 
     //getImageData() 方法返回 ImageData 对象,该对象拷贝了画布指定矩形的像素数据。
    }
    
    function restoreDrawingSurface(){
        context.putImageData(drawingSurfaceImageData,0,0)
        //putImageData() 方法将图像数据(从指定的 ImageData 对象)放回画布上。
    }

   function updateRubberbandRectangle(loc){
       rubberbandRect.width=Math.abs(loc.x-mousedown.x)  //用绝对值求线段的长度
       rubberbandRect.height=Math.abs(loc.y-mousedown.y)  //用绝对值求线段的高度

       if(loc.x>mousedown.x){rubberbandRect.left=mousedown.x}else{
           rubberbandRect.left=loc.x
       }
       if(loc.y>mousedown.y){rubberbandRect.top=mousedown.y}else{
           rubberbandRect.top=loc.y
       }
   }
   function drawRubberbandShape(loc){

       context.beginPath()
       context.moveTo(mousedown.x,mousedown.y)
       context.lineTo(loc.x,loc.y)
       context.stroke()
   }
   function updataRubberband(loc){  //loc是鼠标点在canvas上的坐标集合对象
      // updateRubberbandRectangle(loc)
       drawRubberbandShape(loc)
   }
//这三个函数式辅助线函数
   function drawHorizontalLine(y){
       context.beginPath()
       context.moveTo(0,y+0.5)
       context.lineTo(context.canvas.width,y+0.5)
       context.stroke()
   }
   function drawVerticalLine(x){
       context.beginPath()
       context.moveTo(x+0.5,0)
       context.lineTo(x+0.5,context.canvas.height)
       context.stroke()

   }
   function drawGuidewires(x,y){
       context.save()
       context.strokeStyle="rgba(0,0,230,0.4)"
       context.lineWidth=0.5;
       drawVerticalLine(x)
       drawHorizontalLine(y)
       context.restore()
   }
//这三个函数式辅助线函数
   canvas.onmousedown=function(e){  //只执行一次
     var loc=windowToCanvas(e.clientX,e.clientY); //获取鼠标点在canvas的点坐标
     e.preventDefault();
     saveDrawingSurface()                         //复制canvas画布的像素
     mousedown.x=loc.x;                          //鼠标点击的x轴坐标  这里mousedown记录的是初始位置
     mousedown.y=loc.y;                          //鼠标点击的y轴坐标   这里mousedown记录的是初始位置
     dragging=true;
 }
canvas.onmousemove=function(e){
       var loc;
       if(dragging){
           e.preventDefault()
           loc=windowToCanvas(e.clientX,e.clientY);
           restoreDrawingSurface()
           updataRubberband(loc)  //loc是鼠标点在canvas上的坐标集合对象
           if(guidewires){        //辅助线
               drawGuidewires(loc.x,loc.y)
           }
       }
   }
   canvas.onmouseup=function(e){
       loc=windowToCanvas(e.clientX,e.clientY)
       restoreDrawingSurface()
       updataRubberband(loc)
       dragging=false
   }
   strokeStyleSelect.onchange=function(){

       context.strokeStyle=strokeStyleSelect.value
   }

三次方贝塞尔曲线的绘制

bezierCurveTo
创建一条代表三次方贝塞尔曲线的路径。你需要向该方法传入三个点的坐标
,前两个点是该曲线的控制点,最后一个是锚点


canvas画多边形

由于canvas只提供了画矩形和圆形的方法,
所以涉及到多边形的话,只能自己写方法
其中涉及到 三角函数的API 比如
Math.PI圆周率
Math.sin
Math.cos
这俩就不多介绍了 sin cos 中学学的
大致思路就是只要有中心点 半径 就可以想画几边形就画几边形,
废话不多说,上代码

var canvas=document.getElementById("canvas");
var context=canvas.getContext("2d");

var Point = function (x, y) {
   this.x = x;
   this.y = y;
};

var Polygon=function(centerX,centerY,radius,sides,startAngle,strokeStyle,fillStyle,filled){

    this.x=centerX;
    this.y=centerY;
    this.radius=radius;
    this.sides=sides;
    this.startAngle=startAngle;
    this.strokeStyle=strokeStyle;
    this.fillStyle=fillStyle;
    this.filled=filled;
}
Polygon.prototype={
   getPoints:function(){
     var points=[];
     var angle=this.startAngle||0;
     for(var i=0;i

isPointInPath
isPointInPath表示某个点在当前路径中就会返回true 反之返回false

var edite=false
var mousedown={}//记录鼠标按下起始点
var imageData1=null;
var mouseIn=null;//记录鼠标是否按了下去
var line_list={} //记录鼠标的终点

var Graphical=[];//存放图形引用的数组
var edit_list={}//记录在编辑模式下按的点
var map_name=null//每个生成图形的名称
var foucsIndex=null //被选中移动图形的下标


function saveImage(){  //储存此刻画布数据
      imageData1= context.getImageData(0,0,canvas.width,canvas.height)
}
function loadingImage(){ //导入画布数据
  context.putImageData(imageData1,0,0)
}



editCheckbox.onchange=function(){
  if(this.checked){
   console.log("进入编辑模式")
   edite=true
  }else{
   console.log("进入画图模式")
   edite=false
  }

}

function windowToCanvas(event){  //算出你点击在canvas画布的坐标 并返回
   var rect=canvas.getBoundingClientRect()
   return {
      x:event.clientX-rect.left,
      y:event.clientY-rect.top
   } 
}
function line_width(){
  var x_width=Math.abs(line_list.x-mousedown.x)
  var y_width=Math.abs(line_list.y-mousedown.y)
  
  return Math.sqrt(x_width*x_width+y_width*y_width) 
}



canvas.onmousedown=function(event){
    saveImage()
    var some=windowToCanvas(event)
   
    mousedown.x=some.x;
    mousedown.y=some.y
    
    mouseIn=true
    
    Graphical.forEach(function(el,index){
        el.createPath(context)
        if(context.isPointInPath(mousedown.x,mousedown.y)){
            edit_list.x=some.x;
            edit_list.y=some.y
            foucsIndex=index
         
        }

   
    })
   
}
canvas.onmousemove=function(event){

     if(mouseIn&&edite){//如果按下鼠标并拖行 如果是编辑模式
        loadingImage()
           
            
            var offset_list=windowToCanvas(event);
            var offsetX=offset_list.x-edit_list.x;
            var offsetY=offset_list.y-edit_list.y;
            context.clearRect(0,0,canvas.width,canvas.height)
            Graphical[foucsIndex].move(mousedown.x+offsetX,mousedown.y+offsetY)
            Graphical.forEach(function(el){
                el.createPath(context)
                el.fill(context)
            })
     } 


  
    if(mouseIn&&!edite){//如果按下鼠标并拖行 如果不是编辑模式
        loadingImage()
        line_list=windowToCanvas(event)
        context.beginPath()

        var r=line_width()

        map_name=new Polygon(mousedown.x,mousedown.y,r,sidesSelect.value,0,"red","red")
        map_name.fill(context)
   
        
    }
}

canvas.onmouseup=function(){


    mouseIn=false //鼠标抬起来了
    if(!edite){
        Graphical.push(map_name)
    }

}

globalCompositeOperation
利用修改globalCompositeOperation改变canvas图像默认合成行为

11个合成行为


clip()剪切区域

这里有个坑要十分注意 调用clip()方法的时候,所定义的剪辑区域总是局限于期初的那个剪辑区域范围。
简单来说 clip()方法总是在上一次的剪辑区域基础上进行操作,所以说我们要把clip()方法放在save()和restore()方法中
clip 是对已有路径的剪切

var canvas=document.getElementById("canvas")
var context=canvas.getContext("2d")

function windowToCanvas(x,y){

    var bbox=canvas.getBoundingClientRect()
    return {
        x:x-bbox.left,
        y:y-bbox.top
    }
}

function drawText(){

    context.save()
    context.shadowColor="rgba(100,100,150,0.8)"
    context.shadowOffsetX=5;
    context.shadowOffsetY=5;
    context.shadowBlur=10;

    context.fillStyle="cornflowerblue"
    context.fillText("HTML5",20,250)
    context.strokeStyle="yellow"
    context.strokeText("HTML5",20,250)
    context.restore()

}

function setClippingRegion(radius){
    context.beginPath()
    context.arc(canvas.width/2,canvas.height/2,radius,0,Math.PI*2,false)
    context.clip()
}

function fillCanvas(color){
    context.fillStyle=color
    context.fillRect(0,0,canvas.width,canvas.height)
}

function endAnimation(loop){

    clearInterval(loop)
    setTimeout(function(e){
        context.clearRect(0,0,canvas.width,canvas.height)
        drawText()
    },1000)
}

function drawAnimationFrame(radius){
   setClippingRegion(radius);
   fillCanvas('lightgray')
   drawText()

}
function animate(){
   var radius=canvas.width/2,
       loop;
    loop=window.setInterval(function(){
        radius-=canvas.width/100
        fillCanvas('charcoal')
        if(radius>0){
            context.save()
            drawAnimationFrame(radius)
            context.restore()
        }else{
            endAnimation(loop)
        }
    },16)   

}

canvas.onmousedown=function(){
    animate()
}
context.lineWidth=0.5
context.font='128pt Comic-sans'
drawText()

canvas制造渐变和图案填充文字.

这里主要是利用了 context的createPattern的方法
这个方法接受两个参数 第一个参数是要填充的图案,第二个参数是图案重复方式

制造颜色渐变的方法是createLinearGradient

var canvas=document.getElementById("canvas")
var context=canvas.getContext("2d")
var image=new Image();
var gradient=context.createLinearGradient(0,0,canvas.width,canvas.height)
var text="Canvas"
var pattern;
function drawGradientText(){
  context.fillStyle=gradient
  context.fillText(text,65,200)
  context.strokeText(text,65,200)

}
function drawPatternText(){
    context.fillStyle=pattern
    context.fillText(text,65,450)
    context.strokeText(text,65,450)
}
image.onload=function(e){
    pattern=context.createPattern(image,"repeat")
    drawPatternText()
}
image.src="./images/hover2.png"
context.font="256px Palation"
context.strokeStyle="cornflowerblue"



context.shadowColor="rgba(100,100,150,0.8)"
context.shadowOffsetX=5
context.shadowOffsetY=5
context.shadowBlur=10

gradient.addColorStop(0,"blue")
gradient.addColorStop(0.25,"blue")
gradient.addColorStop(0.5,"white")
gradient.addColorStop(0.75,'red')
gradient.addColorStop(1.0,'yellow')

drawGradientText()

canvas在圆弧周围绘制文本的两种写法

    var canvas=document.getElementById("canvas")
    var context=canvas.getContext("2d")

    var TEXT_FILL_STYLE="rgba(100,130,240,0.5)"
    var TEXT_STROKE_STYLE="rgba(200,0,0,0.7)"
    var TEXT_SIZE=64;
    circle={
        x:canvas.width/2,
        y:canvas.height/2,
        radius:200
    }
    function drawCircularText(string,startAngle,endAngle){
      var radius=circle.radius //圆的半径
      var angleDecrement=(startAngle-endAngle)/(string.length-1)//每个字母占的弧度
      var angle=parseFloat(startAngle) //转一下数字
      var index=0;
      var character;

      context.save()
      context.fillStyle=TEXT_FILL_STYLE;
      context.strokeStyle=TEXT_STROKE_STYLE;
      context.font=TEXT_SIZE+"px Lucida Sans"

      while(index

canvas实现图像的缩放

这里需要注意的是如果你向canvas之中绘制的图像有一部分落在canvas之外,
那么浏览器就会将canvas范围外的那部分图像忽略掉

var canvas=document.getElementById("canvas")
var context=canvas.getContext("2d")

var image=new Image()
var scaleSlider=document.getElementById("scaleSlider")
var scale=1.0
var MINIMUM_SCALE=1.0
var MAXIMUN_SCALE=3.0

function drawImage(){
 var w=canvas.width
 var h=canvas.height
 var sw=w*scale
 var sh=h*scale
 context.clearRect(0,0,canvas.width,canvas.height)
 context.drawImage(image,-sw/2+w/2,-sh/2+h/2,sw,sh)

}
function drawScaleText(value){
  var text=parseFloat(value).toFixed(2)

  scaleOutput.innerText=text



}
scaleSlider.onchange=function(e){
  scale=e.target.value
  if(scaleMAXIMUN_SCALE){scale=MAXIMUN_SCALE}
      drawScaleText(scale)
    drawImage()

}
image.src="./timg.jpg"
image.onload=function(e){
   drawImage()
   drawScaleText(scaleSlider.value)
}

利用离屏canvas提高复制图像放大的效率并添加水印




    图像与视频
    
    


1.0

利用离屏canvas 手动放大图片任意局部位置效果
这里最重要的就是rubberbandEnd这个函数 它会判断鼠标从按下到松开 有没有位移过 如果没有就return 最后把离屏的图片选取局部复制到可见的canvas之中




    图像与视频
    
    


      

canvas利用requestNextAnimationFrame做动画及碰撞检测


   
     Video

      
   

  
      
Canvas not supported

canvas制作无限视差滚动背景图




    背景滚动
   
        



    
      Canvas not supported
    

    

    
   






canvas制作随机粒子移动特效




    背景滚动
   
        



    
      Canvas not supported
    

    

    
   






canvas精灵图制作人物左右移动

var velocityX=10  //X轴的位移速度
var left1=100     //X轴的起始位置 这个值控制人物的横坐标
var img_start=imgid //最开始的精灵贴图
var advance_or="left" //最开始向左移动
SpriteSheetPainter=function(cells){
   this.cells=cells||[]
   this.cellIndex=0

}

SpriteSheetPainter.prototype={

   advance:function(){

    if(this.cellIndex==(this.cells.length-1)){this.cellIndex=0}else{
              this.cellIndex++
             }
   },
   advance2:function(){
        
        if(this.cellIndex==0){this.cellIndex=(this.cells.length-1)}else{
              this.cellIndex--
             }

   },
   paint:function(context,canvas){
    var cell=this.cells[this.cellIndex]
    left1=canvas.left-velocityX

    if(left1<0){ //人物左移临界点判断
       advance_or="right"
       velocityX=-velocityX
       img_start=imgid2
       
       context.drawImage(img_start,cell.x,cell.y,cell.w,cell.h,canvas.left,canvas.top,canvas.w,canvas.h)
      
    }
     if(left1+canvas.w>1024){ //人物右移临界点判断
      advance_or="left"
      velocityX=-velocityX
      img_start=imgid
    
      context.drawImage(img_start,cell.x,cell.y,cell.w,cell.h,canvas.left,canvas.top,canvas.w,canvas.h)
     }

     else{
     if(advance_or=="left"){

      img_start=imgid
      this.advance()
     }
     if(advance_or=="right"){
      img_start=imgid2
      this.advance2()
     }

     context.drawImage(img_start,cell.x,cell.y,cell.w,cell.h,canvas.left,canvas.top,canvas.w,canvas.h)
     }

    
   }
}

window.onload=function(){
   //bomb.paint(context)
   var some=new SpriteSheetPainter([{x:0,y:0,w:41,h:64},
                                    {x:53,y:0,w:41,h:64},
                                    {x:106,y:0,w:41,h:64},
                                    {x:159,y:0,w:41,h:64},
                                    {x:212,y:0,w:41,h:64},
                                    {x:265,y:0,w:41,h:64},
                                    {x:318,y:0,w:41,h:64},
                                    {x:371,y:0,w:41,h:64},
                                    {x:424,y:0,w:41,h:64}
                                    ])

    some.paint(context,{left:100,top:100,w:53,h:64})

   var now=0
   var last=0
   

   function animate(){
     now=(+new Date) 
     var hi=now-last
    
     if(parseInt(hi)>100){
      
      
      last=now

     context.clearRect(0,0,canvas.width,canvas.height)
     // some.advance()
     some.paint(context,{left:left1,top:100,w:53,h:64})

     }
     
     
   
     requestAnimationFrame(animate)
    }

requestAnimationFrame(animate)


}

你可能感兴趣的:(canvas常用API 总结)