在 Raphael 中的路径上附加文本吗?

发布于 2024-08-28 17:40:33 字数 236 浏览 8 评论 0原文

有谁知道如何将文本附加到拉斐尔的路径上?类似于 http://www.w3.org/TR/SVG11/images /text/toap02.svg 我知道 jQuery SVG 可以做到这一点,但我找不到使用 Raphaël js 来做到这一点的简单方法。我想将此文本附加到贝塞尔曲线并移动它。

Does anyone know how to attach a text to a path in Raphaël? Something like http://www.w3.org/TR/SVG11/images/text/toap02.svg
I know that jQuery SVG can do that, but I can't find an easy way to do this by using Raphaël js. I want to attacht this text to a bezier curve and move it.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(3

最美不过初阳 2024-09-04 17:40:33

有两种方法可以做到这一点。

  1. 更简单的方法是使用 Raphael .print()方法。这可以将文本变成路径。每个角色都有自己的道路。然后,您可以迭代每个字符并使用 .translate()< 适当地移动和旋转它/code>.angle()

  2. 更困难的方法是在路径上实现文本 SVG< /a>VML 对于拉斐尔 .text()

这是方法 1 的快速粗略开始,使用 .print()这个字体

window.onload = function() {
    var i, newP,
        R = Raphael("canvas",500,400),

          // Create our set of letter paths
        t = R.print(100, 0, "this is a test", R.getFont("whoa"), 30),

          // Create the path to follow
        p = R.path("M 50 100 C 100 50 150 0 200 50 C 250 100 300 150 350 100" +
                   " C 400 50 450 50 450 50").attr("stroke", "none"),
        pLen = p.getTotalLength(), // Length of path to follow
        tLen = t.length,           // Number of characters
        oneL = pLen/tLen;          // Average length of 1 character
          // You can also use .getBBox() for each character instead       

      // Position each character
    for (i = 0; i < tLen; i++) {

          // Get x,y of the path to follow
        newP = p.getPointAtLength(i * oneL);

          // Move the letter
        t[i].translate((i * oneL)-newP.x, newP.y); 
        t[i].attr("fill", Raphael.getColor());
    }
};​

用这个jsFiddle试试

注意:上面的代码非常粗糙,并且存在一些重要的定位问题,但我认为一般方法是使用 Raphael 将文本放在路径上的方法。

There are 2 ways to do this.

  1. The easier way is to make use of the Raphael .print() method. This can turn text into paths. Each character gets its own path. Then you can iterate over each character and move and rotate it appropriately using .translate() and .angle().

  2. The harder way is to implement text on path for both SVG and VML for a Raphael .text().

Here's a quick and rough start for Method 1 with no rotation using .print() and this font:

window.onload = function() {
    var i, newP,
        R = Raphael("canvas",500,400),

          // Create our set of letter paths
        t = R.print(100, 0, "this is a test", R.getFont("whoa"), 30),

          // Create the path to follow
        p = R.path("M 50 100 C 100 50 150 0 200 50 C 250 100 300 150 350 100" +
                   " C 400 50 450 50 450 50").attr("stroke", "none"),
        pLen = p.getTotalLength(), // Length of path to follow
        tLen = t.length,           // Number of characters
        oneL = pLen/tLen;          // Average length of 1 character
          // You can also use .getBBox() for each character instead       

      // Position each character
    for (i = 0; i < tLen; i++) {

          // Get x,y of the path to follow
        newP = p.getPointAtLength(i * oneL);

          // Move the letter
        t[i].translate((i * oneL)-newP.x, newP.y); 
        t[i].attr("fill", Raphael.getColor());
    }
};​

Try it out with this jsFiddle

Note: The above code is very rough and has some important positioning problems, but I think the general approach is the way to go for putting text on a path with Raphael.

时常饿 2024-09-04 17:40:33

raphael 2.1 print() 函数不再返回一组路径,而是返回包含所有字母的单个路径。所以这里的所有解决方案对于 raphael 2.1(当前版本)都无效。我开发了以下小插件,它将方法 printLetters() 添加到纸张上,单独打印字母并返回一组,就像旧的 print() 方法一样。此外,该插件支持将此文本与路径对齐。例如,要使用插件对齐路径上的文本,您只需执行以下操作:

var r = Raphael(0, 0, 500, 500);
var path1 = "M 50 100 C 100 50 150 0 200 50" +
    " C 250 100 300 150 350 100" +
    " C 400 50 450 50 450 50";
var text1 = r.printLetters(20, 150, "habia una vez una vaca",
        r.getFont("my underwood"), 30, null, null, path1).attr({
    fill : "red",
    stroke : "black"
});

插件代码为:

(function() {
    /**
     * do the job of putting all letters in a set returned bu printLetters in a path
     * @param p - can be a rpahael path obejct or string
     */
    var _printOnPath = function(text, paper, p) {
        if(typeof(p)=="string")
            p = paper.path(p).attr({stroke: "none"});
        for ( var i = 0; i < text.length; i++) {       
            var letter = text[i];
            var newP = p.getPointAtLength(letter.getBBox().x);
            var newTransformation = letter.transform()+
                 "T"+(newP.x-letter.getBBox().x)+","+
                (newP.y-letter.getBBox().y-letter.getBBox().height);       
            //also rotate the letter to correspond the path angle of derivative
            newTransformation+="R"+
                (newP.alpha<360 ? 180+newP.alpha : newP.alpha);
            letter.transform(newTransformation);
        }
    };

    /** print letter by letter, and return the set of letters (paths), just like the old raphael print() method did. */
    Raphael.fn.printLetters = function(x, y, str, font, size,
            letter_spacing, line_height, onpath) {
        letter_spacing=letter_spacing||size/1.5;
        line_height=line_height||size;
        this.setStart();
        var x_=x, y_=y;
        for ( var i = 0; i < str.length; i++) {
            if(str.charAt(i)!='\n') {
                var letter = this.print(x_,y_,str.charAt(i),font,size);
                x_+=letter_spacing;               
            }
            else {
                x_=x;
                y_+=line_height;
            }
        }
        var set = this.setFinish();
        if(onpath) {
            _printOnPath(set, this, onpath);
        }
        return set;
    };   
})();

raphael 2.1 print() function do not return a set of path any more, but a single path with all the letters. So all solutions here are not valid for raphael 2.1 (current version). I developed the following small plugin that adds the method printLetters() to paper, that prints letters individually and return a set, just like the old print() method. Also, the plugin supports aligning this text to a path. For example, for aligning a text on a path using the plugin you only need to do this:

var r = Raphael(0, 0, 500, 500);
var path1 = "M 50 100 C 100 50 150 0 200 50" +
    " C 250 100 300 150 350 100" +
    " C 400 50 450 50 450 50";
var text1 = r.printLetters(20, 150, "habia una vez una vaca",
        r.getFont("my underwood"), 30, null, null, path1).attr({
    fill : "red",
    stroke : "black"
});

And the plugin code is:

(function() {
    /**
     * do the job of putting all letters in a set returned bu printLetters in a path
     * @param p - can be a rpahael path obejct or string
     */
    var _printOnPath = function(text, paper, p) {
        if(typeof(p)=="string")
            p = paper.path(p).attr({stroke: "none"});
        for ( var i = 0; i < text.length; i++) {       
            var letter = text[i];
            var newP = p.getPointAtLength(letter.getBBox().x);
            var newTransformation = letter.transform()+
                 "T"+(newP.x-letter.getBBox().x)+","+
                (newP.y-letter.getBBox().y-letter.getBBox().height);       
            //also rotate the letter to correspond the path angle of derivative
            newTransformation+="R"+
                (newP.alpha<360 ? 180+newP.alpha : newP.alpha);
            letter.transform(newTransformation);
        }
    };

    /** print letter by letter, and return the set of letters (paths), just like the old raphael print() method did. */
    Raphael.fn.printLetters = function(x, y, str, font, size,
            letter_spacing, line_height, onpath) {
        letter_spacing=letter_spacing||size/1.5;
        line_height=line_height||size;
        this.setStart();
        var x_=x, y_=y;
        for ( var i = 0; i < str.length; i++) {
            if(str.charAt(i)!='\n') {
                var letter = this.print(x_,y_,str.charAt(i),font,size);
                x_+=letter_spacing;               
            }
            else {
                x_=x;
                y_+=line_height;
            }
        }
        var set = this.setFinish();
        if(onpath) {
            _printOnPath(set, this, onpath);
        }
        return set;
    };   
})();
流星番茄 2024-09-04 17:40:33

这是基于 raphael4gwt (java) 的代码,但我认为 javascript 程序员可以轻松适应它。它基于raphael 2.0。它与上面的解决方案类似,但更好。它使用转换字符串来绝对定位和旋转每个字母以将其放置在路径上:

/* make some text follow a path */
Font anchorFont = paper.getFont("Anchor Steam NF");
Set text1 = paper.print(120,330,"a text that follows a path", anchorFont, 40);

//the path where we want to place the text
Path p = paper.path(
    "M 50 100 C 100 50 150 0 200 50" +
" C 250 100 300 150 350 100" +
" C 400 50 450 50 450 50");
p.attr(Attrs.create().stroke("none"));//hide the path

/* for each letter, we add an absolute translation to its 
 * transformation string and also add an absolute rotation 
 * to correspond to path angle of derivative. */
for(int i = 0; i<text1.size(); i++) {
    Shape letter = text1.item(i);

    //get the point of a letter on the path
    Point newP = p.getPointAtLength(letter.getBBox().getX());

    String newTransformation = letter.getTransform()+                   
        "T"+(newP.getX()-letter.getBBox().getX())+","+
        (newP.getY()-letter.getBBox().getY()-letter.getBBox().getHeight());

    //also rotate the letter to correspond the path angle of derivative
    newTransformation+="R"+
        (newP.getAlpha()<360 ? 180+newP.getAlpha() : newP.getAlpha());

    letter.setTransform(newTransformation);         
}

this is the code based on raphael4gwt (java), but I think a javascript programmer can easily adapt it. It is based on raphael 2.0. It is similar to the sollution above but better. It uses transformation strings to absolutely position and rotate each letter to place it on the path:

/* make some text follow a path */
Font anchorFont = paper.getFont("Anchor Steam NF");
Set text1 = paper.print(120,330,"a text that follows a path", anchorFont, 40);

//the path where we want to place the text
Path p = paper.path(
    "M 50 100 C 100 50 150 0 200 50" +
" C 250 100 300 150 350 100" +
" C 400 50 450 50 450 50");
p.attr(Attrs.create().stroke("none"));//hide the path

/* for each letter, we add an absolute translation to its 
 * transformation string and also add an absolute rotation 
 * to correspond to path angle of derivative. */
for(int i = 0; i<text1.size(); i++) {
    Shape letter = text1.item(i);

    //get the point of a letter on the path
    Point newP = p.getPointAtLength(letter.getBBox().getX());

    String newTransformation = letter.getTransform()+                   
        "T"+(newP.getX()-letter.getBBox().getX())+","+
        (newP.getY()-letter.getBBox().getY()-letter.getBBox().getHeight());

    //also rotate the letter to correspond the path angle of derivative
    newTransformation+="R"+
        (newP.getAlpha()<360 ? 180+newP.getAlpha() : newP.getAlpha());

    letter.setTransform(newTransformation);         
}
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文