JavaScript Canvas画布

本文详细介绍了HTML5 Canvas的基本用法,包括如何使用JavaScript进行绘图、图像处理及各种绘图技巧。涵盖绘图样式设置、路径绘制、文本渲染、图像处理等方面的内容。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

<canvas>起初是由Apple Inc提出的,使用JavaScript在网页上绘制图形;之后被HTML5标准化,主流的浏览器都支持,IE8及较低版本不支持;

使用<canvas>必须要使用width和height指定绘制区域大小;

绘图前,需要使用getContext()获得绘图的上下文,该方法需要传入上下文,如‘2d’;使用该方法前需要检测该方法是否存在以判断是否支持canvas;

toDataURL()方法可以导出在canvas上绘制的图像,该方法接收一个表示图像MIME类型的参数;

var canvas = document.getElementById('canvas');     // 获取canvas元素
var imgURI = canvas.toDataURL('image/png');     // 取得图像数据URI
// 将其被添加到img并显示
var img = document.createElement('img');
img.src = imgURI;
document.body.appendChild(img);

2D上下文

1、绘图样式通过fillStyle和strokeStyle属性,可以接受的值为字符串、渐变对象、模式对象;字符串值可以是任何格式的颜色值;需要在绘图前设置其样式,否则不会起作用;
2、绘制矩形:fillRect()、strokeRect()、clearRect(),3个方法均接收4个参数,分别为startX、startY、width、height;结合clearRect()可以绘制出很有意思的图像;
3、绘制路径:绘制路径时首先需要调用无参方法beginPath(),具体绘制的方法包括:moveTo(x,y)绘图游标移动到当前点,不画线;lineTo(x,y)从上一点画线到想当前点;rect(x, y, width, height);
arc(x, y, r, startAngle, endAngle, clockwise)(最后一个参数是一个表示从startAngle到endAngle是否顺时针的布尔值,false为顺时针)
arcTo(x1, y1, x2, y2, r)从A(x1,y1)到B(x2,y2)绘制一条弧线穿过A点,B点截止;
bezierCurveTo(c1x, c1y, c2x, c2y, x, y)绘制贝塞尔曲线,(c1x, c1y)和(c2x, c2y)为控制点;
closePath():用于绘制一条连接到路径起点的线条,无参方法;

路径绘制完后需要使用fill()和stroke()方法进行路径描边才能将其绘制到画布上;并可以使用clip()进行剪切;

另外,还有一个isPointInPath()用于在路径关闭前判断画布上的某一点是否在画布上;ctx.isPointInPath(x, y)

/**
 * 绘制时钟
 * @type {[type]}
 */
var canvas = document.getElementById('canvas');
var ctx = canvas.getContext('2d');
ctx.beginPath();
ctx.arc(100, 100, 80, 0, 2 * Math.PI, false);
ctx.moveTo(175, 100);       // 把绘制点移动到内圆上
ctx.arc(100, 100, 75, 0, 2 * Math.PI, false);
ctx.moveTo(100, 25);
ctx.lineTo(100, 30);
ctx.moveTo(100, 175);
ctx.lineTo(100, 170);
ctx.moveTo(25, 100);
ctx.lineTo(30, 100);
ctx.moveTo(175, 100);
ctx.lineTo(170, 100);
// 绘制时针
ctx.moveTo(100, 100);
ctx.lineTo(150, 100);
// 绘制分针
ctx.moveTo(100, 100);
ctx.lineTo(100, 35);

ctx.stroke();

ctx.beginPath();
// 绘制轴
ctx.moveTo(100, 100);
ctx.arc(100, 100, 3, 0, 2 * Math.PI, false);

ctx.fill();

ctx.font = 'italic 12px Fantasy';
ctx.fillText('balco', 85, 140);

这里写图片描述

4、绘制文本
绘制文本的两个方式包括fillText()和strokeText(),接受四个参数需绘制的文本字符串、x坐标、y坐标、可选的最大像素宽度;同时可以通过font(样式/大小/字体)、textAlign(left/center/right/start/end,建议使用start和end)、textBaseline(可能的取值top/hanging/middle/alphabetic/ideographic/bottom)属性设置文字的信息;当然这几个属性有默认值,不是必须要设置的;

5、变换
变换方法:rotate(angle)/ scale(scaleX, scaleY)/ translate(x, y)移动至(x,y);transform(a, b, c, d, e, f)变换矩阵,
a b e
c d f
0 0 1
setTransform(a, b, c, d, e, f)将变换矩阵重置为默认状态,然后调用transform();

可以同时使用ctx.save()和ctx.restore()方法操作一个栈结构,用于操作关于画布的设置;save()方法入栈,restore()方法出栈;

6、绘制图像
drawImage()方法用于把一幅图像绘制到画布上;第一个参数可以是<img>元素或者另一个<canvas>元素;

// 参数对一:第一个参数为`<img>`元素,x和y分别表示绘制图像起点;
var img = document.images[0];
ctx.drawImage(img, x, y) 
// 参数对二:新增的最后两个参数分别表示目标宽度和高度进行图像缩放;
ctx.drawImage(img, x, y, width, height) 
// 参数对三:x0, y0,w0,h0分别表示源图像的x,y坐标及宽度和高度;剩余四个表示目标图像的;这样只会把源图像的一部分复制到目标图像中
ctx.drawImage(img, x0, y0, w0, h0, x1, y1, width1, height1);

这里写图片描述

7、绘制阴影
可以通过shadowColor/ shadowOffsetX/ shadowOffsetY/ shadowBlur属性为形状或者路径添加阴影效果;
不过,不同浏览器对绘制阴影的支持有些差异;

ctx.shadowColor = 'rgba(2, 3, 3, .1)';
ctx.shadowOffsetX = 5;
ctx.shadowOffsetY = 8;
ctx.shadowBlur = 4;

8、渐变
渐变由canvasGradient实例表示,

// 线性渐变
var gradient = ctx.createLinearGradient(0, 0, 200, 200); // (x,y)起点,(a,b)终点
gradient.addColorStop(0, 'red');
gradient.addColorStop(0.5, 'yellow');
gradient.addColorStop(1, 'green');
ctx2.fillStyle = gradient;
ctx2.fillRect(0, 0, 200, 200);
// 径向渐变
var gradient2 = ctx.createRadialGradient(100, 100, 10, 100, 100, 100)   //
gradient2.addColorStop(0, 'red');
gradient2.addColorStop(0.5, 'yellow');
gradient2.addColorStop(1, 'green');
ctx3.fillStyle = gradient2;
ctx3.fillRect(0, 0, 200, 200);

这里写图片描述

9、模式
模式是图像的重复,可以像渐变对象一样可以用于填充或者描边;
通过调用createPattern(imgElement, pattern),第一个参数是<img>元素,第二个参数是表示重复方式的字符串(可选值为‘repeat’‘repeat-x’‘repeat-y’‘no-repeat’);
下图左边为repeat-y模式,右边为repeat模式;

这里写图片描述

10、使用图像数据
2D上下文的一个优势是可以通过getImageData()方法取得原始图像数据,返回的对象时ImageData对象;该方法接受4个参数,分别为画面区域的x,y坐标以及宽度和高度;

ImageData对象有三个属性:width、height、data;data是一个plain数组属性,保存着每个像素的相关数据,每个像素包括红、绿、蓝、透明度值,保存在数组的前四个元素中;

var imgData = ctx.getImageData(40, 40, 50, 50);
var data = imgData.data;
data[0]     // 第一个像素的red值
data[1]     // 第一个像素的green值
data[2]     // 第一个像素的blue值
data[3]     // 第一个像素的alpha值

11、合成
关于canvas合成涉及到两个属性globalAhpha和globalCompositeOperation,这两个属性会被应用到2D上下文的所有绘制操作;可以使用合成操作实现许多非常复杂的图案功能;

var myCanvas2 = document.getElementById('canvas2');
var myCanvas3 = document.getElementById('canvas3');
var myCanvas4 = document.getElementById('canvas4');
var myCanvas5 = document.getElementById('canvas5');

ctx2 = myCanvas2.getContext('2d');
chromaticGraphComposite(ctx2, 'screen');

ctx3 = myCanvas3.getContext('2d');
chromaticGraphComposite(ctx3, 'soft-light');

ctx4 = myCanvas4.getContext('2d');
chromaticGraphComposite(ctx4, 'xor');

ctx5 = myCanvas5.getContext('2d');
chromaticGraphComposite(ctx5, 'multiply');

function chromaticGraphComposite(context, composMethod) {
    context.translate(0, -5);
    context.beginPath();
    context.arc(100, 60, 50, 0, 2 * Math.PI, false);
    context.fillStyle = 'rgba(255, 0, 0, 1)';
    context.fill();
    context.closePath();

    context.globalCompositeOperation = composMethod;
    context.beginPath();
    context.moveTo(100 - 20 * Math.sqrt(3), 180);
    context.arc(100 - 20 * Math.sqrt(3), 120, 50, 0, 2 * Math.PI, false);
    context.fillStyle = 'rgba(0, 255, 0, 1)';
    context.fill();
    context.closePath();

    context.globalCompositeOperation = composMethod;
    context.beginPath();
    context.moveTo(100 + 20 * Math.sqrt(3), 180);
    context.arc(100 + 20 * Math.sqrt(3), 120, 50, 0, 2 * Math.PI, false);
    context.fillStyle = 'rgba(0, 0, 255, 1)';
    context.fill();
    context.closePath();
    context.fillStyle = 'gray';

    context.translate(0, 185);
    context.fillRect(0, 0, 200, 20);
    context.font = 'bold 12px Arial';
    context.textAlign = 'center';
    context.textBaseline = 'top';
    context.fillStyle = 'white';
    context.fillText(composMethod, 100, 3);
    context.closePath();
}

这里写图片描述

globalAlpha:指定所有绘制的透明度(0,1),默认为0;
globalCompositeOperation:指定后绘制图形与先绘制图形的合成方式,取值可以为“source-over”(default)“source-in”“source-out”“source-atop”“destination-over”“destination-in”“destination-out”“destination-atop”“lighter”“copy”“xor”
不同浏览器对该特性的支持还不完善;

具体实现效果可以参考https://developer.mozilla.org/zh-CN/docs/Web/API/Canvas_API/Tutorial/Compositing


WebGL是基于Canvas的3D上下文实现的,WebGL的标准制定者与OpenGL相同,均为Kronos Group,而不是W3C。此处不做详细介绍,可以参考教程http://learningwebgl.com/blog/

MIME类型

MIME类型是一种通知客户端文件传输多样性的机制。由于文件后缀名对网页是没有意义的,因此,正确地设置服务器是很重要的,这样就可以给每个文档传输正确的MIME类型;浏览器则会根据相应的MIME类型决定对从服务器fetch的文档采取什么样的默认行为;

常见的MIME类型基本格式为Type/SubType,并且是大小写不敏感的;
Discrete types
其中Type类型包括text、image、audio、video、application;
常见的类型有text/plain 、text/html、image/jpeg、image/png、audio/mpeg、audio/ogg、audio/mpeg、video/mp4、application/octet-stream(二进制文件默认格式)等;
Multipart types
1、multipart/form-data(主要用于form表单提交,作为一个多部分的文档形式,它由不同的部分组成并由一个边界分隔;每一部分自身就是一个实体,拥有自己的HTTP Header、用于文件上传的Content-Type实体头(标示资源的媒体类型,包括media-type、charset、boundary信息)等;)
2、multipart/byteranges


参考文献
《JavaScript高级程序设计》第三版

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

Neil-

你们的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值