【问题标题】:Zoom and Pan in KineticJSKineticJS 中的缩放和平移
【发布时间】:2012-09-19 22:58:53
【问题描述】:

有没有一种方法可以使用 KineticJS 在画布上进行缩放和平移?我找到了这个库kineticjs-viewport,但只是想知道是否有任何其他方法可以实现这一点,因为这个库似乎使用了很多额外的库,并且不确定哪些是完成工作绝对必要的。

另外,我什至愿意在感兴趣的区域周围绘制一个矩形并放大该特定区域。关于如何实现这一目标的任何想法?一个 JSFiddle 的例子会很棒!

【问题讨论】:

    标签: javascript viewport kineticjs


    【解决方案1】:

    这些答案似乎不适用于 KineticJS 5.1.0。这些主要不适用于 scale 函数的签名更改:

     stage.setScale(newscale); --> stage.setScale({x:newscale,y:newscale});
    

    但是,以下解决方案似乎适用于 KineticJS 5.1.0:

    JSFiddle:http://jsfiddle.net/rpaul/ckwu7u86/3/

    【讨论】:

      【解决方案2】:

      我实际上是写了 kineticjs-viewport。很高兴听到您对此感兴趣。

      它实际上不仅仅用于拖动。它还允许缩放和以性能为中心的剪辑。剪辑区域之外的东西根本不会被渲染,因此即使您有一个包含大量对象的巨大图层,您也可以获得出色的渲染性能。

      这就是我的用例。例如,您可以通过较小的视口区域查看大型 RTS 地图——想想星际争霸。

      我希望这会有所帮助。

      【讨论】:

      【解决方案3】:

      不幸的是,设置状态或图层可拖动会阻止对象不可拖动。 Duopixel 的缩放方案不错,但我宁愿将它设置为舞台级别,而不是图层级别。

      她是我的解决方案

      var stage = new Kinetic.Stage({
          container : 'container',
          width: $("#container").width(),
          height: $("#container").height(),
      });
      var layer = new Kinetic.Layer();
      
      //layer.setDraggable("draggable");
      var center = { x:stage.getWidth() / 2, y: stage.getHeight() / 2};
      
      var circle = new Kinetic.Circle({
          x: center.x-100,
          y: center.y,
          radius: 50,
          fill: 'green',
          draggable: true
      });
      layer.add(circle);
      layer.add(circle.clone({x: center.x+100}));
      
      // zoom by scrollong
      document.getElementById("container").addEventListener("mousewheel", function(e) {
        var zoomAmount = e.wheelDeltaY*0.0001;
        stage.setScale(stage.getScale().x+zoomAmount)
        stage.draw();
        e.preventDefault();
      }, false)
      
      // pan by mouse dragging on stage
      stage.on("dragstart dragmove", function(e) {window.draggingNode = true;});
      stage.on("dragend", function(e) { window.draggingNode = false;});
      $("#container").on("mousedown", function(e) {
          if (window.draggingNode) return false;
          if (e.which==1) {
              window.draggingStart = {x: e.pageX, y: e.pageY, stageX: stage.getX(), stageY: stage.getY()};
              window.draggingStage = true;
          }
      });
      $("#container").on("mousemove", function(e) {
          if (window.draggingNode || !window.draggingStage) return false;
          stage.setX(window.draggingStart.stageX+(e.pageX-window.draggingStart.x));
          stage.setY(window.draggingStart.stageY+(e.pageY-window.draggingStart.y));
          stage.draw();
      });
      $("#container").on("mouseup", function(e) { window.draggingStage = false } );
      
      stage.add(layer);
      

      http://jsfiddle.net/bighostkim/jsqJ2/

      【讨论】:

        【解决方案4】:

        您可以简单地将.setDraggable("draggable") 添加到图层中,只要光标下有对象,您就可以拖动它。您可以添加一个大而透明的rect 以使所有内容都可以拖动。可以通过设置图层的比例来实现缩放。在此示例中,我通过鼠标滚轮控制它,但它只是一个函数,您可以在其中传递要缩放的量(正放大,负缩小)。代码如下:

        var stage = new Kinetic.Stage({
            container: "canvas",
            width: 500,
            height: 500
        });
        
        var draggableLayer = new Kinetic.Layer();
        draggableLayer.setDraggable("draggable");
        
        //a large transparent background to make everything draggable
        var background = new Kinetic.Rect({
            x: -1000,
            y: -1000,
            width: 2000,
            height: 2000,
            fill: "#000000",
            opacity: 0
        });
        
        draggableLayer.add(background);
        
        
        //don't mind this, just to create fake elements
        var addCircle = function(x, y, r){
          draggableLayer.add(new Kinetic.Circle({
                x: x*700,
                y: y*700,
                radius: r*20,
                fill: "rgb("+ parseInt(255*r) +",0,0)"
            })
          );
        }
        
        var circles = 300
        while (circles) {
          addCircle(Math.random(),Math.random(), Math.random())
          circles--;
        }
        
        var zoom = function(e) {
          var zoomAmount = e.wheelDeltaY*0.001;
          draggableLayer.setScale(draggableLayer.getScale().x+zoomAmount)
          draggableLayer.draw();
        }
        
        document.addEventListener("mousewheel", zoom, false)
        
        stage.add(draggableLayer)
        

        http://jsfiddle.net/zAUYd/

        【讨论】:

        • 这很好用,除了在 IE9 中。你知道为什么吗?调试控制台也不会抛出任何错误...
        • 如果我使用 e.wheelDelta 而不是 e.wheelDeltaY 看起来它可以工作。知道为什么吗?
        • 我认为 IE 使用 deltaY。鼠标滚轮缩放只是一个示例,如果您打算保留它,那么您应该使用一个 shim 来弥补浏览器实现中的差异,例如 github.com/cobbweb/jquery-mousewheel
        • 很好,一个问题是如果图层是可拖动的,那么该图层上的对象虽然设置为可拖动,但不能拖动。你知道有什么方法可以设置只有背景可以拖动吗?
        • jsfiddle : jsfiddle.net/zAUYd 不再起作用,无论是在 FF 还是 Chrome 上。你能更新一下吗?
        【解决方案5】:

        这是缩放和平移图层的非常快速和简单的实现。如果您有更多需要同时平移和缩放的图层,我建议将它们分组,然后将 on("click") 应用于该组以获得相同的效果。

        http://jsfiddle.net/renyn/56/

        如果不明显,点击左上角浅蓝色方块放大缩小,点击左下粉红色方块左右平移。

        编辑:请注意,这当然可以更改为支持“mousedown”或其他事件,我不明白为什么不能将转换实现为 Kinetic.Animations 以使其更平滑。

        【讨论】:

        • 太棒了!这正是我想要的。我尝试在舞台上使用鼠标事件,但运气不佳,所以我很想问你 - 你能指导我更多关于支持 mousedown 事件和支持更流畅的动画吗?
        • 我不建议将它们应用到整个舞台上,这样可以毫无偏见地捕获所有鼠标事件。尝试像我一样将它们分配给单个形状。我不确定您究竟需要什么指导,但 Kinetic 的 API 和教程非常有用。
        • 我并不感到惊讶,5.0.0 和 5.0.1 与 4.0.2 相比有很多重大变化。
        • 您能更新答案中提到的 jsfiddle 吗?它不再工作了(Firefox、Chrome)
        【解决方案6】:

        这是我到目前为止所做的......希望它会对你有所帮助。

        http://jsfiddle.net/v1r00z/ZJE7w/

        【讨论】:

          【解决方案7】:

          当我今天与 Kinetic 合作时,我发现了一个您可能感兴趣的 SO question

          我知道作为评论会更好,但我没有足够的代表,无论如何,我希望这会有所帮助。

          【讨论】:

            猜你喜欢
            • 2014-08-13
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 2013-05-31
            • 2012-03-19
            • 2020-04-05
            • 2015-08-08
            • 2013-12-12
            相关资源
            最近更新 更多