H5中的Canvas

Forturn’s wheel takes you very high and then throws you very low, and there is nothing you can do but face the turn of it with courage.

Canvas

设置<canvas>元素的 宽度时,注意不要使用style属性,直接通过指定 <canvas>本身的属性即可。像下面这样:

<canvas id="canvas" width=1000 height=600>xxx</canvas>

取得 canvas对象 var canvas = document.getElementById('canvas');

canvas 除了具备基本绘图能力的 2D 上下文,<canvas>还建议了一个名为 WebGL 的 3D 上下文。

要在这块画布(canvas)上绘图,需要取得绘图上下文(getContext())。
有些浏览器会为 HTML 规范之外的元素创建默认的 HTML 元素对象①。在这种情况下,即使 drawing 变量中保存着一个有效的元素引用,也检测不到 getContext()方法。( Firefox 3 中使用<canvas>元素。虽然浏览器会为该标签创建一个 DOM 对象,而且也可以引用它,但
这个对象中并没有 getContext()方法。)

var context = canvas.getContext('2d');

使用 toDataURL()方法,可以导出在<canvas>元素上绘制的图像。这个方法接受一个参数,即图像的 MIME 类型格式,而且适合用于创建图像的任何上下文。

canvas.toDataURL('image/png');

2D上下文

2D 上下文的两种基本绘图操作是填充和描边。填充,就是用指定的样式(颜色、渐变或图像)填充图形;描边,就是只在图形的边缘画线。 通过设置这两个属性:fillStylestrokeStyle 可以 对 填充和描边进行控制。

  • fillStyle('#cccccc'):填充颜色;
  • strokeStyle('#333'):描边颜色;
  • ctx.linewidth=10:描边宽度;
矩形绘制
  • fillRect():填充矩形
  • strokeRect():描边矩形
  • clearRect(x,y,width, height): 清除绘图区域((x,y)为左上角,宽为width,高为height的大小)的内容;
路径绘制
  • arc(x,y,r,start,end):以(x,y)为圆心,r为半径, 画弧线,start为弧线起始位置的角度,end为弧线结束位置的角度;
  • moveTo(x,y):将当前光标移动到(x,y);
  • lineTo(x,y):从前点画直线到(x,y);
  • stroke():描边路径;
绘制文字
  • 文字格式:ctx.font = "bold 16px Arial";
  • 文字对齐方式:ctx.textAlign = "center";
  • 文本基线:ctx.textBaseline = "middle";
  • 填充文字:ctx.fillText("12", 250, 125);
  • 描边文字:ctx.strokeText()
变换

通过上下文的变换,可以把处理后的图像绘制到画布上。2D 绘制上下文支持各种基本的绘制变换。创建绘制上下文时,会以默认值初始化变换矩阵,在默认的变换矩阵下,所有处理都按描述直接绘制。为绘制上下文应用变换,会导致使用不同的变换矩阵应用处理,从而产生不同的结果。 可以通过如下方法来修改变换矩阵。

  • rotate(angle):围绕原点旋转图像 angle 弧度。
  • scale(scaleX, scaleY):缩放图像,在 x 方向乘以 scaleX,在 y 方向乘以 scaleY。scaleX和 scaleY 的默认值都是 1.0。
  • translate(x, y):将坐标原点移动到(x,y)。执行这个变换之后,坐标(0,0)会变成之前由(x,y)表示的点。
  • transform(m1_1, m1_2, m2_1, m2_2, dx, dy):直接修改变换矩阵,方式是乘以如下 矩阵。

    m1_1 m1_2 dx

    m2_1 m2_2 dy

    0 0 1

  • setTransform(m1_1, m1_2, m2_1, m2_2, dx, dy):将变换矩阵重置为默认状态,然后再调用 transform()。

变换有可能很简单,但也可能很复杂,这都要视情况而定。

除此以外,我们还可以调用save()restore()方法,对设置的上下文进行保存和恢复。

PS:save() 方法保存的只是对绘图上下文的设置和变换, 不会保存绘图上下文的内容。

绘制图像
  • drawImage():最简单的调用方式 是传入一个 HTML 元素,以及绘制该图像的起点的 x 和 y 坐标。绘制到画布上 的图像大小与原始大小一样。
  • drawImage():如果你想改变绘制后图像的大小,可以再多传入两个参数,分别表示目标 宽度和目标高度。通过这种方式来缩放图像并不影响上下文的变换矩阵。
  • drawImage():可以选择把图像中的某个区域绘制到上下文中。drawImage()方法的这种调 用方式总共需要传入 9 个参数:要绘制的图像、源图像的 x 坐标、源图像的 y 坐标、源图像的宽度、源 图像的高度、目标图像的 x 坐标、目标图像的 y 坐标、目标图像的宽度、目标图像的高度。这样调用 drawImage()方法可以获得最多的控制。

drawImage()方法除了可以接受一个image作为参数,还可以接受一个<canvas>对象。

图像不能来自其他域。如果图像来自其他域, 调用 toDataURL() 会抛出一个错误

阴影

2D 上下文会根据以下几个属性的值,自动为形状或路径绘制出阴影。

  • shadowColor:用 CSS 颜色格式表示的阴影颜色,默认为黑色。
  • shadowOffsetX:形状或路径 x 轴方向的阴影偏移量,默认为 0。
  • shadowOffsetY:形状或路径 y 轴方向的阴影偏移量,默认为 0。
  • shadowBlur:模糊的像素数,默认 0,即不模糊。

这些属性都可以通过 context 对象来修改。只要在绘制前为它们设置适当的值,就能自动产生阴 影。

渐变

渐变由 CanvasGradient 实例表示,很容易通过 2D 上下文来创建和修改。要创建一个新的线性渐 变,可以调用 createLinearGradient()方法。这个方法接收 4 个参数:起点的 x 坐标、起点的 y 坐 标、终点的 x 坐标、终点的 y 坐标。 调用这个方法后, 它就会创建一个指定大小的渐变, 并返回 CanvasGradient 对象的实例。

创建了渐变对象后,下一步就是使用 addColorStop()方法来指定色标。这个方法接收两个参数: 色标位置和 CSS 颜色值。色标位置是一个 0(开始的颜色)到 1(结束的颜色)之间的数字。例如:

var gradient = context.createLinearGradient(30, 30, 70, 70);
gradient.addColorStop(0, "white"); 
gradient.addColorStop(1, "black");

此时,gradient 对象表示的是一个从画布上点(30,30)到点(70,70)的渐变。起点的色标是白色,终 点的色标是黑色。然后就可以把 fillStyle 或 strokeStyle 设置为这个对象,从而使用渐变来绘制 形状或描边:

//绘制渐变矩形 
context.fillStyle = gradient; context.fillRect(30, 30, 50, 50);

要创建径向渐变(或放射渐变),可以使用 createRadialGradient()方法。这个方法接收 6 个参数,对应着两个圆的圆心和半径。

模式

模式其实就是重复的图像,可以用来填充或描边图形。要创建一个新模式,可以调用createPattern()方法并传入两个参数:一个 HTML 元素和一表示如何重复图像的字符串。其中,第二个参数的值与 CSS 的 background-repeat 属性值相同,包括”repeat”、”repeat-x”、”repeat-y”和”no-repeat”。

获取图像数据

2D 上下文的一个明显的长处就是,可以通过 getImageData()取得原始图像数据。这个方法接收4 个参数:要取得其数据的画面区域的 x 和 y 坐标以及该区域的像素宽度和高度。例如,要取得左上角坐标为(10,5)、大小为 50×50 像素的区域的图像数据,可以使用以下代码:

var imageData = context.getImageData(10, 5, 50, 50); 

这里返回的对象是 ImageData 的实例。每个 ImageData 对象都有三个属性:width、height 和data。其中 data 属性是一个数组,保存着图像中每一个像素的数据。在 data 数组中,每一个像素用4 个元素来保存,分别表示红、绿、蓝和透明度值。因此,第一个像素的数据就保存在数组的第 0 到第3 个元素中。

WebGL

WebGL 是针对 Canvas 的 3D 上下文。但它并不是W3C制定的标准。

WebGL(全写Web Graphics Library)是一种3D绘图标准,这种绘图技术标准允许把JavaScript和OpenGL ES 2.0结合在一起,通过增加OpenGL ES 2.0的一个JavaScript绑定,WebGL可以为HTML5 Canvas提供硬件3D加速渲染,这样Web开发人员就可以借助系统显卡来在浏览器里更流畅地展示3D场景和模型了,还能创建复杂的导航和数据视觉化。显然,WebGL技术标准免去了开发网页专用渲染插件的麻烦,可被用于创建具有复杂3D结构的网站页面,甚至可以用来设计3D网页游戏等等。

WebGL 涉及的复杂计算需要提前知道数值的精度,而标准的 JavaScript 数值无法满足需要。为此,WebGL 引入了一个概念,叫类型化数组(typed arrays)。类型化数组也是数组,只不过其元素被设置为特定类型的值。

<!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>
    <style>
    </style>
</head>

<body>
    <img src="images/07.png" alt="">
    <div class="box">
        <canvas id="canvas" width="500px" height="500px">Your browser's version is too low and please update it to the newest.</canvas>
    </div>
    <script>
        var canvas = document.getElementById('canvas');
        var ctx = null;

        if (canvas.getContext) {
            ctx = canvas.getContext('2d');
            // ctx.scale(5, 5);

            // ctx.fillStyle = "#ff0000";
            // ctx.fillRect(10, 10, 200, 200); // 宽高是200的矩形 填充色:红色

            // ctx.fillStyle = "rgba(0, 255, 0, 0.3)";
            // ctx.fillRect(110, 110, 200, 200); // 宽高是200的矩形 填充色: 绿色, 透明度 30%

            // ctx.strokeStyle = 'rgba(0, 0, 255, 0.3)';
            // ctx.lineWidth = 30;
            // ctx.strokeRect(109, 109, 202, 202); // 创建描边矩形, 边框宽度是30, 颜色是蓝色


            // setTimeout(() => {
            //     console.log('清掉左上角的宽高为150的区域');
            //     ctx.clearRect(10, 10, 330, 330);
            //     startLine();
            // }, 3000);
            // startLine();

            function startLine() {
                // start draw line
                ctx.lineWidth = 2
                ctx.strokeStyle = "black"
                ctx.beginPath();

                ctx.arc(250, 250, 200, 1, Math.PI - 1);

                // ctx.arc(250, 250, 200, Math.PI+1, 2*Math.PI-1);

                ctx.moveTo(10, 10);
                ctx.lineTo(300, 10);
                ctx.moveTo(400, 250); // 表的中心
                ctx.arc(250, 250, 150, 0, 360); // 表盘
                ctx.moveTo(390, 250);
                ctx.arc(250, 250, 140, 0, 360); // 表盘

                ctx.moveTo(380, 250);
                ctx.lineTo(250, 250); // 分针
                ctx.lineTo(250, 350); // 时针

                ctx.stroke(); // 对路径描边
            }

            // drawText();

            function drawText() {
                ctx.font = "bold 16px Arial";
                ctx.textAlign = "center";
                ctx.textBaseline = "middle";
                ctx.fillText("12", 250, 125);

                ctx.lineWidth = 2;
                ctx.font = "bold 36px Arial";
                ctx.strokeStyle = 'yellow'; // 描边文字颜色
                ctx.textBaseline = 'top'; // 基线
                ctx.textAlign = 'left'; // 水平对齐方式
                ctx.strokeText('This 卜', 10, 10);
            }
            // transform();

            function transform() {
                ctx.translate(50, 50);
                ctx.rotate(0.5);
                ctx.moveTo(0, 0);
                ctx.strokeStyle = 'orange';
                // ctx.fillRect(0, 0, 120, 120);
            }

            // setTimeout(() => {
            //     drawImage();
            // }, 1000);

            function drawImage() {
                var img1 = document.images[0];
                ctx.drawImage(img1, 120, 50);
                ctx.drawImage(img1, 190, 190, 70, 70);
                ctx.drawImage(img1, 0, 0, 100, 100, 0, 0, 50, 50);
            }

            // ctx.rotate(-0.5);
            // ctx.clearRect(0, 0, 500, 500);

            // shadow();

            function shadow() {
                ctx.shadowColor = 'red';
                ctx.shadowBlur = 5;
                ctx.shadowOffsetX = 10;
                ctx.shadowOffsetY = 40;
                ctx.fillStyle = "rgba(0, 200, 0, 0.5)";
                ctx.fillRect(20, 20, 120, 200);
            }

            // saveAndRestore();

            function saveAndRestore() {
                ctx.clearRect(0, 0, 500, 500);
                ctx.shadowColor = 'blue';
                ctx.beginPath();
                ctx.moveTo(50, 50);
                ctx.lineTo(100, 100);
                ctx.stroke();

                ctx.save();
                ctx.shadowColor = 'red';
                ctx.fillRect(100, 10, 50, 100); // 阴影颜色 虹色
                ctx.restore();
                ctx.fillRect(200, 200, 50, 100); // 阴影颜色 蓝色
            }

            ctx.shadowBlur = 0;
            ctx.shadowOffsetX = 0;
            ctx.shadowOffsetY = 0;
            // gradient();

            function gradient() {
                // 线性渐变
                var lineGradient = ctx.createLinearGradient(300, 0, 150, 150);
                lineGradient.addColorStop(0, 'white');
                lineGradient.addColorStop(1, 'green');

                // 应用线性渐变
                ctx.fillStyle = lineGradient;
                ctx.fillRect(200, 100, 150, 150);

                ctx.clearRect(0, 0, 500, 500);
                // 径向渐变
                var radialGradient = ctx.createRadialGradient(100, 100, 30, 100, 100, 50);

                radialGradient.addColorStop(0, "white");
                radialGradient.addColorStop(1, "black");

                //绘制渐变矩形 
                ctx.fillStyle = radialGradient;
                // 注意矩形坐标 及宽高 与 径向渐变 参数的关系
                ctx.fillRect(50, 50, 100, 100);
            }

            ctx.clearRect(0, 0, 500, 500);
            // setTimeout(()=>{pattern();}, 1500);
            // 模式
            function pattern() {
                var ptn = ctx.createPattern(document.images[0], 'repeat');
                ctx.fillStyle = ptn;
                ctx.fillRect(10, 10, 500, 500);

                ctx.clearRect(0, 0, 500, 500);
                ptn = ctx.createPattern(document.images[0], 'repeat-x');
                ctx.fillStyle = ptn;
                ctx.fillRect(10, 10, 500, 500);
            }

            setTimeout(() => {
                getImageData();
            }, 2000);
            var imageData;
            // 获取图像数据
            function getImageData() {
                var img1 = document.images[0];

                ctx.drawImage(img1, 0, 0);
                imageData = ctx.getImageData(0, 0, 128, 128);

                data = imageData.data;

                // 将图像做灰度处理
                for (i = 0, len = data.length; i < len; i += 4) {

                    red = data[i];
                    green = data[i + 1];
                    blue = data[i + 2];
                    alpha = data[i + 3];

                    //求得 rgb 平均值 
                    average = Math.floor((red + green + blue) / 3);

                    //设置颜色值,透明度不变 
                    data[i] = average;
                    data[i + 1] = average;
                    data[i + 2] = average;

                }

                //回写图像数据并显示结果 
                imageData.data = data;
                ctx.putImageData(imageData, 0, 0);
            }





        }
    </script>
</body>

</html>
  • 1
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值