帶你使用canvas製作馬賽克&canvas飛鳥動畫&小球動畫

在這裏插入圖片描述

canvas製作馬賽克&飛鳥動畫&小球拖拽動畫

在這裏插入圖片描述
在這裏插入圖片描述

在這裏插入圖片描述

一、瞭解單像素操作

1、在canvas中的像素操作

到目前爲止,我們尚未深入瞭解Canvas畫布真實像素的原理,事實上,
你可以直接通過ImageData對象操縱像素數據,直接讀取或將數據數組寫入該對象中

2、得到場景像素數據

getImageData():獲得一個包含畫布場景像素數據的ImageData對像,它代表了畫布區域的對象數據

ctx.getImageData(sx, sy, sw, sh)
	sx:將要被提取的圖像數據矩形區域的左上角 x 座標。
	sy:將要被提取的圖像數據矩形區域的左上角 y 座標。
	sw:將要被提取的圖像數據矩形區域的寬度。
	sh:將要被提取的圖像數據矩形區域的高度。

3、ImageData對象

ImageData對象中存儲着canvas對象真實的像素數據,它包含以下幾個只讀屬性:
width:圖片寬度,單位是像素
height:圖片高度,單位是像素
data:Uint8ClampedArray類型的一維數組,
包含着RGBA格式的整型數據,範圍在0至255之間(包括255)
R:0 --> 255(黑色到白色)
G:0 --> 255(黑色到白色)
B:0 --> 255(黑色到白色)
A:0 --> 255(透明到不透明)

4、在場景中寫入像素數據

putImageData()方法去對場景進行像素數據的寫入。
putImageData(myImageData, dx, dy)
dxdy參數表示你希望在場景內左上角繪製的像素數據所得到的設備座標

5、創建一個ImageData對象

ctx.createImageData(width, height);
		width : ImageData 新對象的寬度。
		height: ImageData 新對象的高度。
		

默認創建出來的是透明的

二、canvas使用圖片

1、在canvas中插入圖片(需要image對象)

1.canvas操作圖片時,必須要等圖片加載完才能操作
2.drawImage(image, x, y, width, height)
其中 imageimage或者canvas對象,x 和 y是其在目標 canvas 裏的起始座標。
這個方法多了2個參數:width 和 height,這兩個參數用來控制 當像canvas畫入時應該縮放的大小

 <style type="text/css">
        * {
            margin: 0;
            padding: 0;
        }
        
        html,
        body {
            height: 100%;
            overflow: hidden;
        }
        
        body {
            background: pink;
        }
        
        #test {
            background: gray;
            position: absolute;
            left: 0;
            top: 0;
            right: 0;
            bottom: 0;
            margin: auto;
        }
    </style>
</head>

<body>
    <canvas id="test" width="300" height="300">
			<span>您的瀏覽器不支持畫布元素 請您換成萌萌的谷歌</span>
		</canvas>
</body>
<script type="text/javascript">
    window.onload = function() {
        var canvas = document.querySelector("#test");
        if (canvas.getContext) {
            var ctx = canvas.getContext("2d");

            var img = new Image(); //加載圖片
            img.src = "tg.png";
            img.onload = function() {
                draw(); //加載成功之後
            }

            function draw() {
                ctx.drawImage(img, 0, 0, img.width, img.height)
            }

        }
    }

在這裏插入圖片描述

2、在canvas中設置背景(需要image對象)

1.createPattern(image, repetition)
	image:圖像源
	epetition:
		"repeat" 
		"repeat-x" 
		"repeat-y" 
		"no-repeat" 
		

一般情況下,我們都會將createPattern返回的對象作爲fillstyle的值

漸變

canvas漸變(線性漸變)
createLinearGradient(x1, y1, x2, y2)
表示漸變的起點 (x1,y1) 與終點 (x2,y2)

gradient.addColorStop(position, color)
gradient :createLinearGradient的返回值
addColorStop方法接受 2 個參數,
position 參數必須是一個 0.0 與 1.0 之間的數值,表示漸變中顏色所在的相對位置。
例如,0.5 表示顏色會出現在正中間。
color 參數必須是一個有效的 CSS 顏色值(如 #FFF, rgba(0,0,0,1),等等)

    <style type="text/css">
        * {
            margin: 0;
            padding: 0;
        }
        
        html,
        body {
            height: 100%;
            overflow: hidden;
        }
        
        body {
            background: pink;
        }
        
        #test {
            background: gray;
            position: absolute;
            left: 0;
            top: 0;
            right: 0;
            bottom: 0;
            margin: auto;
        }
    </style>
</head>

<body>
    <canvas id="test" width="300" height="300">
			<span>您的瀏覽器不支持畫布元素 請您換成萌萌的谷歌</span>
		</canvas>
</body>
<script type="text/javascript">
    window.onload = function() {
        var canvas = document.querySelector("#test");
        if (canvas.getContext) {
            var ctx = canvas.getContext("2d");

            /*var img = new Image();
            img.src="tg.png";
            img.οnlοad=function(){
            	draw();
            }*/

            //				function draw(){
            var gradient = ctx.createLinearGradient(0, 0, 300, 300);
            gradient.addColorStop(0, "red");
            gradient.addColorStop(0.5, "yellow");
            gradient.addColorStop(0.7, "pink");
            gradient.addColorStop(1, "green");
            ctx.fillStyle = gradient;
            ctx.fillRect(0, 0, 300, 300);
            //				}

        }
    }
</script>

在這裏插入圖片描述

canvas漸變(徑向漸變)
createRadialGradient(x1, y1, r1, x2, y2, r2)
前三個參數則定義另一個以(x1,y1) 爲原點,半徑爲 r1 的圓,
後三個參數則定義另一個以 (x2,y2) 爲原點,半徑爲 r2 的圓。

		<style type="text/css">
			*{
				margin: 0;
				padding: 0;
			}
			html,body{
				height: 100%;
				overflow: hidden;
			}
			body{
				background: pink;
			}
			#test{
				background: gray;
				position: absolute;
				left: 0;
				top: 0;
				right: 0;
				bottom: 0;
				margin: auto;
			}
		</style>
	</head>
	<body>
		<canvas id="test" width="300" height="300">
			<span>您的瀏覽器不支持畫布元素 請您換成萌萌的谷歌</span>
		</canvas>
	</body>
	<script type="text/javascript">
		window.onload=function(){
			var canvas = document.querySelector("#test");
			if(canvas.getContext){
				var ctx = canvas.getContext("2d");
				
				/*var img = new Image();
				img.src="tg.png";
				img.οnlοad=function(){
					draw();
				}*/
				
//				function draw(){
					var gradient = ctx.createRadialGradient(150, 150, 50, 150, 150, 100)
					gradient.addColorStop(0,"red");
					gradient.addColorStop(0.5,"yellow");
					gradient.addColorStop(0.7,"pink");
					gradient.addColorStop(1,"green");
					ctx.fillStyle=gradient;
					ctx.fillRect(0,0,300,300);
//				}
				
			}
		}
		
		
	</script>

在這裏插入圖片描述

三、飛鳥動畫

效果圖

在這裏插入圖片描述

完整代碼

<!DOCTYPE html>
<html>
	<head>
		<meta charset="UTF-8">
		<title></title>
		<style type="text/css">
			*{
				margin: 0;
				padding: 0;
			}
			html,body{
				height: 100%;
				overflow: hidden;
			}
			body{
				background: pink;
			}
			#test{
				background: white;
				position: absolute;
				left: 0;
				top: 0;
				right: 0;
				bottom: 0;
				margin: auto;
			}
		</style>
	</head>
	<body>
		<canvas id="test" width="300" height="300">
			<span>您的瀏覽器不支持畫布元素 請您換成萌萌的谷歌</span>
		</canvas>
	</body>
	<script type="text/javascript">
		window.onload=function(){
			var canvas = document.querySelector("#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>

四、操作單個像素(行與列)

示例一

<!DOCTYPE html>
<html>
	<head>
		<meta charset="UTF-8">
		<title></title>
		<style type="text/css">
			*{
				margin: 0;
				padding: 0;
			}
			html,body{
				height: 100%;
				overflow: hidden;
			}
			body{
				background: pink;
			}
			#test{
				background: gray;
				position: absolute;
				left: 0;
				top: 0;
				right: 0;
				bottom: 0;
				margin: auto;
			}
		</style>
	</head>
	<body>
		<canvas id="test" width="300" height="300">
			<span>您的瀏覽器不支持畫布元素 請您換成萌萌的谷歌</span>
		</canvas>
	</body>
	<script type="text/javascript">
		window.onload=function(){
			var canvas = document.querySelector("#test");
			if(canvas.getContext){
				var ctx = canvas.getContext("2d");
//				ctx.fillStyle="rgba(255, 192, 203,1)";
//				ctx.fillRect(0,0,100,100);
				//100*100 10000個像素點
				
				/*imageData
					width:橫向上像素點的個數
					height:縱向上像素點的個數
					data:數組
						每一個像素點的rgba信息
				*/
					
				//默認創建出來 rgba(0,0,0,0)
				var imageData = ctx.createImageData(100,100);
				for(var i=0;i<imageData.data.length;i++){
					imageData.data[4*i+3]=255;
				}
				ctx.putImageData(imageData,100,100)
				
			}
		}
		
		
	</script>
</html>

效果圖

在這裏插入圖片描述

示例二

HTML&CSS
   <style type="text/css">
        * {
            margin: 0;
            padding: 0;
        }
        
        html,
        body {
            height: 100%;
            overflow: hidden;
        }
        
        body {
            background: pink;
        }
        
        #test {
            background: gray;
            position: absolute;
            left: 0;
            top: 0;
            right: 0;
            bottom: 0;
            margin: auto;
        }
    </style>
</head>

<body>
    <canvas id="test" width="400" height="300">
			<span>您的瀏覽器不支持畫布元素 請您換成萌萌的谷歌</span>
		</canvas>
</body>
獲取某個點的像素

求出該點像素的座標關係
在這裏插入圖片描述

function getPxInfo(imgdata, x, y) {
            var color = [];

            var data = imgdata.data;
            var w = imgdata.width;
            var h = imgdata.height;

            //(x,y)  x*w+y
            //r
            color[0] = data[(y * w + x) * 4];
            //g
            color[1] = data[(y * w + x) * 4 + 1];
            //b
            color[2] = data[(y * w + x) * 4 + 2];
            //a
            color[3] = data[(y * w + x) * 4 + 3];

            return color;
        }
設置某個點的像素
 function setPxInfo(imgdata, x, y, color) {

            var data = imgdata.data;
            var w = imgdata.width;
            var h = imgdata.height;

            //(x,y)  x*w+y   x:多少列  y:多少行
            //r
            data[(y * w + x) * 4] = color[0];
            //g
            data[(y * w + x) * 4 + 1] = color[1];
            //b
            data[(y * w + x) * 4 + 2] = color[2];
            //a
            data[(y * w + x) * 4 + 3] = color[3];

        }
完整JavaScript代碼
<script type="text/javascript">
    window.onload = function() {
        var canvas = document.querySelector("#test");
        if (canvas.getContext) {
            var ctx = canvas.getContext("2d");
            ctx.save();
            ctx.fillStyle = "pink";
            ctx.beginPath();
            ctx.fillRect(50, 50, 100, 100);
            ctx.restore();


            var imgdata = ctx.getImageData(0, 0, canvas.width, canvas.height);
            /*var color = getPxInfo(imgdata,49,49);
            console.log(color);*/
            for (var i = 0; i < imgdata.width; i++) {
                setPxInfo(imgdata, 30, i, [0, 0, 0, 255]);
            }

            ctx.putImageData(imgdata, 0, 0);
        }
        // console.log(imgdata);

        let color = getPxInfo(imgdata, 49, 49);
        console.log(color);
        for (var i = 0; i < imgdata.width; i++) {
            setPxInfo(imgdata, i, 50, [0, 0, 0, 255]);
        }
        ctx.putImageData(imgdata, 0, 0);

        function getPxInfo(imgdata, x, y) {
            var color = [];

            var data = imgdata.data;
            var w = imgdata.width;
            var h = imgdata.height;

            //(x,y)  x*w+y
            //r
            color[0] = data[(y * w + x) * 4];
            //g
            color[1] = data[(y * w + x) * 4 + 1];
            //b
            color[2] = data[(y * w + x) * 4 + 2];
            //a
            color[3] = data[(y * w + x) * 4 + 3];

            return color;
        }

        function setPxInfo(imgdata, x, y, color) {

            var data = imgdata.data;
            var w = imgdata.width;
            var h = imgdata.height;

            //(x,y)  x*w+y   x:多少列  y:多少行
            //r
            data[(y * w + x) * 4] = color[0];
            //g
            data[(y * w + x) * 4 + 1] = color[1];
            //b
            data[(y * w + x) * 4 + 2] = color[2];
            //a
            data[(y * w + x) * 4 + 3] = color[3];

        }
    }
</script>
效果圖

平行X軸

  for (var i = 0; i < imgdata.width; i++) {
                setPxInfo(imgdata, 30, i, [0, 0, 0, 255]);
            }

平行y軸

for (var i = 0; i < imgdata.width; i++) {
            setPxInfo(imgdata, i, 50, [0, 0, 0, 255]);
        }

在這裏插入圖片描述

五、馬賽克

HTML&CSS


<head>
    <meta charset="UTF-8">
    <title></title>
    <style type="text/css">
        * {
            margin: 0;
            padding: 0;
        }
        
        html,
        body {
            height: 100%;
            overflow: hidden;
        }
        
        #msk {
            position: absolute;
            left: 50%;
            top: 50%;
            transform: translate3d(-50%, -50%, 0);
            /*background: gray;*/
        }
    </style>
</head>

<body>
    <canvas id="msk"></canvas>
</body>

選取馬賽克矩形

  1. 選取一個馬賽克矩形(可以通過size調節模糊程度
  2. 從馬賽克矩形中隨機抽出一個像素點的信息(rgba)
  3. 將整個馬賽克矩形中的像素點信息統一調成隨機抽出的那個

        function draw() {
            ctx.drawImage(img, 0, 0);


            var oldImgdata = ctx.getImageData(0, 0, img.width, img.height);
            var newImgdata = ctx.createImageData(img.width, img.height);
            //馬賽克
            /*
            	1.選取一個馬賽克矩形
            	2.從馬賽克矩形中隨機抽出一個像素點的信息(rgba)
            	3.將整個馬賽克矩形中的像素點信息統一調成隨機抽出的那個
            */
            //選取一個馬賽克矩形
            var size = 5;
            for (var i = 0; i < oldImgdata.width / size; i++) {
                for (var j = 0; j < oldImgdata.height / size; j++) {
                    //(i,j)  每一個馬賽克矩形的座標
                    //(0,0):  (0,0)  (4,4);[0,4]   //(1,0): (5,0) (9,4)
                    //(0,1):  (0,5)  (4,9)	 	   //(1,1): (5,5) (9,9)



                    //Math.random()  [0,1)
                    //Math.random()*size  [0,5)
                    //Math.floor(Math.random()*size) [0,4]
                    //從馬賽克矩形中隨機抽出一個像素點的信息(rgba)
                    var color = getPxInfo(oldImgdata, i * size + Math.floor(Math.random() * size), j * size + Math.floor(Math.random() * size));


                    //將整個馬賽克矩形中的像素點信息統一調成隨機抽出的那個
                    for (var a = 0; a < size; a++) {
                        for (var b = 0; b < size; b++) {
                            setPxInfo(newImgdata, i * size + a, j * size + b, color)
                        }
                    }
                }
            }

單像素操作


        function getPxInfo(imgdata, x, y) {
            var color = [];
            var data = imgdata.data;
            var w = imgdata.width;
            var h = imgdata.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 setPxInfo(imgdata, x, y, color) {
            var data = imgdata.data;
            var w = imgdata.width;
            var h = imgdata.height;
            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>

<head>
    <meta charset="UTF-8">
    <title></title>
    <style type="text/css">
        * {
            margin: 0;
            padding: 0;
        }
        
        html,
        body {
            height: 100%;
            overflow: hidden;
        }
        
        #msk {
            position: absolute;
            left: 50%;
            top: 50%;
            transform: translate3d(-50%, -50%, 0);
            /*background: gray;*/
        }
    </style>
</head>

<body>
    <canvas id="msk"></canvas>
</body>
<script type="text/javascript">
    var oc = document.querySelector("#msk");
    if (oc.getContext) {
        var ctx = oc.getContext("2d");
        var img = new Image();
        img.src = "2.png";
        img.onload = function() {
            oc.width = img.width * 2;
            oc.height = img.height * 2;
            draw();
        }


        function draw() {
            ctx.drawImage(img, 0, 0);


            var oldImgdata = ctx.getImageData(0, 0, img.width, img.height);
            var newImgdata = ctx.createImageData(img.width, img.height);
            //馬賽克
            /*
            	1.選取一個馬賽克矩形
            	2.從馬賽克矩形中隨機抽出一個像素點的信息(rgba)
            	3.將整個馬賽克矩形中的像素點信息統一調成隨機抽出的那個
            */
            //選取一個馬賽克矩形
            var size = 5;
            for (var i = 0; i < oldImgdata.width / size; i++) {
                for (var j = 0; j < oldImgdata.height / size; j++) {
                    //(i,j)  每一個馬賽克矩形的座標
                    //(0,0):  (0,0)  (4,4);[0,4]   //(1,0): (5,0) (9,4)
                    //(0,1):  (0,5)  (4,9)	 	   //(1,1): (5,5) (9,9)

                    //從馬賽克矩形中隨機抽出一個像素點的信息(rgba)
                    var color = getPxInfo(oldImgdata, i * size + Math.floor(Math.random() * size), j * size + Math.floor(Math.random() * size));


                    //將整個馬賽克矩形中的像素點信息統一調成隨機抽出的那個
                    for (var a = 0; a < size; a++) {
                        for (var b = 0; b < size; b++) {
                            setPxInfo(newImgdata, i * size + a, j * size + b, color)
                        }
                    }
                }
            }


            ctx.putImageData(newImgdata, img.width, 0);
        }



        function getPxInfo(imgdata, x, y) {
            var color = [];
            var data = imgdata.data;
            var w = imgdata.width;
            var h = imgdata.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 setPxInfo(imgdata, x, y, color) {
            var data = imgdata.data;
            var w = imgdata.width;
            var h = imgdata.height;
            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>

</html>

效果圖

在這裏插入圖片描述

六、小球動畫

在這裏插入圖片描述

1、角度與弧度的js表達式:

radians=(Math.PI/180)*degrees。

2、canvas繪製圓形

arc(x, y, radius, startAngle, endAngle, anticlockwise)
畫一個以(x,y)爲圓心的以radius爲半徑的圓弧(圓),從startAngle開始到endAngle結束,
按照anticlockwise給定的方向(默認爲順時針)來生成。
ture:逆時針 false:順時針
x,y爲繪製圓弧所在圓上的圓心座標
radius爲半徑
startAngle以及endAngle參數用弧度定義了開始以及結束的弧度。這些都是以x軸爲基準
參數anticlockwis 爲一個布爾值。爲true時,是逆時針方向,否則順時針方向。

3、arcTo

arcTo(x1, y1, x2, y2, radius)
根據給定的控制點和半徑畫一段圓弧
肯定會從(x1 y1) 但不一定經過(x2 y2);(x2 y2)只是控制一個方向

4、實現小球拖拽與自動移動動畫

<!DOCTYPE html>
<html lang="en">

<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Document</title>
</head>
<style>
    * {
        margin: 0;
        padding: 0;
    }
    
    html,
    body {
        height: 100%;
        overflow: hidden;
    }
    
    #canvas {
        position: absolute;
        left: 0;
        right: 0;
        top: 0;
        bottom: 0;
        margin: auto;
        background-color: rgb(255, 235, 205);
    }
</style>

<body>
    <canvas id="canvas" width="600" height="300"></canvas>
</body>
<script>
    var canvas = document.getElementById('canvas');
    var ctx = canvas.getContext('2d');
    var raf;
    var running = false;
    console.log(canvas.offsetHeight, canvas.offsetLeft);
    var ball = {
        x: 100,
        y: 100,
        vx: 5,
        vy: 1,
        radius: 25,
        color: 'blue',
        draw: function() {
            ctx.beginPath();
            ctx.arc(this.x, this.y, this.radius, 0, Math.PI * 2, true);
            ctx.closePath();
            ctx.fillStyle = this.color;
            ctx.fill();
        }
    };

    function clear() {
        ctx.fillStyle = 'rgba(255, 235, 205,0.3)';
        ctx.fillRect(0, 0, canvas.width, canvas.height);
    }

    function draw() {
        clear();
        ball.draw();
        ball.x += ball.vx;
        ball.y += ball.vy;

        if (ball.y + ball.vy > canvas.height || ball.y + ball.vy < 0) {
            ball.vy = -ball.vy;
        }
        if (ball.x + ball.vx > canvas.width || ball.x + ball.vx < 0) {
            ball.vx = -ball.vx;
        }

        raf = window.requestAnimationFrame(draw);
    }

    canvas.addEventListener('mousemove', function(e) {
        if (!running) {
            clear();
            ball.x = e.clientX - canvas.offsetLeft;
            ball.y = e.clientY - canvas.offsetTop;
            // console.log(e.clientX, e.clientY);
            ball.draw();
        }
    });

    canvas.addEventListener('click', function(e) {
        if (!running) {
            raf = window.requestAnimationFrame(draw);
            running = true;
        }
    });

    canvas.addEventListener('mouseout', function(e) {
        window.cancelAnimationFrame(raf);
        running = false;
    });

    ball.draw();
</script>

</html>

在這裏插入圖片描述

七、後記

喜歡的話可以關注我哦,相互交流學習。

在這裏插入圖片描述
在這裏插入圖片描述

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章