Прикрепить текст на пути в Raphaël? - PullRequest
8 голосов
/ 10 апреля 2010

Кто-нибудь знает, как прикрепить текст к пути в Рафаэле? Что-то вроде http://www.w3.org/TR/SVG11/images/text/toap02.svg Я знаю, что jQuery SVG может сделать это, но я не могу найти простой способ сделать это с помощью Raphaël js. Я хочу прикрепить этот текст к кривой Безье и переместить его.

Ответы [ 3 ]

12 голосов
/ 14 октября 2010

Есть 2 способа сделать это.

  1. Более простой способ - использовать метод Рафаэля .print(). Это может превратить текст в пути. Каждый персонаж получает свой собственный путь. Затем вы можете перебирать каждый символ, перемещать и поворачивать его соответствующим образом, используя .translate() и .angle().

  2. Сложнее всего реализовать текст по пути для SVG и VML для Raphael .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

Примечание. Приведенный выше код является очень грубым и имеет некоторые важные проблемы с позиционированием, но я думаю, что общий подход - это способ размещения текста по пути с Рафаэлем.

6 голосов
/ 29 марта 2012

Функция 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;
    };   
})();
0 голосов
/ 02 марта 2012

это код, основанный на raphael4gwt (java), но я думаю, что программист javascript может легко его адаптировать. Он основан на Рафаэле 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);         
}
...