Кто-нибудь знает, как прикрепить текст к пути в Рафаэле? Что-то вроде http://www.w3.org/TR/SVG11/images/text/toap02.svg Я знаю, что jQuery SVG может это сделать, но я не могу найти простой способ сделать это с помощью Raphaël js. Я хочу прикрепить этот текст к кривой Безье и переместить его.
Прикрепить текст к пути в Рафаэле?
Ответы (3)
Есть 2 способа сделать это.
Более простой способ — использовать метод Raphael
.print()
. Это может превратить текст в пути. У каждого персонажа свой путь. Затем вы можете перебирать каждый символ, перемещать и поворачивать его соответствующим образом, используя.translate()
и.angle()
.Более сложный способ — внедрить текст по пути для SVG. и VML< /strong> для Рафаэля
.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.
Функция print() raphael 2.1 больше не возвращает набор путей, а один путь со всеми буквами. Таким образом, все решения здесь недействительны для 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;
};
})();
это код, основанный на 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);
}
.print()
, который требует изменения шрифта, чтобы он стал шрифтом Cufon (который добавляет вес, создает общие пути/многоугольники SVG, а не живой выбираемый текст, и может нарушить лицензию на шрифт), есть другой подход с использованием.text()
и позиции пути в этом связанном вопросе. - person user56reinstatemonica8   schedule 01.10.2013