5

HTML5 Canvas

canvas是html5新加的标签,主要有2D和3D,2D的应用是动画和图像,3D的应用是游戏渲染。

1. 2D基础

1.1绘制线

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <meta http-equiv="X-UA-Compatible" content="ie=edge">
    <title>canvas</title>
</head>
<body>
    <canvas id="canvas"></canvas>

    <script>
        window.onload = function(){
            var canvas = document.getElementById('canvas');
            var ctx = canvas.getContext('2d');
            ctx.beginPath();
            ctx.moveTo(100,100);
            ctx.lineTo(500,100)
            ctx.strokeStyle = "#000";
            ctx.stroke();
            ctx.endPath();
        } 
    </script>

</body>
</html>

line

1.3 绘制矩形

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <meta http-equiv="X-UA-Compatible" content="ie=edge">
    <title>canvas</title>
</head>
<body>
    <canvas id="canvas"></canvas>
    <script>
        window.onload = function(){
            var canvas = document.getElementById('canvas');
            var ctx = canvas.getContext('2d');
            ctx.fillStyle = "green";
            ctx.fillRect(100,100,500,1000)
        } 
    </script>
</body>
</html>

rect

1.4 绘制圆

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <meta http-equiv="X-UA-Compatible" content="ie=edge">
    <title>canvas</title>
</head>
<body>
    <canvas id="canvas" width="800" height="800"></canvas>
    <script>
        window.onload = function(){
            var canvas = document.getElementById('canvas');
            var ctx = canvas.getContext('2d');

            ctx.beginPath();
            ctx.fillStyle = "green";
            ctx.arc(100,100,80,0,Math.PI*2,true);
            ctx.fill()
            ctx.endPath();
        } 
    </script>
</body>
</html>

circle

1.5 绘制文字

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <meta http-equiv="X-UA-Compatible" content="ie=edge">
    <title>canvas</title>
</head>
<body>
    <canvas id="canvas" width="800" height="800"></canvas>
    <script>
        window.onload = function(){
            var canvas = document.getElementById('canvas');
            var ctx = canvas.getContext('2d');
            ctx.fillStyle = "#F47C7C";
            ctx.font="30px Arial";
            ctx.fillText("Hello World",10,50);

        } 
    </script>
</body>
</html>

word

1.6 表格练习

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Canvas绘制表格</title>
</head>
<body style="padding: 100px;">
  <canvas id="canvas" width="900" height="600" style="border:1px solid #000"></canvas>

<script>
    var canvas = document.getElementById("canvas");
    var ctx = canvas.getContext("2d");

    // 绘制表格
    var marginXY = 10;
    var rows = canvas.height / marginXY,
        cols = canvas.width / marginXY;
    // 绘制横线
    for (var i=1; i<rows; i++){
        // 起点
        ctx.moveTo(0, i*marginXY);
        // 终点
        ctx.lineTo(canvas.width, i*marginXY);
    }

    // 绘制竖线
    for (var i=1; i<cols; i++){
         // 起点
         ctx.moveTo(i*marginXY, 0);
         // 终点
         ctx.lineTo(i*marginXY, canvas.height);
    }

    // 绘制
    ctx.strokeStyle = '#000';
    ctx.lineWidth = .5;
    ctx.stroke();

    // 绘制坐标
    var x0 = 100, y0 = 500;
    var maxWidth = 500, maxHeight = 400;

    ctx.beginPath();
    ctx.moveTo(x0, y0);
    ctx.lineTo(x0 + maxWidth, y0);
    ctx.lineTo(x0 + maxWidth - marginXY, y0 - marginXY);
    ctx.moveTo(x0 + maxWidth - marginXY, y0 + marginXY); // 起点
    ctx.lineTo(x0 + maxWidth, y0);

    ctx.moveTo(x0, y0);
    ctx.lineTo(x0, y0 - maxHeight);
    ctx.lineTo(x0 - marginXY, y0 - maxHeight + marginXY);
    ctx.moveTo(x0 + marginXY, y0 - maxHeight + marginXY); // 起点
    ctx.lineTo(x0, y0 - maxHeight);

    ctx.strokeStyle = 'blue';
    ctx.lineWidth = 2;
    ctx.stroke();

    // 绘制折线
    var data = [20, 40, 30, 60, 30, 80, 20];

    //设置缩放比例
    var w = maxWidth / data.length,
        h = maxHeight / 100; // 1: 100

    //生成坐标点
    var pointArr = [];
    for(var i=0; i<data.length; i++){
        pointArr.push({
            x: x0 + (i+1) * w,
            y: y0 - data[i] * h
        });
    }
    console.log(pointArr);

    // 绘制
    ctx.beginPath();
    ctx.moveTo(x0, y0);
    for(var i=0; i<pointArr.length; i++){
        ctx.lineTo(pointArr[i].x, pointArr[i].y);
    }
    ctx.strokeStyle = 'red';
    ctx.lineWidth = 4;
    ctx.stroke();



</script>
</body>
</html>

chart

2. canvas动画

2.1动画原理

//requestAnimationFrame会根据刷新频率自动调用callback
(function drawFrame(){
   window.requestAnimationFrame(drawFrame, canvas);
}());

2.2进度条练习

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>canvas动画</title>
    <style>
        body{
            background:#000;
        }
        canvas{
            border:1px solid #fff;
        }
    </style>
</head>
<body>
   <canvas id="canvas" width='500' height="500">
       <P>you browser not support canvas!</P>
   </canvas>
   <script>
       window.onload = function(){
        var canvas = document.getElementById('canvas') 
            context = canvas.getContext('2d'),           
            centerX = canvas.width/2,                    
            centerY = canvas.height/2,                   
            rad = Math.PI*2/100,                         
            speed = 0.1; 
        //绘制蓝色外圈
        function blueCircle(n){
            context.save();
            context.beginPath();
            context.strokeStyle = "blue";
            context.lineWidth = 12;
            context.arc(centerX, centerY, 100 , -Math.PI/2, -Math.PI/2 + n*rad, false);
            context.stroke();
            context.restore();
        }
             
        //绘制绿色外圈
        function whiteCircle(){
            context.save();
            context.beginPath();
            context.strokeStyle = "green";
            context.lineWidth = 12;
            context.arc(centerX, centerY, 100 , 0, Math.PI*2, false);
            context.stroke();
            context.closePath();
            context.restore();
        }
             
        //百分比文字绘制
        function text(n){
            context.save();
            context.fillStyle = "#F47C7C";
            context.font = "40px Arial";
            context.textAlign = "center";
            context.textBaseline = "middle";
            context.fillText(n.toFixed(0)+"%", centerX, centerY);
            context.restore();
       }
             
        //动画循环
        (function drawFrame(){
             window.requestAnimationFrame(drawFrame, canvas);
             context.clearRect(0, 0, canvas.width, canvas.height);
                 
             whiteCircle();
             text(speed);
             blueCircle(speed);
                    
             if(speed > 100) speed = 0;
             speed += 0.1;
        }());
    }
 </script>
</body>

</html>

progress

2.3弹动小球练习

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>ball animate</title>
    <style>
        body {
            margin:0;
            padding:0;
            height: 100%;
            /*background: #000;*/
            overflow: hidden;
        }
        canvas {
            padding: 0;
            background: #000;
            border: 1px solid;
        }
    </style>
</head>
<body>
<canvas id="canvas"></canvas>
<script>
    var canvas = document.getElementById('canvas');
    var SCREEN_WIDTH = window.innerWidth,
            SCREEN_HEIGHT = window.innerHeight,
            ACCURACY = 1, ACCURACY_COMPARE = 1e-5;
    canvas.width = 500;
    canvas.height = 500;
    var context = canvas.getContext('2d'),
            animation, running = false;
 
    var Ball = function(){
        // x 坐标
        this.x = 100;
        // y 坐标
        this.y = 100;
 
        // x 方向初始速度
        this.vx = 10;
        // y 方向初始速度
        this.vy = 25;
 
        // x 方向位移
        this.dx = function() {
            return this.s(this.vx, this.ax, this.dt);
        };
        // y 方向位移
        this.dy = function() {
            return this.s(this.vy, this.ay, this.dt);
        };
        // 计算位移
        this.s = function(v, a, t){
            return v * t + (1 / 2.0) * a * t * t;
        };
 
        // x 方向碰撞速度损失
        this.loss_x = 0.8;
        // y 方向碰撞速度损失
        this.loss_y = 0.8;
 
        // 水平方向加速度
        this.ax = 0;
        // 竖直方向加速度
        this.ay = 1;
 
        // 两帧之间的时间间隔
        this.dt = 1;
        // 小球半径
        this.radius = 20;
        // 小球质量
        this.m = 1;
        // 小球颜色
        this.color = 'cyan';
    };
    // 小球绘制函数
    Ball.prototype.draw = function() {
        context.beginPath();
        context.arc(this.x, this.y, this.radius, 0, Math.PI * 2, true);
        context.closePath();
        context.fillStyle = this.color;
        context.fill();
    };
    // 清除小球
    Ball.prototype.clear = function() {
        context.clearRect(this.x - this.radius,
                this.y - this.radius,
                this.radius * 2,
                this.radius * 2);
    };
    // 获取小球下一个状态
    Ball.prototype.next = function() {
        // 记录当前状态值
        var current_x = this.x, current_vx = this.vx, t1, self = this,
                current_y = this.y, current_vy = this.vy;
 
        // 下一状态理想坐标
        this.x += this.dx();
        this.y += this.dy();
 
        // 下一状态理想速度
        this.vx = this.vx + this.ax * this.dt;
        this.vy = this.vy + this.ay * this.dt;
 
        function boundary(top, right, bottom, left) {
            // 边界判断,预判下一状态是否碰撞下方墙壁
            if (self.y > bottom) {
                // 越界需要重新计算速度和坐标
                // 计算刚好碰到边界之前的速度: vt = sqrt(2aS + v0^2)
                self.vy = Math.sqrt(Math.abs(2 * self.ay * (bottom - current_y) + current_vy * current_vy));
                self.vy = current_vy > 0 ? self.vy : -self.vy;
                if (isNaN(self.vy)) {
                    self.vy = 0;
                    self.ay = 0;
                    self.y = bottom;
                    return false;
                }
                // 计算从当前位置到碰撞位置的时间
                if (self.ay == 0) {
                    if (self.vy == 0) {
                        t1 = 0;
                    } else {
                        t1 = (bottom - current_y) / self.vy;
                    }
                } else {
                    t1 = Math.abs((self.vy - current_vy) / self.ay);
                }
                // 碰撞后速度衰减并反向
                self.vy = -self.vy * self.loss_y;
                // 碰撞后反弹的位移位置
                self.y = bottom + self.s(self.vy, self.ay, self.dt - t1);
                // 位移小于阈值,则速度归零
                if (bottom - self.y < ACCURACY) {
                    self.vy = 0;
                    self.y = bottom;
                    self.ay = 0;
                }
            }
            else if (self.x > right) {
                // 越界需要重新计算速度和坐标
                // 计算刚好碰到边界之前的速度: vt = sqrt(2aS + v0^2)
                self.vx = Math.sqrt(Math.abs(2 * self.ax * (right - current_x) + current_vx * current_vx));
                self.vx = current_vx > 0 ? self.vx : -self.vx;
                if (isNaN(self.vx)) {
                    self.vx = 0;
                    self.ax = 0;
                    self.x = right;
                    return false;
                }
                // 计算从当前位置到碰撞位置的时间
                if (self.ax == 0) {
                    if (self.vx == 0) {
                        t1 = 0;
                    } else {
                        t1 = (right - current_x) / self.vx;
                    }
                } else {
                    t1 = Math.abs((self.vx - current_vx) / self.ax);
                }
                // 碰撞后速度衰减并反向
                self.vx = -self.vx * self.loss_x;
                // 碰撞后反弹的位移位置
                self.x = right + self.s(self.vx, self.ax, self.dt - t1);
                // 位移小于阈值,则速度归零
                if (right - self.x < ACCURACY) {
                    self.vx = 0;
                    self.ax = 0;
                    self.x = right;
                }
            }
            else if (self.x < left) {
                // 越界需要重新计算速度和坐标
                // 计算刚好碰到边界之前的速度: vt = sqrt(2aS + v0^2)
                self.vx = Math.sqrt(Math.abs(2 * self.ax * (current_x - left) + current_vx * current_vx));
                self.vx = current_vx > 0 ? self.vx : -self.vx;
                if (isNaN(self.vx)) {
                    self.vx = 0;
                    self.ax = 0;
                    self.x = left;
                    return false;
                }
                // 计算从当前位置到碰撞位置的时间
                if (self.ax == 0) {
                    if (self.vx == 0) {
                        t1 = 0;
                    } else {
                        t1 = (current_x - left) / self.vx;
                    }
                } else {
                    t1 = Math.abs((self.vx - current_vx) / self.ax);
                }
                // 碰撞后速度衰减并反向
                self.vx = -self.vx * self.loss_x;
                // 碰撞后反弹的位移位置
                self.x = self.s(self.vx, self.ax, self.dt - t1);
                // 位移小于阈值,则速度归零
                if (self.x - left < ACCURACY) {
                    self.vx = 0;
                    self.ax = 0;
                    self.x = left;
                }
            }
            else if (self.y < top) {
                // 越界需要重新计算速度和坐标
                // 计算刚好碰到边界之前的速度: vt = sqrt(2aS + v0^2)
                self.vy = Math.sqrt(Math.abs(2 * self.ay * (current_y - top) + current_vy * current_vy));
                self.vy = current_vy > 0 ? self.vy : -self.vy;
                if (isNaN(self.vy)) {
                    self.vy = 0;
                    self.ay = 0;
                    self.y = top;
                    return false;
                }
                // 计算从当前位置到碰撞位置的时间
                if (self.ay == 0) {
                    if (self.vy == 0) {
                        t1 = 0;
                    } else {
                        t1 = (top - current_y) / self.vy;
                    }
                } else {
                    t1 = Math.abs((self.vy - current_vy) / self.ay);
                }
                // 碰撞后速度衰减并反向
                self.vy = -self.vy * self.loss_y;
                // 碰撞后反弹的位移位置
                self.y = self.s(self.vy, self.ay, self.dt - t1);
                // 位移小于阈值,则速度归零
                if (self.y - top < ACCURACY) {
                    self.vy = 0;
                    self.ay = 0;
                    self.y = top;
                }
            }
            else {}
        }
 
        boundary(0, canvas.width - this.radius, canvas.height - this.radius, 0);
 
    };
 
    function clear() {
        context.fillStyle = 'rgba(0,0,0,0.3)';
        context.fillRect(0,0,canvas.width,canvas.height);
    }
 
    var ball = new Ball(), animate;
    function draw() {
        clear();
        ball.draw();
        ball.next();
    }
 
    canvas.addEventListener('click',function(e){
        if (!running) {
            ball.x = e.clientX;
            ball.y = e.clientY;
            animate = setInterval(function() {
                draw();
            }, 20);
            running = true;
        } else {
            running = false;
            clearInterval(animate);
        }
    });
 
    ball.draw();
</script>
</body>
</html>

bounceball

3.canvas图像

3.1基础api

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>ball animate</title>
    <style>
        body {
            margin:0;
            padding:0;
            height: 100%;
            /*background: #000;*/
            overflow: hidden;
        }
        canvas {
            padding: 0;
            background: #000;
            border: 1px solid;
        }
    </style>
</head>
<body>
<canvas id="canvas" width="800" height="800"></canvas>
<script>
    var canvas = document.getElementById('canvas');
    var ctx = canvas.getContext('2d');
    var img = new Image();
    img.src = './1.png';
    img.onload = function() {
        ctx.drawImage(img,280,280)
    }
    // 绘制裁剪路径
    //ctx.arc(100, 100, 75, 0, Math.PI*2, false);
    //ctx.clip();

    //ctx.fillRect(0, 0, 100,100);
</script>
</body>
</html>

canvasImg

3.2canvas放大镜效果练习

<!DOCTYPE html>
<html>
<head lang="en">
    <meta charset="UTF-8">
    <title></title>
</head>
<body style="background: black;">

    <canvas id="canvas" style="display:block;margin:0 auto;border:1px solid #aaa;">
        您的浏览器尚不支持canvas
    </canvas>

    <canvas id="offCanvas" style="display: none">
    </canvas>

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

        var offCanvas = document.getElementById("offCanvas")
        var offContext = offCanvas.getContext("2d")

        var image = new Image()
        var isMouseDown = false
        var scale

        window.onload = function(){

            canvas.width = 1152
            canvas.height = 768

            image.src = "img-lg.jpg"
            image.onload = function(){

                offCanvas.width = image.width
                offCanvas.height = image.height
                scale = offCanvas.width / canvas.width

                context.drawImage( image , 0 , 0 , canvas.width , canvas.height )
                offContext.drawImage( image , 0 , 0 )
            }
        }

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

        canvas.onmousedown = function(e){
            e.preventDefault()
            isMouseDown = true
            point = windowToCanvas( e.clientX , e.clientY )
            console.log( point.x , point.y )
            drawCanvasWithMagnifier( true , point )
        }

        canvas.onmouseup = function(e){
            e.preventDefault()
            isMouseDown = false
            drawCanvasWithMagnifier( false )
        }

        canvas.onmouseout = function(e){
            e.preventDefault()
            isMouseDown = false
            drawCanvasWithMagnifier( false )
        }

        canvas.onmousemove = function(e){
            e.preventDefault()
            if( isMouseDown == true ){
                point = windowToCanvas( e.clientX , e.clientY )
                console.log( point.x , point.y )
                drawCanvasWithMagnifier( true , point )
            }
        }

        function drawCanvasWithMagnifier( isShowMagnifier , point ){

            context.clearRect( 0 , 0 , canvas.width , canvas.height )
            context.drawImage( image , 0 , 0 , canvas.width , canvas.height )
            if( isShowMagnifier == true ){
                drawMagnifier( point )
            }
        }

        function drawMagnifier( point ){

            var mr = 200

            var imageLG_cx = point.x * scale
            var imageLG_cy = point.y * scale

            var sx = imageLG_cx - mr
            var sy = imageLG_cy - mr

            var dx = point.x - mr
            var dy = point.y - mr

            context.save()

            context.lineWidth = 10.0
            context.strokeStyle = "#069"

            context.beginPath()
            context.arc( point.x , point.y , mr , 0 , Math.PI*2 , false )
            context.stroke()
            context.clip()
            context.drawImage( offCanvas , sx , sy , 2*mr , 2*mr , dx , dy , 2*mr , 2*mr )
            context.restore()
        }

    </script>
</body>
</html>

oversize

3.3canvas缩放效果练习

<!DOCTYPE html>
<html>
<head lang="en">
    <meta charset="UTF-8">
    <title></title>
</head>
<body style="background: black;">

    <canvas id="canvas" style="display:block;margin:0 auto;border:1px solid #aaa;">
    您的浏览器尚不支持canvas
    </canvas>
    <canvas id="watermark-canvas" style="display:none;margin:0 auto;border:1px solid #aaa;">
        您的浏览器尚不支持canvas
    </canvas>
    <input type="range" id="scale-range" min="0.5" max="3.0" step="0.01" value="0" style="display:block;margin:20px auto;width:800px"/>

    <script>
        var canvas = document.getElementById("canvas")
        var context = canvas.getContext("2d")
        var slider = document.getElementById("scale-range")
        var image = new Image()

        var watermarkCanvas = document.getElementById("watermark-canvas")
        var watermarkContext = watermarkCanvas.getContext("2d")

        
        window.onload = function(){

            canvas.width = 1152
            canvas.height = 768

            var scale = slider.value
            image.src = "img-lg.jpg"
            image.onload = function(){
                //缩放
                drawImageByScale( scale )
                slider.onmousemove = function(){
                    scale = slider.value
                    drawImageByScale( scale )
                }
            }
        }
        function drawImageByScale( scale ){

            var imageWidth = 1152 * scale
            var imageHeight = 768 * scale
            x = canvas.width /2 - imageWidth / 2
            y = canvas.height / 2 - imageHeight / 2

            context.clearRect( 0 , 0 , canvas.width , canvas.height )
            context.drawImage( image , x , y , imageWidth , imageHeight )
        }
    </script>
</body>
</html>

scale

3.4canvas水印效果练习


<!DOCTYPE html>
<html>
<head lang="en">
    <meta charset="UTF-8">
    <title></title>
</head>
<body style="background: black;">

    <canvas id="canvas" style="display:block;margin:0 auto;border:1px solid #aaa;">
        您的浏览器尚不支持canvas
    </canvas>
    <input type="range" id="scale-range" min="0.5" max="3.0" step="0.01" value="1.0" style="display:block;margin:20px auto;width:800px"/>

    <canvas id="watermark-canvas" style="display:none;margin:0 auto;border:1px solid #aaa;">
        您的浏览器尚不支持canvas
    </canvas>

    <script>
        var canvas = document.getElementById("canvas")
        var context = canvas.getContext("2d")
        var slider = document.getElementById("scale-range")

        var watermarkCanvas = document.getElementById("watermark-canvas")
        var watermarkContext = watermarkCanvas.getContext("2d")

        window.onload = function(){

            canvas.width = 1152
            canvas.height = 768

            var image = new Image()
            var scale = 1.0
            image.src = "img-lg.jpg"
            image.onload = function(){
                drawImage( image , scale )

                slider.onmousemove = function(){
                    scale = slider.value
                    drawImage( image , scale )
                }
            }

            //setup watermark canvas
            watermarkCanvas.width = 600
            watermarkCanvas.height = 100

            watermarkContext.font = "bold 50px Arial"
            watermarkContext.lineWidth = "1"
            watermarkContext.fillStyle = "rgba( 255 , 255 , 255 , 0.5 )"
            watermarkContext.textBaseline = "middle";
            watermarkContext.fillText( "SFY❤GYK" , 20 , 50 )
        }

        function drawImage( image , scale ){

            imageWidth = 1152 * scale
            imageHeight = 768 * scale
            x = canvas.width /2 - imageWidth / 2
            y = canvas.height / 2 - imageHeight / 2

            context.clearRect( 0 , 0 , canvas.width , canvas.height )
            context.drawImage( image , x , y , imageWidth , imageHeight )
            context.drawImage( watermarkCanvas , canvas.width - watermarkCanvas.width ,
                                                  canvas.height - watermarkCanvas.height )
        }


    </script>
</body>
</html>

water

3.4canvas滤镜效果练习

<!DOCTYPE html>
<html>
<head lang="en">
    <meta charset="UTF-8">
    <title></title>
</head>
<body>

    <div style="margin: 20px auto; width:1700px;">
        <canvas id="canvasa" width="800" height="560" style="display:block;float:left;border:1px solid #aaa;">
        </canvas>

        <canvas id="canvasb" width="800" height="560" style="display:block;float:right;border:1px solid #aaa;">
        </canvas>
    </div>
    <div style="clear: both"></div>

    <div style="text-align: center; margin-top:50px;font-size:20px;">
        <a href = "javascript:greyEffect()" >Grey Effect</a>
        <a href = "javascript:blackEffect()" >Black and White Effect</a>
        <a href = "javascript:reverseEffect()" >Reverse Effect</a>
        <a href = "javascript:blurEffect()" >Blur Effect</a>
        <a href = "javascript:mosaicEffect()" >Mosaic Effect</a>
    </div>
    <script>
        var canvasa = document.getElementById("canvasa")
        var contexta = canvasa.getContext("2d")

        var canvasb = document.getElementById("canvasb")
        var contextb = canvasb.getContext("2d")

        var image = new Image()
        window.onload = function(){

            image.src = "autumn.jpg"
            image.onload = function(){

                contexta.drawImage( image , 0 , 0 , canvasa.width , canvasa.height )
            }
        }

        function greyEffect(){
            var imageData = contexta.getImageData( 0 , 0 , canvasa.width , canvasa.height )
            var pixelData = imageData.data
            for( var i = 0 ; i < canvasb.width * canvasb.height ; i ++ ){

                var r = pixelData[i*4+0]
                var g = pixelData[i*4+1]
                var b = pixelData[i*4+2]

                var grey = r*0.3+g*0.59+b*0.11

                pixelData[i*4+0] = grey
                pixelData[i*4+1] = grey
                pixelData[i*4+2] = grey
            }

            contextb.putImageData( imageData , 0 , 0 , 0 , 0 , canvasb.width , canvasb.height )
            context.putImageData()
        }

        function blackEffect(){

            var imageData = contexta.getImageData( 0 , 0 , canvasa.width , canvasa.height )
            var pixelData = imageData.data
            for( var i = 0 ; i < canvasb.width * canvasb.height ; i ++ ){

                var r = pixelData[i*4+0]
                var g = pixelData[i*4+1]
                var b = pixelData[i*4+2]

                var grey = r*0.3+g*0.59+b*0.11
                if(grey > 125){
                    pv = 255
                }
                else{
                    pv = 0
                }

                pixelData[i*4+0] = pv
                pixelData[i*4+1] = pv
                pixelData[i*4+2] = pv
            }

            contextb.putImageData( imageData , 0 , 0 , 0 , 0 , canvasa.width , canvasa.height )
        }

        function reverseEffect(){

            var imageData = contexta.getImageData( 0 , 0 , canvasa.width , canvasa.height )
            var pixelData = imageData.data
            for( var i = 0 ; i < canvasb.width * canvasb.height ; i ++ ){

                var r = pixelData[i*4+0]
                var g = pixelData[i*4+1]
                var b = pixelData[i*4+2]

                pixelData[i*4+0] = 255 - r
                pixelData[i*4+1] = 255 - g
                pixelData[i*4+2] = 255 - b
            }

            contextb.putImageData( imageData , 0 , 0 , 0 , 0 , canvasb.width , canvasb.height )
        }

        function blurEffect(){

            var tmpImageData = contexta.getImageData( 0 , 0 , canvasa.width , canvasa.height )
            var tmpPixelData = tmpImageData.data

            var imageData = contexta.getImageData( 0 , 0 , canvasa.width , canvasa.height )
            var pixelData = imageData.data

            var blurR = 3
            var totalnum = (2*blurR + 1)*(2*blurR + 1)

            for( var i = blurR ; i < canvasb.height - blurR ; i ++ )
                for( var j = blurR ; j < canvasb.width - blurR ; j ++ ){

                    var totalr = 0 , totalg = 0 , totalb = 0
                    for( var dx = -blurR ; dx <= blurR ; dx ++ )
                        for( var dy = -blurR ; dy <= blurR ; dy ++ ){

                            var x = i + dx
                            var y = j + dy

                            var p = x*canvasb.width + y
                            totalr += tmpPixelData[p*4+0]
                            totalg += tmpPixelData[p*4+1]
                            totalb += tmpPixelData[p*4+2]
                        }

                    var p = i*canvasb.width + j
                    pixelData[p*4+0] = totalr / totalnum
                    pixelData[p*4+1] = totalg / totalnum
                    pixelData[p*4+2] = totalb / totalnum
                }

            contextb.putImageData( imageData , 0 , 0 , 0 , 0 , canvasb.width , canvasb.height )
        }

        function mosaicEffect(){

            var tmpImageData = contexta.getImageData( 0 , 0 , canvasa.width , canvasa.height )
            var tmpPixelData = tmpImageData.data

            var imageData = contexta.getImageData( 0 , 0 , canvasa.width , canvasa.height )
            var pixelData = imageData.data

            var size = 16
            var totalnum = size*size
            for( var i = 0 ; i < canvasb.height ; i += size )
                for( var j = 0 ; j < canvasb.width ; j += size ){

                    var totalr = 0 , totalg = 0 , totalb = 0
                    for( var dx = 0 ; dx < size ; dx ++ )
                        for( var dy = 0 ; dy < size ; dy ++ ){

                            var x = i + dx
                            var y = j + dy

                            var p = x*canvasb.width + y
                            totalr += tmpPixelData[p*4+0]
                            totalg += tmpPixelData[p*4+1]
                            totalb += tmpPixelData[p*4+2]
                        }

                    var p = i*canvasb.width+j
                    var resr = totalr / totalnum
                    var resg = totalg / totalnum
                    var resb = totalb / totalnum

                    for( var dx = 0 ; dx < size ; dx ++ )
                        for( var dy = 0 ; dy < size ; dy ++ ){

                            var x = i + dx
                            var y = j + dy

                            var p = x*canvasb.width + y
                            pixelData[p*4+0] = resr
                            pixelData[p*4+1] = resg
                            pixelData[p*4+2] = resb
                        }
            }

            contextb.putImageData( imageData , 0 , 0 , 0 , 0 , canvasb.width, canvasb.height )

        }
    </script>
</body>
</html>

在使用上面的代码的时候会有跨域问题,解决方法如下:
npm install http-server -g
http-server -p 8081
filter

canvas应用的场景有很多,写这篇文章参考了很多别人的总结,链接放在下面大家去看看:

炫丽的倒计时效果Canvas绘图与动画基础:https://www.imooc.com/learn/133
Canvas绘图详解:https://www.imooc.com/learn/185
Canvas玩转图像处理:https://www.imooc.com/learn/476


旧城
94 声望6 粉丝

每行代码都产生价值。


« 上一篇
从URL到页面
下一篇 »
html5之svg