2

Подскажите пожалуйста, как прописать формулу(или указать параметры), для правильного масштабирования элементов SVG. Приведу пример

window.onload = function() {
  var $allFigures = $('#figures'),
    $figure = $('.figure'),
    $circle = $('circle'),
    $rect = $('rect'),
    $polygon = $('polygon'),
    attrBox = $allFigures.attr('viewBox'),
    initialWidth,
    initialHeight,
    initialX,
    initialY;

console.log($figure.length + " = $figure count")

$circle.click(function() { var R = $(this).attr("r"); $(this).attr({ "r": R * 2 }); })

$rect.click(function() { initialX = $(this).attr("x"); initialY = $(this).attr("y"); initialWidth = $(this).attr("width"); initialHeight = $(this).attr("height");

$(this).attr({
  "x": initialX / 2,
  "y": initialY / 2,
  "width": initialWidth * 2,
  "height": initialHeight * 2
});

})

$figure.on("click", $figure, function() { $(this).css({ "fill": "#0f0" }); })

}

/*.figure:hover{
  transform: scale(1.2);
}*/
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<svg version="1.1" id="figures" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px" viewBox="0 0 600 400" style="enable-background:new 0 0 600 400;" xml:space="preserve">
  <rect x="386" y="138.5" class="figure" fill="#A21E22" stroke="#000" stroke-miterlimit="10" width="185" height="123"/>
  <circle class="figure" fill="#4CA146" stroke="#000" stroke-miterlimit="10" cx="118" cy="200" r="48"/>
  <polygon class="figure" fill="#FEE33A" stroke="#000" stroke-miterlimit="10" points="287,123.2 304.3,176.3 360.1,176.3 314.9,209.1 332.2,262.2 287,229.3 241.8,262.2 
    259.1,209.1 213.9,176.3 269.7,176.3 "/>
</svg>

Как произвести постепенное масштабирование полигонального объекта SVG? Из-за того что в SVG есть область видимости viewBox, я так понимаю, что единственный способ здесь пересчитывать точки нахождения points для объекта? Или есть ещё какой-нибудь метод равномерного масштабирования объекта?

Alexandr_TT
  • 110,146
  • 23
  • 114
  • 384

2 Answers2

4

Метод есть и не нужно самому пересчитывать координаты фигур. Это за вас сделает интерпретатор SVG. Смотрите, к вашему файлу я добавлю только одну строчку анимации viewBox. И будет плавное увеличение и уменьшение размера фигур.

<svg version="1.1" id="figures" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
 viewBox="0 0 600 400" style="enable-background:new 0 0 600 400;" xml:space="preserve">
 <rect  x="386" y="138.5" class="figure" fill="#A21E22" stroke="#000"  stroke-miterlimit="10" width="185" height="123"/>
 <circle  class="figure" fill="#4CA146" stroke="#000"  stroke-miterlimit="10" cx="118" cy="200" r="48"/>
 <polygon  class="figure" fill="#FEE33A" stroke="#000"  stroke-miterlimit="10" points="287,123.2 304.3,176.3 360.1,176.3 314.9,209.1 332.2,262.2 287,229.3 241.8,262.2 
 259.1,209.1 213.9,176.3 269.7,176.3 "/>
   <animate  attributeName = "viewBox" begin = "0s" dur = "10s" values = "0 0 600 400;-300 -200 1200 800;0 0 600 400" 
  fill = "freeze" repeatCount="indefinite" /> 
 </svg>

Увеличение 3 и 4-го атрибута viewBox уменьшает масштаб, а изменение первых двух атрибутов viewBox удерживают фигуру на месте. подробнее здесь

Хотите начать анимацию по клику? добавляем begin = "svg2.click", где svg2 идентификатор всего полотна.

<svg id="svg2"  version="1.1" id="figures" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
 viewBox="0 0 600 400" style="enable-background:new 0 0 600 400;" xml:space="preserve">
 <rect  x="386" y="138.5" class="figure" fill="#A21E22" stroke="#000"  stroke-miterlimit="10" width="185" height="123"/>
 <circle  class="figure" fill="#4CA146" stroke="#000"  stroke-miterlimit="10" cx="118" cy="200" r="48"/>
 <polygon  class="figure" fill="#FEE33A" stroke="#000"  stroke-miterlimit="10" points="287,123.2 304.3,176.3 360.1,176.3 314.9,209.1 332.2,262.2 287,229.3 241.8,262.2 
 259.1,209.1 213.9,176.3 269.7,176.3 "/>
   <animate  attributeName = "viewBox" begin = "svg2.click" dur = "10s" values = "0 0 600 400;-300 -200 1200 800;0 0 600 400" 
  fill = "freeze" repeatCount="indefinite" /> 
 </svg>

Окружность можно масштабировать увеличением, уменьшением радиуса, не трогая cx и cy

<svg version="1.1" id="figures" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" 
 width="600" height="400" viewBox="0 0 600 400" style="border:1px solid red;" >
  <circle  class="figure" fill="#4CA146" stroke="#000"   cx="118" cy="200" r="48">
   <animate  attributeName = "r" begin = "0" dur = "10s" values = "48;5;48" 
  fill = "freeze" repeatCount="indefinite" /> 
  </circle>  
</svg>
Alexandr_TT
  • 110,146
  • 23
  • 114
  • 384
  • Спасибо, это конечно всё замечательно, но как проделывать анимацию только над одни элементом, при этом другие элементы в процесс масштабиравания что бы не входили? К примеру для моего полигонального объекта(звезды) необходимо увеличить масштаб по клику в 2 раза, но при этом другие объекты не должны менять свои размеры. Да и сразу же задам вопрос на счет перекрытия, ведь если слой который будет анимироватся находиться ПОД элементом соседом, то он будет перекрываться? – BlackStar1991 Jan 28 '17 at 20:52
  • @BlackStar1991 Создайте, пожалуйста новый вопрос, надеюсь, что смогу помочь. Ведь в этом вопросе речь шла о плавном изменении координат , и ни слова не было о раздельном масштабировании фигур. – Alexandr_TT Jan 28 '17 at 22:32
  • 1
    Как вариант использовать transform scale . – Profet Apr 01 '18 at 15:19
3

Коли речь зашла о раздельном масштабировании каждой из фигур - можно опробовать и такой вариант:

p {
  padding: 6px;
  text-align: center;
  background: #929292;
}

#figura, #figures { width: 200px; height: 200px; border: 2px solid #2cc; border-radius: 50%; }

<p>SVG-масштабирование - клик по фигуркам внизу</p>
<svg version="1.1" id="figura" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" viewBox="0 0 200 200">
  <symbol id="figur" width="200" height="200" viewBox="0 0 200 200" > 
    <polygon id="star" points="100,0 40,180 195,70 5,70 160,180" 
    style="fill-rule: nonzero; fill: #00BD00; cursor: pointer; stroke: none;" /> 
  </symbol>
  <use xlink:href="#figur" x="0" y="0" width="200" height="200"/>
  <animate id="star" attributeName = "viewBox" begin = "star.click" dur = "5s" values = "0 0 200 200;-900 -900 2000 2000;0 0 200 200" fill = "freeze" repeatCount="2"/> <!-- indefinite -->
</svg>
<svg version="1.1" id="figures" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" width="200" height="200" viewBox="0 0 200 200">
  <radialGradient id="grad" cx="50%" y="50%">
    <stop class="stop-1" offset="0%" stop-color="#becccc"/>
    <stop class="stop-2" offset="75%" stop-color="#929292"/>
    <stop class="stop-3" offset="100%" stop-color="#becccc"/>
  </radialGradient>
  <circle  class="figure" cx="100" cy="100" r="100" fill="url(#grad)" stroke="#000" style="cursor: pointer;">
  <animate  attributeName="r" begin="click" dur="5s" values="100;1;100" fill="freeze" repeatCount="2"/> <!-- indefinite -->
  </circle> 
</svg>

Анимация иных фигур, вписанных между <symbol>...</symbol> аналогична анимации звезды.