我们终于找到了解决方案,如果有人遇到同样的问题:
1)由于对
this._$svgElement
的平移和在代码完全不同的部分计算
vpx
,该元素处于像素之间(例如x为
100.88945px)。这会导致线条变模糊。我通过一个简单的
Math.round()来修复这一部分。
this._hammerCanvas.on('panmove', (event: any) => {
const translate3d = 'translate3d(' + Math.round(this._oldDeltaX + ((vpx === imgData.x) ? 0 : vpx) + event.deltaX) + 'px, ' + Math.round(this._oldDeltaY + ((vpy === imgData.y) ? 0 : vpy) + event.deltaY) + 'px, 0)';
this._$svgElement.css({
transform: translate3d
});
}
2) 为了解决SVG视口和线条粗细之间的问题,我不得不实现一种方法,计算描边宽度等于1个“真实”像素,关于SVG的尺寸。
更新后的代码如下:(这是从服务器加载SVG后的初始代码。在缩放中,上面的旧代码仍然相同)
const pixelRatio = devicePixelRatio || 1;
const widthRatio = this._initSVGWidth / svgContainerWidth;
const heightRatio = this._initSVGHeight / svgContainerHeight;
this._svgZoomFactor = Math.max(widthRatio, heightRatio);
const strokeWidth1px = this.computeStrokeWidth1px(widthRatio, heightRatio);
for (let i = 0; i < svgPaths.length; ++i) {
this._initalStrokeWidth[i] = parseFloat($(svgPaths[i]).css('stroke-width'));
const newStrokeWidth = Math.max(strokeWidth1px / pixelRatio, this._svgZoomFactor * this._initalStrokeWidth[i]);
$(svgPaths[i])[0].setAttribute('style', 'stroke-width:' + newStrokeWidth);
this._oldStrokeWidth[i] = newStrokeWidth;
}
和计算机相关:
protected computeStrokeWidth1px (widthRatio: number, heightRatio: number): number {
const viewBox = this._$svgElement[0].getAttribute('viewBox').split(' ');
const viewBoxWidthRatio = parseFloat(viewBox[2]) / this._$svgElement.width();
const viewBoxHeightRatio = parseFloat(viewBox[3]) / this._$svgElement.height();
return widthRatio > heightRatio ? viewBoxWidthRatio : viewBoxHeightRatio;
}
vector-effect="non-scaling-stroke"
。MDN引用:non-scaling-stroke
是一个预定义的矢量效果关键字,它使得对象的描边宽度不受变换和缩放的影响。 - enxanetashape-rendering="crispEdges"
? - Flash Thunder