如何绘制不受缩放和缩放影响的线

时间:2018-01-06 12:37:37

标签: javascript html5-canvas fabricjs

我正在尝试构建一个应用程序,用户可以在其中添加各种对象(矩形,圆形),并且可以使用鼠标滚轮缩放 -in和缩小。

对于这种缩放我设置了这样的事件处理程序:

    TheCanvas.on('mouse:wheel', function(options){

        var p = new fabric.Point(
            options.e.clientX,
            options.e.clientY
        );
        var direction = (options.e.deltaY > 0) ? 0.9 : 1.1;
        var newZoom = TheCanvas.getZoom() * direction;

        // restrict too big/small zoom here:
        if ((newZoom > 50) || (newZoom < 0.7)) return false;

        TheCanvas.zoomToPoint( p, newZoom );
    }

到目前为止一切正常。现在我想在画布上的所有对象上绘制十字准线。像这样:

enter image description here

所以我创建了自己的自定义对象:

CrossHairClass = fabric.util.createClass(fabric.Object, {
    strokeDashArray: [1,2], // I want lines to be dashed
    ........

我的问题是:

当用户使用鼠标滚轮进行缩放时,我的十字线也会缩放它们的厚度,并且小破折号会变大。但我不想要那个。我希望我的十字线是一个&#34;头发&#34; line =理想情况下,无论画布的缩放系数如何,都始终为1像素。还有很好的虚线。

渲染我的班级的功能:

    _render: function (ctx) {

        // I tried it like this
        var zoom = TheCanvas.getZoom();
        var scale = (1/zoom) * 3.333; // with this scale it visually looked the best

        // I have to scale it in X and Y while I want small dashes to stay small and also thickness of the line to stay "hair-line"
        this.scaleX = this.scaleY = scale;

        this.width = CROSSHAIR_SIZE / scale; // my constant from elsewhere

        ctx.lineWidth = 1;
        ctx.beginPath();

        // this example is for horizontal line only
        ctx.moveTo(-this.width / 2, 0);
        ctx.lineTo(this.width / 2, 0);
        this._renderStroke(ctx);
    }

我尝试了按比例因子或缩放因子进行乘法或除法的各种组合,但如果我最终将线条变薄,我就无法保持其大小,无论画布缩放如何,都必须保持不变(以像素为单位)。请帮忙。

P.S。:现在我有了一个主意。也许我应该在我当前的画布上创建另一个画布并在上部画布上绘制这个十字准线,它不会缩放?

编辑1

根据@andreabogazzi的回答,我尝试了各种方法,但这终于成功了!谢谢! :)

_render: function (ctx) {

    var zoom = TheCanvas.getZoom();

    // ctx.save(); // this made no difference

    // ctx.setTransform(1/zoom, 0, 0, 1/zoom, 0, 0); // this didn't work
    this.setTransformMatrix([1/zoom, 0, 0, 1/zoom, 0, 0]);

    ctx.strokStyle = 'red';
    ctx.lineWidth = 1;

    ctx.beginPath();
    ctx.moveTo(-this.widthHalf, 0); // widthHalf computed elsewhere
    ctx.lineTo(this.widthHalf, 0);

    this._renderStroke(ctx); // I use this instead of ctx.stroke() while this ensures my line is still nicely dashed

    // ctx.restore(); // this made no difference
}

1 个答案:

答案 0 :(得分:2)

由于您创建了自定义类,因此在绘制之前,可以反转画布的缩放

在子类的_render函数上,由于您应该位于十字准线的中心,因此应用比例因子的变换矩阵,比例因子为1/zoomLevel,一切都应该有效。< / p>

我会说正确的方法是:

_render: function (ctx) {

    var zoom = TheCanvas.getZoom();

    ctx.save(); // this is done anyway but if you add custom ctx transform is good practice to wrap it in a save/restore couple

    ctx.transform(1/zoom, 0, 0, 1/zoom, 0, 0);
    ctx.strokStyle = 'red';
    ctx.lineWidth = 1;

    ctx.beginPath();
    ctx.moveTo(-this.widthHalf, 0); // widthHalf computed elsewhere
    ctx.lineTo(this.widthHalf, 0);

    this._renderStroke(ctx); // I use this instead of ctx.stroke() while this ensures my line is still nicely dashed
    ctx.restore(); // this is done anyway but if you add custom ctx transform is good practice to wrap it in a save/restore couple
}

现在碰巧这个对象从fabricJS缓存系统缓存,它可能会根据画布缩放创建缓存。

我不了解此对象的最终用法,但您应该在缓存画布大小计算中包含此计算。