提高篇Word文档下载推荐.docx
《提高篇Word文档下载推荐.docx》由会员分享,可在线阅读,更多相关《提高篇Word文档下载推荐.docx(27页珍藏版)》请在冰豆网上搜索。
![提高篇Word文档下载推荐.docx](https://file1.bdocx.com/fileroot1/2023-1/3/76a5a7e1-0dc5-4012-8f94-c30000988817/76a5a7e1-0dc5-4012-8f94-c300009888171.gif)
r、g、b、alpha的值,其范围均是是(0——255)。
有了这样的理论逻辑我们可以通过canvas上的任意一点(x,y)计算出imageData中表示次像素的第一个元素的索引值。
计算方式如下代码:
functiongetStartIndex(x,y){
returny*width*4+x*4;
}
有了上面的理论知识,大家应该知道我们下面要做什么了吧?
对就是利用中点画圆算法对每一个像素进行颜色值(rgb)的修改。
2.光栅学——中点画圆
首先我们通过圆的对称性将其分为8个部分。
现在我们假设,这个圆的中点位于(0,0)的位置。
设d是点p(x,y)到圆心的距离:
则我们得到这样的圆方程FX(X,Y)
=d。
这里我们按照Bresenham算法,推出:
(此部分可能需要有图形学学习经验的同学,再以后的随笔中可能会介绍Bresenham算法)。
如果dM<
0,表示下一点M在圆内,得
如果dM>
0,表示下一点M在圆外,得
有了上面的理论知识,我们就可以轻松的写出绘制圆的算法了:
//中点画圆法
functioncircle(x,y,r,color){
vartx=0,ty=r,d=1-r;
while(tx<
=ty){
//利用圆的八分对称性画点
putpixel(x+tx,y+ty,color);
putpixel(x+tx,y-ty,color);
putpixel(x-tx,y+ty,color);
putpixel(x-tx,y-ty,color);
putpixel(x+ty,y+tx,color);
putpixel(x+ty,y-tx,color);
putpixel(x-ty,y+tx,color);
putpixel(x-ty,y-tx,color);
if(d<
0){
d+=2*tx+3;
}else{
d+=2*(tx-ty)+5;
ty--;
}
tx++;
putpixel函数用于将每一个像素的颜色值填入对应的数组当中,这里我们的颜色只表示灰度值,因为还没有对彩色做任何处理。
functionputpixel(x,y,color){
varindex=getStartIndex(x,y);
for(vari=0;
i<
4;
i++){
if(i==3){
imageData[index+i]=255;
else{
//varco=parseInt(Math.random()*255)
imageData[index+i]=color;
至此我们就已经把一个圆的像素填入我们的像素数组当中,最后将像素对象放回原来的canvas当中,就实现了圆的光栅画法:
cxt.putImageData(data,0,0);
3.案例
下面这个案例以1w个圆的边界碰撞检测运动为例,说明了我们实现的光栅图形性能完全可以胜任各种bt场景。
(首要推荐chrome18其他浏览器可能解析js代码比较慢)
开始停止
下次提高班预告:
实现光栅算法中的画线算法。
本课题是我今年毕业设计的课题,现在我边做边跟大家分享,希望能通过“canvas矢量图形渲染器”让大家对canvas元素和其中的性能优化有更深的理解。
1.首先说说这个矢量渲染器是什么。
canvas元素封装了很对对图形绘制的接口,但是他跟flex相比最大的区别是我们通过fill()或是stroke()方法绘制的图形是一张像素图片,当放大或是缩小的时候会出现模糊等各种状况。
所以直接调用canvasAPI来绘制矢量图形非常不合适。
这样我们就需要设计一渲染器,里面封装了各种图形的绘制接口,并通过调用渲染器的绘制方法按照我们想发来绘制每一个矢量元素。
每一个矢量元素都是一个继承自矢量图形基类的对象,比如可以使点,线,面等。
每一个图形有自己的大小和位置信息,我们依次把每个图形送入渲染器,渲染器结合自己当前的属性(缩放百分比,中心点等)就可以计算出每一个图形需要绘制的真实像素位置,之后再调用canvas的底层API实现图形的绘制。
基本的类图结构如下(在设计的过程当中可能会增加一些新的功能类):
一些点、线、面的基本矢量元素继承自Geometry类,Geometry定义了矢量图形的形状信息。
同时也是Vector类的一个属性,Vector类里面还包括矢量元素的其他信息(如id、添加时间等)。
Layer类表示了当前图层的一些基本信息,例如声明了一个图层(大小是400px*400px),同时我在坐标为(0,0)的点放置了一个半径为50px的圆,当前的缩放为100%,视图中心点也是(0,0)则我们会得到下面的这样一张图片:
注:
Layer类所表示的属性:
外侧的方框代表当前的视图范围(viewBounds),坐标(0,0)点则代表视图的中心点(center),zoom的值代表当前的缩放百分比。
Vector类所表示的属性:
拥有一个Geometry属性表示半径为70像素的圆,且拥有一个Style属性表示填充的颜色为橙色。
下面说说Layer类,Vector类和Canvas类是如何协调工作的:
Canvas类也就是渲染器类,是本课题的核心,其中定义了各种绘制Geometry图形的方法。
但是我们该如何调用他进行绘制呢?
1.我们声明一个Vector类的实例V1(他表示一个矢量图形,其形状信息保存在Geometry属性当中)。
2.我们的Layer类必然有一个接口,用于接收由Vector声明的实例V1(比如addVectors方法),当我们把所有的矢量图形都接收到Layer当中后,我们就想要在浏览器当中看到我们所创建的的矢量图形。
3.之后我们就应该请渲染器类出场了,他接收了Layer的所有矢量图形的引用、当前的缩放级别、当前的视图范围和当前的中心点,之后渲染器通过一大堆的计算就神奇的把Geometry中的属性变成了CanvasAPI中可以调用的数据。
就拿上个例子来说圆的中心点是(0,0),半径是70像素,通过渲染器的一系列计算最后我们会调用“context.arc(200,200,70,Math.PI*2,true);
context.fill()”这两句代码。
(200,200)这两个位置便是渲染器所要计算的绘制中心点,而70这个半径参数是通过70*zoom(当前为100%)得到的。
当然我们不能单单考虑这么简单的一种情况,后面会跟大家介绍这些Geometry对应的点到底是如何计算的。
2.从构建基本的几何基类、点开始。
1.geometry类。
这个类是一个几何图形的基类。
functionGeometry(){
this.id=CanvasSketch.getId("
geomtry_"
//bounds属性定义了当前Geometry外接矩形范围。
Geometry.prototype.bounds=null;
//定义Geometry的id属性。
Geometry.prototype.id=null;
//定义对bounds基类克隆的方法
Geometry.prototype.clone=function(){
returnnewGeometry();
//销毁当前的Geometry
Geometry.prototype.destroy=function(){
this.bounds=null;
this.id=null;
其中的SketchCanvas.getId方法会返回一个唯一的id值。
这个方法其实很简单就是用一个全局变量不断加1(后面的下载中有提供)。
2.Point类,继承自Geometry。
point类作为继承自Geometry最简单的类,我们首先来介绍他。
functionPoint(x,y){
Geometry.apply(this,arguments);
this.x=x;
this.y=y;
Point.prototype=newGeometry();
//point类的横坐标。
Point.prototype.x=null;
//point类的纵坐标。
Point.prototype.y=null;
//得到点的范围。
Point.prototype.getBounds=function(){
if(!
this.bounds){
varx=this.x;
vary=this.y;
this.bounds=newCanvasSketch.Bounds(x,y,x,y);
returnthis.bounds;
}else{
//clone方法。
Point.prototype.clone=function(){
returnnewPoint(this.x,this.y);
这个Point类定义了几个比较基本,简单的方法:
getBounds、clone,使用prototype进行对Geometry类的继承。
最重要的是Point会接受两个参数(x、y)也就是其位置信息。
这样我们就可以用以下的语句声明一个点了:
varpoint=newPoint(0,0);
这样的声明让我们的程序看起来更加简洁,扩展性会更强。
点在图形当中所充当的是一个无大小、只表示位置的几何对象。
但是,通常我们需要为点设置一个半径,以便让大家可以看到。
所以说点在任何缩放级别下的半径大小都是一个固定的像素值。
同样,线的宽度也可以这样理解。
3.添加、显示矢量图形
上面我们已经讲了如何创建一个矢量的点,但是我们该如何把这个点显示到我们的浏览器当中呢?
一个方法就是把这些矢量图形先存放到一个图层当中,这个图层中的一些属性(中心点、缩放百分比、视图范围)共同影响着矢量图形的显示结果。
当然我们可以将绘制的核心代码写到这个图层类当中,但是更好的做法就是用一个渲染器类控制关于显示的方法,使以后可以更好的维护、扩展。
1.图层类
这个课题的第一节,我们的图层类只有几个必须的方法,以控制添加、显示。
在以后的随笔中会更深入的增加图层的功能。
(同样渲染器类也是如此)
//图层类
functionLayer(div){
varstyle=div.style;
varsize=newCanvasSketch.Size(parseInt(style.width),parseInt(style.height));
this.size=size;
this.div=div;
this.maxBounds=newCanvasSketch.Bounds(-size.w/2,-size.h/2,size.w/2,size.h/2);
this.bounds=newCanvasSketch.Bounds(-size.w/2,-size.h/2,size.w/2,size.h/2);
this.zoom=100;
this.vectors={};
//加入矢量图形的总个数。
this.vectorsCount=0;
//创建一个渲染器。
this.renderer=newCanvas(this);
Layer.prototype.addVectors=function(vectors){
this.renderer.lock=true;
for(vari=0,len=vectors.length;
i<
len;
if(i==len-1){this.renderer.lock=false;
this.vectors[vectors[i].id]=vectors[i];
this.drawVector(vectors[i]);
this.vectorsCount+=vectors.length;
Layer.prototype.drawVector=function(vector){
vector.style){
style=newCanvasSketch.defaultStyle();
this.renderer.drawGeometry(vector.geometry,style);
定义过图层类后,我们就可以为一个div创建图层。
首先我们得在DOM树中创建一个div,作为图层的容器,如:
<
bodyonload="
init()"
>
<
divstyle="
width:
400px;
height:
300px;
"
id="
renderer"
/div>
/body>
这样我们就可以在init函数中为这个id为“renderer”的div创建图层了:
vardiv=document.getElementById("
varlayer=newLayer(div);
之后我们所要做的就是声明一个矢量图形数组,调用layer.addVectors来为我们的图层添加矢量元素。
for(vari=0;
1000;
varpoint=newPoint((Math.random()*400-200),(Math.random()*300-150));
vectors.push(newVector(point));
layer.addVectors(vectors);
创建1000个x坐标随机在(-200,200)和y坐标随机在(-150,150)之间的点,并添加到图层当中。
上面的代码中,我们通过newVector()创建一个矢量图形,其几何信息就是之前声明的point变量。
Vector类的声明如下(在目前看来Vector类,就是将geometry和attributes整合到一起的一个类,但是以后会为这个Vector增加更多的方法和属性的)
functionVector(geometry,attributes){
vector"
this.geometry=geometry;
if(attributes){
this.attributes=attributes;
下一篇随笔会介绍渲染器类的构建方法,在下面提供的源码当中有今天所有讲过的类、和没有涉及到的类(一些工具类,和渲染器类)。
这一节我们只是构建了一个大体的渲染器使用框架,在后面的随笔中会完善他的功能~
下面这个demo展示了我们这个渲染器的基本用法。
运行示例
尝试一下:
改变for循环的个数可以控制产生多少个点,可以自定义x,y值来精确定位点。
下次随笔预告:
1.重点介绍渲染器类的构建。
2.大家发现没有上面的demo是以左上角为中心点缩放的,下次添加缩放中心点。
3.增加更多的几何类型(圆和矩形)。
请关注~
本次随笔的所有源码+Demo,点击下载。
上