【问题标题】:Stroke quality/anti-aliasing with svgsvg 的描边质量/抗锯齿
【发布时间】:2014-09-29 00:42:12
【问题描述】:

我正在尝试使用 svgs 制作动画语音气泡,但我注意到笔划上的抗锯齿缺乏清晰度并且有明显的污迹。我已经尝试通过四舍五入来解决这个问题,但这只会让污迹变得更糟——我该怎么做才能得到 1px 粗的黑线?

HTML:

<div id="inset">
    <svg id="svg" width="100%" height="100%"></svg>
</div>

CSS:

body, html {
    width: 100%;
    height: 100%;
    border: 0;
    padding: 0;
    margin: 0;
}

#inset {
 width: 20%;
 height: 50%;
 position: absolute;
 bottom: 0;
 left: 50%;
}

#svg {
}

Javascipt:

$(function() {

    var sponsorBubble = function(el, html, cornerRad) {
        this.html = html,
        this.width = el.parent().width(),
        this.x_center = (el.parent().width()/2),
        this.height = el.parent().height(),
        this.arrowWidth = (el.parent().width()/4),
        this.arrowHeight = (el.parent().height()/8),
        this.cornerRad = cornerRad,
        this.arrowRad = this.cornerRad/3,
        this.arrowControlRatio = this.arrowRad * ((this.arrowWidth/2 - (this.arrowRad*2)) / (this.arrowHeight - (this.arrowRad*2)));

        var bubble = s.path(
            "M" +
            Math.round(this.x_center)
            + ", " +
            Math.round(this.height)
            + ", Q" +
            Math.round(this.x_center - this.arrowRad)
            + ", " +
            Math.round(this.height)
            + ", " +
            Math.round(this.x_center - this.arrowRad)
            + ", " +
            Math.round(this.height - this.arrowRad)
            + ", Q" +
            Math.round(this.x_center - this.arrowRad)
            + ", " +
            Math.round(this.height - (this.arrowRad*2))
            + ", " +
            Math.round(this.x_center)
            + ", " +
            Math.round(this.height - (this.arrowRad*2))
            + ", Q" +
            Math.round(this.x_center + this.arrowRad)
            + ", " +
            Math.round(this.height - (this.arrowRad*2))
            + ", " +
            Math.round(this.x_center + this.arrowRad)
            + ", " +
            Math.round(this.height - this.arrowRad)
            + ", Q" +
            Math.round(this.x_center + this.arrowRad)
            + ", " +
            Math.round(this.height)
            + ", " +
            Math.round(this.x_center)
            + ", " +
            Math.round(this.height)
            + ", Z"
        );

        bubble.attr({ 
            stroke: 'black',
            fill: 'none'
        });

        bubble.animate({
            d:
                "M" + 
                Math.round(this.x_center)
                + ", " +
                Math.round(this.height)
                + ", Q" +
                Math.round(this.x_center - this.arrowRad + this.arrowControlRatio)
                + ", " +
                Math.round(this.height)
                + ", " +
                Math.round(this.x_center - this.arrowRad)
                + ", " +
                Math.round(this.height - this.arrowRad)
                + ", L" +
                Math.round(this.x_center - (this.arrowWidth/2) + this.arrowRad)
                + ", " +
                Math.round(this.height - this.arrowHeight + this.arrowRad)
                + ", Q" +
                Math.round(this.x_center - (this.arrowWidth/2) + this.arrowRad - this.arrowControlRatio)
                + ", " +
                Math.round(this.height - this.arrowHeight)
                + ", " +
                Math.round(this.x_center - (this.arrowWidth/2))
                + ", " +
                Math.round(this.height - this.arrowHeight)
                + ", L" +
                Math.round(this.cornerRad)
                + ", " +
                Math.round(this.height - this.arrowHeight)
                + ", Q" +
                0
                + ", " +
                Math.round(this.height - this.arrowHeight)
                + ", " +
                0
                + ", " +
                Math.round(this.height - this.arrowHeight - this.cornerRad)
                + ", L" +
                0
                + ", " +
                Math.round(this.cornerRad)
                + ", Q" +
                0
                + ", " +
                0
                + ", " +
                Math.round(this.cornerRad)
                + ", " +
                0
                + ", L" +
                Math.round(this.width - this.cornerRad)
                + ", " +
                0
                + ", Q" +
                Math.round(this.width)
                + ", " +
                0
                + ", " +
                Math.round(this.width)
                + ", " +
                Math.round(this.cornerRad)
                + ", L" +
                Math.round(this.width)
                + ", " +
                Math.round(this.height - this.arrowHeight - this.cornerRad)
                + ", Q" +
                Math.round(this.width)
                + ", " +
                Math.round(this.height - this.arrowHeight)
                + ", " +
                Math.round(this.width - this.cornerRad)
                + ", " +
                Math.round(this.height - this.arrowHeight)
                + ", L" +
                Math.round(this.x_center + (this.arrowWidth/2))
                + ", " +
                Math.round(this.height - this.arrowHeight)
                + ", Q" +
                Math.round(this.x_center + (this.arrowWidth/2) - this.arrowRad + this.arrowControlRatio)
                + ", " +
                Math.round(this.height - this.arrowHeight)
                + ", " +
                Math.round(this.x_center + (this.arrowWidth/2) - this.arrowRad)
                + ", " +
                Math.round(this.height - this.arrowHeight + this.arrowRad)
                + ", L" +
                Math.round(this.x_center + this.arrowRad)
                + ", " +
                Math.round(this.height - this.arrowRad)
                + ", Q" +
                Math.round(this.x_center + this.arrowRad - this.arrowControlRatio)
                + ", " +
                Math.round(this.height)
                + ", " +
                Math.round(this.x_center)
                + ", " +
                Math.round(this.height)
                + ", Z"
            }, 
            100
        );

    };


s = Snap('#svg');

var bubble_obj = new sponsorBubble($('#svg'), "test_content", 15);
});

jdfiddle: http://jsfiddle.net/L5k48hwm/

【问题讨论】:

    标签: javascript jquery svg snap.svg


    【解决方案1】:
    svg path { // or rect, circle, etc
        shape-rendering: crispEdges;
    }
    

    话虽如此,您可以尝试使用 jQuery UI .animate() 创建类似 jsfiddle 示例的效果(反转此动画以匹配您的规格)。这避免了复杂的路径生成和更平滑的线条。

    更新:这里是代码 sn-p。

    $('div').append('<svg xmlns:svg="http://www.w3.org/2000/svg" xmlns="http://www.w3.org/2000/svg" version="1.1" x="0.00000000" y="0.00000000" width="100%" height="100%" id="svg3" viewbox="0 0 1000 600" >  <path fill="#FFFFFF" stroke="#000000" stroke-width="10" d="M916.902,397.331c14.126,0,17.344-9.739,17.344-9.739   c0-27.635,7.992-42.357,26.927-42.357c0,0,13.702,1.668,13.702-14.946c0-0.001,0.619-43.408-1.901-141.244   c-2.514-97.836-9.537-109.333-9.537-109.333c0-14.125-9.129-13.284-9.129-13.284c-24.67,0-53.406,4.151-53.406-30.893   c0,0,1.558-11.866-15.041-11.866c0,0-159.78-14.301-423.823-14.301c-264.041,0-375.12,2.352-375.12,2.352   c-14.125,0-13.284,9.136-13.284,9.136c0,22.479-13.575,42.622-30.319,42.622c0,0-13.705,0.341-13.705,16.949   c0,0-4.551,60.914-4.551,117.724c0,56.808,4.551,126.899,4.551,126.899c0,14.125,9.127,13.28,9.127,13.28   c24.9,0,29.944,10.568,29.944,30.322c0,0,1.038,15.744,25.709,15.744l248.677,5.155c0,0,46.81,25.855,64.76,39.665   c17.952,13.808,27.714,26.235,12.526,41.426c-6.669,6.666-11.966,12.474-9.571,21.187c2.277,8.256,26.797,22.168,29.903,23.746   c0.261,0.127,61.957,30.323,84.796,41.37c16.646,8.047,33.288,16.074,49.292,25.362c2.152,1.253,14.271,9.614,16.804,7.089   c2.484-2.479-11.174-12.959-12.823-14.315c-9.084-7.442-16.206-16.462-24.158-25.027c-12.481-13.465-25.133-26.788-37.746-40.133   c-7.044-7.464-13.884-15.167-21.144-22.43c-1.791-1.79-1.476-4.571,0.699-7.001c7.682-8.531,25.246-28.013,27.384-30.14   c2.739-2.731-1.814-7.121-1.814-7.121l-62.959-51.678L916.902,397.331z"/>  </svg>');
    
    $('div').draggable({
        handle: 'rect'
    });
    
    $('div').animate({
        width: "500px",
        height: "300px",
        top: "0px",
        left: "0px"
    }, 2000).animate({
        width: "100px",
        height: "60px",
        top: "240px",
        left: "230px"
    }, 2000);
    <script src="//ajax.googleapis.com/ajax/libs/jquery/1.11.1/jquery.min.js"></script>
    <script src="//ajax.googleapis.com/ajax/libs/jqueryui/1.9.2/jquery-ui.min.js"></script>
    <div style="width:100px; height:60px; border:solid thin #888; padding:0px; border-radius:4px; background-color:yellow; top:240px; left:230px">
    </div>

    【讨论】:

    • 虽然我很感激付出的努力,但这根本不能回答我的问题。我不是在寻求帮助来制作语音气泡(有一百万种方法可以做到这一点),我试图让我的 svg 线条看起来更干净(形状渲染也不能解决这个问题)。
    • 啊,你想要的是一个不断增长的气泡,但路径 stroke-width 保持相同的厚度(并且平滑),因此你的路径生成算法。在您的代码中使用'stroke-width': '3',您可以看到它在某些区域变厚。想...
    • 你试过Snap.path.toCubic(pathString)函数吗?路径生成函数还会在底部产生一个奇怪的旋转(慢到 2000 毫秒的动画,你会看到它)。
    • 是的,我也注意到了奇怪的旋转......不知道如何解决它。也许我需要在中间有另一个中间帧?
    【解决方案2】:

    我认为要获得漂亮的弯角,您需要做两件事:

    1. 改进路径生成算法。这是因为当您放大 SVG 时,您可以看到拐角处的路径宽度变大。我没有时间或专业知识来帮助解决这个问题。
    2. 尝试为shape-rendering CSS property 使用不同的值。它们可以为您提供更清晰的渲染。

    【讨论】:

    • 我不是特别指弯曲的角落,而是整体缺乏围绕形状的实体跟踪。路径的一两个像素内有太多的灰色阴影,而我真的更喜欢整个过程中只有一条粗壮的 1px 粗线。我尝试了不同的形状渲染值,但没有一个能真正解决边缘强度问题。
    猜你喜欢
    • 1970-01-01
    • 2011-03-03
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2014-02-18
    • 1970-01-01
    • 2014-01-04
    • 1970-01-01
    相关资源
    最近更新 更多