网站建设与规划实验心得,wordpress免费主题网站,宁波网页设计招聘,东莞网站建设黄页免费软件1.RequestAnimationFrame
早期定时动画
setTimeout和setInterval不能保证时间精度#xff0c;第二个参数只能保证何时将代码添加到浏览器的任务队列 requestAnimationFrame(cb)的cb在浏览器重绘屏幕前调用
function updateProgress(){const div document.getElementById(d…
1.RequestAnimationFrame
早期定时动画
setTimeout和setInterval不能保证时间精度第二个参数只能保证何时将代码添加到浏览器的任务队列 requestAnimationFrame(cb)的cb在浏览器重绘屏幕前调用
function updateProgress(){const div document.getElementById(div);div.style.width (parseInt(div.style.width, 10) 5) %;if (div.style.width ! 100%){requestAnimationFrame(updateProgress);}
}
requestAnimationFrame(updateProgress);requestAnimationFrame()的函数实际上可以接受一个参数该参数为DOMHighResTimeStamp的实例表示下次重绘的时间点。
cancelAnimationFrame(id); // 对应clearTimeout clearIntervalrequestAnimationFrame可以用作节流
let enabled true;
function expensiveOperation(){console.log(scroll, Date.now());
}
window.addEventListener(scroll, () {if (enabled) {enabled false;window.requestAnimationFrame(expensiveOperation);setTimeout(() enabled true, 50)}
}2.基本的画布功能
canvas元素必须要指定width和height两个属性标签之间的内容是在浏览器不支持的情况下展示的内容
getContext();// 获取绘制上下文参数为‘2d’或者‘webgl’
toDataURL(); // 导出canvas元素上的图像接受一个MIME类型参数3、2D绘图上下文
原点00在左上角width和height分别为x轴和y轴的最大值
填充和描边
fillStyle和strokeStyle两个属性属性值可以是字符串、渐变对象和图案对象
const myCanvas document.getElementById(myCanvas);
const ctx myCanvas.getContext(2d);
ctx.strokeStyle red;
ctx.fillStyle #0000ff;绘制矩形
fillRect(x,y, width, height);
strokeRect(x, y, width, height);
clearRect(x, y, width, height);绘制路径
必须beginPath()开始绘制新路径closePath()绘制一条返回起点的路径。而后可以指定fillStyle属性后使用fill()填充区域或者指定strokeStyle属性后使用stroke()填充路径或者使用clip()创建一个新的剪切区域。
方法说明arc(x, y, startAngle, endAngle, counterclockwise)以x,y为圆心从起始角度到结束角度绘制弧线最后一个参数为是否顺时针默认为truearcTo(x1, y1, x2, y2, radius)给定半径经过x1, y1从上一个点绘制到x2,y2的弧线bezierCurveTo(c1x, c1y, c2x, c2y, x, y)以(c1x, c1y)(c2x, c2y)为控制点绘制从上一点到x,y的三次贝塞尔曲线lineTox,y)上一点到x,y的直线moveTo(x,y)移动光标到x,yquadraticCurveTo(cx, cy)以cx, cy为控制点绘制从上一点到x,y的二次贝塞尔曲线rect(x, y, width, height)绘制一个矩形路径而非图形isPointInPath(x, y)判断x, y是否在当前路径
绘制文本
fillText(contentStr, x, y, maxWidth);
strokeText(contentStr, x, y, maxWidth);
// 相关设置属性
ctx.font; // 以css样式指定字体样式、大小、字体簇
ctx.textAlign; // 文本对齐方式 start/end/left/right/center
ctx.textBaseLine; // 文本基线 top/hanging/middle/alphabetic/ideographic/bottom辅助确定文本大小的方法measureText(str),返回一个TextMetrics对象
变换
方法rotate(angle)围绕原点将图像旋转anglescale(scaleX, scaleY)在x轴和y轴上分别缩放相应倍数translate(x, y)将坐标原点移动到x, ytransform(m1_1, m1_2, m2_1, m2_2, dx, dy)通过矩阵乘法直接修改上下文矩阵m1_1m2_1dxm1_2m2_2dy001setTransform(m1_1, m1_2, m2_1, m2_2, dx, dy)先将上下文变换矩阵重置然后以传入的参数调用transform
save()可以将所有设置放入一个暂存栈需要恢复时调用restore()
绘制图像
drawImage()可以接受三组不同的参数
//1.传入一个HTML的img元素
let img document.images[0];
ctx.drawImage(img, x, y);
ctx.drawImage(img, x, y, width, height); // width和height默认为img的宽高
// 2.将图像的部分绘制到指定区域
ctx.drawImage(img, srcX, srcY, srcWidth, srcHeight, targetX, targetY, targetWidth, targetHeight);
// 3.第一个参数可以是另外一个canvas元素
// 操作的结果可以通过toDataURL() 获取阴影
属性值设置
属性说明shadowColorCSS颜色值默认黑色shadowOffsetXx坐标偏移量shadowOffsetYy坐标偏移量shadowBlur阴影模糊量
渐变
线性渐变通过CanvasGradient的实例表示createLinearGradient()创建一个CanvasGradient实例接受起点和终点的坐标作为参数 addColorStop()方法为gradient对象添加色标接受两个参数位置0-1颜色
const gradient ctx.createLinearGradient(30,30,70,70);
gradient.addColorStop(0, white);
gradient.addColorStop(1, black);
// 绘制红色矩形
ctx.fillStyle #FF0000;
ctx.fillRect(10,10,50,50);
// 绘制渐变矩形
ctx.fillStyle gradient;
ctx.fillRect(30,30,50,50);径向渐变通过createRadialGradient()创建接受六个参数分别为起点和终点的圆心坐标、半径、
ctx.createRadialGradient(startX, startY, startR, endX, endY, endR);图案
用于填充和描画重复图案调用createPattern()接受两个参数第一个参数为img或者video 和canvas,第二个参数为重复模式repeat-x, repeat-y, repeat, no-repeat
图像数据
getImageData(startX, startY, width, height)返回一个ImageData对象每个ImageData包含三个属性width, height, data,其中data中每四个值分别表示第i个像素点的红、绿、蓝和透明度值取值范围为0-255
合成
属性值说明globalAlpha全局透明度0-1 用于指定绘制内容的透明度globalCompositionOperation新绘制的形状如何与已有的上下文形状融合source-over新图形在原图形上面默认值source-in只画出新图形与原图形重叠的部分画布上其他部分全部透明source-out只画出新图形不重叠的部分画布上其他部分全部透明source-atop只画出新图形重叠部分其他部分不受影响destination-over新图形在原图形下面重叠部分只有原图形透明像素下可见destination-in新图形在原图形下面画布上只留下两者重叠部分其他部分全部透明destination-out新图形与原图形重叠部分透明不重叠部分不画画布其他部分不受影响destination-atop新图形在原图形下面原图形不重叠部分全部透明lighter新图形与原图形重叠部分像素值相加让该部分变亮copy新图形将擦除并完全取代原图形xor新图形与原图形在重叠部分取“异或”操作
4.WebGL
webgl上下文
getContext(‘webgl’);
webgl基础
可以在调用getContext()时传入配置项指定创建的上下文的一些选项
配置项说明默认值alpha是否为上下文创建透明通道缓冲区truedepth是否使用16位深缓冲区truestencil是否使用8位模板缓冲区falseantialias是否使用默认机制执行抗锯齿操作truepremultipliedAlpha绘图缓冲区是否预乘透明度truepreserveDrawingBuffer绘图完成后是否保留绘图缓冲区false
let drawing document.getElementById(drawing);
// 确保浏览器支持canvas
if (drawing.getContext) {let gl drawing.getContext(webgl, { alpha: false });if (gl) {// 使用 WebGL}
} 1.常量
OpenGL中以GL_开头的常量大部分都被webGL支持但不需要这个前缀
gl.COLOR_BUFFER_BIT // GL_COLOR_BUFFER_BIT2.方法命名
参数数量1-4数据类型‘f’, ‘i’如 gl.uniform4f()
3.准备绘图
绘图之前需要使用clearColor(r, g, b, a) 使用一种颜色清除canvas元素 rgba参数值都在0-1 也可以使用gl.clear(gl.COLOR_BUFFER_BIT)使用之前定义的颜色填充画图
4.视口与坐标
默认情况下视口为整个canvas区域也可以使用viewport()方法改变视口
gl.viewport(x, y, width, height)定义视口的坐标系统是canvas像素坐标系统而视口中中心点是原点0,0左下角是-1,-1右上角是1,1。
5.缓冲区
const buffer gl.createBuffer(); // 创建缓冲区
gl.bindBuffer(gl.ARRAY_BUFFER, buffer); // 将缓冲区绑定到上下文中此处是将buffer与ARRAY_BUFFER绑定将buffer设置为当前上下文的缓冲区
gl.bufferData(gl.ARRAY_BUFFER, new Float32Array([0,0.5,1]), gl.STATIC_DRAW); // 将数据写入缓冲区第三个参数可以有3个选择
/**
gl.STATIC_DRAW 数据加载一次可以在多次绘制中使用
gl.STREAM_DRAW 数据加载一次只能在几次绘制中使用
gl.DYNAMIC_DRAW 数据可以重复修改在多次绘制中使用
**/
// 不再需要缓冲区
gl.deleteBuffer(buffer);6.错误
webGL操作中通常不会抛出错误gl.getError()方法会返回一个常量表示发生的错误类型
gl.NO_ERROR没有发生错误gl.INVALID_ENUM上一次操作没有传入webgl预定的常量gl.INVALID_VALUE上一次操作需要无符号数值但是传入了负数gl.INVALID_OPERATION上一次操作在当前状态下无法完成gl.OUT_OF_MEMORY上次操作因内存不足无法完成gl.CONTEXT_LOST_WEBGL上次操作因外部事件而丢失了上下文
7.着色器
定点着色器将3D顶点绘制为2D的点 片元着色器将计算每个像素的颜色值 使用GLSL编程
编写着色器
每个着色器有一个main()方法绘制期间反复执行 给着色器传递数据的方式有两种attribute和uniform attribute将定点传入定点着色器uniform将任意常量值传入任意着色器
创建着色器程序
gl.createShader(shaderType); // shaderType gl.VERTEX_SHADER, gl.FRAGMENT_SHADER 创建着色器
gl.shaderSource(shader, shaderSource);// 将glsl代码应用于着色器
gl.compileShader(shader); // 编译着色器const program gl.createProgram(); // 创建着色器程序
gl.attachShader(program, shader); // 将着色器添加到着色器程序需要调用两次分别传入定点着色器和片元着色器
gl.linkProgram(program); // 将两个着色器链接到变量program
gl.useProgram(program); // 让webgl上下文使用该程序给着色器传值
// 1.找到接受值的变量位置
let uColorLocation gl.getUniformLocation(program, uColor); // 针对uniform变量uColor
let aVertextPosLocation gl.getAttribLocation(program, aVertextPosition); // 针对attribute变量aVertexPosition
// 2.传值
// 针对uniform变量
gl.uniform4fv(uColorLocation, [0,0,0,1]);
// 针对attribte变量
gl.enableVertexAttribArray(aVertexPosLocation);
gl.vertexAttribPointer(aVertexPosLocation, itemSize, gl.FLOAT, false, 0, 0) ; // 创建一个指向bindBuffer()指定的缓冲区指针并保存在aVertexPosLocation中8.绘图
webGL只能绘制3中基本图形点、线、三角形 绘图方法有两种 drawArrays()使用数组缓冲区 drawElements()操作元素数组缓冲区 drawArrays()接受三个参数第一个参数表示形状第二个参数是数组缓冲区的起点索引第三个参数是数组缓冲区顶点集合的数量 形状参数列表
参数意义gl.POINTS将每个顶点当做一个点gl.LINES将数组作为一系列点每两个点依次绘制直线,顶点数必须是偶数gl.LINE_LOOP将数组作为一系列顶点依次依次绘制直线连接成封闭形状gl.LINE_STRIP类似于gl.LINE_LOOP区别在于最后不会连接终点和起点gl.TRIANGLES将数组作为一系列顶点在这些顶点间绘制三角形每个三角形都不会共享顶点gl.TRIANGLES_STRIP类似于gl.TRIANGLES,区别在于共享点如果有ABCD四个点则会绘制两个三角形ABC和BCDgl.TRIANGLES_FAN如果有ABCD四个点则会绘制ABC, ACD三角形
/****** 绘制一个三角形 ******/const canvas document.querySelector(#canvas);const gl canvas.getContext(webgl) || canvas.getContext(experimental-webgl);const vSource attribute vec4 a_position;void main(){gl_Position a_position;};const fSource precision highp float;uniform vec4 uColor;void main(){gl_FragColor uColor;};const program gl.createProgram();const vShader gl.createShader(gl.VERTEX_SHADER);gl.shaderSource(vShader, vSource);gl.compileShader(vShader);const fShader gl.createShader(gl.FRAGMENT_SHADER);gl.shaderSource(fShader, fSource);gl.compileShader(fShader);gl.attachShader(program, vShader);gl.attachShader(program, fShader);gl.linkProgram(program);gl.useProgram(program);const uColorLocation gl.getUniformLocation(program, uColor);gl.uniform4f(uColorLocation, 1, 0, 0, 0.5);const positionData [0.5, 0, 0, 0, 0.5, 0, -0.5, -0.5, 0.5];const positionBuffer gl.createBuffer();gl.bindBuffer(gl.ARRAY_BUFFER, positionBuffer);gl.bufferData(gl.ARRAY_BUFFER, new Float32Array(positionData), gl.STATIC_DRAW);const positionLocation gl.getAttribLocation(program, a_position);gl.vertexAttribPointer(positionLocation, 3, gl.FLOAT, false, 0, 0);gl.enableVertexAttribArray(positionLocation);gl.clearColor(0,1,1,1);gl.clear(gl.COLOR_BUFFER_BIT)gl.drawArrays(gl.TRIANGLES, 0, 3);纹理
纹理的来源可以是图片、video或者canvas
let image new Image(),texture;
image.src smile.gif;
image.onload function() {texture gl.createTexture(); // 创建纹理gl.bindTexture(gl.TEXTURE_2D, texture); // 绑定缓冲区gl.pixelStorei(gl.UNPACK_FLIP_Y_WEBGL, true); // 设置存储格式gl.texImage2D(gl.TEXTURE_2D, 0, gl.RGBA, gl.RGBA, gl.UNSIGNED_BYTE, image);gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MAG_FILTER, gl.NEAREST);gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MIN_FILTER, gl.NEAREST);// 除当前纹理gl.bindTexture(gl.TEXTURE_2D, null);
} 读取像素
// 读取(0,0)到25,25区域的像素并写入pixels数组rgba四值0-255
let pixels new Uint8Array(25*25);
gl.readPixels(0, 0, 25, 25, gl.RGBA, gl.UNSIGNED_BYTE, pixels);