在Flex3中从自定义按钮调用上下文菜单的缩放功能

10
我希望能够从自定义按钮中调用Adobe Flex应用程序中的上下文菜单的缩放功能。
代码类似于这样:
onZoomInButtonClick()
{
this.contextMenu.customItems.zoom.doIn();
}

1
好问题。我认为没有本地解决方案是不可能的。 - Ilya Zaytsev
有没有其他方法进行缩放?我想在AdvancedDataGrid中使用Ctrl +鼠标滚轮进行缩放。 - AsadYarKhan
3个回答

7

据我所知,没有办法通过代码访问Flash播放器的缩放控制命令。

不过,您可以通过在文档类(即舞台下方的最顶层显示对象)中执行以下操作来模拟它:

stage.addEventListener(MouseEvent.MOUSE_WHEEL,mouseWheel,true,2); //listen on the capture phase of the event and give a higher priority than default so it reacts before your grid

function mouseWheel(e:MouseEvent):void {
    if(!e.ctrlKey) return; //Ctrl has to be pressed or we ignore the wheel

    e.stopImmediatePropagation(); //this stops the event from firing on anything else, like your data grid

    var tmpScale:Number = scaleX + (e.delta > 0 ? .2 : -.2); //lets zoom in/out in incriments of 20% (.1)

    if(tmpScale < 1){ //if the scale is less than one now, lets keep it at 1
        tmpScale = 1;
        this.scaleX = 1;
        this.x = 0;
        this.scaleY = 1;
        this.y = 0;
        return;
    }

    if(tmpScale > 4){ //lets set the max to 4
        tmpScale = 4;
    }

    scaleAroundMouse(this,tmpScale);

}

function scaleAroundMouse(objectToScale:DisplayObject, scaleAmount:Number, bounds:Rectangle = null):void {
    // scaling will be done relatively
    var relScaleX:Number = scaleAmount / objectToScale.scaleX;
    var relScaleY:Number = scaleAmount / objectToScale.scaleY;
    // map vector to centre point within parent scope

    var scalePoint:Point = objectToScale.localToGlobal( new Point(objectToScale.mouseX, objectToScale.mouseY));
    scalePoint = objectToScale.parent.globalToLocal( scalePoint );
    // current registered postion AB
    var AB:Point = new Point( objectToScale.x, objectToScale.y );
    // CB = AB - scalePoint, objectToScale vector that will scale as it runs from the centre
    var CB:Point = AB.subtract( scalePoint );
    CB.x *= relScaleX;
    CB.y *= relScaleY;
    // recaulate AB, objectToScale will be the adjusted position for the clip
    AB = scalePoint.add( CB );
    // set actual properties

    if(bounds){
     var limits:Rectangle = new Rectangle(
        bounds.x + (bounds.width - (objectToScale.width * relScaleX)),
        bounds.y + (bounds.height - (objectToScale.height * relScaleY)),
        (objectToScale.width * relScaleX) - bounds.width,
        (objectToScale.height * relScaleY) - bounds.height
     );

     if(AB.x < limits.x) AB.x = limits.x;
     if(AB.x > limits.x + limits.width) AB.x = limits.x + limits.width;
     if(AB.y < limits.y) AB.y = limits.y;
     if(AB.y > limits.y + limits.height) AB.y = limits.y + limits.height;       
    }

    objectToScale.scaleX = scaleAmount;
    objectToScale.scaleY = scaleAmount;
    objectToScale.x = AB.x;
    objectToScale.y = AB.y;
}

谢谢,你的代码几乎可以工作了,但如果这些问题得到解决,它将被标记为答案并且赏金归你。 - AsadYarKhan
请问如何在按下Ctrl键时禁用网格滚动,当我按下Ctrl并在网格上滚动时,它开始垂直滚动而不是缩放。 - AsadYarKhan
1
我已更新代码以解决您上面的第一个请求。您的第二条评论让我有点困惑?这可能与Flash IDE无法正确分派鼠标滚轮事件有关。请参见此链接:https://dev59.com/ilfUa4cB1Zd3GeqPMerG#12570330 - BadFeelingAboutThis
1
你是否正在使用标准的DataGrid组件?spark.components.dataGrid?看起来它有一些奇怪的代码,考虑到它的全局规模。你可以为该组件编写自定义的itemRenderer,这可能会有所帮助。 - BadFeelingAboutThis
1
@AsadYarKhan - 谢谢。我不确定Spark数据网格是否会有任何不同的行为。实际上,我根本不使用Flex组件,但我知道许多组件在缩放时会尝试变得“聪明”。如果你非常决心,你可以编写自己的组件或尝试第三方组件。 - BadFeelingAboutThis
显示剩余8条评论

3

好的,advancedatagrid可以监听键盘事件,当按下ctrl键时,它会监听鼠标滚轮事件并改变比例尺,参见示例:

<?xml version="1.0" encoding="utf-8"?>
<s:Application xmlns:fx="http://ns.adobe.com/mxml/2009" 
               xmlns:s="library://ns.adobe.com/flex/spark" 
               xmlns:mx="library://ns.adobe.com/flex/mx" minWidth="955" minHeight="600">
        <fx:Script>
            <![CDATA[

                protected function doMouseWheel(evt:MouseEvent):void 
                {
                    scaleX = scaleY += evt.delta * 0.1;
                }

                protected function adg_keyDownHandler(event:KeyboardEvent):void
                {
                    if (event.ctrlKey)
                    {
                        systemManager.addEventListener(MouseEvent.MOUSE_WHEEL, doMouseWheel);
                    }
                }

                protected function adg_keyUpHandler(event:KeyboardEvent):void
                {
                    if (!event.ctrlKey)
                    {
                        systemManager.removeEventListener(MouseEvent.MOUSE_WHEEL, doMouseWheel);
                    }
                }

            ]]>
        </fx:Script>    

        <mx:AdvancedDataGrid id="adg" keyDown="adg_keyDownHandler(event)" keyUp="adg_keyUpHandler(event)"
                             horizontalCenter="0" verticalCenter="0">
            <mx:columns>
                <mx:AdvancedDataGridColumn dataField="@label"/>
                <mx:AdvancedDataGridColumn dataField="@data" />
            </mx:columns>
            <mx:dataProvider>
                <s:XMLListCollection id="dp">
                    <s:source>
                        <fx:XMLList>
                            <product label="Product 1" data="3" />
                            <product label="Product 2" data="1" />
                            <product label="Product 3" data="4" />
                            <product label="Product 4" data="1" />
                            <product label="Product 5" data="5" />
                            <product label="Product 6" data="9" />
                        </fx:XMLList>
                    </s:source>
                </s:XMLListCollection>
            </mx:dataProvider>
        </mx:AdvancedDataGrid>

    </s:Application>

缩放并没有产生高质量的结果。我想要缩放功能。 - AsadYarKhan
你认为有差异吗? - Ilya Zaytsev
是的,在缩放中,我们增加对象的宽度和高度,但在缩放中,我们会调整画布,可以参考这个链接:http://superuser.com/questions/153998/whats-the-difference-between-zoom-and-scale-in-gimp。 - AsadYarKhan

2
为了放大/缩小矢量图形,您只需统一更改其scaleXscaleY属性。Flash的矢量渲染器将为您绘制正确的图片。如果要放大位图并避免出现像素化输出,则必须将其转换为矢量图形对象,如下所示:
var sh:Shape=new Shape();
sh.graphics.beginBitmapFill(yourBitmap);
sh.graphics.lineStyle(0,0,0); // to not have border lines
sh.graphics.drawRect(0,0,yourBitmap.width,yourBitmap.height);
sh.graphics.endFill();

然后调整该形状的scaleXscaleY将产生您所需的插值输出。


我的对象是 AdvanceDatagrid 或 Grid。我想要缩放网格而不是位图 :) - AsadYarKhan
你必须深入到基本操作。同时,检查你的数据网格的 cacheAsBitmap 是否为 false。 - Vesper
请解释一下“go down to primitive”的含义? - AsadYarKhan
1
我快速查找了一下Flex中用于显示任何内容的工具,但未能找到任何撕毁引擎的方法,因此不能“降级到原始数据”。但是,您可以控制AdvancedDataGrid对象的cacheHeuristic属性,将其设置为false可能会强制Flex允许Flash图形渲染器按照您所需的方式插值数据网格图像。但是,请首先检查手册有关此和cachePolicy属性的说明。也许将两者都关闭将会产生效果。 - Vesper

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接