简体   繁体   English

缩放到KineticJS中的固定点

[英]Scaling to a fixed point in KineticJS

I'm having some problems with scaling a container to a fixed point. 我在将容器缩放到固定点时遇到了一些问题。
In my case I'm trying to scale (zoom) a stage to the mouse cursor. 在我的情况下,我正在尝试将一个舞台缩放(缩放)到鼠标光标。

Here is a way to do with pure canvas: http://phrogz.net/tmp/canvas_zoom_to_cursor.html (as discussed at Zoom Canvas to Mouse Cursor ) 以下是纯画布的一种方法: http//phrogz.net/tmp/canvas_zoom_to_cursor.html (在Zoom Canvas到Mouse Cursor中讨论过)

I just can't get figure out how to apply the same logic while using the KineticJS API. 在使用KineticJS API时,我无法弄清楚如何应用相同的逻辑。

Sample code: 示例代码:

var position = this.stage.getUserPosition();
var scale = Math.max(this.stage.getScale().x + (0.05 * (scaleUp ? 1 : -1)), 0);
this.stage.setScale(scale);
// Adjust scale to position...?
this.stage.draw();

After a lot of struggling and searching and trying, using the tip provided by @Eric Rowell and the code posted in the SO question Zoom in on a point (using scale and translate) I finally got the zooming in and out of a fixed point working using KineticJS . 经过大量的努力和搜索和尝试,使用@Eric Rowell提供的提示和SO问题中发布的代码放大一个点(使用比例和翻译)我终于得到了放大和缩小固定点的工作使用KineticJS

Here's a working DEMO . 这是一个有效的DEMO

And here's the code: 这是代码:

var ui = {
    stage: null,
    scale: 1,
    zoomFactor: 1.1,
    origin: {
        x: 0,
        y: 0
    },
    zoom: function(event) {
        event.preventDefault();
        var evt = event.originalEvent,
            mx = evt.clientX /* - canvas.offsetLeft */,
            my = evt.clientY /* - canvas.offsetTop */,
            wheel = evt.wheelDelta / 120;
        var zoom = (ui.zoomFactor - (evt.wheelDelta < 0 ? 0.2 : 0));
        var newscale = ui.scale * zoom;
        ui.origin.x = mx / ui.scale + ui.origin.x - mx / newscale;
        ui.origin.y = my / ui.scale + ui.origin.y - my / newscale;

        ui.stage.setOffset(ui.origin.x, ui.origin.y);
        ui.stage.setScale(newscale);
        ui.stage.draw();

        ui.scale *= zoom;
    }
};

$(function() {
    var width = $(document).width() - 2,
        height = $(document).height() - 5;
    var stage = ui.stage = new Kinetic.Stage({
        container: 'container',
        width: width,
        height: height
    });
    var layer = new Kinetic.Layer({
        draggable: true
    });
    var rectX = stage.getWidth() / 2 - 50;
    var rectY = stage.getHeight() / 2 - 25;

    var box = new Kinetic.Circle({
        x: 100,
        y: 100,
        radius: 50,
        fill: '#00D200',
        stroke: 'black',
        strokeWidth: 2,
    });

    // add cursor styling
    box.on('mouseover', function() {
        document.body.style.cursor = 'pointer';
    });
    box.on('mouseout', function() {
        document.body.style.cursor = 'default';
    });

    layer.add(box);
    stage.add(layer);

    $(stage.content).on('mousewheel', ui.zoom);
});​

You need to offset the stage such that it's center point is positioned at the fixed point. 您需要偏移舞台,使其中心点位于固定点。 Here's an example, because the center point of the stage is defaulted to the upper left corner of the canvas. 这是一个例子,因为舞台的中心点默认为画布的左上角。 Let's say that your stage is 600px wide and 400px tall, and you want the stage to zoom from the center. 假设你的舞台宽600像素,高400像素,你想让舞台从中心变焦。 You would need to do this: 你需要这样做:

var stage = new Kinetic.Stage({
   container: 'container',
   width: 600,
   height: 400,
   offset: [300, 200]
};

updated @juan.facorro 's demo to scale shape instead of stage 更新@ juan.facorro的演示来缩放形状而不是舞台

jsFiddle 的jsfiddle

var ui = {
    stage: null,
    box: null,
    scale: 1,
    zoomFactor: 1.1,
    zoom: function(event) {
        event.preventDefault();
        var evt = event.originalEvent,
            mx = evt.offsetX,
            my = evt.offsetY,
            wheel = evt.wheelDelta / 120; //n or -n
        var zoom = (ui.zoomFactor - (evt.wheelDelta < 0 ? 0.2 : 0));
        var newscale = ui.scale * zoom;

        var origin = ui.box.getPosition();
        origin.x = mx - (mx - origin.x) * zoom;
        origin.y = my - (my - origin.y) * zoom;

        ui.box.setPosition(origin.x, origin.y);
        ui.box.setScale(newscale);
        ui.stage.draw();

        ui.scale *= zoom;
    }
};

$(function() {
    var width = $(document).width() - 2,
        height = $(document).height() - 5;
    var stage = ui.stage = new Kinetic.Stage({
        container: 'container',
        width: width,
        height: height
    });
    var layer = new Kinetic.Layer();
    var rectX = stage.getWidth() / 2 - 50;
    var rectY = stage.getHeight() / 2 - 25;

    var box = ui.box = new Kinetic.Circle({
        x: 100,
        y: 100,
        radius: 50,
        fill: '#00D200',
        stroke: 'black',
        strokeWidth: 2,
        draggable: true
    });

    // add cursor styling
    box.on('mouseover', function() {
        document.body.style.cursor = 'pointer';
    });
    box.on('mouseout', function() {
        document.body.style.cursor = 'default';
    });

    layer.add(box);
    stage.add(layer);

    $(stage.content).on('mousewheel', ui.zoom);
});

The demo above only works if the x and y coordinates of the stage are 0. If eg the stage is draggable it will change these coordinates while dragging so they need to be included in the offset calculation. 上面的演示仅在舞台的x和y坐标为0时才有效。例如,如果舞台可拖动,它将在拖动时更改这些坐标,因此它们需要包含在偏移计算中。 This can be achieved by subtracting them from the canvas offsets: 这可以通过从画布偏移量中减去它们来实现:

jsfiddle 的jsfiddle

zoom: function(event) {
    event.preventDefault();
    var evt = event.originalEvent,
        mx = evt.offsetX - ui.scale.getX(),
        my = evt.offsetY - ui.scale.getY(),
    var zoom = (ui.zoomFactor - (evt.wheelDelta < 0 ? 0.2 : 0));
    var newscale = ui.scale * zoom;

    var origin = ui.box.getPosition();
    origin.x = mx - (mx - origin.x) * zoom;
    origin.y = my - (my - origin.y) * zoom;

    ui.box.setPosition(origin.x, origin.y);
    ui.box.setScale(newscale);
    ui.stage.draw();

    ui.scale *= zoom;
}

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM