Raphael JS combine paths

2019-05-16 11:48发布

I'm pretty new at SVG and Raphael, but I've been using Illustrator for many years, so I have some assumptions on how it works. I want to combine two paths which should return a single element.

I need to make a speech bubble, but it could be anything really. In this case I tried to make two rect, one with round corners and another square rect which was rotated. It looked alright, but when I tried to move the speech bubble, the rotated element moved in the wrong direction, because of the 45 degree rotation.

How can I compbine paths which I can later manipulate as if it was a single element/path?

Example of speech bubble

标签: svg raphael
3条回答
地球回转人心会变
2楼-- · 2019-05-16 12:24

Here you go DEMO

var paper = Raphael('canvas',400,400),
    r1    = paper.rect(100,100,200,100).attr({fill:'black'}),
    r2    = paper.rect(130,130,140,40,5).attr({fill:'white','stroke':'white'}),
    r3    = paper.path("M200 170L240 170 220 180z").attr({fill:'white', 'stroke':'white'}), 
    p     = paper.set(r1,r2,r3);

// the rest of the code is in the demo

Note, that it is easier to create triangle via path() and not worry about rotation. Good Luck ;)

查看更多
仙女界的扛把子
3楼-- · 2019-05-16 12:27

First thing is that you could push your 2 elements into a Raphael set which you would later move with Element.transform(). This would let you apply the move handler once, and not twice.

Also for your issue, it is acually documented:

... There are also alternative “absolute” translation, rotation and scale: T, R and S. They will not take previous transformation into account. For example, ...T100,0 will always move element 100 px horisontally, while ...t100,0 could move it vertically if there is r90 before. Just compare results of r90t100,0 and r90T100,0. ...

查看更多
Fickle 薄情
4楼-- · 2019-05-16 12:30

If you mean merging paths like using the Illustrator Pathfinder panel - turning several paths into one path (not a set of paths), merging overlap - I'm pretty sure there's no direct Raphael or SVG equivalent.

The closest thing is, creating a compound path (aka composite path) - the equivalent of cmd-8 or Object > Make Compound Path in Illustrator. This merges paths together into one path, but doesn't remove areas of overlap.

Basically, for a set paper.set( paper.path('M0,0 4,0 0,4z'),paper.path('M9,9 4,9 9,4z') );, an equivalent compound path would be paper.path('M0,0 4,0 0,4z M9,9 4,9 9,4z'); - just joining the path definitions into one, each starting with its own M.

Some differences to Raphael sets:

  • Less overhead (it's just one complex path, not several separate individual path elements)
  • Fewer surprises when you move it, sort it, etc:
    • Things applied to a Raphael set apply to each item in turn, not to the set as a unit - so for example toFront() changes the order within the set, and transforms centre around each item, like Illustrator's transform each, unless you give the transform static co-ordinates.
    • Things applied to a compound path, however, apply to the whole compound path as one unit.
  • It's not possible for subpaths of a compound path to have different attributes
  • Things like gradients apply once across the whole of the compound path, whereas with sets, there will be separate gradients on each separate path

JSBIN demo - compare the gradients, and see how the compound pair is just one path on the DOM.


Here's a simple plugin that adds the ability to take a set and create a compound path from it:

Raphael.st.compoundPath = function(){
    var positions = [];
    this.forEach( function( element ){
        positions.push( element.compoundPath() );
    });
    return positions.join('');
} 
Raphael.el.compoundPath = function(){
    var path = this.attr('path');
    return path ? Raphael.parsePathString( path ).join('') : '';
}

Then use it like this:

var someSet = paper.set(paper.path('M0,0 4,0 0,4z'),paper.path('M9,9 4,9 9,4z'));
var compPath = paper.path( someSet.compoundPath() );
someSet.remove(); // if you want to replace the set with a compound path

Note that it only combines paths in a set - if you need to combine other shapes with paths, you'll need a way to convert them into paths first.

查看更多
登录 后发表回答