超酷滚动公式实现自定义滚动条

作者: egoldy

性质: 原创

阅读次数: 42872

发表时间: 2006-11-10 15:46:28


此教程是webstudio的预计将在11月底出版的新书<<Flash网站建设技术精粹>>第八章最后一节中的内容,以此用作示范,使更多的flash网友了解这本书.webstudio专为此书开设了在线问答版块.同时也希望在此版块中倾听网友的建议和意见,以使我们可以做的更好.




Scrollbar即滚动条,对我们来说再熟悉不过了,从我们开始使用Windows操作系统那一天开始就已经知道滚动条了,它可以帮助我们在较 小的区域内显示更多的内容,这也是它非常实用的主要原因。在我们创建Flash站点时,总会或多或少的用到它。下面将研究滚动条的应用。

1.文本滚动
首先来看一个简单的文本滚动,最简单的滚动就是我们常见的上下箭头,它同样可以达到滚动的效果,如下图所示。

当然你可以任意对它的位置进行变换,它的应用是比较简单的,只是TextField.scroll方法的应用而已。
范例11

演示文件

范例11源文件
booksource/第8章/scrollbar/scroll_external_text.fla

(1)重新创建好了一个FLA文档,将它存为scroll_external_text.fla。
(2)准备两个按钮,例如一个向上和一个向下的MovieClip,这里准备使用的是MovieClip,当然你可以使用按钮。将它们放在第一层上,摆好位置,并在属性面板上分别为其命名为down_btn和up_btn。
(3)选中场景中上的第1帧,按下F9键,打开ActionScript面板,在其中写入如下脚本。

//载入外部文本
var my_lv = new LoadVars();
my_lv.onLoad  = function(success){
    if(success){
        my_txt.text = this.mytext;
        my_txt.setTextFormat(my_fmt);
    }else{
        trace("error load the external files");
    }
}
my_lv.load("hello.txt");
//创建字体各式实例对象
var my_fmt = new TextFormat();
my_fmt.bullet = true;
my_fmt.bold = true;
my_fmt.color ="0x669933";
//创建动态文本并指定文本格式
this.createTextField("my_txt",this.getNextHighestDepth(),10,10,530,120);
my_txt.wordWrap = true;
my_txt.multiline = true;
my_txt.border = true;
//+++++++++++++++++++++++++++++++++++++++++++++++++++++++++
//滚动
//向上滚动
down_btn.onRelease = function(){
    my_txt.scroll--;
}
//向下滚动
up_btn.onRelease = function(){
    my_txt.scroll++;
}
//++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 

前面的一大段代码都是介绍过的内容,最后一段是应用的滚动方式,如my_txt.scroll--和my_txt.scroll++,这两句中的 scroll是TextField的滚动方法,至于++和--实际上相当于my_txt.scroll =my_txt.scroll+1和my_txt.scroll = my_txt.scroll-1。
(4)测试影片,点击按钮MovieClip,文本就可以上下滚动了。
(5)可能你还希望两个滚动按钮能够在被按下去不放时一直让内容不停地滚动,那么只要找一种方法让scroll不断地循环执行就可以了,首选当然是onEnterFrame。
只需要将滚动代码改写如下即可。
范例12

演示文件

范例12源文件
booksouce/第8章/scrollbar/ scroll_external001_text.fla

//滚动
down_btn.onRelease = function() {
    my_txt.scroll--;
    delete onEnterFrame;
};
up_btn.onRelease = function() {
    my_txt.scroll++;
    delete onEnterFrame;
};


down_btn.onPress = function() {
    onEnterFrame = function() {
        my_txt.scroll--;
        
    };
};
up_btn.onPress = function() {
    
    onEnterFrame = function() {
        my_txt.scroll++;
        
    };
}; 

再深入一点,如果需要文本能够支持鼠标的滚轮操作,可你查看webstudio.com.cn上的教程,鼠标滚轮在Flash 7中的应用。
http://www.webstudio.com.cn/tutorial/show.php?id=18

2.超级滚动公式自定义滚动条
我们虽然比较熟悉滚动条,几乎是每天在使用它,但它的制作看上去并不是很简单,虽然Macromedia已在Flash中提供了滚动条组件,但一 方面由于通用性的原因,它的体积大小比较大,另一方面,对于设计师来讲它可能并不适合,通常情况下我们都希望能自已定义一个适合自已设计特点的滚动条。
下面我们就准备来制作一个自定义的滚动条,我做过多个版本的滚动条,经过多次的实验,发现可以将它总结为一个公式来操作,这样无论遇到什么样的滚动条,只要掌握了这个公式,滚动条的制作就自然不是问题了,下面首先分析一下滚动的原理。
滚动条---超级滚动数学公式如下:

滚动内容的位置=内容的起始位置-(滚动百分比×可滚动的区域);
为了方便说明问题,我们把它写成变量表达示如下。
content_position = top_scroll - (percent_scrolled * scrollable)
下面用图来说明这个公式,如下图所示。

下面根据上图所示来分析一下这个公式。
首先需要把要滚动的内容放置在一个MovieClip当中,我们需要用滚动内容的位置,也就是_y来作为滚动的依据,在可视区域,实际上是在滚动内容上加入了一个遮罩,它就是我们的可视区域。
content_position = top_scroll - (percent_scrolled * scrollable)
top_scroll
在上图中我们看到的两条红线的交点就是场景的原点(0,0),那么这里的topscroll就是滚动内容的初始位置,换句话说就是可视区域的位置。如果可视区域在原点位置,那么这个topscroll就是0。
Percent_scrolled
滚动百分比,这个百分比是指在滚动条上dragger所在滚条上位置的百分比,那么如果想求出它的百分比位置是不难的。
Percent_scrolled = (dragger._y-btnup._height)/(scrollbg._height-dragger._height);

Scrollable
可滚动的区域,是指除了用遮罩遮住的区域之外的区域,那么计算出它也很容易。
Scrollable = contentMain._height –maskedView._heigh

也就是使用滚动内容的高度减去遮罩的高度即可。
公式中的各个值已经计算出来了,那么也就得出了conten_position的位置,它实际上就是用滚动条的百分比换算成可滚动区域的位置的百 分比,如果现在你理解了这个公式,那其他的工作就简单了,你只要会更新content_position的位置,就已经会制作自定义的滚动条了。
那么下面就开始着手制作这个滚动条。
范例13

演示文件

范例13源文件
booksource/第8章/scrollbar/scrollbar.fla

(1)新建一个Flash文档。将其命名为scrollbar.fla。
(2)在主场景中分别创建上下按钮、滚动条背景、滚动内容的MovieClip和遮罩,如下图所示布局。


 

在主场景中层的布局如下。

(3)选中actionscript层的第1帧,在这个布局上添写代码,依照公式的原理,你可以试一下在了解了公式的情况下是否可以独立完成它。
代码如下:

function scrolling (){
    //滚动速度
    var moveSpeed = 1;
    var scrollHeight = scrollbg._height;
    //可滚动的区域
    var scrollable = contentMain._height - maskedView._height;
    var top_scroll = contentMain._y;
    //滑块可拖动的区域
    var left = scrollbg._x;
    var top = scrollbg._y;
    var right = scrollbg._x;
    var bottom = scrollbg._y+scrollbg._height-dragger._height;
    //在开始前检测滚动是否可行,如果内容高度不足则不执行滚动,隐藏dragger等,并返回
    if(scrollable <0){
        dragger._visible =false;
        btnup._alpha =50;
        btndown._alpha =50;
        scrollbg._alpha=50;
        btnup.enabled = false;
        btndown.enabled = false;
        return;
    }
    //更新滚动内容的位置,公式的应用
    function updateContentPos(){
        var percent_scrolled =(dragger._y-btnup._height)/(scrollHeight-dragger._height);
        contentMain._y = Math.round(top_scroll -(scrollable * percent_scrolled));
    }
    //拖动滑块
    dragger.onPress = function(){
        startDrag(this,false,left,top,right,bottom);
        this.onMouseMove = function(){
            updateContentPos();
        }
    }
    dragger.onRelease = function(){
        stopDrag();
        delete this.onEnterFrame;
    }
    btnup.onPress = function(){
        this.onEnterFrame = function(){
            //技巧
            dragger._y = Math.max(top,dragger._y-moveSpeed);
            updateContentPos();
        }
    }
    btnup.onRelease = function(){
        delete this.onEnterFrame;
    }
    btndown.onPress = function(){
        this.onEnterFrame = function(){
            dragger._y = Math.min(bottom,dragger._y+moveSpeed);
            updateContentPos();
        }
    }
    btndown.onRelease = function(){
        delete this.onEnterFrame;
    }
    updateContentPos();
}
//调用函数
scrolling(); 

虽然看到上面这么长的代码,但是并不需要担心,因为大部分都是我们常见的简单的功能代码,这里面最为关键的是公式的应用,也就是updateContentPos()。整段代码在做的事情无非就是不断地更新updateContentPos()。
(4)测试影片,如下图所示。

现在你已经能制作自已的滚动条了,你只需要发挥一下设计能力,就会诞生一个自定义的有特色的滚动条了。

3.为自定义滚动条加入缓动
有了上面的范例,要加入easing缓动,就很简单了,对于easing无非就是新位置和老位置的问题,对于当前的滚动条来说,只要在拖动时让contentMain不断地移向新位置就可以了。移动过程就是要加入easing的过程。

范例14

演示文件

范例14源文件
booksource/第8章/scrollbar/scrollbar_ease.fla

针对这个范例的其他操作过程这里就不赘述了,现在直接打开上例中的源文件scrollbar.fla。
选中第1帧,打开ActionScript面板,将其中的代码做一下简单的改写如下。

function scrolling (easing){
    //滚动速度
    var moveSpeed = 1;
    var easingSpeed =10;
    var scrollHeight = scrollbg._height;
    //可滚动的区域
    var scrollable = contentMain._height - maskedView._height;
    var top_scroll = contentMain._y;
    //滑块可拖动的区域
    var left = scrollbg._x;
    var top = scrollbg._y;
    var right = scrollbg._x;
    var bottom = scrollbg._y+scrollbg._height-dragger._height;
    //在开始前检测滚动是否可行,如果内容高度不足则不执行滚动,隐藏dragger等,并返回
    if(scrollable <0){
        dragger._visible =false;
        btnup._alpha =50;
        btndown._alpha =50;
        scrollbg._alpha=50;
        btnup.enabled = false;
        btndown.enabled = false;
        return;
    }
    //更新滚动内容的位置,公式的应用
    function updateContentPos(){
        var percent_scrolled =(dragger._y-btnup._height)/(scrollHeight-dragger._height);
        contentMain.newY = Math.round(top_scroll -(scrollable * percent_scrolled));
    }
    contentMain.onEnterFrame = function()
    {
        if (!easing || easing == undefined)
        {
            this._y = this.newY;
        }
        else
        {
            this._y += (this.newY-this._y)/easingSpeed;
        }
    };

    //拖动滑块
    dragger.onPress = function(){
        startDrag(this,false,left,top,right,bottom);
        this.onMouseMove = function(){
            updateContentPos();
        }
    }
    dragger.onRelease = function(){
        stopDrag();
        delete this.onEnterFrame;
    }
    btnup.onPress = function(){
        this.onEnterFrame = function(){
            //技巧
            dragger._y = Math.max(top,dragger._y-moveSpeed);
            updateContentPos();
        }
    }
    btnup.onRelease = function(){
        delete this.onEnterFrame;
    }
    btndown.onPress = function(){
        this.onEnterFrame = function(){
            dragger._y = Math.min(bottom,dragger._y+moveSpeed);
            updateContentPos();
        }
    }
    btndown.onRelease = function(){
        delete this.onEnterFrame;
    }
    updateContentPos();
}
//调用函数
scrolling(true); 

在这段代吗中所有标红的部分是修改过的,我们在scrolling函数中加入了一个开关,可用来打开和关闭easing。
在updateContentPos()函数中我们把原有的contentMain._y改为contentMain.newY,通过它确定移动的新位置目标。下面的这段代码就是移动到新位置的缓动过程。

contentMain.onEnterFrame = function()
    {
        if (!easing || easing == undefined)
        {
            this._y = this.newY;
        }
        else
        {
            this._y += (this.newY-this._y)/easingSpeed;
        }
}; 

最后通过scrolling(true)传递true给easing来执行缓动,如果不执行缓动,那么newY仍是原值this._y。
这种标准的缓动在前面的第3章就已经有过介绍,现在看上去并不算复杂了,只要理解了原理,就增加了无限的创意空间了。
最后给你留下一点发挥的空间,你可以试试缓动动态载入文本,做一提示,在遮罩时需要应用setMask()方法。如果你实在做不出来,可以访问如下地址提出疑问。
ws-forum:http://www.webstudio.com.cn/forum.

附加内容:
上边的内容为本书原稿内容,下面是应群内网友的要求,特增加如下两个功能.自动滚动和中键滚动.

自动滚动

演示文件

如果你能完成上面的例子,并理解了滚动公式,那现面的问就变得很简单了.

操作方法:
1.    打开scrollbar_ease.fla文件,将其另存为auto_scrollbar_ease.fal
2.    打开后,选中actionscript层,按下F9,打开actionscript面板.我们将在此代码的基础上进行修改.
3.    将原来的代码修改为所下所示:

//copyright by webstudio.com.cn.author by egoldy.
function scrolling(easing, auto) {
    //滚动速度
    var moveSpeed = 1;
    var easingSpeed = 10;
    var scrollHeight = scrollbg._height;
    //可滚动的区域
    var scrollable = contentMain._height-maskedView._height;
    var top_scroll = contentMain._y;
    //滑块可拖动的区域
    var left = scrollbg._x;
    var top = scrollbg._y;
    var right = scrollbg._x;
    var bottom = scrollbg._y+scrollbg._height-dragger._height;
    //在开始前检测我们的滚动是否可滚动,如果内容不足滚动,隐藏dragger等,并返回。
    if (scrollable<0) {
        dragger._visible = false;
        btnup._alpha = 50;
        btndown._alpha = 50;
        scrollbg._alpha = 50;
        btnup.enabled = false;
        btndown.enabled = false;
        return;
    }
    //更新滚动内容的位置。公式的应用    
    function updateContentPos() {
        var percent_scrolled = (dragger._y-btnup._height)/(scrollHeight-dragger._height);
        contentMain.newY = Math.round(top_scroll-(scrollable*percent_scrolled));
        trace(contentMain.newY);
    }
    contentMain.onEnterFrame = function() {
        if (!easing || easing == undefined) {
            this._y = this.newY;
        } else {
            this._y += (this.newY-this._y)/easingSpeed;
        }
    };
    //拖动滑块
    dragger.onPress = function() {
        startDrag(this, false, left, top, right, bottom);
        this.onMouseMove = function() {
            updateContentPos();
        };
    };
    dragger.onRelease = dragger.onReleaseOutside=function () {
        stopDrag();
        delete this.onEnterFrame;
    };
    btnup.onPress = function() {
        this.onEnterFrame = function() {
            //技巧
            dragger._y = Math.max(top, dragger._y-moveSpeed);
            updateContentPos();
        };
    };
    btnup.onRelease = function() {
        delete this.onEnterFrame;
    };
    btndown.onPress = function() {
        this.onEnterFrame = function() {
            dragger._y = Math.min(bottom, dragger._y+moveSpeed);
            updateContentPos();
        };
    };
    btndown.onRelease = function() {
        delete this.onEnterFrame;
    };
    updateContentPos();
    //++++++++++++++++++++++++++++++++++++++++++
    //自动滚动代码段
    if (auto == true) {
        onEnterFrame = function () {
            if (dragger._y<bottom) {
                dragger._y = dragger._y+0.2;
                updateContentPos();
            } else {
                dragger._y = top;
            }
        };
    }
    
}
//调用函数
scrolling(true, true); 

在这段代码中,有两处变化,一处是我们把原来的scrolling(easeing)函数增加了一个参数,变为scrolling(easeing,auto),目的是可以随意的开关,另一处就是自动滚动代码段,我已经标出了自动滚动代码段.

//自动滚动代码段
    if (auto == true) {
        onEnterFrame = function () {
            if (dragger._y<bottom) {
                dragger._y = dragger._y+0.2;
                updateContentPos();
            } else {
                dragger._y = top;
            }
        };
    } 

在变段代码中,如果scrolling(true,true)则开启easing缓动和自动功能,所以在自动滚动代码段中判断auto是否等于true, 如果等于执行自动滚动,因为在scrollbar_ease.fla中我们已经知道了拖动dragger滑块就可以实现滚动,现在要做的就是自动的让 dragger滑块滑动.ok. 通过onEnterFrame的循环,不断的让dragger._y增加,同进调用updateContentPos()函数来更新内容的位置.当 dragger._y到底端bottom时,回到top顶端..
4.    现在就测试吧.J

鼠标中键滚动

演示文件

有了上面的过程,下面的这个过程,我们只是在增加一段代码,操作如下:
1.    打开刚刚完成的auto_scrollbar_ease.fla.将它另存为mouse_scrollbar_ease.fla
2.    打开actionscript面板.修改上面的代码:

//copyright by webstudio.com.cn author by egoldy.
function scrolling(easing, auto, mouse) {
    //滚动速度
    var moveSpeed = 1;
    var easingSpeed = 10;
    var scrollHeight = scrollbg._height;
    //可滚动的区域
    var scrollable = contentMain._height-maskedView._height;
    var top_scroll = contentMain._y;
    //滑块可拖动的区域
    var left = scrollbg._x;
    var top = scrollbg._y;
    var right = scrollbg._x;
    var bottom = scrollbg._y+scrollbg._height-dragger._height;
    //在开始前检测我们的滚动是否可滚动,如果内容不足滚动,隐藏dragger等,并返回。
    if (scrollable<0) {
        dragger._visible = false;
        btnup._alpha = 50;
        btndown._alpha = 50;
        scrollbg._alpha = 50;
        btnup.enabled = false;
        btndown.enabled = false;
        return;
    }
    //更新滚动内容的位置。公式的应用    
    function updateContentPos() {
        var percent_scrolled = (dragger._y-btnup._height)/(scrollHeight-dragger._height);
        contentMain.newY = Math.round(top_scroll-(scrollable*percent_scrolled));
        trace(contentMain.newY);
    }
    contentMain.onEnterFrame = function() {
        if (!easing || easing == undefined) {
            this._y = this.newY;
        } else {
            this._y += (this.newY-this._y)/easingSpeed;
        }
    };
    //拖动滑块
    dragger.onPress = function() {
        startDrag(this, false, left, top, right, bottom);
        this.onMouseMove = function() {
            updateContentPos();
        };
    };
    dragger.onRelease = dragger.onReleaseOutside=function () {
        stopDrag();
        delete this.onEnterFrame;
    };
    btnup.onPress = function() {
        this.onEnterFrame = function() {
            //技巧
            dragger._y = Math.max(top, dragger._y-moveSpeed);
            updateContentPos();
        };
    };
    btnup.onRelease = function() {
        delete this.onEnterFrame;
    };
    btndown.onPress = function() {
        this.onEnterFrame = function() {
            dragger._y = Math.min(bottom, dragger._y+moveSpeed);
            updateContentPos();
        };
    };
    btndown.onRelease = function() {
        delete this.onEnterFrame;
    };
    updateContentPos();
    //++++++++++++++++++++++++++++++++++++++++++
    //自动滚动代码段
    if (auto == true) {
        onEnterFrame = function () {
            if (dragger._y<bottom) {
                dragger._y = dragger._y+0.2;
                updateContentPos();
            } else {
                dragger._y = top;
            }
        };
    }
    //+++++++++++++++++++++++++++++++++++++++++++  
    //中键滚动代码段
    if (mouse == true) {
        var mouseListener = new Object();
        //创建onMouseWheel函数
        mouseListener.onMouseWheel = function(delta) {
            if (dragger._y<bottom) {
                dragger._y += delta+3;
                updateContentPos();
            } else {
                dragger._y = bottom-3;
            }
            if (dragger._y>top) {
                dragger._y += delta;
                updateContentPos();
            } else {
                dragger._y = top;
            }
        };
        Mouse.addListener(mouseListener);
    }
    //++++++++++++++++++++++++++++++++++++++++++++
}
//调用函数
scrolling(true, false, true); 

在这段代码当中,我又改了两处,一处是scrolling函数改为scrolling(ease,auto,mouse),我们设置了三个开关.通过这三个开关基本上可以实现你所有的滚动需求了,同时你可以组合成不同的效果.J
另一处修改就是我们增加了中键滚动代码,所上面代码所示;详细的中键滚动方法你可以参看webstudio教程中心的文章这里. http://www.webstudio.com.cn/tutorial/show.php?id=18
在中键滚动代码中同自动滚动一样,因为dragger._y是公式中的变量,我们要做的是控制dragger._y滑块的位置,然后调用updateContentPos(),来更新内容的滚动.综合所有的过程,我们使用公式最重要的一点是理清了思路,简化了过程.

Ps by egoldy: 个人认为此篇教程有极高的实用性,应说90%的Flash网站上或多或少都要用到滚动.虽然你可以四处下载代码,但真正想要定义一个属于自已的滚动条,也 并不一件很轻松的事,通过此教程,希望能够从理解的角度出发,那定义出你自已风格的滚动格相信不是什么难事了.cheers!

 

源文件下载

讨论此教程
 

服务项目_SERVICE

关于我们

万博思图(北京)信息技术有限公司,专业的flash,flex开发团队,5年经验。公司致力于互联网上的业务的开展,对于互动网站行销,互联网应用程序开发有成熟的解决方案。我们关注互联网市场动态,关注新技术,更注重在新的领域不断探索发现。
万博思图业务内容主要包括企业品牌Flash网站开发,企业形象宣传Flash设计,动画,多媒体演示,Flex企业级应用程序开发,拥有众多成功案例,欢迎来电咨询。
 
COPYRIGHT BY WEBSTUDIO INTERACTIVE DESIGN Co.,Ltd. ALL RIGHTS RESERVED.
公司地址: 北京市朝阳区朝外SOHO D 座727室 邮编: 100026 EMAIL: WEBSTUDIO@WEBSTUDIO.COM.CN
电话: 010-59070059 / 010-86390986-802  手机: 13693660520 传真: 010-59070059-801
京公网安备:110108006741      京ICP备08002333号-4
王先生