HTML5的canvas和webgl
2019-10-16 本文已影响0人
jadefan
<canvas>是HTML5新增的元素,负责在页面中设定一个区域,可以通过js动态地在这个区域中绘制图形。
<canvas>最早是由苹果公司推出的,当时主要用在其Dashboard微件中。
<canvas>中绘制基本二维图形多用2D上下文,而绘制三维图形时采用名为webgl的3D上下文,
WEBGL并不是W3C指定的标准,而是由Khronos Group指定的,
Khronos Group是一个由非盈利的由会员资助的协会,专注于为并行计算以及各种平台和设备上的图形及动态媒体指定无版税的开放标准,
Khronos Group设计的图形处理API中包括OpenGL ES,
浏览器中使用的WebGL就是基于OpenGL ES制定的。
所以在使用webgl时,如果有OpenGL基础会更容易理解和上手。
基本用法
作为H5的一个要素,和普通要素一样,先添加再设置属性
<canvas id='canvas' style="border:solid"></canvas>
添加时不设置属性,默认宽300高150,而且不绘制内容时是透明的看不到

绘制图形之前要获取2D或3D上下文,得到结果进而判断是否支持绘制
var canvas = document.getElementById('canvas');
var ctx = canvas.getContext('2d');
if (ctx) {
//...
}
2D上下文
原点位于左上角,坐标(0,0)
var canvas = document.getElementById('canvas');
var ctx = canvas.getContext('2d');
if (ctx) {
ctx.fillStyle = 'red'; //设置填充样式
ctx.strokeStyle = 'graw'; //设置边框样式
//填充矩形,参数:起点x,起点y,矩形宽度,矩形高度
ctx.fillRect(10, 10, 30, 20);
//绘制矩形边框,参数:起点x,起点y,矩形宽度,矩形高度
ctx.strokeRect(10, 40, 30, 20);
//清楚画布的矩形区域,参数:起点x,起点y,矩形宽度,矩形高度
//ctx.clearRect(0, 0, canvas.width, canvas.height);
//开始绘制新的路径
ctx.beginPath();
//绘制圆形:参数:起点x,起点y,半径长度,开始角度(弧度表示),截止角度(弧度表示),是否逆时针
ctx.arc(100, 70, 50, 0, 2 * Math.PI, false);
//移动绘制起点
ctx.moveTo(130,70);
//画小圆
ctx.arc(100, 70, 30, 0, 2 * Math.PI, false);
//描边路径-不描边是看不到的
ctx.stroke();
}

还有更多绘制API,参考官方文档
3D上下文:webgl
WebGL的目前最新版本是2.0,基于OpenGL ES 3.0规范实现
WebGL 2.0规范:https://www.khronos.org/Registry/WebGL/specs/Update/2.0/
WebGL 1.0规范:https://www.khronos.org/Registry/WebGL/specs/1.0.2/
WebGL 2.0的浏览器支持工作还在进行中,现阶段先用1.0来学习
坐标系:
创建视口坐标系的坐标系起点在左下角
视口内部绘图时的坐标系起点在画布中央的中心点

<body>
<canvas id="canvas"></canvas>
<script id="vertexShader" type="x-webgl">
attribute vec2 position;
void main(){
gl_Position = vec4(position, 0.0, 1.0);
}
</script>
<script id="fragmentShader" type="x-weggl">
#ifdef GL_ES
precision mediump float;
#endif
uniform vec4 uColor;
void main(){
gl_FragColor = uColor;
}
</script>
<script>
debugger;
//获取着色器代码
var vertexGlsl = document.getElementById('vertexShader').text;
var fragmentGlsl = document.getElementById('fragmentShader').text;
var canvas = document.getElementById('canvas');
//获取webgl上下文
var gl = canvas.getContext('webgl');
//判断是否支持
if (gl) {
//用指定颜色清理画布
gl.clearColor(0, 0, 0, 1);
gl.clear(gl.COLOR_BUFFER_BIT);
//创建视口
//gl.viewport(0, 0, canvas.width, canvas.hight);
// 编译着色器
var vertexShader = gl.createShader(gl.VERTEX_SHADER);
gl.shaderSource(vertexShader, vertexGlsl);
gl.compileShader(vertexShader);
var fragmentShader = gl.createShader(gl.FRAGMENT_SHADER);
gl.shaderSource(fragmentShader, fragmentGlsl);
gl.compileShader(fragmentShader);
//错误检测
if (!gl.getShaderParameter(vertexShader, gl.COMPILE_STATUS)) {
alert(gl.getShaderInfoLog(vertexShader));
}
if (!gl.getShaderParameter(fragmentShader, gl.COMPILE_STATUS)) {
alert(gl.getShaderInfoLog(fragmentShader));
}
// 链接着色器
var program = gl.createProgram();
gl.attachShader(program, vertexShader);
gl.attachShader(program, fragmentShader);
gl.linkProgram(program);
gl.useProgram(program);
//错误检测
if (!gl.getProgramParameter(program, gl.LINK_STATUS)) {
alert(gl.getProgramInfoLog(program));
}
// 坐标准备
var vertices = new Float32Array([0, 1, 0.7, -1, -0.7, -1]),
buffer = gl.createBuffer(),
vertextSetSize = 2,
vertextSetCount = vertices.length / vertextSetSize;
gl.bindBuffer(gl.ARRAY_BUFFER, buffer);
gl.bufferData(gl.ARRAY_BUFFER, vertices, gl.STATIC_DRAW);
// 着色器传值
var uColor = gl.getUniformLocation(program, 'uColor');
gl.uniform4fv(uColor, [1.0, 0.0, 0.0, 1.0]);
var position = gl.getAttribLocation(program, 'position');
gl.vertexAttribPointer(position, vertextSetSize, gl.FLOAT, false, 0, 0);
gl.enableVertexAttribArray(position);
// 图形绘制
gl.drawArrays(gl.TRIANGLES, 0, vertextSetCount);
}
</script>
</body>