Porfessional JS(15.2.10-Image Data/Composition/Typed Array/WebGL Context[part])

1.Working with Image Data
+①

var drawing=document.getElementById('drawing');
//确定浏览器支持<canvas>元素
if(drawing.getContext){
    var context=drawing.getContext('2d'),
        //获取文档中第一张图像
        image=document.images[0],
        imageData,data,i,len,average,
        red,green,blue,alpha;
    //绘制原始图像,起始坐标(0,0)
    context.drawImage(image,0,0);
    //获取图像数据,起始坐标(0,0),大小(宽度+高度)
    imageData=context.getImageData(0,0,image.width,image.height);
    //图像数据的data属性是一个数组,保存着图像中每一个像素的数据---r,g,b,alpha
    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);
}

2.Compositing(合成)
+①globalAlpha属性

var drawing=document.getElementById('drawing');
if(drawing.getContext){
    var context=drawing.getContext('2d');
    context.fillStyle='#f00';
    context.fillRect(10,10,50,50);
    //修改全局透明度
    context.globalAlpha=0.3;
    context.fillStyle='rgba(0,0,255,0.8)';//alpha:0.8被全局透明度覆盖
    context.fillRect(30,30,50,50);
    //重置全局透明度
    context.globalAlpha=0.8;
    context.fillStyle='#f8a303';
    context.fillRect(50,50,50,50);
}

这里写图片描述

@*8+②globalCompositeOperation属性

var drawing=document.getElementById('drawing');
if(drawing.getContext){
    var context=drawing.getContext('2d');
    //1
    context.fillStyle='#f00';
    context.fillRect(10,10,50,50);
    context.fillStyle='rgba(0,0,255,0.5)';
    context.fillRect(30,30,50,50);
    //2
    context.fillStyle='#f00';//source
    context.fillRect(100,10,50,50);
    //后绘制的图形---source || 先绘制的图形----destination
    context.globalCompositeOperation='source-over';
    context.fillStyle='rgba(0,0,255,0.5)';
    context.fillRect(120,30,50,50);

    /*
    //3
    context.fillStyle='#f00';//source
    context.fillRect(200,10,50,50);
    context.globalCompositeOperation='source-in';
    context.fillStyle='rgba(0,0,255,0.5)';
    context.fillRect(220,30,50,50);
    */

    /*
    //4
    context.fillStyle='#f00';//source
    context.fillRect(300,10,50,50);
    context.globalCompositeOperation='source-out';
    context.fillStyle='rgba(0,0,255,0.5)';
    context.fillRect(320,30,50,50);
    */

    /*
    //5
    context.fillStyle='#f00';//source
    context.fillRect(400,10,50,50);
    context.globalCompositeOperation='source-atop';
    context.fillStyle='rgba(0,0,255,0.5)';
    context.fillRect(420,30,50,50);
    */

    //6
    context.fillStyle='#f00';//source
    context.fillRect(10,100,50,50);
    context.globalCompositeOperation='destination-over';
    context.fillStyle='rgba(0,0,255,0.5)';
    context.fillRect(30,120,50,50);

    /*
    //7
    context.fillStyle='#f00';//source
    context.fillRect(100,100,50,50);
    context.globalCompositeOperation='destination-in';
    context.fillStyle='rgba(0,0,255,0.5)';
    context.fillRect(120,120,50,50);
    */

    /*
    //8
    context.fillStyle='#f00';//source
    context.fillRect(200,100,50,50);
    context.globalCompositeOperation='destination-out';
    context.fillStyle='rgba(0,0,255,0.5)';
    context.fillRect(220,120,50,50);
    */

    /*
    //9
    context.fillStyle='#f00';//source
    context.fillRect(300,100,50,50);
    context.globalCompositeOperation='destination-atop';
    context.fillStyle='rgba(0,0,255,0.5)';
    context.fillRect(320,120,50,50);
    */

    //10
    context.fillStyle='#f00';//source
    context.fillRect(400,100,50,50);
    context.globalCompositeOperation='destination-lighter';//source图形与destination图形重叠部分的值相加,使该部分变得更亮
    context.fillStyle='rgba(0,0,255,0.5)';
    context.fillRect(420,120,50,50);
    /*
    //11
    context.fillStyle='#f00';//source
    context.fillRect(500,100,50,50);
    context.globalCompositeOperation='copy';//只有source图形
    context.fillStyle='rgba(0,0,255,0.5)';
    context.fillRect(520,120,50,50);
    */

    //12
    context.fillStyle='#f00';//source
    context.fillRect(10,200,50,50);
    context.globalCompositeOperation='xor';//source图形与destination图形重叠部分进行"异或"操作。
    context.fillStyle='rgba(0,0,255,0.5)';
    context.fillRect(30,220,50,50);
}

这里写图片描述 source-over[standard]

这里写图片描述souce-in

这里写图片描述source-out

这里写图片描述source-atop

这里写图片描述destination-in

destination-outdestination-out

这里写图片描述destination-atop

这里写图片描述xor

这里写图片描述

3.Typed Arrays
+①Views

//在内存中分配20B
var buffer=new ArrayBuffer(20);
var bytes=buffer.byteLength;
//基于整个数组缓冲器创建一个新视图
var view=new DataView(buffer);
//创建一个开始于字节9的新视图
var view=new DataView(buffer,9);
//创建一个从字节9开始到字节18的视图[9+10-1=18]--10是一段字节长度
var view=new DataView(buffer,9,10);
//实例化后,DataView对象会把字节偏移量和字节长度分别保存在byteOffset和byteLength属性中
alert(view.byteOffset);
alert(view.byteLength);

②小端(littleEndian):把数据的最低有效位保存在低内存地址中。

③类型化视图,也成类型化数组,因此它们除了元素必须是某种特定的数据类型外,与常规数组一样。继承自DataView。

+④能够指定缓冲器中可用的字节段,意味着能在同一个缓冲器中保存着不同类型的数值。

//使用缓冲器的一部分保存8位整数,另一部分保存16位整数
var int8s=new Int8Array(buffer,0,10);
var uint16s=new Uint16Array(buffer,11,10);

+⑤每个视图构造函数都有一个名为BYTES_PER_ELEMENT的属性,表示类型化数组的每个元素需要多少字节。

//需要10B
var int8s=new Int8Array(buffer,0,10*Int8Array.BYTES_PER_ELEMENT);
//在int8s之后再来5*2B=10B
var uint16s=new Uint16Array(buffer,int8s.byteOffset+int8s.byteLength,
            5*Uint16Array.BYTES_PER_ELEMENT);

+⑥创建类型化视图还可以不同首先创建ArrayBuffer对象,只要传入希望数组保存的元素数,相应的构造函数就可以自动创建一个包含足够字节数的ArrayBuffer对象。

//创建一个数组保存10个8位整数(10B)
var int8s=new Int8Array(10);
//等价于
var buffer=new ArrayBuffer(20);
var int8s=new Int8Array(buffer,0,10);//0--byteOffset || 10---byteLength
//another one--创建一个数组保存着8个16位整数(16B)
var int16s=new int16Array(8);
//创建一个数组保存着5个8位整数(5B)
var int8s=new Int8Array([1,2,3,4,5]);


var uint16s=new Uint16Array(10);
uint16s[0]=65589;
console.log(uint16s[0]);//53---65589-2^16

+⑦类型化视图(数组)还有一个方法:subarray()—基于底层数组缓冲器的子集创建一个新视图。

var uint16s=new Uint16Array(10);
var sub=uint16s.subarray(2,5);//sub也是Uint16Array的一个实例

4.WebGL:Graphics Library
+①可以为getContext()传递第二个参数,该参数为WebGL上下文设置一些选项。这个参数本身是一个对象,可以包含如下属性:
a)alpha:值为true,表示为上下文创建一个Alpha通道缓冲区;默认值为true。
b)depth:值为true,表示可以使用16位深缓冲区;默认值为true。
c)stencil:值为true,表示可以使用8位模板缓冲区;默认值为false。
d)antialias:值为true,表示将使用默认机制执行抗锯齿操作;默认值为true。
e)premultipledAlpha:值为true,表示绘图缓冲区有预乘Alpha值;默认值为true。
f)preserveDrawingBuffer:值为true,表示在绘图完成后保留绘图缓冲区;默认值为false。【影响性能】

var drawing=document.getElementById('drawing');
if(drawing.getContext){
    var gl=drawing.getContext('experimental-webgl',{alpha : false});
    if(gl){
        //using WebGL
    }
}

//保险起见,将其封装到一个try-catch块中
var drawing=document.getElementById('drawing');
if(drawing.getContext){
    try{
        gl=drawing.getContext('experimental-webgl');
    }catch(ex){
        //do nothing
    }

    if(gl){
        //using WebGL
    }else{
        alert('WebGL context could not be created.');
    }
}

+②Error

var errorCode=gl.getError();
while(errorCode){
    console.log('Error occurred: ' + errorCode);
    errorCode=gl.getError();
}

③Shader(着色器):是使用GLSL(OpenGL Shading Language)OpenGL着色语言写的。
a)顶点着色器:将3D顶点转换为需要渲染的2D点。
b)片段(像素)着色器:用于精确计算要绘制的每个像素的颜色。

+④Creating Shader Programs:GLSL cannot be natively understood by a browser,so you must have a string of GLSL ready for compilation(编译) and linking(链接) into a shader program.For ease of use,shaders are typically included in a page using

/*
1.编写着色器(获得GLSL字符串),嵌入<script>元素,通过text属性提取。
2.创建着色器对象,将GLSL字符串传递给该对象,并编译该对象。
3.创建着色器程序,将对象链接到该程序,最后通知WebGL使用该程序。
*/
//【1】
<script type="x-webgl/x-vertex-shader" id='vertexShader'>//顶点着色器
    attribute vec2 aVectexPosition; //关键字|数组(包含2个元素)|变量名
    void main(){
        gl_Position = vec4(aVectexPosition,0,0 , 1.0);
    }
</script>

<script type="x=webgl/x-fragment-shader" id='fragmentShader'>//片段着色器
    uniform vec4 uColor;
    void main(){
        gl_FragColor = uColor;
    }
</script>

//通过text属性提取出<script>元素中的内容
var vertexGlsl=document.getElementById('vertexShader').text,
    fragmentGlsl=document.getElementById('fragmentShader').text;

//【2】创建两个着色器,分别保存在vertexShader和fragmentShader中
var vertexShader = gl.createShader(gl.VERTEX_SHADER);//着色器类型:gl.VERTEX_SHADER || gl.FRAGMENT_SHADER
gl.shaderSource(vertexShader,vertexGlsl);//字符串传递
gl.compileShader(vertexShader);//编译着色器

var fragmentShader = gl.createShader(gl.FRAGMENT_SHADER);
gl.shaderSource(fragmentShader,fragmentGlsl);
gl.compileShader(fragmentShader);

//【3】将两个对象链接到着色程序中
var program=gl.createProgram();//创建程序
//调用attachShader()方法包含了两个着色器
gl.attachShader(program,vertexShader);
gl.attachShader(program,fragmentShader);
//调动gl.linkProgram()方法把两个着色器封装到变量program中
gl.linkProgram(program);
//通过gl.useProgram()方法通知WebGL使用这个程序
gl.useProgram(program);

+⑤为着色器传入值

//Attribute变量
var aVectexPosition=gl.getAttribLocation(program,'aVectexPosition');
gl.enableVertexAttribArray(aVectexPosition);
gl.vertextAttribPointer(aVectexPosition,itemSize,gl.FLOAT,false,0,0);
//Uniform变量
var uColor=gl.getUniformLocation(program,'uColor');
gl.uniform4fv(uColor,[0,0,0,1]);

+⑥调试着色器和程序

//用于检测编译状态
if(!gl.getShaderParameter(vertexShader,gl.COMPILE_STATUS)){
    alert(gl.getShaderInfoLog(vertexShader));//错误消息是一个表示问题所在的字符串
}
//用于检测执行状态
if(!gl.getProgramParameter(program,gl.LINK_STATUS)){
    akert(gl.getProgramInfoLog(program));
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值