例または概念の確認を探しています。アプリで Raphael JS を使用することを検討しており、Illustrator などのグラフィック デザイン アプリケーションと同様にテキストをワープできるようにしたいと考えています。
質問する
4618 次
2 に答える
7
以下は、ドロップイン関数としてリファクタリングされ、機能が追加された Chris Wilson のコードの適応です。
- IE8 / VML モードのサポートとGecko / Firefox のサポート(ローテーションの起点を定義することにより、これがないと IE8 と Firefox はページ全体にテキストをスローしてしまいます)
- Gecko ブラウザー ( Firefoxなど)でテキストの見苦しさを軽減するための小さな調整- これがないと、文字間隔が勝手に大きくなります
- 手動で定義されたフォント サイズと文字間隔、および動的な「パスを埋める」サイズと間隔のサポート
- 手動カーニング(文字間隔の微調整) のサポート。パス上のテキストは、非常に醜い文字スペースを作成することがよくあります。これにより、次の方法でこれらを修正するための手動調整を定義できます。
- 文字列内の数値位置、または、
- 文字、または、
- 文字のペア (前の文字に基づく文字のインスタンスに適用されます。たとえば、以下の例では「ae」のペアを引き締め、「rn」のペアを広げています)
JSBINデモ
function textOnPath( message, path, fontSize, letterSpacing, kerning, geckoKerning) {
// only message and path are required, other args are optional
// if fontSize or letterSpacing are undefined, they are calculated to fill the path
// 10% of fontSize is usually good for manual letterspacing
// Gecko, i.e. Firefox etc, inflates and alters the letter spacing
var gecko = /rv:([^\)]+)\) Gecko\/\d{8}/.test(navigator.userAgent||'') ? true : false;
var letters = [], places = [], messageLength = 0;
for (var c=0; c < message.length; c++) {
var letter = paper.text(0, 0, message[c]).attr({"text-anchor" : "middle"});
letters.push(letter);
if (kerning) {
if(gecko && geckoKerning) {
kerning = geckoKerning;
}
var character = letter.attr('text'), kern = 0;
var predecessor = letters[c-1] ? letters[c-1].attr('text') : '';
if (kerning[c]) {
kern = kerning[c];
} else if (kerning[character]) {
if( typeof kerning[character] === 'object' ) {
kern = kerning[character][predecessor] || kerning[character]['default'] || 0;
} else {
kern = kerning[character];
}
}
if(kerning['default'] ) {
kern = kern + (kerning['default'][predecessor] || 0);
}
messageLength += kern;
}
places.push(messageLength);
//spaces get a width of 0, so set min at 4px
messageLength += Math.max(4.5, letter.getBBox().width);
}
if( letterSpacing ){
if (gecko) {
letterSpacing = letterSpacing * 0.83;
}
} else {
letterSpacing = letterSpacing || path.getTotalLength() / messageLength;
}
fontSize = fontSize || 10 * letterSpacing;
for (c = 0; c < letters.length; c++) {
letters[c].attr("font-size", fontSize + "px");
p = path.getPointAtLength(places[c] * letterSpacing);
var rotate = 'R' + (p.alpha < 180 ? p.alpha + 180 : p.alpha > 360 ? p.alpha - 360 : p.alpha )+','+p.x+','+p.y;
letters[c].attr({ x: p.x, y: p.y, transform: rotate });
}
}
于 2013-10-01T17:36:10.340 に答える
6
Kevin Nielsen が示唆するように、これは path.getPointAtLength を使用することでそれほど難しくありません。
path = paper.path("M50,100c40,-50 270,50 300,0").attr("stroke", "#CCC");
message = "I want to do this in RaphaelJS";
//since not every letter is the same width, get the placement for each letter
//along the length of the string
//however, Raphael appears to group the width of letters into intervals of 4px,
//so this won't be perfect
for (; c < message.length; c += 1) {
letter = paper.text(0, 0, message[c]).attr({"text-anchor" : "start"});
letters.push(letter);
places.push(message_length);
//spaces get a width of 0, so set min at 4px
message_length += Math.max(4, letter.getBBox().width);
}
ratio = path.getTotalLength() / message_length;
fontsize = 10 * ratio;
for (c = 0; c < letters.length; c += 1) {
letters[c].attr("font-size", fontsize + "px");
p = path.getPointAtLength(places[c] * ratio);
//there does appear to be a bug in p.alpha around 180. Here's the fix
letters[c].attr({ x: p.x, y: p.y, transform: 'r' + (p.alpha < 180 ? p.alpha + 180 : p.alpha)});
}
于 2013-01-03T16:44:24.333 に答える