【问题标题】:Scale and move drawing using KineticJs使用 KineticJs 缩放和移动绘图
【发布时间】:2013-08-22 23:09:38
【问题描述】:

我无法使用 KineticJs 正确缩放绘图。我有一个由多个 Kinetic 绘图对象组成的绘图,这些对象都保存在一个组中。我正在尝试做的是对绘图的长度进行调整,如果新长度超过某个阈值,那么绘图将被重新缩放。

到目前为止,它运行良好。重新缩放按预期工作,但我在再次居中绘图时遇到问题。正在计算绘图的原点,我正在尝试使用

移动它
    drawingGroup.move(newOrigin.x, newOrigin.y)

初始原点大约为 200 像素。当绘图开始重新缩放时,此值为 0,但随着图像继续缩小,它开始从屏幕左侧滑落。

我还没有找到一个很好的例子来调整绘图的长度,然后缩放、调整大小和居中新绘图。有什么好办法吗?

【问题讨论】:

    标签: javascript html html5-canvas kineticjs


    【解决方案1】:

    如何缩小你的小组以适应舞台,即使小组扩大了

    此图显示了起始的“蓝色”组 - 未加宽且未缩放。

    此图显示了蓝色组已扩大到舞台之外并缩小后。

    以下是在不向左“浮动”的情况下缩小群组的方法:

    • 撤消任何先前的组偏移量(按任何先前缩放因子的量)。
    • 计算新的比例因子(例如:按比例缩小)。
    • 保存新的缩放因子以供将来进行缩放。
    • 根据新的缩放因子计算新的组偏移量。
    • 将组的偏移量设置为新缩放的偏移量。
    • 重绘图层。

    您需要向 drawingGroup 添加几个与缩放相关的属性:

    // the current SCALED offset
    drawingGroup.offsetX=0;
    drawingGroup.offsetY=0;
    
    // the point from which all scaling will occur
    drawingGroup.scalePtX=0;
    drawingGroup.scalePtY=0;
    
    // the amount of current scaling applied to the group
    // ==1.00 is the beginning un-scaled group
    // >1.00 scales the group larger
    // <1.00 scales the group smaller
    drawingGroup.scaleFactor=1.00;
    

    然后将此方法添加到 drawingGroup 以实际进行缩放:

    drawingGroup.scaleBy=function(scaleChange){
    
        // undo previous offset
        this.offsetX += this.scalePtX/this.scaleFactor;
        this.offsetY += this.scalePtY/this.scaleFactor;
    
        // calc new scaling factor
        var newScaleFactor = this.scaleFactor*(1+scaleChange);
    
        // create new offset
        this.offsetX -= this.scalePtX/newScaleFactor;
        this.offsetY -= this.scalePtY/newScaleFactor;
    
        // set new scale factor
        this.scaleFactor=newScaleFactor;
    
        // do the new offset
        this.setOffset(this.offsetX,this.offsetY);
    
        // do the new scale
        this.setScale(this.scaleFactor);
    
        layer.draw();
    
    };
    

    这是一个测试代码,既扩大了组的范围,又自动缩小它以适应舞台:

    此测试代码还在缩减后重新定位组。

        // widen by 20px
        // if wider than stage, scale down by 15%
        $("#wider").click(function(){
            drawingGroup.setWidth(drawingGroup.getWidth()+20);
            rect.setWidth(drawingGroup.getWidth());
            var width=drawingGroup.getWidth()*drawingGroup.scaleFactor;
            if(drawingGroup.getX()+width>stageWidth){
                drawingGroup.scaleBy(-0.15);
                recenter();
            }
            setStatus();
            layer.draw();
        });
    
        function recenter(){
            var w=drawingGroup.getWidth()*drawingGroup.scaleFactor;
            var h=drawingGroup.getHeight()*drawingGroup.scaleFactor;
            drawingGroup.setX(stage.getWidth()/2-w/2);
            drawingGroup.setY(stage.getHeight()/2-h/2);
        }
    

    请注意,setX()/setY() 可以正常用于组。

    请务必通过乘以 scalingFactor 来计算 scaled 组的宽度/高度。

    这是完整的代码和小提琴:http://jsfiddle.net/m1erickson/UyDbW/

    <!DOCTYPE html>
    <html>
      <head>
        <meta charset="utf-8">
        <script type="text/javascript" src="http://code.jquery.com/jquery.min.js"></script>
        <script src="http://d3lp1msu2r81bx.cloudfront.net/kjs/js/lib/kinetic-v4.5.4.min.js"></script>
    
    <style>
    body{ padding:15px; }
    #container{
      border:solid 1px #ccc;
      margin-top: 10px;
      width:300px;
      height:300px;
    }
    </style>        
    <script>
    $(function(){
    
        var stage = new Kinetic.Stage({
          container: 'container',
          width: 300,
          height: 300
        });
        var layer = new Kinetic.Layer();
        stage.add(layer);
    
        // objects used in jquery events
        var drawingGroup;
        var rect,circle;
        var stageWidth=stage.getWidth();
        var stageHeight=stage.getHeight();
    
    
        drawingGroup=new Kinetic.Group({
            x:stageWidth/2-50,
            y:stageHeight/2-50,
            width:100,
            height:100,
        });
        drawingGroup.offsetX=0;
        drawingGroup.offsetY=0;
        drawingGroup.scalePtX=0;
        drawingGroup.scalePtY=0;
        drawingGroup.scaleFactor=1.00;
        drawingGroup.scaleBy=function(scaleChange){
    
            // undo previous offset
            this.offsetX += this.scalePtX/this.scaleFactor;
            this.offsetY += this.scalePtY/this.scaleFactor;
    
            // calc new scaling factor
            var newScaleFactor = this.scaleFactor*(1+scaleChange);
    
            // create new offset
            this.offsetX -= this.scalePtX/newScaleFactor;
            this.offsetY -= this.scalePtY/newScaleFactor;
    
            // set new scale factor
            this.scaleFactor=newScaleFactor;
    
            // do the new offset
            this.setOffset(this.offsetX,this.offsetY);
    
            // do the new scale
            this.setScale(this.scaleFactor);
    
            layer.draw();
    
        };
        layer.add(drawingGroup);
    
        var rect=new Kinetic.Rect({
            x:0,
            y:0,
            width:100,
            height:100,
            stroke:"lightgray",
            fill:"skyblue"
        });
        drawingGroup.add(rect);
    
        var circle=new Kinetic.Circle({
            x:50,
            y:50,
            radius:20,
            fill:"blue"
        });
        drawingGroup.add(circle);
    
        var status=new Kinetic.Text({
            x:15,
            y:15,
            text:"width=100, scale=1.00",
            fontSize:18,
            fill:"red"
        });
        layer.add(status);
    
        setStatus();
    
        layer.draw();
    
        function setStatus(){
            var width=drawingGroup.getWidth();
            var scale=Math.round(drawingGroup.scaleFactor*100);
            status.setText("Width: "+width+", Scale: "+scale+"%");
        }
    
    
        // widen by 20px
        // if wider than stage, scale down by 15%
        $("#wider").click(function(){
            drawingGroup.setWidth(drawingGroup.getWidth()+20);
            rect.setWidth(drawingGroup.getWidth());
            var width=drawingGroup.getWidth()*drawingGroup.scaleFactor;
            if(drawingGroup.getX()+width>stageWidth){
                drawingGroup.scaleBy(-0.15);
                recenter();
            }
            setStatus();
            layer.draw();
        });
    
        function recenter(){
            var w=drawingGroup.getWidth()*drawingGroup.scaleFactor;
            var h=drawingGroup.getHeight()*drawingGroup.scaleFactor;
            drawingGroup.setX(stage.getWidth()/2-w/2);
            drawingGroup.setY(stage.getHeight()/2-h/2);
        }
    
    
    }); // end $(function(){});
    
    </script>       
    </head>
    
    <body>
        <p>Blue group will scale if extending past stage</p>
        <button id="wider">Wider</button>
        <div id="container"></div>
    </body>
    </html>
    

    【讨论】:

    • 这与我要找的很接近。不同之处在于,每次绘图组的长度扩展时,我都会尝试在重绘图层时重新定位图层内的图像。你知道这样做的好方法吗?
    • 我编辑了我的答案,以便在缩小组后重新定位该组。请注意,您可以在组上正常使用 setX/setY。但是,getWidth/getHeight 将报告未缩放的值,因此您必须将该宽度/高度乘以 drawingGroup 的 scaleFactor 以获得缩放的尺寸。
    • 我有这个问题的更新。我想做的是调整绘图的长度并随着每个增量重新缩放绘图。我想让绘图以 y 轴为中心,但绘图应设置为距舞台左侧 20 像素。使用增量/减量时,我无法使缩放正常工作。有没有办法让它工作?
    • 我已经设置了一个小提琴,显示我希望结果在这里jsfiddle.net/tctruckscience/rsEyA/15。与我目前正在尝试做的不同之处在于,绘图在绘制之前已经被缩放。例如,它的长度为 9900,屏幕尺寸为 1060,因此每个比例单位的像素为 1060/9900 = 0.10707。但是,当绘制图像时,比例设置为 1。如果将 100 添加到绘图长度,则计算为 1060/10000 = 0.106,但在这种情况下我无法正确计算比例。有没有办法让它工作?
    • 第 1 部分:您可以通过将组的 X 位置设置为 20 并且不调用recenter 轻松修复组的左侧位置(尽管您要求我为您放入recenter ![咧嘴笑])。第 2 部分:我不是 SURE 您要问什么,但如果您想将矩形保持在固定宽度,您需要计算缩放组宽度所需的 scaleFactor == 您想要的宽度(originalWidth/newWidth)...然后将相同的 scaleFactor 应用于高度。注意:由于您的内容可能不会以这种“人为固定”的因素进行缩放,因此当缩放更大时,您的内容可能会落在容器矩形之外。
    猜你喜欢
    • 2012-09-19
    • 2014-08-13
    • 2012-08-31
    • 1970-01-01
    • 2013-08-09
    • 2013-05-31
    • 2013-08-04
    • 1970-01-01
    • 2012-09-28
    相关资源
    最近更新 更多