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);
}
}
}
如您所见,您可以创建水平和垂直滚动条。现在,滚动条有两个问题:
- 由于某些原因,当用鼠标拖动手柄up/left时,手柄的移动速度远比光标慢
另外,水平滚动条稍微向右滚动时,容器的左边部分被截断,无法再回滚已解决现在,查看更新 #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) 后,慢慢向上拖动手柄。这次,
鼠标相对于手柄的位置发生变化。如果一个人在手柄的最顶部边缘开始拖动并开始
向上拖动,手柄没有跟上鼠标和
鼠标位置(相对于手柄)将在手柄上方
拖动后,即使它在
手柄。
要解决第一个问题,请添加 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){
我在 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);
}
}
}
如您所见,您可以创建水平和垂直滚动条。现在,滚动条有两个问题:
- 由于某些原因,当用鼠标拖动手柄up/left时,手柄的移动速度远比光标慢
另外,水平滚动条稍微向右滚动时,容器的左边部分被截断,无法再回滚已解决现在,查看更新 #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) 后,慢慢向上拖动手柄。这次, 鼠标相对于手柄的位置发生变化。如果一个人在手柄的最顶部边缘开始拖动并开始 向上拖动,手柄没有跟上鼠标和 鼠标位置(相对于手柄)将在手柄上方 拖动后,即使它在 手柄。
要解决第一个问题,请添加 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){