[3D]flash 360度3D虚拟实境(cubicVR)实现原理

mikel阅读(781)

flash 360度3D虚拟实境(cubicVR)实现原理

flash的3D虚拟实境最早源自于德国的flash图形学大牛andre.michelle在其labsite:lab.andre- michelle.com上发表了一篇关于虚拟实境的文章,并提供了一个实例(NaN sourcecode).为了深入虚拟实境,在接下来的2个月里我陆续找到一些cubicVR的源文件并尝试破译了一些源码,我同时尝试开发了一个简单的 flash3D引擎以及图片3D拉伸算法,所有这些的思想均来自于andre-michelle在其日志中提到的一些idea.现在在这篇文章中所用的实 例依然是我对andre早期版本的整理,虽然目前我开发的新版本有更好的结构以及执行效率,但此版本的编程思想更通俗易懂。我想利用这个假期时间开发出 flash球型虚拟实境,使它变得更真实。

在flash里部署3D虚拟实境无疑是一个革命性进步,我们再也不用去安装java虚拟机和QTVR了,事实上,在基于flash的可编程矢量图形 界面基础上开发出来的虚拟现实可以通过创新的用户界面以达到完美的用户体验。city8.com既采用这种技术来部署他们的全景体验城市地图。

demo:鼠标拖拽以转换camera视角

原理:

点透视与投影

通过1点透视来产生远小近大的变化以产生空间感,在cubicVR中,设想观察者camera在一个正六面体中央,通过一点透视来计算每个面的在空间投影中的位置,以产生透视效果。

demo:没有导入透视方程的情况:

细分贴图

flash的matrix类只支持2D图形变换:切变、缩放、平面位移。位图无法实现3D变换,这与openGL不同,openGL只需要在定义多 边型顶点和贴图法线,位图就会自动贴到一个面片上,而且整个贴图过程完全由GPU完成。而在flash中必须使用细分贴图的方法来欺骗人们的眼睛,既:将 一张图片细分为n张小的三角面片,再将小三角面片进行平面切变,正因为如此,flash3D一旦涉及贴图必然导致大量占用cpu运算资源。

细分贴图的demo:
http://godson.blueidea.com/archives/2006/3708.shtml

消隐算法

如果没有消隐算法,那么观察者只能看到离屏幕最近的面,而不能看到整个3D空间,理论上消隐算法有3个步骤:1在一个六面体中,面法线与视锥体夹角 大于180度则应设为不可见,2在同一个像素上,只显示与camera最近的多边形(Zbuffer算法),3投影在屏幕以外的多边型不可见,但这三种算 法非常占用cpu资源,andrew设计了一种更简单的算法:1多边形的中心与camera重合,在camera坐标系中Z值<0的多边形不可 见,2投影在屏幕以外的多边型不可见。

经典论坛讨论
http://bbs.blueidea.com/thread-2717880-1-1.html

本文链接:http://www.blueidea.com/tech/multimedia/2007/4486.asp

[资源]JS编辑器

mikel阅读(835)

  1. 非常实用的163邮箱编辑器

    new163Editor.rar (395.12 KB)
    2 soEditor v 2.5 lite

官方: http://www.siteobjects.com/pages/index.cfm
下载: http://www.siteobjects.com/pages/order.cfm
可以下载的是lite版, 目前还没找到pro版的. 可以支持ASP,Coldfusion,ASP.NET.
界面做的很整洁,但没有文件管理,最大的问题是对于直接从其他处复制来的图片
不会做自动修正.当然这个也仁者见仁了.
soEditor 2.5 is an extremely powerful browser-based WYSIWYG content authoring tool

designed specifically for dynamic web applications. This customizable editor allows

developers to make it possible for anyone to create, edit and maintain web content

without the need for HTML knowledge or programming expertise.
3 AreaEdit V 0.4.2
演示:
http://www.formvista.com/uploaded_html/demos/areaedit/examples/simple_example.php
下载: http://www.formvista.com/goalTracker/stream_download.php/14/areaedit_0.4.3.tar.gz
支持: http://www.formvista.com/forum
修改htmlarea的编辑器增加了图片文件管理器
htmlarea 作为在线编辑器领域的开源作品享有不错的知名度
有很多的支持者和插件开发者,这些都得益于html良好的扩展性.
AreaEdit is a formVista compatible fork of the rapidly developing Xinha project.

It is the code that is generated by the formVista FVML <htmleditor> tag during rendering.
Xinha itself is a fork of the original HTMLArea component created by Mihai Bazon and

sponsored by Interactivetools. AreaEdit maintains the original HTMLArea (modified BSD)

license and is free to use.
While it is designed to work within formVista without modification, AreaEdit does not

requre formVista. It is a fully functional editor component supporting a number of

plugins and can as easily be used as a standalone editor component for any PHP web

application.
The primary difference between AreaEdit and Xinha is one of focus. The Xinha project

aims to be a rapidly developing feature-filled editor with many plugins.
By contrast, AreaEdit takes a slower minimalists approach. It aims first and foremost

to be functional and maintainable. The feature set we are focusing on is targeted

squarely at the serious non-technical business user. Business users don't care

about the nuances of HTML <br> and <p> tags, they just want the editor to work as

they would expect.
If your audience is primarly composed to developers or those familar with HTML, you

 should take a look at Xinha.
AreaEdit is known to work with MSIE 5.5 or later and any modern Gecko based

browsers. (FireFox, Mozilla).
4 DevEdit Version 5.0.1 破解版
官方网站:
http://www.interspire.com
演示: http://www.interspire.com/devedit/demo.php
下载: http://bbs.80nian.net/thread-259-1-1.html?acdt=/devedit.rar
警告: 本程序是商业程序,仅供网友研究学习,请在下载后24小时内删除. 对于由此产生的法律问题本站概不负责
5 Web Wiz Rich Text Editor v3.0
下载:
http://www.webwizguide.info/asp/sample_scripts/RTE_application.asp
演示: http://www.richtexteditor.org/demo/
支持在线文件管理,跨浏览器,但对表格编辑功能不强,界面不够精致
6 KTML.Pro.v3.5.6-SPK100
下载:
http://bbs.80nian.net/thread-259-1-1.html?acdt=/KTML_PRO-3.5.6.ZIP
警告: 本程序是商业程序,仅供网友研究学习,请在下载后24小时内删除. 对于由此产生的法律问题概不负责.
有着类似dw一样的属性栏,这个是pro版,提供了lite版没有的对表格的属性编辑等功能,

有兴趣的可以去官方看看lite版.
7 TextArea Rich v3.0
下载:
http://bbs.80nian.net/thread-259-1-1.html?acdt=/textarea.rich.v3.0.rar
做的很干净的编辑器,适合于CMS.功能强大.
8 Tabula WYSIWYG HTML editor ver. 2.2
演示:
http://www.tabula.biz/showArticle.asp?articleid=253
下载: http://www.tabula.biz/ShowArticle.asp?MID=5&ArticleID=257
和ewebsoft很像的编辑器右键功能强悍,界面做的稍稍差了点点:)
9 TinyMCE 2.0RC3
官方网站:
http://tinymce.moxiecode.com/
官方演示: http://tinymce.moxiecode.com/example_full.php?example=true
下载: http://keihanna.dl.sourceforge.net/sourceforge/tinymce/tinymce_2_0RC3.zip
有一个很好的开源编辑器,界面,功能和可扩展性做的都很好
10 网页在线编辑器 mEditor ASP 中文版 v2.0
下载:
http://bbs.80nian.net/thread-259-1-1.html?acdt=/meditor.zip
运行环境支持:
操作系统支持: Windows 2000 系列 / Window Xp 系列 / Window 2003 系列
网络服务器支持:
Asp 版本要求安装IIS 5.0版本或更高版本
浏览器支持: 正常运行在IE5.5以上版本,部分特殊功能要求IE版本升级到6.0以才能使用
>>> 在网络服务器设置完成后,运行index.asp进行样式管理.
>>> 建议将mEditor放在项目的根目录.
注意事项 有关无组件上传类
v2.0 升级事项
1.修正内核部分字符编码的问题.
2.增强系统运行的健壮性与稳定性.
3.增加了"模式按钮"栏式管理,可随意启用/取消模式按钮.
4.在编辑器的样式上进行了整体的修改.
5.增加了编辑器的缩放功能,仅适用于IE5.5以上版本.
6.增加了"搜索替换"功能(快捷键CTRL+R),仅适用于IE5.5以上版本.
7.将部分功能移植到"代码模式"使用,如:"全选","删除","复制"…..
8.增加快捷键CTRL+1(预览模式),CTRL+2(代码模式),CTRL+3(视图模式),CTRL+R(查找替换).
11
EWELive JScript Editor 0.4
6

下载:  
http://www.ewelive.com/downloads/0_64_JS.zip
我曾经仔细的去汉化过这个版本的编辑器,加了一些自己的界面设计和按钮.
速度很快,功能简单使用,容易修改. 对于喜欢简单一族的朋友可以下来看看.
官方:
http://www.ewelive.com
演示: http://www.ewelive.com/demo_js/sample.php
12 InnovaStudio WYSIWYG Editor v2.3
警告: 本程序是商业程序,仅供网友研究学习,请在下载后24小时内删除. 对于由此产生的法律问题概不负责.
界面做的很是精细, 功能极强大,非常优秀之作,强烈推荐
下载
http://www225.fixdown.com/code/sp-iwe23.rar
13 CuteEditor for ASP Enterprise License
警告: 本程序是商业程序,仅供网友研究学习,请在下载后24小时内删除. 对于由此产生的法律问题概不负责.
Cuteditor 我曾研究过,不亏为成熟的商业作品,各方面做的都很规范,功能强大,也提供简体中文语言包,

个人非常喜欢.强烈推荐
下载: http://bbs.80nian.net/thread-259-1-1.html?acdt=/CuteEditor_for_ASP_Enterprise_License.rar
14 FCKeditor 2.6 精简版第三版新增表格功能
http://bbs.80nian.net/viewthread.php?tid=158&highlight=FC

[观点]RAM硬盘

mikel阅读(791)

Jim Gray在过去40年中对技术发展有过巨大的贡献,“内存是新的硬盘,硬盘是新的磁带”是他的名言。“实时”Web应用不断涌现,达到海量规模的系统越来越多,这种后浪推前浪的发展模式对软硬件又有何影响?
Tim Bray早在网格计算成为热门话题之前,就讨论过以RAM和网络为中心的硬件结构的优势,可以用这种硬件建立比磁盘集群速度更快的RAM集群。

对 于数据的随机访问,内存的速度比硬盘高几个数量级(即使是最高端的磁盘存储系统也只是勉强达到1,000次寻道/秒)。其次, 随着数据中心的网络速度提高,访问内存的成本更进一步降低。通过网络访问另一台机器的内存比访问磁盘成本更低。就在我写下这段话的时候,Sun的 Infiniband产品线中有一款具备9个全互联非阻塞端口交换机,每个端口的速度可以达到30Gbit/sec!Voltaire产品的端口甚至更 多;简直不敢想象。(如果你想了解这类超高性能网络的最新进展,请关注Andreas Bechtolsheim在Standford开设的课程。)

Tim还指出Jim Gray的名言中后半句所阐述的真理:“对于随机访问,硬盘慢得不可忍受;但如果你把硬盘当成磁带来用,它吞吐连续数据的速率令人震惊;它天生适合用来给以RAM为主的应用做日志(logging and journaling)。”
时间闪到几年之后的今天,我们发现硬件的发展趋势在RAM和网络领域势头不减,而在硬盘领域则止步不前。Bill McColl提到用于并行计算的海量内存系统已经出现

内 存是新的硬盘!硬盘速度提高缓慢,内存芯片容量指数上升,in-memory软件架构有望给各类数据密集的应用带来数量级的性能提升。小型机架服务器 (1U、2U)很快就会具备T字节、甚至更大量的内存,这将会改变服务器架构中内存和硬盘之间的平衡。硬盘将成为新的磁带,像磁带一样作为顺序存储介质使 用(硬盘的顺序访问相当快速),而不再是随机存储介质(非常慢)。这里面有着大量的机会,新产品的性能有望提高10倍、100倍。

Dare Obsanjo指出如果不把这句真言当回事,会带来什么样的恶劣后果—— 也就是Twitter正面临的麻烦。论及Twitter的内容管理,Obsanjo说,“如果一个设计只是简单地反映了问题描述,你去实现它就会落入磁盘 I/O的地狱。不管你用Ruby on Rails、Cobol on Cogs、C++还是手写汇编都一样,读写负载照样会害死你。”换言之,应该把随机操作推给RAM,只给硬盘留下顺序操作。
Tom WhiteHadoop Core项目的提交者,也是Hadoop项目管理委员会的成员。他对Gray的真言中“硬盘是新的磁带”部分作了更深入地探讨。White在讨论MapReduce编程模型的时候指出,为何对于Hadloop这类工具来说,硬盘仍然是可行的应用程序数据存储介质:

本 质上,在MapReduce的工作方式中,数据流式地读出和写入硬盘,MapReduce是以硬盘的传输速率不断地对这些数据进行排序和合并。 与之相比,访问关系数据库中的数据,其速率则是硬盘的寻道速率(寻道指移动磁头到盘面上的指定位置读取或写入数据的过程)。为什么要强调这一点?请看看寻 道时间和磁盘传输率的发展曲线。寻道时间每年大约提高5%,而数据传输率每年大约提高20%。寻道时间的进步比数据传输率慢——因此采用由数据传输率决定 性能的模型是有利的。MapReduce正是如此。

虽然固态硬盘(SSD)能否改变寻道时间/传输率的对比还有待观察,White文章的跟贴中,很多人都认为SSD会成为RAM/硬盘之争中的平衡因素
Nati Shalom对内存和硬盘在数据库部署和使用中的角色作了一番有理有据的评述。 Shalom着重指出用数据库集群和分区来解决性能和可伸缩性的局限。他说,“数据库复制和数据库分区都存在相同的基本问题,它们都依赖于文件系统/硬盘 的性能,建立数据库集群也非常复杂”。他提议的方案是转向In-Memory Data Grid(IMDG),用Hibernate二级缓存或者GigaSpaces Spring DAO之类的技术作支撑,将持久化作为服务(Persistence as a Service)提供给应用程序。Shalom解释说,IMDG

提供在内存中的基于对象的数据库能力,支持核心的数据库功能,诸如高级索引和查询、事务语义和锁。IMDG还从应用程序的代码中抽象出了数据的拓扑。通过这样的方式,数据库不会完全消失,只是挪到了“正确的”位置。

IMDG相比直接RDBMS访问的优势列举如下:

  • 位于内存中,速度和并发能力都比文件系统优越得多
  • 数据可通过引用访问
  • 直接对内存中的对象执行数据操作
  • 减少数据的争用
  • 并行的聚合查询
  • 进程内(In-process)的局部缓存
  • 免除了对象-关系映射(ORM)

你是否需要改变对应用和硬件的思维方式,最终取决于你要用它们完成的工作。但似乎公论认为,开发者解决性能和可伸缩性的思路已经到了该变一变的时候。

查看英文原文:RAM is the new disk…

[MVC]asp.net的MVC编程、MV编程以及URL重写

mikel阅读(786)

前一段时间做一个网站项目(运行于win2003+.net2.0环境),其间自己写了一个MVC架构,觉得比较适合团队快速开发ASP.NET web站点,现在拿出来和大家一起共享,请多指正。

一、MVC编程:
      针对用户的浏览器来说,网站可以看作一个实体、一个接口,其接收浏览器的请求,并将相应的信息返回给浏览器;因此,网站程序完全可以用一个程序来完成,而 实际上也确实如此,IIS、apache等web服务器本身就是一个程序,而运行其中的asp、aspx、php、jsp、html等等的单个页面,只不 过是帮助web服务器来实现一定功能而已。

      由此可以引申出:我们完全可以用一个aspx页面来处理针对网站的所有动态请求。

      而这个页面,我们就把它起名为index.aspx吧。

      在apache、tomcat等web服务器,都有相应的技术,将网站符合一定规则的所有http请求,都转向一个程序页面(如index.jsp或 index.php)来处理。而IIS在IIS7(前面提到,我们的网站服务器是windows2003,IIS版本为6.0)出来以前,只能借助于第三 方组件实现(windows2008的IIS7.0可以不借助第三方组件实现URLRewrite,网上可以找到相关代码)。这其中比较有名的2个是 ISAPI_Rewrite(Full版收费,Lite版免费)和IonicIsapiRewriter(免费),而对于我们这个MVC架构来 说,ISAPI_Rewrite Lite版(下载ISAPI_Rewrite Lite这里有ISAPI_Rewrite Lite的最新版本,我们使用的是ISAPI_Rewrite3_0047_Lite.msi)就足够了,由它来控制请求到我们的index.aspx(具体代码参见DotNetMVC示例网站代码)。

(一) 网站的目录结构
      为了使图片、css文件、js文件、html文件等免于ISAPI_Rewrite处理,需在网站根目录建立一个单独的mvc目录,其中存放MVC架构需要的aspx文件,从而网站的目录结构如下:
ROOT
  |–App_Code
        |–DotNetMVC
              |–DAL
                  |–UserDA.cs
              |–Model
                  |–User.cs
              |–Util
                  |–ControllerUtil.cs
                  |–DBUtil.cs
  |–Bin
      |–log4net.dll
  |–css
  |–images
  |–js
  |–mvc
      |–application
             |–controllers
                  |-default.aspx
                  |-user.aspx
             |–views
                  |–default
                       |-index_view.aspx
                  |–share
                  |–user
                       |-home_view.aspx
                       |-list_view.aspx
      |–cache
      |–log
      |-index.aspx
  |-Default.aspx
  |-Global.asax
  |-web.config

      上面的结构中,css、images、js放什么文件分别存放站点用的样式文件、图片文件、JavaScript脚本文件;Bin存放公共组件(目前有一 个日志组件log4net.dll,其配置信息在web.config配置文件中),App_Code存放自定义的公共类,这是.net2.0规定 的,mvc目录的作用上面说了,不再赘述。

     下面再看App_Code和mvc下的子目录构成:
      App_Code->Util目录,存放一些实用工具类,目前有2个,DBUtil.cs是SQLServer数据库处理工具类,而 ControllerUtil.cs则是我们这个MVC架构比较核心的URL路由工具类,其中ParseUri方法解析URI返回控制器、控制分支、参数 等,LinkTo方法产生需要的网站链接URL(具体代码参见DotNetMVC示例网站代码)。大家还可以在其中添加一些需要的功能,如上传、Email、字符串、分页、图形处理等。
      而App_Code->DAL和App_Code->Model目录中的内容一起组成MVC架构中M层逻辑,其中Model目录的仅仅是数据 库表的数据抽象类(这些类可以自己写,也可以通过工具结合数据库表自动生成),DAL目录中的类则通过访问数据库返回数据抽象类的对象实例或实例列表,供 控制层调用。
      mvc根目录下的index.aspx文件,如上所述是MVC架构的入口文件。
      mvc->cache和mvc->log目录分别存放缓存文件和日志文件,如果需要的话。
      mvc->application目录中的controllers目录和views目录分别是控制器文件和视图文件,即MVC架构中的C和V层,其 中一个控制器对应一个aspx文件(如user.aspx),并在views目录中有一个视图子目录对应(如views->user),其中存放多 个此控制器可能用到的视图文件(如home_view.aspx和list_view.aspx等);views->share目录中,则是一些视 图文件可能用到的公共文件,如头尾包含页、母板页等。

(二)MVC运转流程:

      前面曾经提到,要把所有针对本站点的动态请求,都统一到index.aspx这个文件来集中处理,因此需要借助ISAPI_Rewrite,在ISAPI_Rewrite Lite的配置文件httpd.conf(位于ISAPI_Rewrite Lite的安装目录)中增加下面一条记录即可:
RewriteRule /mvc/(.*)$ /mvc/index.aspx\?idu=$1 [NC,NE]

      这条规则是将针对/mvc这个URI及其后的所有访问,都导向到index.aspx这个文件来处理,并将URI路径作为idu参数的值传给index.aspx
      下面看看index.aspx文件的内容:

<%@ Page Language="C#" %>
<%@ import namespace="System.Threading" %>
<%
    
string controller;
    
string method;
    
string[] parameters;
    
string uri_string = Request.QueryString["idu"];
    DotNetMVC.Util.ControllerUtil.ParseUri(uri_string, 
out controller, out method, out parameters);

    Context.Items.Add(
"method", method);
    Context.Items.Add(
"parameters", parameters);
    
    
string ctlpage = "system/application/controllers/" + controller + ".aspx";
    
try
    
{
        Server.Transfer(ctlpage, 
true);
    }

    
catch (HttpException e)
    
{
        log4net.LogManager.GetLogger(
"LogFile").Error("\r\n客户机IP:" + Request.UserHostAddress + "\r\n错误地址:" + Request.Url, e);
    }

%>

      上面代码的关键是,通过对idu值的解析,取得controller、method、parameters这3个参数;其中controller对应于一 个控制器文件,method对应控制器中的一个控制分支,parameters则是参数的字符串数组(参数顺序自己把握),其对应URI如下:
/mvc/controller/method/parameter1/parameter2/parameterN
      目前这个MVC架构的URI,都是一个控制器,后跟一个分支,再后跟多个参数,如果没有controller、method、parameters,则默 认调用default控制器的index分支,如果没有method、parameters,则默认调用本控制器的index分支;如果以上不满足要求, 大家可以自己更改ControllerUtil类的ParseUri方法或者写一个复杂的URL Routing(我个人认为不管什么,够用就好,controller、method已经能够表达复杂的网站层次了)。Server.Transfer方 法的第2个参数为true,是确保request、cookie、session等变量能够传递到控制器程序中。

      下面通过default.aspx这个控制器(可以一个功能或一个模块作为一个控制器)说明一下控制器的流程:

<%@ Page Language="C#" %>
<%@ import namespace="DotNetMVC.Util" %>
<%
string method = (string)Context.Items["method"];
string[] parameters = (string[])Context.Items["parameters"];
try
{
    
if (method == "index")
    
{
        Context.Items.Add(
"loginurl", ControllerUtil.LinkTo("user""login"""));
        Context.Items.Add(
"userlisturl", ControllerUtil.LinkTo("user""list"""));
        Server.Execute(
"application/views/default/index_view.aspx");
    }

}

catch (HttpException e)
{
    log4net.LogManager.GetLogger(
"LogFile").Error("\r\n客户机IP:" + Request.UserHostAddress + "\r\n错误地址:" + Request.Url, e);
}

%>

      上面代码中,首先通过Context获取index.aspx中 得到的method、parameters参数,然后根据method值的不同,走不同的处理分支(这里可以调用M层获取数据)产生数据并保存在 Context(目前仅找到用Context来传递数据到视图)中,再调用不同的视图;这里只有一个默认index分支,去调用首页视图 index_view.aspx。


      最后看看views->default目录下index_view.aspx这个视图文件内容:

<%@ Page Language="C#" EnableViewStateMac="false"%>
<%
    
string loginurl = (string)Context.Items["loginurl"];
    
string userlisturl = (string)Context.Items["userlisturl"];
%>
<!– #include file="../share/top.aspx" –>
<center>
<form name=frm1 method=post action=<%=loginurl %>>
昵称:
<input type=text name=nick size=20>&nbsp;&nbsp;
密码:
<input type=password name=pass size=20>
<input type=submit value=登陆> &nbsp;<a href=<%=userlisturl %>>去用户列表</a>
</form>
</center>
<!– #include file="../share/bottom.aspx" –>

      这个视图文件中的代码则通过Context接收控制器传过来的数据并显示它。
      至此,整个MVC的运转流程就完成了;其他更复杂的一些操作,大家可以参照DotNetMVC示例网站代码,相信根据这个示例,就可以直接建立并快速开发自己的MVC网站了,并有URL重写功能;在其中的user控制器及视图中,大家可以看到这种编程有一个好处,那就是可以充分利用visual studio的代码智能感知功能。
      不过,有一点需要大家注意,因为需要经过ISAPI_Rewrite过滤器与Transfer、Execute处理,所以会有一些性能损失。根据流程的复 杂程度,其损失所占比重会有所不同:越复杂的流程,其损失所占比重越小,越简单的流程,其损失所占比重越大;所以大家在用这套流程开发网站时,应充分注意 这一点,并适当进行程序优化,或者干脆别用它了

二、MV编程:

      大家在看上面的DotNetMVC示例网站代码的时候,肯定有一个感觉:在控制层产生数据,要赋给Context,视图层再从Context中取出数据来显示,似乎多此一举;所以引出下面的MV编程(可能会丧失一些灵活性和可维护性,但开发一般的网站应该足够了)。

      我们只需要把DotNetMVC示例网站代码中的代码简单做一下修改就可以了。

      首先,修改index.aspx如下:

<%@ Page Language="C#" %>
<%@ import namespace="System.Threading" %>
<%
    
string controller;
    
string method;
    
string[] parameters;
    
string uri_string = Request.QueryString["idu"];
    DotNetMVC.Util.ControllerUtil.ParseUri(uri_string, 
out controller, out method, out parameters);

    Context.Items.Add(
"method", method);
    Context.Items.Add(
"parameters", parameters);

    
string ctlpage = "application/views/" + controller + "/" + method + ".aspx";
    
try
    
{
        
//Server.Transfer(ctlpage, true);
        Server.Execute(ctlpage);
    }

    
catch (HttpException e)
    
{
        log4net.LogManager.GetLogger(
"LogFile").Error("\r\n客户机IP:" + Request.UserHostAddress + "\r\n错误地址:" + Request.Url, e);
    }

%>

      这里直接用controller和method组合出视图路径,并用Server.Execute去执行它(因为Server.Transfer总是抛出 System.Threading.ThreadAbortException异常,虽然不影响运行,这似乎是ASP.NET的一个小问题)。
      然后删除控制器目录的内容,并将控制器页面中的代码转移到视图中即可,具体请参看DotNetMV示例网站代码。这样,既减少了编程复杂度,又增加的开发效率和运行性能,同时URL重写和代码智能感知等优点仍然得以保留。

附:

      下载DotNetMVC示例网站代码DotNetMV示例网站代码到本地后,请注意示例网站代码是一个完整的网站架构,大家可以直接在VS中打开此网站(VS2005和VS2008),根据实际修改web.config文件,在IIS中配置dotnetmv(c)为站点根目录,并配置站点属性“目录安全性”标签为“集成windows身份验证”,同时将站点应用程序配置为“启用ASP服务器脚本调试”和“启用ASP客户端脚本调试”;运行调试前,请先安装ISAPI_RewriteLite(下载ISAPI_Rewrite Lite),并修改其配置文件;调试时,请注意修改站点的“启动选项”使用本地IIS,因为VS中的DevelopWebServer无法加载ISAPI_Rewrite过滤器。
      另外,测试数据表建立脚本给出如下:

Create TABLE [dbo].[users](
    
[id] [int] IDENTITY(1,1NOT NULL,
    
[nick] [varchar](50) COLLATE Chinese_PRC_CI_AS NULL,
    
[pass] [varchar](20) COLLATE Chinese_PRC_CI_AS NULL,
    
[reg_date] [datetime] NULL CONSTRAINT [DF_test_inputdate]  DEFAULT (getdate())
ON [PRIMARY]

[资源]Lucene.net的相关网站

mikel阅读(699)

 lucene 官方网站,  Luncene.net 官方网站(英文) 这两个网站大家应该都知道了,里面还有一个邮件列表,有兴趣可以加入这个邮件列表,这样就可以和全球的爱好者一起来讨论Lucene.net的相关问题了。
    中文资源
    博客园 lucene.net 讨论小组 一个园子里面的,当然要重点推荐一下了。
    博客园 搜索引擎讨论小组 我创建的小组,主要讨论搜索引擎技术,数据挖掘技术和中文分词技术,由于和lucene高度相关,所以一些lucene的问题也会在这个小组中进行讨论。
    Nutch中文网论坛 Lucene学习资料 
    JavaEye lucene爱好者
    
    中文资源目前就找到这么一点,感觉实在太少了,还望大家补充。
    
    英文资源
    lucene apache 组织中的 wiki 这个网址有很多lucene 的相关资源
    lucene 的英文博客网站 这个是lucene的鼻祖Doug Cutting的Blog
    维基百科Lucene相关的介绍
    Lucene forum at nabble.com
    http://groups.drupal.org/lucene-and-nutch
    http://lucene.grantingersoll.com/

[文档]ADO三大对象的属性、事件、方法

mikel阅读(733)

Connection对象
属性
属性名称数据类型和用途
Attributes 可读写Long类型,通过两个常数之和指定是否使用保留事务(retainningtransactions)。常数 adXactCommitRetaining表示调用CommitTrans方法时启动一个新事务;常数adXactAbortRetaning表示调用 RollbackTrans方法时启动一个新事务。默认值为0,表示不使用保留事务。
CommandTimeout可读写Long类型,指定中止某个相关Command对象的Execute调用之前必须等待的时间。默认值为30秒。
ConnectionString可读写String类型,提供数据提供者或服务提供者打开到数据源的连接所需要的特定信息
ConnectionTimeout可读写Long类型,指定中止一个失败的Connection.Open方法调用之前必须等待的时间,默认值为15秒。
CursorLocation可读写Long类型,确定是使用客户端(adUseClient)游标引擎,还是使用服务器端(adUseServer)游标引擎。默认值是adUseServer。
DefaultDatabase可读写String类型,如果ConnectString中未指定数据库名称,就使用这里所指定的名称,对SQLServer而言,其值通常是pubs
IsolationLevel可读写Long类型,指定和其他并发事务交互时的行为或事务。见IsolationLevel常数
ModeLong类型,指定对Connection的读写权限。见Mode常数
Provider可读写String类型,如果ConnectionString中未指定OLEDB数据或服务提供者的名称,就使用这时指定的名称。默认值是MSDASQL(MicrosoftOLEDBProviderforODBC)。
State可读写Long类型,指定连接是处于打开状态,还是处于关闭状态或中间状态。见State常数
Version只读String类型,返回ADO版本号。
注意:上面所列出的大多数可读写的属性,只有当连接处于关闭状态时才是可写的。
只有当用户为Connection对象用BeginTrans…CommitTrans…RollbackTrans方法定义了不遗余力,事务隔离程度的指定才真正有效。如果有多个数据库用户同时执行事务,那么应用程序中必须指定如何响应运行中的其他事务。
方法
方法用途
BeginTrans初始化一个事务;其后必须有CommitTrans和/或RollbackTrans相呼应
Close关闭连接
CommitTrans提交一个事务,以完成对数据源的永久改变(要求使用之前必须调用了BeginTrans方法)
Execute人SelectSQL语句返回一个forward-onlyRecordset对象,也用来执行那些不返回Recordset语句,如Insert、Update、Delete查询或DDL语句
Open用连接字符串来打开一个连接
OpenSchema返回一个Recordset对象以提供数据源的结构信息(metadata)
RollbackTrans取消一个事务,恢复对数据源做的临时性改变(要求使用之前必须调用了BeginTrans方法)
注:只有Execute、Open和OpenSchema三个方法才能接受变元参数。Execute的语法为:
cnnName.ExecutestrCommand,[lngRowsAffected[,lngOptions]]
strCommand 的值可以是SQL语句、表名、存储过程名,也可以是数据提供者所能接受的任意字符串。为了提高性能,最好为lngOptions参数指定合适的值(详见 lngOptions参数用到的常数),以使提供者解释语句时不用再去判定其类型。可选参数lngRowsAffected将返回Insert、 Update或Delete查询执行以后所影响的数目。这些查询会返回一个关闭的Recordset对象。一个Select查询将返回 lngRowsAffected值为0并且返回带有一行或多行内容的打开的forward-onlyRecordset。
事件
事件名称触发时机
BeginTransCompleteBeginTrans方法执行以后。
PrivateSubcnnName_BeginTransComplet(ByValTransactionLevelAsLong,ByValpErrorAsADODB.Error,adStatusAsADODB.EventStatusEnum,ByValpConnectionAsADODB.Connection)
CommitTransCompleteCommitTrans方法执行以后
PrivateSubConnection1_CommitTransComplete(ByValpErrorAsADODB.Error,adStatusAsADODB.EventStatusEnum,ByValpConnectionAsADODB.Connection)
ConnectComplete成功建立到数据源的Connection之后
PrivateSubConnection1_ConnectComplete(ByValpErrorAsADODB.Error,adStatusAsADODB.EventStatusEnum,ByValpConnectionAsADODB.Connection)
DisconnectConnection关闭之后
PrivateSubConnection1_Disconnect(adStatusAsADODB.EventStatusEnum,ByValpConnectionAsADODB.Connection)
ExecuteComplete完成Connection.Execute或Command.Execute之时
PrivateSubConnection1_ExecuteComplete(ByValRecordsAffectedAsLong,ByValpErrorAsADODB.Error,adStatusAsADODB.EventStatusEnum,ByValpCommandAsADODB.Command,ByValpRecordsetAsADODB.Recordset,ByValpConnectionAsADODB.Connection)
InfoMessage一个Error对象被添加到ADODB.Connectio.Error集合之时
PrivateSubConnection1_InfoMessage(ByValpErrorAsADODB.Error,adStatusAsADODB.EventStatusEnum,ByValpConnectionAsADODB.Connection)
RollbackTransCompleteRollbackTrans方法执行之后
PrivateSubConnection1_RollbackTransComplete(ByValpErrorAsADODB.Error,adStatusAsADODB.EventStatusEnum,ByValpConnectionAsADODB.Connection)
WillConnect即将调用Connection.Open方法之时
PrivateSubConnection1_WillConnect(ConnectionStringAsString,UserIDAsString,PasswordAsString,OptionsAsLong,adStatusAsADODB.EventStatusEnum,ByValpConnectionAsADODB.Connection)
WillExecute即将调用Connection.Execute或Command.Execute方法之时
PrivateSubConnection1_WillExecute(SourceAsString,CursorTypeAsADODB.CursorTypeEnum,LockTypeAsADODB.LockTypeEnum,OptionsAsLong,adStatusAsADODB.EventStatusEnum,ByValpCommandAsADODB.Command,ByValpRecordsetAsADODB.Recordset,ByValpConnectionAsADODB.Connection)
注:其中的adStatus参数所用到的常数的名称和含义详见adStatus所用的常数
常数
IsolationLevel常数
常数含义
adXactCursorStability只允许读其他事务已提交的改变(默认值)
adXactBrowse允许读其他事务未提交的改变
adXactChaos本事务不会覆盖其他位于更高隔离程度的事务所做的改变
adXactIsolated所有事务相互独立
adXactReadCommitted等同于adXactCursorStability
adXactReadUncommitted等同于adXactBrowse
adXactRepeatableRead禁止读其他事务的改变
adXactSerializable等同于adXactIsolated
adXactUnspecified不能确定提供者的事务隔离程度
Mode常数
常数含义
adModeUnknown未指定数据源的连接许可权(默认值)
adModeRead连接是只读的
adModeReadWrite连接是可读写的
adModeShareDenyNone不拒绝其他用户的读写访问(JetOLEDBProvider的默认值)
adModeShareDenyRead拒绝其他用户打开到数据源的读连接
adModeShareDenyWrite拒绝其他用户打开到数据源的写连接
adModeShareExclusive以独占方式打开数据源
adModeWrite连接是只写的
State常数
常数含义
adStateClosedConnection(或其他对象)是关闭的(默认值)
adStateConnecting正在连接数据源的状态
adStateExecutingConnection或Command对象的Execute方法已被调用
adStateFetching返回行(row)到Recordset对象
adStateOpenConnection(或其他对象)是打开的(活动的)
Execute方法中lngOption参数用到的常数
Command类型常数含义
adCmdUnknownCommand类型未定(默认值),由数据提供者去判别Command语法
adCmdFileCommand是和对象类型相应的文件名称
adCmdStoredProcCommand是存储过程名称
adCmdTableCommand是能产生内部Select*FROMTableName查询的表名称
adCmdTableDirectCommand是能直接从表中获取行内容的表名称
adCmdTextCommand是一条SQL语句
ADODB事件处理子过程参数adStatus所用的常数
常数含义
adStatusCancel操作被用户取消
adStatusCnatDeny操作不能拒绝其他用户对数据源的访问
adStatusErrorsOccurred操作导致错误并已送到Errors集合中
adStatusOK操作成功
adStatusUnWantedEvent操作过程中一个未预料到的事件被激活->

[代码]生成验证码的控件

mikel阅读(773)

看过网上很多关于ASP.NET生成 验证码的东西。大部分都牺牲了一个aspx页面来生成验证码图片。 而且还不利于二次使用。 于是想一直琢磨着想写一个不用牺牲一个aspx页面来完成验证码的控件,在使用的时候只需要引用一个dll并且在工具箱中直接拖到页面上就可。 经过几天努力还真琢磨出来了一个个人认为比较好的方法,于是拿出来共享一下,希望和大家交流交流意见。
现在开始

using System;
using System.Collections.Generic;
using System.Text;

using System.Web;
using System.Drawing;
using System.IO;
using System.Web.SessionState;

namespace jdTools.Web
{
    
public class VerifyImageHttpHandle : IHttpHandler, IRequiresSessionState
    
{
        
private string GetRandomNumberString(int codeCount)
        
{
            
int j1;
            
string strChoice = "2,3,4,5,6,7,8,9,A,B,C,D,E,F,G,H,J,K,L,M,N,P,Q,R,S,T,U,V,W,X,Y,Z";
            
string[] strResult = strChoice.Split(new Char[] ',' });
            
string strReturn = "";
            Random rnd 
= new Random(unchecked((int)DateTime.Now.Ticks));
            
for (int i = 0; i < codeCount; i++)
            
{
                Random rnd1 
= new Random(rnd.Next() * unchecked((int)DateTime.Now.Ticks));
                j1 
= rnd1.Next(strResult.Length);
                rnd 
= new Random(rnd.Next() * unchecked((int)DateTime.Now.Ticks));
                strReturn 
= strReturn + strResult[j1].ToString();
            }

            
return strReturn;  
        }

        
private Color GetColor()
        
{
            
return Color.Black;
        }

        
private Bitmap CreateImage(string str_ValidateCode)
        
{
            Random newRandom 
= new Random((int)DateTime.Now.Ticks);
            
int int_ImageWidth = str_ValidateCode.Length * 14;
            
int int_ImageHeight = 20;
            
//  图高20px
            Bitmap theBitmap = new Bitmap(int_ImageWidth, int_ImageHeight);
            Graphics theGraphics 
= Graphics.FromImage(theBitmap);
            
//  白色背景
            theGraphics.Clear(Color.White);
            
//  灰色边框
            theGraphics.DrawRectangle(new Pen(Color.LightGray, 1), 00, int_ImageWidth  1, int_ImageHeight);

            
int num = theBitmap.Width * theBitmap.Height * 30 / 100;
            
for (int iCount = 0; iCount < num; iCount++)
            
{
                
// 在随机的位置使用随机的颜色设置图片的像素
                int x = newRandom.Next(theBitmap.Width);
                
int y = newRandom.Next(theBitmap.Height);
                
int r = newRandom.Next(255);
                
int g = newRandom.Next(255);
                
int b = newRandom.Next(255);
                Color c 
= Color.FromArgb(r, g, b);
                theBitmap.SetPixel(x, y, c);
            }
//for


            
//  10pt的字体
            Font theFont = new Font("Arial"12, FontStyle.Bold);

            
for (int int_index = 0; int_index < str_ValidateCode.Length; int_index++)
            
{
                
string str_char = str_ValidateCode.Substring(int_index, 1);
                Brush newBrush 
= new SolidBrush(GetColor());
                Point thePos 
= new Point(int_index * 13 + 1 + newRandom.Next(3), 1 + newRandom.Next(3));
                theGraphics.DrawString(str_char, theFont, newBrush, thePos);
            }

            
            theGraphics.Dispose();
            
return theBitmap;
            
        }


        
#region IHttpHandler 成员

        
public bool IsReusable
        
{
            
get return true; }
        }

        
public void ProcessRequest(HttpContext context)
        
{
            HttpResponse Response 
= context.Response;
            
//  将生成的图片发回客户端
            MemoryStream ms = new MemoryStream();
            
string NumStr=GetRandomNumberString(5);
            context.Session.Add(
"Verify", NumStr);

            Bitmap theBitmap 
= CreateImage(NumStr);
            theBitmap.Save(ms, System.Drawing.Imaging.ImageFormat.Jpeg);
            Response.ClearContent(); 
//需要输出图象信息 要修改HTTP头 
            Response.ContentType = "image/jpeg";
            Response.BinaryWrite(ms.ToArray());
            theBitmap.Dispose();
            ms.Close();
            ms.Dispose();
            Response.End();
        }

        
#endregion

    }

}

GetRandomNumberString方法用于生成指定个数的随机数字符串。
IHttpHandle接口的ProcessRequest方法可以启用 HTTP Web 请求的处理。
VerifyImageHttpHandle 继承了IHttpHandle接口用于自定义程序处理的Web请求。然后在web.config的<system.web>节中配置

      <httpHandlers>
        
<add verb="*" path="VerifyImg.jd" type="jdTools.Web.VerifyImageHttpHandle"/>
      
</httpHandlers>

此时在浏览器中访问VerifyImg.jd时就会得到一个验证码图片,生成验证码的内容就完成了。
现在我们要自定义一个WEB自定义控件。其代码如下:

using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Text;
using System.Web;
using System.Web.UI;
using System.Web.UI.WebControls;


namespace jdTools.Web.UI
{
    [ToolboxData(
"<{0}:VerifyImage runat=server></{0}:VerifyImage>")]
    
public class VerifyImage : WebControl
    
{
        
public string Value
        
{
            
get return HttpContext.Current.Session["Verify"].ToString(); }
        }

        
public virtual ImageAlign ImageAlign
        
{
            
get
            
{
                
object obj2 = this.ViewState["ImageAlign"];
                
if (obj2 != null)
                
{
                    
return (ImageAlign)obj2;
                }

                
return ImageAlign.NotSet;
            }

            
set
            
{
                
if ((value < ImageAlign.NotSet) || (value > ImageAlign.TextTop))
                
{
                    
throw new ArgumentOutOfRangeException("value");
                }

                
this.ViewState["ImageAlign"= value;
            }


        }


        
public VerifyImage()
            : 
base(HtmlTextWriterTag.Img)
        
{ }
        
protected override void AddAttributesToRender(HtmlTextWriter writer)
        
{
            
base.AddAttributesToRender(writer);
            writer.AddStyleAttribute(HtmlTextWriterStyle.Cursor, 
"pointer");
            writer.AddAttribute(
"onclick""this.src='VerifyImg.jd?id='+Math.random()"true);
            writer.AddAttribute(HtmlTextWriterAttribute.Src, 
"VerifyImg.jd");
            
string str2;
            
switch (this.ImageAlign)
            
{
                
case ImageAlign.Left:
                    str2 
= "left";
                    
break;

                
case ImageAlign.Right:
                    str2 
= "right";
                    
break;

                
case ImageAlign.Baseline:
                    str2 
= "baseline";
                    
break;

                
case ImageAlign.Top:
                    str2 
= "top";
                    
break;

                
case ImageAlign.Middle:
                    str2 
= "middle";
                    
break;

                
case ImageAlign.Bottom:
                    str2 
= "bottom";
                    
break;

                
case ImageAlign.AbsBottom:
                    str2 
= "absbottom";
                    
break;

                
case ImageAlign.AbsMiddle:
                    str2 
= "absmiddle";
                    
break;

                
case ImageAlign.NotSet:
                    str2
="";
                    
break;
                
default:
                    str2 
= "texttop";
                    
break;
            }

            
if (str2 != "")
                writer.AddAttribute(HtmlTextWriterAttribute.Align, str2);
        }

    }

}

VerifyImage 类定义了两个属性。其中Value属性用于取得session中存放的验证码的值。
这里就很简单了,没有必要详说。
在使用的时候aspx页面如下:

                    <ul>
                        
<li>用户名:<asp:TextBox ID="txtUserName" runat="server"></asp:TextBox></li>
                        
<li>密 码:<asp:TextBox ID="txtPassWord" runat="server"></asp:TextBox></li>
                        
<li>检证码:<asp:TextBox ID="txtVerify" runat="server" Width="50px"></asp:TextBox><jd:VerifyImage ID="verify" runat="server" Height="23px" ImageAlign="AbsMiddle"/></li>
                    
</ul>

aspx.cs中:

            if (txtVerify.Text != verify.Value)
            
{
                
//.验证码错误
            }

            
else
            
{
                
//验证码正确
            }

[资源].net网站

mikel阅读(688)

博客园博客堂CSDN 当然是不用说了,大家都知道的。
51ASPX.com
国内非常优秀的ASP.NET源码发布下载站,相信很多人都到过这里下载过源码。
孟子E章
很多非常实用的技术实例,当你遇到什么问题不妨先到这里看看,没准儿会有意想不到的收获。
CodeUsing.com
一个不错的.NET资源分享站,也算一个Web2.0的网站,注册用户可以发布资源。
msproject.cn
简单整洁的.NET开源技术社区,以前是一个开源技术论坛,改版后又增加了一些功能:视屏、公司点评等。
.NET正则表达式库(regex-lib.net)
博客园 Anders Liu 刚发布的正则表达式分享网站

C#资源大全
不用说,是一些开源资源了,只是好像两年没有更新了。
http://java.poac.ac.cn/codeopen/jiaocheng/cs-open/index.html

[代码]JavaScript 图片切换展示效果

mikel阅读(887)

看到alibaba的一个图片切换效果,感觉不错,想拿来用用。但代码一大堆的,看着昏,还是自己来吧。
由于有了做JavaScript 图片滑动展示效果的经验,做这个就容易得多了。
先看看效果:
根据alibaba做的效果:

  • 1
  • 2
  • 3

alibaba的按钮有一个延迟的功能,应该加个定时器,但这个不是重点就省了吧。
扩展成能左右切换:

  • 1
  • 2
  • 3

其他扩展功能:



切换速度:
停顿时间:


程序说明:
首先需要一个容器,设置它的overflow为hidden,position为relative;
容器里面还要一个滑动对象,设置它的position为
absolute;
initialize()函数里初始化一些属性。
在切换之前先执行Start()函数,进行相关设置,
主要是设置Index属性(索引)和_target属性(目标值):


if(this.Index < 0){
    
this.Index = this._count  1;
else if  (this.Index >= this._count){ this.Index = 0; }
this._target = 1 * this._parameter * this.Index;

接着就执行Move()函数开始移动了,原理通过设置滑动对象的top(或left)来做出移动的效果,
而减速的效果就需要执行GetStep()函数来获取步长:

var iStep = (iTarget  iNow) / this.Step;

用目标值减当前值再除以一个参数,得到步长,
这样取得的步长在当前值越接近目标值时会越来越小,也做成了减速的效果,
然后在top(或left)的设置中加上这个步长,并设置定时器继续Move(),直到到达目标值:


this._slider.style[style] = (iNow + iStep) + "px";
this._timer = setTimeout(function(){ oThis.Move(); }, this.Time);

下面例子里的容器结构:


<div class="container" id="idTransformView">
  
<ul class="slider" id="idSlider">
    
<li><img src="http://shundebk.cn/temp/1.jpg"/></li>
    
<li><img src="http://shundebk.cn/temp/2.jpg"/></li>
    
<li><img src="http://shundebk.cn/temp/3.gif"/></li>
  
</ul>
  
<ul class="num" id="idNum">
    
<li>1</li>
    
<li>2</li>
    
<li>3</li>
  
</ul>
</div>

要美观的话需要css设置一下:


.container, .container *{margin:0; padding:0;}
.container
{width:408px; height:168px; overflow:hidden;}
.slider
{position:absolute;}
.slider li
{ list-style:none;display:inline;}
.slider img
{ width:408px; height:168px; display:block;}
.slider2
{width:2000px;}
.slider2 li
{float:left;}
.num
{ position:absolute; right:5px; bottom:5px;}
.num li
{
    float
: left;
    color
: #FF7300;
    text-align
: center;
    line-height
: 16px;
    width
: 16px;
    height
: 16px;
    font-family
: Arial;
    font-size
: 12px;
    cursor
: pointer;
    overflow
: hidden;
    margin
: 3px 1px;
    border
: 1px solid #FF7300;
    background-color
: #fff;
}
.num li.on
{
    color
: #fff;
    line-height
: 21px;
    width
: 21px;
    height
: 21px;
    font-size
: 16px;
    margin
: 0 1px;
    border
: 0;
    background-color
: #FF7300;
    font-weight
: bold;
}

样式的设置跟程序也有一定关系,例如宽和高,这里就不说明了。
接着就可以实例化了:


var tv = new TransformView ("idTransformView", "idSlider", 168, 3, {
    onStart : function(){ Each(objs, function(o, i) { o.className = tv.Index == i ? "on" : ""; })  }//按钮样式
});

这里主要有4个参数,分别是容器对象、滑动对象、切换参数和切换数量。
当程序是上下切换时,切换参数切换的高度,当左右切换时,是切换的宽度。
切换数量就是有多少个切换对象了,例如上面的例子就是3个。
最后的参数是一些设置:
属性: 默认值//说明
Up:   true,//是否向上(否则向左)
Step:  5,//滑动变化率
Time:  10,//滑动延时
Auto:  true,//是否自动转换
Pause:  2000,//停顿时间(Auto为true时有效)
onStart: function(){},//开始转换时执行
onFinish: function(){}//完成转换时执行

例子里设置了onStart属性,作用是在切换开始时,设置按钮的样式
例子里完整的测试代码:


function Each(list, fun){
    
for (var i = 0, len = list.length; i < len; i++) { fun(list[i], i); }
};
var objs = $("idNum").getElementsByTagName("li");
var tv = new TransformView("idTransformView""idSlider"1683,  {
    onStart : 
function(){ Each(objs, function(o, i) { o.className = tv.Index == i ? "on" : ""; }) }//按钮样式
});
tv.Start();
Each(objs, 
function (o, i){
    o.onmouseover 
= function(){
        o.className 
= "on";
        tv.Auto 
= false;
        tv.Index 
= i;
        tv.Start();
    }
    o.onmouseout 
= function(){
        o.className 
= "";
        tv.Auto 
= true;
        tv.Start();
    }
})

源码:


var $ = function (id) {
    
return "string" == typeof id ? document.getElementById(id) : id;
};
var Class = {
  create: 
function() {
    
return function() {
      
this.initialize.apply(this, arguments);
    }
  }
}
Object.extend 
= function(destination, source) {
    
for (var property in source) {
        destination[property] 
= source[property];
    }
    
return destination;
}
var TransformView = Class.create();
TransformView.prototype 
= {
  
//容器对象,滑动对象,切换参数,切换数量
  initialize: function(container, slider, parameter, count, options) {
    
if(parameter <= 0 || count <= 0return;
    
var oContainer = $(container), oSlider = $(slider), oThis = this;
    
this.Index = 0;//当前索引
    
    
this._timer = null;//定时器
    this._slider = oSlider;//滑动对象
    this._parameter = parameter;//切换参数
    this._count = count || 0;//切换数量
    this._target = 0;//目标参数
    
    
this.SetOptions(options);
    
    
this.Up = !!this.options.Up;
    
this.Step = Math.abs(this.options.Step);
    
this.Time = Math.abs(this.options.Time);
    
this.Auto = !!this.options.Auto;
    
this.Pause = Math.abs(this.options.Pause);
    
this.onStart = this.options.onStart;
    
this.onFinish = this.options.onFinish;
    
    oContainer.style.overflow 
= "hidden";
    oContainer.style.position 
= "relative";
    
    oSlider.style.position 
= "absolute";
    oSlider.style.top 
= oSlider.style.left = 0;
  },
  
//设置默认属性
  SetOptions: function(options) {
    
this.options = {//默认值
        Up:            true,//是否向上(否则向左)
        Step:        5,//滑动变化率
        Time:        10,//滑动延时
        Auto:        true,//是否自动转换
        Pause:        2000,//停顿时间(Auto为true时有效)
        onStart:    function(){},//开始转换时执行
        onFinish:    function(){}//完成转换时执行
    };
    Object.extend(
this.options, options || {});
  },
  
//开始切换设置
  Start: function() {
    
if(this.Index < 0){
        
this.Index = this._count  1;
    } 
else if (this.Index >= this._count){ this.Index = 0; }
    
    
this._target = 1 * this._parameter * this.Index;
    
this.onStart();
    
this.Move();
  },
  
//移动
  Move: function() {
    clearTimeout(
this._timer);
    
var oThis = this, style = this.Up ? "top" : "left", iNow = parseInt(this._slider.style[style]) || 0, iStep = this.GetStep(this._target, iNow);
    
    
if (iStep != 0) {
        
this._slider.style[style] = (iNow + iStep) + "px";
        
this._timer = setTimeout(function(){ oThis.Move(); }, this.Time);
    } 
else {
        
this._slider.style[style] = this._target + "px";
        
this.onFinish();
        
if (this.Auto) { this._timer = setTimeout(function(){ oThis.Index++; oThis.Start(); }, this.Pause); }
    }
  },
  
//获取步长
  GetStep: function(iTarget, iNow) {
    
var iStep = (iTarget  iNow) / this.Step;
    
if (iStep == 0return 0;
    
if (Math.abs(iStep) < 1return (iStep > 0 ? 1 : 1);
    
return iStep;
  },
  
//停止
  Stop: function(iTarget, iNow) {
    clearTimeout(
this._timer);
    
this._slider.style[this.Up ? "top" : "left"= this._target + "px";
  }
};

下载测试代码