Svg (snapsvg) 创建一个对话泡泡

Svg (snapsvg) creating a speech bubble

我正在创建一个聊天程序,屏幕上有一些数字在四处移动,与其他人聊天。

我需要完成这个项目的最后一件事是,当有人说某事时,它会被放入一个可扩展的对话泡泡中。

因为我在使用 SVG 方面还很陌生,这是我第一个真正的 "Game" 项目,所以我认为 "Let's use some CSS to make sure that it scales correctly"

所以我做了以下CSS:

    .bubble {
    background-color: #eee;
    border: 2px solid #333;
    border-radius: 5px;
    color: #333;
    display: inline-block;
    font: 16px/24px sans-serif;
    padding: 12px 24px;
    position: relative;
}
.bubble:after,
.bubble:before {
    border-left: 20px solid transparent;
    border-right: 20px solid transparent;
    border-top: 20px solid #eee;
    bottom: -20px;
    content: '';
    left: 50%;
    margin-left: -20px;
    position: absolute;
}

/* Styling for second triangle (border) */

.bubble:before {
    border-left: 23px solid transparent;
    border-right: 23px solid transparent;
    border-top: 23px solid;
    border-top-color: inherit; /* Can't be included in the shorthand to work */
    bottom: -23px;
    margin-left: -23px;
}

但遗憾的是,这没有用。后来我发现是因为 SVG 不支持所有 CSS 属性。所以现在我有点迷路了?我不太确定如何在 SVG 中创建一个可缩放的对话泡泡,我希望你们中的任何一位能好心为我指明正确的方向。

SVG path 我试过了:

我设法创建了一个非常小的 SVG 路径,但是我不确定如何将其变大并填充文本:

    var mesasgeBox = chatSvg.path("M 200.444444444444446,200v-6h10.444444444444446v6h-4l-3.1111111111111107,1.6222222222222236l0.11111111111111072,-1.6222222222222236Z");

没有具体的填充文本的方法,但你可以自己放置并制作动画。

这将创建一个气泡并使文本具有相同的效果。

一个尺度变换,可以写成'sX,Y,CX,CY'。 CX/CY 作为缩放的中心点。 Snap 会自动尝试围绕中心进行缩放(不同于普通的 svg scale(x,y))。

因此 's20,20' 会将元素在 x 和 y 方向上缩放 20。

var b = s.path("M 200.444444444444446,200v-6h10.444444444444446v6h-4l-3.1111111111111107,1.6222222222222236l0.11111111111111072,-1.6222222222222236Z").attr({ fill: 'gray' });

b.animate({ transform: 's10,10' }, 2000)

var t = s.text(190,200,'stuff!').attr({ stroke: 'yellow', fill: 'yellow', transform: 's0.2,0.2'})
t.animate({ transform: 's2,2'}, 2000)

jsfiddle

它只需要根据您想要的外观和任何对齐方式进行调整。

嵌入 div 的短 SVG。 jQuery 用于动画大小+位置。回调用于使单词可见,第二行使用 .fadeIn()

希望对您有所帮助。

$('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"/> <text x="200" y="200" font-size="72" color="blue" id="myText" style="display: none;" >Hello Whosebug</text> <text x="200" y="300" font-size="72" color="blue" id="myText2" style="display: none;" >Delayed text</text> </svg>');

$('div').draggable({
    handle: 'rect'
});

$('div').animate({ // shrink it
    width: "100px",
    height: "60px",
    top: "240px",
    left: "220px"
}, 0) 
.animate({ // animate to full size
    width: "500px",
    height: "300px",
    top: "0px",
    left: "0px"
}, 2000, function() { // show text
    // Animation complete.

     $('#myText').show();
     $('#myText2').fadeIn('slow');
  });
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/jqueryui/1.11.4/jquery-ui.min.js"></script>
<div style="width:500px; height:300px; ">
</div>

在不使用 SnapSVG 的情况下,您可以: 创建一些 SVG(我使用 Illustrator):

    <?xml version="1.0" encoding="utf-8"?>
<!-- Generator: Adobe Illustrator 18.1.1, SVG Export Plug-In . SVG Version: 6.00 Build 0)  -->
<svg version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
     viewBox="0 0 200 115.9" enable-background="new 0 0 150 115.9" xml:space="preserve">
<g>
    <g>
        <linearGradient id="SVGID_1_" gradientUnits="userSpaceOnUse" x1="33.5436" y1="98.5111" x2="92.6585" y2="11.8584">
            <stop  offset="0" style="stop-color:#FFFFFF"/>
            <stop  offset="1" style="stop-color:#D1D3D4"/>
        </linearGradient>
        <path fill="url(#SVGID_1_)" stroke="#000000" stroke-miterlimit="10" d="M138.5,14.8c-7.8-2.2-33.8-3.8-64.7-3.8
            c-31.2,0-57.4,1.6-64.9,3.8c-0.4,0.1-0.8,0.2-1.1,0.4c-0.3,0.1-0.6,0.3-0.7,0.4c-1.5,1-2.4,2.7-2.4,4.6L14,80.4
            c0.3,2.6,1.6,4.4,3.4,5.1c1.7,0.8,5.9,1.6,11.8,2.2l9.7,0.8c6.6,0.4,14.4,0.7,22.8,0.8c-1.2,6.9,0.4,9.1-4,13.3
            c-8.7,8.3-14.1,7.7-14.1,7.7c1.4,0.5,11,1.7,20-4.8c6.9-4.9,6.1-8.4,7.7-16.2c0,0,0,0,0,0c28.4,0,51.8-1.9,54.5-4.3
            c1.4-0.9,2.4-2.6,2.8-4.7l14.6-60.2C143.1,17.5,141.1,15.3,138.5,14.8z"/>
        <g>
            <path fill="#E2E2E2" d="M138.5,14.8c-7.8-2.2-33.8-3.8-64.7-3.8c-31.2,0-57.4,1.6-64.9,3.8c-0.4,0.1-0.8,0.2-1.1,0.4
                c-0.3,0.1-0.6,0.3-0.7,0.4c-0.4,0.2-0.7,0.5-1,0.8c0.1,0,0.2-0.1,0.2-0.1C6.6,16.2,7,16.1,7.4,16c7.5-2.2,33.7-3.8,64.9-3.8
                c30.9,0,56.9,1.6,64.7,3.8c2.6,0.5,4.6,2.7,4.6,5.4L127,81.6c-0.3,1.6-0.9,3-1.8,3.9c0.2-0.1,0.4-0.2,0.5-0.3
                c1.4-0.9,2.4-2.6,2.8-4.7l14.6-60.2C143.1,17.5,141.1,15.3,138.5,14.8z"/>
        </g>
    </g>
</g>
<text id="bubbleText" transform="matrix(1 0 0 1 21.6668 57.9542)" font-family="'MyriadPro-Regular'" font-size="15.3912">POW! Shazaam. </text>
</svg>

通过 JS 操作文本

document.getElementById('bubbleText').textContent = "new text";

使用 SVG 根元素上的 'viewBox' 属性 缩放 SVG

JSFiddle

下面的源代码需要一个位置 (x/y) 来知道出现的位置和文本换行的最大宽度。它是作为插件编写的,因此您可以轻松使用它。我没有优化过,可以通过font-size缓存字母宽度来提高性能。
字体环绕代码基于这里的解决方案 How to either determine SVG text box width, or force line breaks after 'x' characters?

请将插件内的 paper.rect 替换为您喜欢的气泡布局。

Snap.plugin(function (Snap, Element, Paper, glob) {
     Paper.prototype.bubbletext = function (x, y, txt, maxWidth, attributes) {

        var svg = Snap();
        var abc = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ.";
        var preText = svg.text(0, 0, abc);
        preText.attr(attributes);
        var letterWidth = (preText.getBBox().width / abc.length);
        svg.remove();

        var words = txt.split(" ");
        var widthCalc = 0, activeLine = 0, lines=[''];
        for (var letterCount = 0; letterCount < words.length; letterCount++) {

           var l = words[letterCount].length;
           if (widthCalc + (l * letterWidth) > maxWidth) {
              lines.push('');
              activeLine++;
              widthCalc = 0;
           }
           widthCalc += l * letterWidth;
           lines[activeLine] += words[letterCount] + " ";
        }

        var padding = 10;

        var t = this.text(x+padding, y+15+padding, lines).attr(attributes);

        t.selectAll("tspan:nth-child(n+2)").attr({
           dy: "1.2em",
           x: x+padding
        });

        var boxHeight = t.node.clientHeight + (padding * 3);
        var messageBox = this.path("M " + (x-padding) + "," + (y-padding+boxHeight) + "v-" + boxHeight + "h" +  (t.node.clientWidth + (padding*3)) + "v"+boxHeight+"h-6l-9,15l0,-15Z");
        messageBox.attr({
            fill:"rgba(0, 0, 255, .3)"
        });
        t.before(messageBox);
        return t;
     };
  });

var div = document.querySelector('div.wrap');
var bubble = Snap('100%','100%').attr({ viewBox: '0  0 200 200' });;
bubble.bubbletext(0, 0, "Hallo Mike how are you. These text is auto wraped and the bubble size automaticaly. The svg result is also scaleable. Please change this text to test.", 155,
    { "font-size": "15px", "fill": "#000"});
div.appendChild(bubble.node);

CODEPEN

更新

将气泡布局添加到代码笔示例中。

更新 2
我更新源示例。

如果您将 svg heightwidth 设置为 100% svg 节点将响应它的容器并且使用 viewbox 您可以控制视图内部元素;

然后 svg 将对应用于容器的任何缩放做出响应。

pen

您可能不想使用 SVG,除非您显示的其余部分已经以 SVG 为中心。对话泡泡会四处移动以避免遮挡面孔和控件,缩放文本,SVG 文本本身就是受苦的动物。 SVG 的优势仅限于其可扩展性、在 DOM 中进行操作的能力以及需要嵌套转换的应用程序。

而是考虑在纯 CSS as seen here 中制作对话泡泡。或者,您可以预渲染一组语音气泡图形,根据需要进行拉伸,然后在其上书写文本。 Purr CSS 最适合快速弹出窗口,而预渲染图形最适合如果您不希望有小思想泡泡、动画或其他可爱的附加内容。