2016-12-21 8 views
10

У меня есть стрелка в виде SVG, длина которой я хочу изменить в зависимости от ширины обертывания DIV (например).Изменение размеров отдельных фигур динамически без масштабирования всего SVG

Все мои предыдущие попытки привели в такое поведение (масштабирование всего SVG):

Scaling whole SVG

Вместо этого, я хочу добиться такого поведения:

Scaling shapes only

Is можно просто изменить отдельные фигуры внутри SVG, просто добавив в код процентуальные значения? Если нет, как я могу это сделать?

SVG как код:.

<svg width="35px" viewBox="0 0 35 985" version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink"> 
 
    <g id="Group" stroke="none" stroke-width="1" fill="none" fill-rule="evenodd" transform="translate(0.000000, 0.000000)"> 
 
    <rect id="Rectangle-2" fill="#5FDCC7" x="12" y="19.7987928" width="11" height="100%"></rect> 
 
    <polygon id="Triangle" fill="#5FDBC6" points="17.5 0 35 20.7887324 0 20.7887324"></polygon> 
 
    <rect id="Rectangle-3" fill="#5FDBC6" x="0" y="973.110664" width="35" height="11"></rect> 
 
    </g> 
 
</svg>

+0

так что вы хотите, чтобы средняя линия растянулась по пространству? – Stewartside

+0

да, точно ... (но динамически в ответ, скажем, ширина div) – to7be

+0

okay дайте мне 5 минут – Stewartside

ответ

8

Как правило, нет возможности создать масштабируемый SVG, где его части не масштабируются. Если SVG имеет viewBox, и вы масштабируете его, тогда все содержимое будет масштабироваться. Невозможно пометить часть содержимого как неуязвимое для масштабирования.

Ближайшим, что вы можете сделать, является ограничение масштабирования по оси X. Однако наконечник стрелки все еще растягивается.

<svg width="35px" height="150px" viewBox="0 0 35 985" preserveAspectRatio="none"> 
 

 
     <g id="Group" stroke="none" stroke-width="1" fill="none" fill-rule="evenodd" transform="translate(0.000000, 0.000000)"> 
 
      <rect id="Rectangle-2" fill="#5FDCC7" x="12" y="19.7987928" width="11" height="100%"></rect> 
 
      <polygon id="Triangle" fill="#5FDBC6" points="17.5 0 35 20.7887324 0 20.7887324"></polygon> 
 
      <rect id="Rectangle-3" fill="#5FDBC6" x="0" y="973.110664" width="35" height="11"></rect> 
 
     </g> 
 
</svg> 
 

 

 
<svg width="35px" height="300px" viewBox="0 0 35 985" preserveAspectRatio="none"> 
 

 
     <g id="Group" stroke="none" stroke-width="1" fill="none" fill-rule="evenodd" transform="translate(0.000000, 0.000000)"> 
 
      <rect id="Rectangle-2" fill="#5FDCC7" x="12" y="19.7987928" width="11" height="100%"></rect> 
 
      <polygon id="Triangle" fill="#5FDBC6" points="17.5 0 35 20.7887324 0 20.7887324"></polygon> 
 
      <rect id="Rectangle-3" fill="#5FDBC6" x="0" y="973.110664" width="35" height="11"></rect> 
 
     </g> 
 
</svg>

Если вы хотите обобщенное решение, то вы должны контролировать размер события и обновления SVG динамически.

Ограниченность подлый умное решение ...

Сказав все это, есть умный метод, который работает в ограниченном наборе обстоятельств. Ограничения:

  1. SVG простирается только в одном направлении.
  2. «немасштабируемые» детали находятся на одном или обоих концах растяжки.
  3. Конечные части прочные и не имеют отверстий.
  4. Вы в порядке, на фоне SVG, являющегося сплошным цветом, а не прозрачным.

Настоящая демоверсия вашей формы реализована с использованием этой техники. При изменении размеров окна по горизонтали, вы увидите, что она простирается соответствующим .:

<svg width="100%" height="35px"> 
 

 
    <svg viewBox="0 0 1 1" preserveAspectRatio="none"> 
 
    <rect x="0" y="0" width="1" height="1" fill="white"/> 
 
    <rect x="0" y="0.4" width="1" height="0.2" fill="#5FDBC6"/> 
 
    </svg> 
 
    
 
    <svg viewBox="0 0 0.2 1" preserveAspectRatio="xMinYMid"> 
 
    <rect x="0" y="0" width="0.2" height="1" fill="#5FDBC6"/> 
 
    </svg> 
 

 
    <svg viewBox="0 0 0.8 1" preserveAspectRatio="xMaxYMid"> 
 
    <rect x="0" y="0" width="0.8" height="1" fill="white"/> 
 
    <polygon points="0,0 0.8,0.5 0,1" fill="#5FDBC6"/> 
 
    </svg> 
 

 
</svg>

+0

Как я могу жить с ограничениями, это отлично работает для меня! Спасибо! – to7be

+0

как проницательный и умный –

+0

привет, Пол, есть еще более общее решение. используя проценты и преобразование, вы можете позиционировать символы слева и снизу, так что вы можете позиционировать любую фигуру в любой точке реагирующего svg ... см. мой ответ ниже ... ;-) –

1

С помощью символа вы можете сделать формы вы хотите, и просто включить их в Затем продлить среднюю секцию, просто сделать новый путь и сделайте линию длиннее. Они могут быть расположены где угодно, используя свойство transform

<svg xmlns="http://www.w3.org/2000/svg"> 
 

 
    <symbol id="base"> 
 
    <g xmlns="http://www.w3.org/2000/svg"> 
 
     <path fill="#5FDBC6" d="M0,0 L0,20 L4,20 L4,0z"></path> 
 
    </g> 
 
    </symbol> 
 
    <symbol id="triangle" > 
 
    <g> 
 
     <path fill="#5FDBC6" d="M0,0 L15,10 L0,20z"></path> 
 
    </g> 
 
    </symbol> 
 

 
    <path stroke-width="4" stroke="#5FDBC6" d="M0,10 L100,10"></path> 
 
    <g class="first" transform="translate(0,00)"> 
 
    <use xlink:href="#base" /> 
 
    </g> 
 
    <g class="first" transform="translate(90,00)"> 
 
    <use xlink:href="#triangle" /> 
 
    </g> 
 
    
 
    <path stroke-width="4" stroke="#5FDBC6" d="M0,50 L200,50"></path> 
 
    <g class="first" transform="translate(0,40)"> 
 
    <use xlink:href="#base" /> 
 
    </g> 
 
    <g class="first" transform="translate(200,40)"> 
 
    <use xlink:href="#triangle" /> 
 
    </g> 
 

 

 
</svg>

+0

Спасибо! Поскольку это для меня совершенно новая тема, я никогда не рассматривал этот подход. У меня есть много, чтобы прочитать здесь, и следующий шаг - объединиться со всеми позициями и переводами, чтобы достичь желаемого динамического равновесия. – to7be

+0

@ to7be, если он отлично работает в конце концов, не забудьте принять :) – Stewartside

+1

Это не отвечает на вопрос OPs. OP хотел знать, как сделать отзывчивый SVG, когда часть SVG не масштабируется. Это принципиально невозможно. –

0

** EDITED **

Такое поведение вызвано вашим атрибутом <svg>viewBox. Соотношение сторон вашего SVG сохраняется по умолчанию. Вы хотите этого поведения на #Triangle и #Rectangle-3, но не на #Rectangle-2 (вы хотите, чтобы height увеличился, но width не изменился).

Я думаю, что вы хотите добавить в свой preserveAspectRatio=none<svg> инлайн CSS, а затем сделать некоторые настройки (так как это портит соотношение сторон экрана вашего #Triangle и #Rectangle-3 - или вместо этого, вы можете попытаться изменить height из #triangle-2 на той же высоте, что и ваша обертка div (в моей скрипте JS я сделал это так, установив #Triangle-2 с высоты до 25vh). Игра с высотой окна - высота #Rectangle-2 удлиняется, но не меняет ширину, хотя Я еще не получил ваш #Rectangle-3, чтобы динамически придерживаться нижней части #Rectangle-2 (#Rectangle-3 застрял у подножия окна): https://jsfiddle.net/KyleVassella/dnagft6q/6/

Я подозреваю, вы будете знать, как это исправить, но в любом случае я буду продолжать работать над ней и в то же время вы можете прочитать здесь, где есть гораздо больше информации по этой теме:

How can I make an svg scale with its parent container?

+0

Thx для приятной ссылки! В области SVG так много основ, которые вы должны понять, прежде чем сможете испытать успехи. 'preserveAspectRatio' был очень полезен. Для меня ваше решение идет очень хорошо в правильном направлении. Следующим шагом является автоматическое выравнивание #Triangle в верхней части и # Rectangle-3 до нижней части DIV обертки. Эта позиционирующая вещь по-прежнему бросает вызов мне :) thx! – to7be

+1

Ваш совет неисправен. 'preserveAspectRatio' не является допустимым атрибутом для элемента' '. Это не будет иметь никакого эффекта. –

+0

@Paul LeBeau Вы правы, спасибо, что указали это. Я отредактировал свой ответ. @ to7be, расскажите мне об этом! В следующий раз я просто оставлю комментарий со ссылкой, я думаю, что в этом случае было бы гораздо полезнее (и правильно). Надеюсь, что кто-то приходит и решает все это время. Я буду продолжать работать над этим после некоторого сна. –

3

Для этого particlular USECASE, я думаю, что я бы пойти на CSS подход, он может (в зависимости от вашего markup) добавляет элемент html, если вы не можете использовать псевдоэлементы, но для него не требуется JS или вводимые вручную значения для элементов ширины штриха или преобразования.

Вот способ сделать эту стрелку с помощью пункта тег:

p { 
 
    position: relative; 
 
    max-width: 300px; 
 
    border-bottom: 4px solid #5FDBC6; 
 
    padding-bottom:6px; 
 
} 
 
p:nth-child(2) {max-width: 400px;} 
 
p:nth-child(3) {max-width: 200px;} 
 
p::before, p::after{ 
 
    content:''; 
 
    position:absolute; 
 
    bottom:-8px; 
 
} 
 
p::before { 
 
    height: 12px; 
 
    left:0; 
 
    border-left: 4px solid #5FDBC6; 
 
} 
 
p::after{ 
 
    right:-4px; 
 
    border-style:solid; 
 
    border-width:6px 0 6px 8px; 
 
    border-color:transparent transparent transparent #5FDBC6; 
 
}
<p>Lorem ipsum dolor sit amet, consectetur adipiscing elit. a dapibus, tincidunt velit eget, rutrum urna.</p> 
 
<p>Lorem ipsum dolor sit amet, consectetur adipiscing elit. Cras in purus risus. Ut id est suscipit, tincidunt sem a, fermentum magna. Class aptent taciti sociosqu ad litora torquent per conubia nostra, per inceptos himenaeos. Ut rutrum ac ligula</p> 
 
<p>Lorem ipsum dolor sit amet, consectetur adipiscing elit. Cras in purus risus. Ut id est suscipit, tincidunt sem a, fermentum magna.</p>

+0

Это отличный подход, который определенно работает. Замечательно видеть, как эта проблема может быть решена псевдоэлементами! – to7be

3

Да, вы можете использовать проценты в SVG.

для основных форм его довольно просто. Вы можете написать свой основной прямоугольник, как

<rect x="0" y="5" width="100%" height="10"/> 

ваш второй прямоугольник еще проще, так как она сидит на 0,0 Все время

<rect x="0" y="0" width="10" height="20"/> 

но со стрелкой есть проблема в трактах и ​​многоугольник вы не можете использовать проценты. Для решения этой проблемы существует двухэтапное решение.

первый положил путь в символе элемента:

<symbol id="arrow" viewBox="0 0 20 20" width="20" height="20"> 
    <path d="M0,0L20 10L0 20z" /> 
</symbol> 

теперь вы можете расположить этот символ, как вы бы расположить прямоугольник ... легко ...

<use xlink:href="#arrow" x="100%" y="0" width="20" height="20"/> 

но теперь ваша стрелка начинает 100% и полностью выходит за пределы вашего окна просмотра. вы можете просто установить переполнение: видимо на вашем svg и покончить с ним, но это не то, что мы хотим ... мы хотим, чтобы стрела закончилась со 100%. Но так легко, мы знаем, что стрела шириной 20 пикселей.Так просто перевести обратно 20px Использовать:

<use xlink:href="#arrow" x="100%" y="0" width="20" height="20" transform="translate(-20 0)"/> 

, используя этот подход, вы можете поместить любую форму в любом положении основания на процентах ...

деформировать все это, ваш полный SVG теперь выглядит следующим образом :

<svg id="svg" height="20px" xmlns:xlink="http://www.w3.org/1999/xlink"> 
    <symbol id="arrow" viewBox="0 0 20 20" width="20" height="20"> 
    <path d="M0,0L20 10L0 20z" /> 
    </symbol> 
    <g id="Group" fill="#5FDCC7"> 
    <rect x="0" y="5" width="100%" height="10" transform="translate(-20 0)" /> 
    <rect x="0" y="0" width="10" height="20" /> 
    <use xlink:href="#arrow" width="20" height="20" x="100%" y="0" transform="translate(-20 0)" /> 
    </g> 
</svg> 

и вот фрагмент с помощью этого СВГ с 3 различной ширины:

svg:nth-of-type(1) { 
 
    width: 100px 
 
} 
 
svg:nth-of-type(2) { 
 
    width: 200px 
 
} 
 
svg:nth-of-type(3) { 
 
    width: 300px 
 
}
<svg height="20px" xmlns:xlink="http://www.w3.org/1999/xlink"> 
 
    <symbol id="arrow" viewBox="0 0 20 20" width="20" height="20"> 
 
    <path d="M0,0L20 10L0 20z" /> 
 
    </symbol> 
 
    <g id="Group" fill="#5FDCC7"> 
 
    <rect x="0" y="5" width="100%" height="10" transform="translate(-20 0)" /> 
 
    <rect x="0" y="0" width="10" height="20" /> 
 
    <use xlink:href="#arrow" width="20" height="20" x="100%" y="0" transform="translate(-20 0)" /> 
 
    </g> 
 
</svg> 
 
<br/> 
 
<svg height="20px" xmlns:xlink="http://www.w3.org/1999/xlink"> 
 
    <symbol id="arrow" viewBox="0 0 20 20" width="20" height="20"> 
 
    <path d="M0,0L20 10L0 20z" /> 
 
    </symbol> 
 
    <g id="Group" fill="#5FDCC7"> 
 
    <rect x="0" y="5" width="100%" height="10" transform="translate(-20 0)" /> 
 
    <rect x="0" y="0" width="10" height="20" /> 
 
    <use xlink:href="#arrow" width="20" height="20" x="100%" y="0" transform="translate(-20 0)" /> 
 
    </g> 
 
</svg> 
 
<br/> 
 
<svg height="20px" xmlns:xlink="http://www.w3.org/1999/xlink"> 
 
    <symbol id="arrow" viewBox="0 0 20 20" width="20" height="20"> 
 
    <path d="M0,0L20 10L0 20z" /> 
 
    </symbol> 
 
    <g id="Group" fill="#5FDCC7"> 
 
    <rect x="0" y="5" width="100%" height="10" transform="translate(-20 0)" /> 
 
    <rect x="0" y="0" width="10" height="20" /> 
 
    <use xlink:href="#arrow" width="20" height="20" x="100%" y="0" transform="translate(-20 0)" /> 
 
    </g> 
 
</svg>

+0

Могу ли я попросить избирателя о том, что случилось с моим ответом? Будет приятно исправить это ... –