如何让线宽不管怎么缩放画布,都保持渲染为 1px

我们需要的效果

画布缩放,就是用滚轮放大或缩小整个画布,会导致画布中的图形变大会变小,虽然我们没有改图形的属性值。

实现上是 修改图形树根节点的 matrix 矩阵,这个其实就是视图矩阵,作用是把场景坐标转换为视口坐标。

画布缩放,会让图形的线宽在渲染上也发生变化。

比如图形的线宽为 1px,如果画布放大为 2 倍,线宽也会渲染为原来的两倍。如果画布缩小为原来的一半,线宽也会跟随变成 0.5px(抗锯齿,变成颜色比较浅的线)。

我们希望无论怎么缩放画布,线宽永远保持不变,为 1px。

为什么需要这个效果?

  1. 绘制选中图形的高亮轮廓线。做法通常是复制一份图形,fill 丢掉,stroke 的颜色改成高亮色,然后线宽不能随画布缩放改变

  2. 可用于类 CAD 的绘制线框图形的编辑器。这类编辑器注重的是图形的形状,图形是基于线条,也希望画布缩放前后线宽不变。

SVG 下的做法

SVG 就非常方便,我们只要给图形节点的样式设置为:

 

arduino

代码解读

复制代码

vector-effect: non-scaling-stroke;

就可以了。

我给矩形添加属性 vector-effect="non-scaling-stroke",圆形保持不变,对比看看效果。

也可以写成全局的。

 

arduino

代码解读

复制代码

svg * {   vector-effect: non-scaling-stroke; }

strokeWidth 不强制要求为 1px,可以设置为任意你希望的像素值。

图形库

SVG 在图形很多的时候性能不太好,我们选择基于 Canvas 实现的图形库。

有些图形库是支持类似效果的。

比如性能非常强的图形库 Pixijs7,可以这样写:

 

javascript

代码解读

复制代码

const rect = new Graphics()   .lineStyle(1, 0xffffff, undefined, undefined, true)   .drawRect(20, 20, 200, 100);

lineStyle 方法的最后一个参数 native 如果为 true,就会使用 LINES 模式而不是 TRIANGLE_STRIP 模式。

同样给矩形应用效果,和没有应用效果的圆形对比,效果如下:

遗憾的是,strokeWidth 不管设置为多少,渲染的都是 1px,这是 WebGL 特性带来的效果。

另外,Pixi.js 8 目前不支持这个特性,因为还没把 pixi.js 7 的全部功能都迁移完成。大概是因为要兼容 WebGPU 的原因。

paperjs 可以这样设置:

 

ini

代码解读

复制代码

paper.project.currentStyle.strokeScaling = false;

其它都就不知道了,读者可自行查阅官方文档。

数据层修改

上面是从渲染器层面着手的,SVG 支持这种特性,所以我们才能做到线宽不变。

如果你的渲染器不支持这个特性,只能从数据层修改了。

当画布缩放值 zoom 发生改变时,要修改图形的 strokeWidth 为真实值的 1 / zoom 倍

假设图形 strokeWidth 为 1,zoom 为 2,strokeWidth 就会渲染为 2。你说,诶,我把图形 stokeWidth值设置为 0.5,那放大 2 倍,渲染出来的线宽还是 1,这样也实现了渲染 strokeWidth 不变的效果。

这样就保持 strokeWidth 不变了,缺点是会破坏图形的缓存,需要重新做三角化。

不适用于有大量图形的场景。

还有一种就是计算图形的所有场景坐标系点,转换为视口坐标系的点,然后放到在视口坐标容器上,因为 zoom 永远为 1,此时 strokeWidth 设置为 1px 即可。

原文链接:https://juejin.cn/post/7419248237733445684

### 回答1: QGraphicsItem是Qt中的一个类,用于在图形场景中绘制2D图形对象。线宽是QGraphicsItem中一个可调整的属性,用于定义绘制线条的宽度。缩放是另一个属性,用于调整绘制对象的大小。 在QGraphicsItem中,可以通过设置线宽属性来改变绘制线条的粗细。可以使用setPen方法来设置线条的颜色和宽度。例如,可以通过以下代码将线条宽度设置为2个像素: QPen pen; pen.setWidth(2); item->setPen(pen); 通过设置线宽,可以调整绘制对象的外观,以便更好地满足设计需求。 缩放是另一个重要的操作,可以通过设置QGraphicsItem的缩放属性来调整绘制对象的大小。可以使用setScale方法来设置缩放因子,该因子指定了对象在水平和垂直方向上的缩放倍数。例如,可以使用以下代码将对象在水平和垂直方向上都缩放为原来的一半: item->setScale(0.5); 通过缩放功能,可以实现图形对象的放大和缩小效果,以及实现不同尺寸的图形对象的显示。 QGraphicsItem的线宽缩放属性是灵活的,可以根据具体需求进行调整。通过设置线宽缩放属性,我们可以实现绘制具有不同外观和大小的图形对象,以满足不同的图形设计要求。 ### 回答2: QGraphicsItem中的线宽缩放是指在对图形项进行缩放操作时,其边界线的宽度是否也会相应地进行缩放。 QGraphicsItem是Qt中用于绘制2D图形的基类,它提供了丰富的绘图功能。在进行缩放操作时,QGraphicsItem会根据其当前的缩放因子对图形进行相应的缩放,包括图形的位置、大小和旋转角度等。 在默认情况下,QGraphicsItem的线宽不会随着缩放而改变,也就是说,在缩放过程中,图形项的线宽保持不变。这是为了保持图形的清晰度和边界的一致性。 然而,如果我们希望在缩放过程中同时改变线宽,我们可以通过以下步骤实现: 1. 在创建QGraphicsItem的时候,设置其属性QGraphicsItem::ItemIgnoresTransformations,这样它就会忽略缩放操作对其的影响。 2. 重写QGraphicsItem的paint()函数,在函数中根据当前的缩放因子和线宽比例绘制图形。可以通过调用pen()方法获取当前的画笔对象,并设置其线宽。 这样,在进行缩放操作时,图形项的线宽也会相应地进行缩放,保证了图形的比例和线宽的一致性。 总而言之,QGraphicsItem中的线宽缩放是可以实现的,只需要通过设置属性和重写绘制函数的方式来实现。这样可以根据实际需求来调整图形项在缩放线宽的变化。 ### 回答3: QGraphicsItem 的线宽是指在绘制图形元素时所使用的线条的宽度。默认情况下,线宽为0,即不可见。 在QGraphicsItem 中,可以通过 setPen() 函数来设置线宽。可以传入一个 QPen 对象,通过设置其线宽属性来修改线宽的大小。例如,可以使用 setWidth() 函数来设置线宽的大小。较大的线宽将会生成更宽的线条,而较小的线宽则会生成更细的线条。 线宽缩放可以通过 setScale() 函数来实现。该函数可以对图形元素进行缩放操作。通过设置缩放因子,可以将图形元素的大小进行相应的缩放。当缩放因子为1时,图形元素保持原始大小。当缩放因子大于1时,图形元素放大;当缩放因子小于1时,图形元素缩小。 需要注意的是,QGraphicsItem 会维护一个绘制的轮廓区域,而不是实际的几何形状。当进行缩放操作时,线宽也会相应地进行缩放。因此,线宽缩放是相对于图形元素的轮廓区域而言的,而不是相对于实际几何形状。 总之,QGraphicsItem 的线宽可以通过设置 QPen 的宽度属性来修改,较大的线宽将会生成更宽的线条,而较小的线宽则会生成更细的线条。线宽缩放可以通过设置缩放因子来实现,相应地缩放线宽和图形元素的大小。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值