AS3滚动条脚本的问题

时间:2015-02-20 22:20:38

标签: actionscript-3 user-interface

我在adobe flash中有一个滚动条的符号:
scrollbar symbol
暗部的实例名称为handle,较亮部分的实例名称为bar。符号是Scroll类的实例:

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. 由于某种原因,当用鼠标向上/向左拖动手柄时,手柄的移动速度远远低于光标
  2. 此外,当您向右滚动一个水平滚动条时,容器的左侧部分会被切断,您无法再滚动回来了现在解决了,请参阅更新#2
  3. 我真的不知道造成这些问题的原因,所以有人可以帮助我,或者至少指出我的代码中的错误在哪里?

    更新

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

    enter image description here
    这是需要垂直滚动条的情况草图。滚动条将按如下方式启动:

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

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

    如果您想要创建水平滚动条,除了将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)并缓慢向上拖动手柄。这次, 鼠标相对于手柄的位置发生变化。如果在手柄的最顶部边缘启动拖动并启动 向上拖动,手柄跟不上鼠标和 鼠标位置(相对于手柄)将位于手柄上方 拖动之后,即使它开始拖动内部 处理
    3. 源代码:
      http://host.undeadzone.net/scrollBarTest.zip

1 个答案:

答案 0 :(得分:1)

要修复第一个问题,请添加e.updateAfterEvent

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

<强>更新

mouseY返回Number而不是int。 替换此行:

protected var _mousePrevPos:int;

用这个:

protected var _mousePrevPos:Number;

Scroll课程中。

更新#2

替换

protected function _moveHandle(moveDifference:int){

protected function _moveHandle(moveDifference:Number){