<html lang="en">
<head>
<meta charset="UTF-8">
<title>canvastitle>
head>
<body>
<canvas id="drawing" width="200" height="200">A drawing of something.canvas>
body>
html>
<script type="text/javascript">
let drawing = document.getElementById("drawing");
if(drawing.getContext){//检查浏览器是否支持
//取得图像的数据URL
let imgURL = drawing.toDataURL("image/png");
//显示图像
let image = document.createElement("img");
image.src = imgURL;
document.body.appendChild(image);
}
script>
属性:fillStyle
和strokeStyle
。两个属性的值可以是字符串、渐变对象或模式对象,默认值为#000000
var drawing = document.getElementById("drawing");
if(drawing.getContext){
let context = drawing.getContext("2d");
context.strokeStyle = "red";
context.fillStyle = "#0000ff";
}
与矩形有关的方法包括fillRect()、strokeRect()和clearRect()。这三个方法都能接收4 个参数:矩形的x 坐标、矩形的y 坐标、矩形宽度和矩形高度。这些参数的单位都是像素。
var drawing = document.getElementById("drawing");
let context = drawing.getContext("2d");
//绘制红色矩形
context.fillStyle = "#ff0000";
context.fillRect(10, 10, 50, 50);
//绘制半透明的蓝色矩形
context.fillStyle = "rgba(0, 0, 255, 0.5)";
context.fillRect(30, 30, 50, 50);
//绘制红色描边矩形
context.strokeStyle = "#ff0000";
context.strokeRect(10, 10, 50, 50);
//绘制半透明的蓝色描边矩形
context.strokeStyle = "rgba(0,0,255,0.5)";
context.strokeRect(30, 30, 50, 50);
//clearRect()方法用于清除画布上的矩形区域
context.clearRect(40, 40, 10, 10);
要绘制路径,首先需要调用beginPath()方法,然后再调用以下方法来绘制路径:
创建了路径后,接下来有几种可能的选择。如果想绘制一条连接到路径起点的线条,可以调用closePath()。如果路径已经完成,你想用fillStyle 填充它,可以调用fill()方法。另外,还可以调用stroke()方法对路径描边,描边使用的是strokeStyle。最后还可以调用clip(),这个方法可以在路径上创建一个剪切区域。
<html lang="en">
<head>
<meta charset="UTF-8">
<title>canvastitle>
head>
<body>
<canvas id="clock" height="200" width="200">canvas>
body>
html>
<script type="text/javascript">
var clock = document.getElementById("clock");
let context = clock.getContext("2d");
context.beginPath();//开始
context.arc(100, 100, 99, 0, 2 * Math.PI, false);//外圆
context.moveTo(194, 100);
context.arc(100, 100, 94, 0, 2 * Math.PI, false);//内圆
context.moveTo(100, 100);
context.lineTo(100, 15);//分针
context.moveTo(100, 100);
context.lineTo(35, 100);//时针
context.stroke();//描边
script>
两个方法:fillText()和strokeText()。接收4个参数:要绘制的文本字符串、x 坐标、y 坐标和可选的最大像素宽度。三个属性:
//在表盘的上方绘制了数字12
context.font = "bold 10px Arial";
context.textAlign = "center";
context.textBaseline = "middle";
context.fillText("12", 100, 12);
//起点对齐
context.textAlign = "start";
context.fillText("12", 100, 40);
//终点对齐
context.textAlign = "end";
context.fillText("12", 100, 60);
确定文本大小的方法:measureText(),接收一个参数,即要绘制的文本,返回一个TextMetrics对象。
let cfont = document.getElementById("font");
let context = cfont.getContext("2d");
let fontSize = 100;
context.font = fontSize + "px Arial";
while(context.measureText("Hello world").width > 140){
fontSize--;
context.font = fontSize + "px Arial";
}
context.fillText("Hello world", 10, 10);
context.fillText("Font size is" + fontSize + "px", 10, 50);
修改变化矩阵的方法:
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()。
context.translate(100, 100);//将原点移动到100,100
context.moveTo(0, 0);
context.lineTo(0, -85);
context.moveTo(0, 0);
context.lineTo(-65, 0);
context.rotate(1);//向右旋转一定角度
有两个方法可以跟踪上下文的状态变化。如果将来要返回某组属性与变换的组合,可以调用save()方法。调用这个方法后,当时的所有设置都会进入一个栈结构,可以调用restore()方法回到之前保存的设置。
var can = document.getElementById("save");
let context = can.getContext("2d");
context.fillStyle = "#ff0000";
context.save();
context.fillStyle = "#00ff00";
context.translate(100, 100);
context.save();
context.fillStyle = "#0000ff";
context.fillRect(0, 0, 100, 200);//蓝色
context.restore();
context.fillRect(10, 10, 100, 200);//绿色
context.restore();
context.fillRect(0, 0, 100, 200);//红色
let image = document.images[0];
let canv = document.getElementById("image");
let context = canv.getContext("2d");
context.drawImage(image, 10, 10);//起点(10,10)
context.drawImage(image, 50, 10, 20, 30);//变成20*30像素
context.drawImage(image, 0, 10, 50, 50, 0, 100, 40, 60);//9个参数:要绘制的图像、源图像的x 坐标、源图像的y 坐标、源图像的宽度、源图像的高度、目标图像的x 坐标、目标图像的y 坐标、目标图像的宽度、目标图像的高度。
属性值:
//设置阴影
context.shadowOffsetX = 5;
context.shadowOffsetY = 5;
context.shadowBlur = 4;
context.shadowColor = "rgba(0, 0, 0, 0.5)";
由CanvasGradient实例表示。通过createLinearGradient()方法,接收4个参数:起点的x坐标、起点的y坐标、终点的x坐标、终点的y坐标。
使用addColorStop()方法来指定色标。接收两个参数:色标位置和CSS颜色值。
var gradient = context.createLinearGradient(30, 30, 70, 70);
gradient.addColorStop(0, "white");
gradient.addColorStop(1, "black");
var gra = document.getElementById("gradient");
let context = gra.getContext("2d");
let gradient = context.createLinearGradient(30, 30, 70, 70);
gradient.addColorStop(0, "white");
gradient.addColorStop(1, "black");
//绘制红色矩形
context.fillStyle = "#ff0000";
context.fillRect(10, 10, 50, 50);
//绘制渐变矩形
context.fillStyle = gradient;
context.fillRect(30, 30, 50, 50);
要创建径向渐变或放射渐变,可以使用createRadialGradient()方法。接收6 个参数,对应着两个圆的圆心和半径。前三个参数指定的是起点圆的原心(x 和y)及半径,后三个参数指定的是终点圆的原心(x 和y)及半径。
var gradient = context.createRadialGradient(55, 55, 10, 55, 55, 30);
模式就是重复的图像,用来填充或描边图形。通过调用createPattern()方法,两个参数:一个HTML
元素和一个表示如何重复图像的字符串。第二个字符串:repeat
、repeat-x
、repeat-y
和no-repeat
let image = document.images[0];
let pattern = context.createPattern(image, "repeat");
context.fillStyle = pattern;
context.fillRect(10, 10, 150, 150);
//
可以改为
var imageData = context.getImageData(10, 5, 50, 50);
返回的对象是ImageData 的实例。每个ImageData 对象都有三个属性:width、height 和data。data 属性是一个数组,保存着图像中每一个像素的数据。在data 数组中,每一个像素用4 个元素来保存,分别表示红、绿、蓝和透明度值
var drawing = document.getElementById("drawing");
//确定浏览器支持
if (drawing.getContext){
var context = drawing.getContext("2d"),
image = document.images[0],
imageData, data,
i, len, average,
red, green, blue, alpha;
//绘制原始图像
context.drawImage(image, 0, 0);
//取得图像数据
imageData = context.getImageData(0, 0, image.width, image.height);
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;
context.putImageData(imageData, 0, 0);
}
两个属性:globalAlpha 和globalComposition-Operation
//绘制红色矩形
context.fillStyle = "#ff0000";
context.fillRect(10, 10, 50, 50);
//修改全局透明度
context.globalAlpha = 0.5;
//绘制蓝色矩形
context.fillStyle = "rgba(0,0,255,1)";
context.fillRect(30, 30, 50, 50);
//重置全局透明度
context.globalAlpha = 0;
第二个属性的可能值:
//绘制红色矩形
context.fillStyle = "#ff0000";
context.fillRect(10, 10, 50, 50);
//设置合成操作
context.globalCompositeOperation = "destination-over";
//绘制蓝色矩形
context.fillStyle = "rgba(0,0,255,1)";
context.fillRect(30, 30, 50, 50);
类型化数组的核心就是一个名为ArrayBuffer 的类型。每个ArrayBuffer 对象表示的是内存中指定的字节数
var buffer = new ArrayBuffer(20);//分配20B
var bytes = buffer.byteLength;
最常见的视图是DataView,通过它可以选择ArrayBuffer中的一小段字节。创建DataView实例的时候传入一个ArrayBuffer、一个可选的字节偏移量(从该字节开始选择)和一个可选的要选择的字节数。
//基于整个缓冲器创建一个新视图
var view = new DataView(buffer);
//创建一个开始于字节9 的新视图
var view = new DataView(buffer, 9);
//创建一个从字节9 开始到字节18 的新视图
var view = new DataView(buffer, 9, 10);
alert(view.byteOffset);
alert(view.byteLength);
DataView支持的数据类型和相应的读写方法:
第一个参数都是字节偏移量,表示从哪个字节开始读入或写出
var buffer = new ArrayBuffer(20),
view = new DataView(buffer),
value;
view.setUint16(0, 25);
view.setUint16(2, 50); //不能从字节1开始,因为16位整数要用2B
value = view.getUint16(0);
littleEndian是一个布尔值,表示读写数值时是否采用小端字节序(即将数据的最低有效位保存在低内存地址中),而不是大端字节序(即将数据的最低有效位保存在高内存地址中)
var buffer = new ArrayBuffer(20),
view = new DataView(buffer),
value;
view.setUint16(0, 25);
value = view.getInt8(0);
alert(value); //0
都继承DataView,可分为以下几种:
//创建一个新数组,使用整个缓冲器
var int8s = new Int8Array(buffer);
//只使用从字节9 开始的缓冲器
var int16s = new Int16Array(buffer, 9);
//只使用从字节9 到字节18 的缓冲器
var uint16s = new Uint16Array(buffer, 9, 10);
//使用缓冲器的一部分保存8 位整数,另一部分保存16 位整数
var int8s = new Int8Array(buffer, 0, 10);
var uint16s = new Uint16Array(buffer, 11, 10);
每个视图构造函数都有一个名为BYTES_PER_ELEMENT 的属性,表示类型化数组的每个元素需要多少字节
//需要10 个元素空间
var int8s = new Int8Array(buffer, 0, 10 * Int8Array.BYTES_PER_ELEMENT);
//需要5 个元素空间
var uint16s = new Uint16Array(buffer, int8s.byteOffset + int8s.byteLength,5 * Uint16Array.BYTES_PER_ELEMENT);
//类型化视图
//创建一个数组保存5 个8 位整数(10 字节)
var int8s = new Int8Array([10, 20, 30, 40, 50]);
类型化视图的一个方法:subarray(),基于底层数组缓冲器的子集创建一个新视图。这个方法接收两个参数:开始元素的索引和可选的结束元素的索引
var uint16s = new Uint16Array(10),
sub = uint16s.subarray(2, 5);
let drawing = document.getElementById("drawing");
let gl = drawing.getContext("webgl");
if(gl){
alert("Exist!");
}
通过给getContext()传递第二个参数,可以对WebGL上下文进行一些设置。这个参数是一个对象,包含以下属性:
var gl = drawing.getContext("experimental-webgl", { alpha: false});
使用clearColor()方法来指定要使用的颜色值,该方法接收4 个参数:红、绿、蓝和透明度。
gl.clearColor(0,0,0,1); //black
gl.clear(gl.COLOR_BUFFER_BIT);//使用之前定义的颜色来填充相关区域
默认情况下,视口可以使用整个区域。要改变视口大小,可以调用viewport()方法并传入4 个参数:(视口相对于
元素的x 坐标、y 坐标、宽度和高度
//视口是
gl.viewport(0, 0, drawing.width/2, drawing.height/2);
//视口是
gl.viewport(0, drawing.height/2, drawing.width/2, drawing.height/2);
//视口是
gl.viewport(drawing.width/2, 0, drawing.width/2, drawing.height/2);
var buffer = gl.createBuffer();
gl.bindBuffer(gl.ARRAY_BUFFER, buffer);
gl.bufferData(gl.ARRAY_BUFFER, new Float32Array([0, 0.5, 1]), gl.STATIC_DRAW);
gl.bufferData()的最后一个参数用于指定使用缓冲区的方式,取值范围是如下几个常量。
gl.deleteBuffer(buffer);
WebGL 操作一般不会抛出错误。所以我们需要在调用某个可能出错的方法后,手工调用gl.getError()方法。这个方法返回一个表示错误类型的常量。可能的错误常量:
WebGL 中有两种着色器:顶点着色器和片段(或像素)着色器。顶点着色器用于将3D 顶点转换为需要渲染的2D 点。片段着色器用于准确计算要绘制的每个像素的颜色。
//OpenGL 着色语言
//着色器,作者Bartek Drozdz,摘自他的文章
//http://www.netmagazine.com/tutorials/get-started-webgl-draw-square
attribute vec2 aVertexPosition;
void main() {
gl_Position = vec4(aVertexPosition, 0.0, 1.0);
}
//OpenGL 着色语言
//着色器,作者Bartek Drozdz,摘自他的文章
//http://www.netmagazine.com/tutorials/get-started-webgl-draw-square
uniform vec4 uColor;
void main() {
gl_FragColor = uColor;
}
片段着色器必须返回一个值,赋给变量gl_FragColor,表示绘图时使用的颜色
如果您觉得我的文章对您有帮助的话,可以点个赞,点个关注,也可以扫描下方二维码关注我。我将在这个公众号上更新自己的学习笔记,以及分享一些算法知识
Study and progress together with me!