AS3 滚动条脚本的问题

Problems with AS3 scrollbar script

我在 adobe flash 中有这个滚动条符号:

深色部分的实例名称为handle,浅色部分的实例名称为bar。该符号是 Scroll class:

的实例
package ui {
    import flash.display.MovieClip;
    import flash.events.MouseEvent;
    
    public class Scroll extends MovieClip{
        public static const VERTICAL = 0; 
        public static const HORIZONTAL = 1;
        protected var _handleRatio = 1;
        protected var _orientation = VERTICAL;
        protected var _mousePrevPos:int;
        protected var _handleMargin:int;
        protected var _container:MovieClip;
        protected var _containerInitialPosition:int; //added after update #2

        public function Scroll(container:MovieClip, visibleLength:int, orientation:int = VERTICAL) {
            _orientation = orientation;
            _container = container;
            
            var containerLength:int;
            switch(_orientation){
                case VERTICAL:
                    rotation = 0;
                    containerLength = container.height;
                    _containerInitialPosition = container.y; //added after update #2
                    break
                
                case HORIZONTAL:
                    rotation = - 90;
                    containerLength = container.width;
                    _containerInitialPosition = container.x; //added after update #2
                    break;
                
                default:
                    throw new Error('Unknown orientation');
                    break;
            }
            
            if((_handleRatio = visibleLength/containerLength) > 1)
                _handleRatio = 1;
            
            handle.height = _handleRatio*height;
            
            _handleMargin = handle.y;
            
            handle.addEventListener(MouseEvent.MOUSE_DOWN, _startDrag, false, 0, true);
        }
        
        protected function _startDrag(e:MouseEvent){
            stage.addEventListener(MouseEvent.MOUSE_UP, _stopDrag, false, 0, true);
            stage.addEventListener(MouseEvent.MOUSE_MOVE, _dragHandle, false, 0, true);
            _mousePrevPos = mouseY;
        }
        
        protected function _stopDrag(e:MouseEvent = null){
            stage.removeEventListener(MouseEvent.MOUSE_UP, _stopDrag);
            stage.removeEventListener(MouseEvent.MOUSE_MOVE, _dragHandle);
            _mousePrevPos = NaN;
        }
        
        protected function _dragHandle(e:MouseEvent){
            _moveHandle(mouseY - _mousePrevPos);
            _mousePrevPos = mouseY;
        }
        
        protected function _moveHandle(moveDifference:int){
            if(moveDifference > 0 && !(handle.y + handle.height + _handleMargin > bar.height)){
                if(!(handle.y + handle.height + moveDifference + _handleMargin > bar.height))
                    handle.y = handle.y + moveDifference;
                else
                    handle.y = bar.height - handle.height - _handleMargin;
            }
            
            if(moveDifference < 0 && !(handle.y < _handleMargin)){
                if(!(handle.y + moveDifference < _handleMargin))
                    handle.y += moveDifference;
                else
                    handle.y = _handleMargin;
            }
            
            switch(_orientation){
                case VERTICAL:
                    _container.y = _containerInitialPosition -((handle.y-_handleMargin)/(bar.height-_handleMargin*2)*_container.height);
                    // since update #2, the calculated y position is subtracted from the initial y position
                    break
                
                case HORIZONTAL:
                    _container.x = _containerInitialPosition -((handle.y-_handleMargin)/(bar.height-_handleMargin*2)*_container.width);
                    // since update #2, the calculated x position is subtracted from the initial x position
                    break;
                
                default:
                    throw new Error('Unknown orientation');
                    break;
            }
        }
        
        public function resize(newWidth, newHeight){
            switch(_orientation){
                case VERTICAL:
                    width = newWidth;
                    height = newHeight;
                    break
                
                case HORIZONTAL:
                    rotation = 0;
                    width = newHeight;
                    height = newWidth;
                    rotation = -90;
                    break;
                
                default:
                    throw new Error('Unknown orientation');
                    break;
            }
        }
        
        public function scrollHandle(e:MouseEvent){
            _moveHandle(-e.delta);
        }
    }
    
}

如您所见,您可以创建水平和垂直滚动条。现在,滚动条有两个问题:

  1. 由于某些原因,当用鼠标拖动手柄up/left时,手柄的移动速度远比光标慢
  2. 另外,水平滚动条稍微向右滚动时,容器的左边部分被截断,无法再回滚已解决现在,查看更新 #2

我真的不知道是什么导致了这些问题,所以任何人都可以帮助我或者至少指出我的代码中的错误在哪里?

更新

一些有助于解释代码的额外信息:


这是需要垂直滚动条的情况的草图。滚动条将像这样启动:

var scrollBar:Scroll = new Scroll(container, mask.height, Scroll.VERTICAL);

当滚动条的手柄向下 dragged/scrolled 时,容器会向上移动,这样您就可以看到容器的下半部分 - 反之亦然:如果向上滚动,容器会向上移动向下移动。

如果您想创建一个水平滚动条,除了将 Scroll.VERTICAL 更改为 Scroll.HORIZONTAL 之外,您还需要将 mask.width 作为 visibleLength 而不是 mask.height.

我想 container 不一定是 MovieClip 但可以是任何 DisplayObject.

此外,我没有使用 startDrag(),因此我可以通过一种方法 (_moveHandle()) 拖动手柄并上下滚动手柄。

更新 #2

我解决了问题#2:容器的左边部分被切断了,因为当容器还没有滚动时,容器的 x 位置在舞台中间的某个地方。当它向右滚动一点时,我忘记将容器的x位置设置为计算出的x位置+初始x位置。我更新了上面的代码,在新部分后面添加了注释,这样您就可以看到我所做的更改。

更新 #3

您可以在此处查看使用滚动条的 Flash 文件:http://host.undeadzone.net/scrollBarTest.swf

要重现问题 #1,请执行以下操作:

  1. 用鼠标抓住手柄,慢慢向下拖动滑块,可以注意到鼠标相对于滑块的位置保持不变。 (如果您单击手柄的最上边缘开始拖动,当手柄到达屏幕底部时,鼠标仍将位于最上边缘。这是预期的行为,一切都很好。
  2. 现在反其道而行之(松开鼠标也没关系 完成步骤 1) 后,慢慢向上拖动手柄。这次, 鼠标相对于手柄的位置发生变化。如果一个人在手柄的最顶部边缘开始拖动并开始 向上拖动,手柄没有跟上鼠标和 鼠标位置(相对于手柄)将在手柄上方 拖动后,即使它在 手柄。

源代码:
http://host.undeadzone.net/scrollBarTest.zip

要解决第一个问题,请添加 e.updateAfterEvent:

protected function _dragHandle(e:MouseEvent){
    _moveHandle(mouseY - _mousePrevPos);
    _mousePrevPos = mouseY;
    e.updateAfterEvent();
}

更新

mouseY returns Number 不是 int。 替换此行:

protected var _mousePrevPos:int;

有了这个:

protected var _mousePrevPos:Number;

Scroll class.

更新 #2

替换

protected function _moveHandle(moveDifference:int){

protected function _moveHandle(moveDifference:Number){