Вот код, обобщающий лучшие из приведенных выше ответов и дающий путям Рафаэля простой атрибут .attr({pathXY: [newXPos, newYPos]})
, аналогичный .attr({x: newXPosition})
и .animate({x: newXPosition})
для фигур.
Это позволяет вам переместить ваш путь к фиксированной, абсолютной позиции или стандартным способом, переместив его на относительную величину без жесткого кодирования строк пути или пользовательских вычислений.
Редактировать: Код ниже работает в IE7 и IE8. Более ранняя версия этого не удалась в режиме IE8 / VML из-за ошибки Raphael, которая возвращает массивы в .attr ('path') в режиме SVG, но в .attr ('path') в режиме VML .
Код
Добавьте этот код ( Raphael customAttribute и вспомогательную функцию) после определения paper
, используйте, как показано ниже.
paper.customAttributes.pathXY = function( x,y ) {
// use with .attr({pathXY: [x,y]});
// call element.pathXY() before animating with .animate({pathXY: [x,y]})
var pathArray = Raphael.parsePathString(this.attr('path'));
var transformArray = ['T', x - this.pathXY('x'), y - this.pathXY('y') ];
return {
path: Raphael.transformPath( pathArray, transformArray)
};
};
Raphael.st.pathXY = function(xy) {
// pass 'x' or 'y' to get average x or y pos of set
// pass nothing to initiate set for pathXY animation
// recursive to work for sets, sets of sets, etc
var sum = 0, counter = 0;
this.forEach( function( element ){
var position = ( element.pathXY(xy) );
if(position){
sum += parseFloat(position);
counter++;
}
});
return (sum / counter);
};
Raphael.el.pathXY = function(xy) {
// pass 'x' or 'y' to get x or y pos of element
// pass nothing to initiate element for pathXY animation
// can use in same way for elements and sets alike
if(xy == 'x' || xy == 'y'){ // to get x or y of path
xy = (xy == 'x') ? 1 : 2;
var pathPos = Raphael.parsePathString(this.attr('path'))[0][xy];
return pathPos;
} else { // to initialise a path's pathXY, for animation
this.attr({pathXY: [this.pathXY('x'),this.pathXY('y')]});
}
};
Использование
Для абсолютного перевода (переместите в фиксированное положение X, Y) - Live JSBIN demo
Работает с любым путем или набором путей, включая наборы наборов (демо) . Обратите внимание: поскольку наборы Рафаэля являются массивами, а не группами, каждый элемент в наборе перемещается в определенную позицию, а не в центр набора.
// moves to x=200, y=300 regardless of previous transformations
path.attr({pathXY: [200,300]});
// moves x only, keeps current y position
path.attr({pathXY: [200,path.pathXY('y')]});
// moves y only, keeps current x position
path.attr({pathXY: [path.pathXY('x'),300]});
Рафаилу необходимо обрабатывать координаты x и y вместе в одном и том же пользовательском атрибуте, чтобы они могли анимироваться вместе и чтобы они были синхронизированы друг с другом.
Для относительного перевода (переместить на +/- X, Y) - Live JSBIN demo
// moves down, right by 10
path.attr({pathXY: [ path.pathXY('x')+10, path.pathXY('y')+10 ]},500);
Это также работает с наборами, но опять же не забывайте, что наборы Рафаэля не похожи на группы - каждый объект перемещается на одну позицию относительно средней позиции набора, поэтому результаты могут не соответствовать ожидаемым ( пример демо ).
Для анимации (переместить путь в относительные или абсолютные позиции)
Перед анимацией в первый раз , вам необходимо установить значения pathXY из-за ошибки / отсутствующей функции до Raphael 2.1.0, где всем настраиваемым атрибутам нужно дать числовое значение, прежде чем они будут анимированы (в противном случае они превратят каждое число в NaN и ничего не сделают, молча проваливаясь без ошибок или не оживляя и прыгая прямо в конечную позицию).
Перед использованием .animate({pathXY: [newX,newY]});
, запустите эту вспомогательную функцию:
somePath.pathXY();