ActionScript 3 缩放和滚动问题
ActionScript 3 Issues with zooming and scrolling
我正在使用 TransformGestureEvent、StartDrag 和 StopDrag 事件,但遇到了一些问题。
我会尽力解释,当我放大时,我的图像放大并在放大时居中。放大后,我开始拖动到图像的顶部,当我到达顶部时,我现在无法滚动更多(到目前为止一切都按预期工作)但是当我缩小图像时,y 轴不再位于顶部,我的图片应该是空白的 space。
这是我的代码:
mapMC.addEventListener(TransformGestureEvent.GESTURE_ZOOM, zoom);
mapMC.addEventListener(MouseEvent.MOUSE_DOWN, dragStart);
mapMC.addEventListener(MouseEvent.MOUSE_UP, dragEnd);
//Zooming Method
function zoom (event:TransformGestureEvent):void{
var locX:Number=event.localX;
var locY:Number=event.localY;
var stX:Number=event.stageX;
var stY:Number=event.stageY;
var prevScaleX:Number=mapMC.scaleX;
var prevScaleY:Number=mapMC.scaleY;
var mat:Matrix;
var externalPoint=new Point(stX,stY);
var internalPoint=new Point(locX,locY);
mapMC.scaleX *= event.scaleX;
mapMC.scaleY *= event.scaleY;
if(mapMC.scaleX > 6){
mapMC.scaleX=prevScaleX;
mapMC.scaleY=prevScaleY;
}
if(mapMC.scaleY > 6){
mapMC.scaleX=prevScaleX;
mapMC.scaleY=prevScaleY;
}
if(mapMC.scaleX < 1){
mapMC.scaleX=1;
mapMC.scaleY=1;
}
if(mapMC.scaleY < 1){
mapMC.scaleX=1;
mapMC.scaleY=1;
}
mat=mapMC.transform.matrix.clone();
MatrixTransformer.matchInternalPointWithExternal(mat,internalPoint,externalPoint);
mapMC.transform.matrix=mat;
}
//Dragging Start Method
function dragStart(e:MouseEvent):void
{
mapMC.startDrag(false, new Rectangle(0,0,-mapMC.width + stage.stageWidth, -mapMC.height + stage.stageHeight));
}
//Dragging Stop Method
function dragEnd(e:MouseEvent):void
{
mapMC.stopDrag();
}
我期望发生的事情是在中心放大,能够在我的 startDrag 中的矩形内滚动并在中心缩小,同时图像的顶部保持在舞台的顶部和左侧图像停留在舞台的左侧。
我尝试在我的缩放方法中添加这两行代码,它有效但我无法在中心放大:
mapMC.y = 0;
mapMC.x = 0;
这是一个 link 示例项目,它将向您展示我的意思
https://drive.google.com/open?id=0B-p_9V3gzZZTcXpQZzI0RU9ZY0k
由于 Air 的内置触摸手势对此不是很方便,我使用 MultitouchInputMode.TOUCH_POINT
实现了自制的缩放功能。
import flash.events.Event;
import flash.geom.Rectangle;
import flash.events.MouseEvent;
import flash.ui.MultitouchInputMode;
import flash.events.TouchEvent;
import flash.geom.Point;
//Vars
var touchpoints:Array = []
var touch_mode:String = null
var touch_start:Point
var map_start:Point
var map_zoom:Number
var map_width:Number
var map_height:Number
var zoom_startdist:Number
//Config
var max_zoom:Number = 6
var min_zoom:Number = 1
var map_bounds:Rectangle = new Rectangle(0,0,mapMC.width,mapMC.height) // this defines the area in which the map should fit
//Allow Touch Gestures
Multitouch.inputMode = MultitouchInputMode.TOUCH_POINT;
//Zoom and Drag Event Listeners
stage.addEventListener(TouchEvent.TOUCH_BEGIN, touchBegin)
stage.addEventListener(TouchEvent.TOUCH_MOVE, touchMoved)
stage.addEventListener(TouchEvent.TOUCH_END, touchEnd)
// Touch Handlers
function touchBegin(e:TouchEvent){
if(touchpoints.length<2){ // only accept 2 active touchpoints, ignore the 3rd,4th,etc
touchpoints.push({id:e.touchPointID,x:e.stageX,y:e.stageY})
touchpointsChanged()
}
}
function touchMoved(e:TouchEvent){
var touchpoint:Object = getTouchPointById(e.touchPointID) // get current touchpoint...
if(touchpoint){
// ... and update the position
touchpoint.x = e.stageX
touchpoint.y = e.stageY
touchpointMoved()
}
}
function touchEnd(e:TouchEvent){
removeTouchPoint(e.touchPointID)
touchpointsChanged()
}
// Pan & Zoom logic
function touchpointsChanged(){
if(touchpoints.length==1){ // 1 touch point => panning
startPan()
}else if(touchpoints.length==2){ // 2 touch points => zooming
startZoom()
}
}
function startPan(){
touch_mode = 'pan'
touch_start = new Point(touchpoints[0].x,touchpoints[0].y)
map_start = new Point(mapMC.x,mapMC.y)
}
function startZoom(){
touch_mode = 'zoom'
touch_start = getZoomCenter()
zoom_startdist = getZoomDist()
map_start = new Point(mapMC.x,mapMC.y)
map_zoom = mapMC.scaleX
map_width = mapMC.width
map_height = mapMC.height
}
function touchpointMoved(){
switch(touch_mode){
case 'pan':
mapMC.x = map_start.x + touchpoints[0].x - touch_start.x
mapMC.y = map_start.y + touchpoints[0].y - touch_start.y
break
case 'zoom':
var current_scale:Number = map_zoom*getZoomFactor() // get current zoom factor (relative to the previous zoom of the map)
current_scale = Math.min(max_zoom,Math.max(min_zoom,current_scale)) // limit zoom (as defined in -> Config)
mapMC.scaleX = mapMC.scaleY = current_scale
// Set map position to the current center of zoom
var zoom_pos:Point = getZoomCenter()
mapMC.x = map_start.x + zoom_pos.x - touch_start.x
mapMC.y = map_start.y + zoom_pos.y - touch_start.y
// Correct map position regarding the scaling
mapMC.x += -(current_scale-map_zoom)*map_width*((touch_start.x-map_start.x)/map_width)/map_zoom
mapMC.y += -(current_scale-map_zoom)*map_height*((touch_start.y-map_start.y)/map_height)/map_zoom
break
}
// Make sure the map doesnt leave its defined area - see Config (map_bounds)
if(mapMC.x>map_bounds.x)
mapMC.x = map_bounds.x
else if(mapMC.x+mapMC.width<map_bounds.x+map_bounds.width)
mapMC.x = map_bounds.x+map_bounds.width-mapMC.width
if(mapMC.y>map_bounds.y)
mapMC.y = map_bounds.y
else if(mapMC.y+mapMC.height<map_bounds.y+map_bounds.height)
mapMC.y = map_bounds.y+map_bounds.height-mapMC.height
}
// Helper functions
function getTouchPointById(id:int):Object{
for(var i:uint=0;i<touchpoints.length;i++){
if(touchpoints[i].id==id)
return touchpoints[i]
}
return null
}
function removeTouchPoint(id:int){
for(var i:uint=0;i<touchpoints.length;i++){
if(touchpoints[i].id==id){
touchpoints.splice(i,1)
return
}
}
}
function getZoomCenter():Point{
//get the average of the 2 touchpoints
return new Point((touchpoints[0].x+touchpoints[1].x)/2,(touchpoints[0].y+touchpoints[1].y)/2)
}
function getZoomDist():Number{
// calculate the distance between the 2 touchpoints
return getDist(touchpoints[0].x,touchpoints[0].y,touchpoints[1].x,touchpoints[1].y)
}
function getZoomFactor():Number{
// calculate the difference of distance between the 2 touchpoints from when the zoom gesture started
return getZoomDist()/zoom_startdist
}
function getDist(x1:Number,y1:Number,x2:Number,y2:Number){
// pythagoras, yo
var deltaX:Number = x2-x1
var deltaY:Number = y2-y1
return Math.sqrt(deltaX*deltaX + deltaY*deltaY)
}
如果有任何不清楚的地方,请告诉我,我会尝试添加更多评论。
我正在使用 TransformGestureEvent、StartDrag 和 StopDrag 事件,但遇到了一些问题。
我会尽力解释,当我放大时,我的图像放大并在放大时居中。放大后,我开始拖动到图像的顶部,当我到达顶部时,我现在无法滚动更多(到目前为止一切都按预期工作)但是当我缩小图像时,y 轴不再位于顶部,我的图片应该是空白的 space。
这是我的代码:
mapMC.addEventListener(TransformGestureEvent.GESTURE_ZOOM, zoom);
mapMC.addEventListener(MouseEvent.MOUSE_DOWN, dragStart);
mapMC.addEventListener(MouseEvent.MOUSE_UP, dragEnd);
//Zooming Method
function zoom (event:TransformGestureEvent):void{
var locX:Number=event.localX;
var locY:Number=event.localY;
var stX:Number=event.stageX;
var stY:Number=event.stageY;
var prevScaleX:Number=mapMC.scaleX;
var prevScaleY:Number=mapMC.scaleY;
var mat:Matrix;
var externalPoint=new Point(stX,stY);
var internalPoint=new Point(locX,locY);
mapMC.scaleX *= event.scaleX;
mapMC.scaleY *= event.scaleY;
if(mapMC.scaleX > 6){
mapMC.scaleX=prevScaleX;
mapMC.scaleY=prevScaleY;
}
if(mapMC.scaleY > 6){
mapMC.scaleX=prevScaleX;
mapMC.scaleY=prevScaleY;
}
if(mapMC.scaleX < 1){
mapMC.scaleX=1;
mapMC.scaleY=1;
}
if(mapMC.scaleY < 1){
mapMC.scaleX=1;
mapMC.scaleY=1;
}
mat=mapMC.transform.matrix.clone();
MatrixTransformer.matchInternalPointWithExternal(mat,internalPoint,externalPoint);
mapMC.transform.matrix=mat;
}
//Dragging Start Method
function dragStart(e:MouseEvent):void
{
mapMC.startDrag(false, new Rectangle(0,0,-mapMC.width + stage.stageWidth, -mapMC.height + stage.stageHeight));
}
//Dragging Stop Method
function dragEnd(e:MouseEvent):void
{
mapMC.stopDrag();
}
我期望发生的事情是在中心放大,能够在我的 startDrag 中的矩形内滚动并在中心缩小,同时图像的顶部保持在舞台的顶部和左侧图像停留在舞台的左侧。
我尝试在我的缩放方法中添加这两行代码,它有效但我无法在中心放大:
mapMC.y = 0;
mapMC.x = 0;
这是一个 link 示例项目,它将向您展示我的意思
https://drive.google.com/open?id=0B-p_9V3gzZZTcXpQZzI0RU9ZY0k
由于 Air 的内置触摸手势对此不是很方便,我使用 MultitouchInputMode.TOUCH_POINT
实现了自制的缩放功能。
import flash.events.Event;
import flash.geom.Rectangle;
import flash.events.MouseEvent;
import flash.ui.MultitouchInputMode;
import flash.events.TouchEvent;
import flash.geom.Point;
//Vars
var touchpoints:Array = []
var touch_mode:String = null
var touch_start:Point
var map_start:Point
var map_zoom:Number
var map_width:Number
var map_height:Number
var zoom_startdist:Number
//Config
var max_zoom:Number = 6
var min_zoom:Number = 1
var map_bounds:Rectangle = new Rectangle(0,0,mapMC.width,mapMC.height) // this defines the area in which the map should fit
//Allow Touch Gestures
Multitouch.inputMode = MultitouchInputMode.TOUCH_POINT;
//Zoom and Drag Event Listeners
stage.addEventListener(TouchEvent.TOUCH_BEGIN, touchBegin)
stage.addEventListener(TouchEvent.TOUCH_MOVE, touchMoved)
stage.addEventListener(TouchEvent.TOUCH_END, touchEnd)
// Touch Handlers
function touchBegin(e:TouchEvent){
if(touchpoints.length<2){ // only accept 2 active touchpoints, ignore the 3rd,4th,etc
touchpoints.push({id:e.touchPointID,x:e.stageX,y:e.stageY})
touchpointsChanged()
}
}
function touchMoved(e:TouchEvent){
var touchpoint:Object = getTouchPointById(e.touchPointID) // get current touchpoint...
if(touchpoint){
// ... and update the position
touchpoint.x = e.stageX
touchpoint.y = e.stageY
touchpointMoved()
}
}
function touchEnd(e:TouchEvent){
removeTouchPoint(e.touchPointID)
touchpointsChanged()
}
// Pan & Zoom logic
function touchpointsChanged(){
if(touchpoints.length==1){ // 1 touch point => panning
startPan()
}else if(touchpoints.length==2){ // 2 touch points => zooming
startZoom()
}
}
function startPan(){
touch_mode = 'pan'
touch_start = new Point(touchpoints[0].x,touchpoints[0].y)
map_start = new Point(mapMC.x,mapMC.y)
}
function startZoom(){
touch_mode = 'zoom'
touch_start = getZoomCenter()
zoom_startdist = getZoomDist()
map_start = new Point(mapMC.x,mapMC.y)
map_zoom = mapMC.scaleX
map_width = mapMC.width
map_height = mapMC.height
}
function touchpointMoved(){
switch(touch_mode){
case 'pan':
mapMC.x = map_start.x + touchpoints[0].x - touch_start.x
mapMC.y = map_start.y + touchpoints[0].y - touch_start.y
break
case 'zoom':
var current_scale:Number = map_zoom*getZoomFactor() // get current zoom factor (relative to the previous zoom of the map)
current_scale = Math.min(max_zoom,Math.max(min_zoom,current_scale)) // limit zoom (as defined in -> Config)
mapMC.scaleX = mapMC.scaleY = current_scale
// Set map position to the current center of zoom
var zoom_pos:Point = getZoomCenter()
mapMC.x = map_start.x + zoom_pos.x - touch_start.x
mapMC.y = map_start.y + zoom_pos.y - touch_start.y
// Correct map position regarding the scaling
mapMC.x += -(current_scale-map_zoom)*map_width*((touch_start.x-map_start.x)/map_width)/map_zoom
mapMC.y += -(current_scale-map_zoom)*map_height*((touch_start.y-map_start.y)/map_height)/map_zoom
break
}
// Make sure the map doesnt leave its defined area - see Config (map_bounds)
if(mapMC.x>map_bounds.x)
mapMC.x = map_bounds.x
else if(mapMC.x+mapMC.width<map_bounds.x+map_bounds.width)
mapMC.x = map_bounds.x+map_bounds.width-mapMC.width
if(mapMC.y>map_bounds.y)
mapMC.y = map_bounds.y
else if(mapMC.y+mapMC.height<map_bounds.y+map_bounds.height)
mapMC.y = map_bounds.y+map_bounds.height-mapMC.height
}
// Helper functions
function getTouchPointById(id:int):Object{
for(var i:uint=0;i<touchpoints.length;i++){
if(touchpoints[i].id==id)
return touchpoints[i]
}
return null
}
function removeTouchPoint(id:int){
for(var i:uint=0;i<touchpoints.length;i++){
if(touchpoints[i].id==id){
touchpoints.splice(i,1)
return
}
}
}
function getZoomCenter():Point{
//get the average of the 2 touchpoints
return new Point((touchpoints[0].x+touchpoints[1].x)/2,(touchpoints[0].y+touchpoints[1].y)/2)
}
function getZoomDist():Number{
// calculate the distance between the 2 touchpoints
return getDist(touchpoints[0].x,touchpoints[0].y,touchpoints[1].x,touchpoints[1].y)
}
function getZoomFactor():Number{
// calculate the difference of distance between the 2 touchpoints from when the zoom gesture started
return getZoomDist()/zoom_startdist
}
function getDist(x1:Number,y1:Number,x2:Number,y2:Number){
// pythagoras, yo
var deltaX:Number = x2-x1
var deltaY:Number = y2-y1
return Math.sqrt(deltaX*deltaX + deltaY*deltaY)
}
如果有任何不清楚的地方,请告诉我,我会尝试添加更多评论。