Что я хочу сделать?
Обновления по этому вопросу: 7/10/2012 - "gradientTransform not not" Вдохновленный Duopixel 7/11/2012 - "SVG-код из примера" 7/16/2012 - "@dignifiedquire возьмите эту проблему"
Я пытаюсь создать инструмент, позволяющий пользователю динамически изменять размер полигонов. Большинство полигонов заполнены градиентами fill="url(#top_surface_1_gradient)"
. Как я это делаю, это простой JavaScript script, который:
- ищет mousemove и события click над определенным полигоном
- измеряет количество движения
- изменяет половину координат многоугольника (для того, чтобы иметь эффект растяжения), используя этот алгоритм для определения новых координат:
x = x_movement
,y = x_movement * Math.tan( 31 * (Math.PI/180) )
- многоугольники, заполненные одним цветом, ОК
- многоугольники, заполненные градиентом, не позволяют мне продемонстрировать:
Визуально
Итак, это первый шаг, пользователь не растягивает.
Здесь возникает проблема. Поскольку я не знаю, как изменить координаты x1, y1
и x2, y2
для градиента, он просто остается висящим в нем старой позицией, в то время как многоугольник растянут. Результатом является форма, которая не выдерживает иллюзию глубины.
Конечный результат, который я ищу. И не забывайте, что градиент может иметь совершенно произвольный угол от начала. В результате этого результата, который я ищу, изменились координаты градиента x1, y1
и x2, y2
. Какой алгоритм должен использоваться для расчета этих позиций? Я ищу решение, которое полностью слепило к углу градиента.
Ниже приведен SVG со всеми соответствующими координатами, которые были использованы для генерации этих примеров:
Использование SVG-кода
Шаг 1:
<!-- Step 1 -->
<linearGradient id="top_surface_1_gradient" gradientUnits="userSpaceOnUse" x1="165.3425" y1="39.7002" x2="-49.991" y2="43.0337">
<stop offset="0" style="stop-color:#FFFFFF"/>
<stop offset="0.6687" style="stop-color:#CCCCCC"/>
<stop offset="1" style="stop-color:#FFFFFF"/>
</linearGradient>
<polygon id="top_surface_1" fill="url(#top_surface_1_gradient)" points="137.145,41.204 68.572,0 0,41.204 68.572,82.396"/>
Шаг 2
<!-- Step 2 -->
<linearGradient id="top_surface_2_gradient" gradientUnits="userSpaceOnUse" x1="250.0491" y1="233.8115" x2="23.7637" y2="237.3146">
<stop offset="0" style="stop-color:#FFFFFF"/>
<stop offset="0.6687" style="stop-color:#CCCCCC"/>
<stop offset="1" style="stop-color:#FFFFFF"/>
</linearGradient>
<polygon id="top_surface_2" fill="url(#top_surface_2_gradient)" points="205.788,215.557 137.215,174.354 0.078,256.629 68.649,297.823"/>
Шаг 3
<!-- Step 3 -->
<linearGradient id="top_surface_3_gradient" gradientUnits="userSpaceOnUse" x1="248.4543" y1="454.5225" x2="-75.535" y2="459.5381">
<stop offset="0" style="stop-color:#FFFFFF"/>
<stop offset="0.6687" style="stop-color:#CCCCCC"/>
<stop offset="1" style="stop-color:#FFFFFF"/>
</linearGradient>
<polygon id="top_surface_3" fill="url(#top_surface_3_gradient)" points="205.788,415.557 137.215,374.354 0.078,456.629 68.649,497.823"/>
Я потратил бесчисленное количество часов на разработку решений для этой проблемы, и я просто не мог обойти это. Любая помощь будет принята с благодарностью.
Обновление: gradientTransform не совсем
Использование атрибута gradientTransform и отсутствие x1, y1; x2, y2 для градиента, мы достигаем результатов, которые заполняют многоугольник так, как это необходимо (это решение можно найти здесь: http://jsfiddle.net/hqXx2/). Единственное место, где разрывается решение, - это когда полигон заполнен градиентом, который начинается за пределами многоугольника и/или заканчивается где-то снаружи/внутри. Позвольте мне проиллюстрировать:
Это то, что достигается с помощью решения, которое предлагает Duopixel.
Это пример использования, которого невозможно достичь, используя упомянутое выше решение. Я изменил окраску, чтобы заметно усилить угол и градиентные остановки.
Код SVG из примера
Здесь код для большей, правильно расширенной группы полигонов:
<g>
<linearGradient id="surface_center_inside_bottom_1_" gradientUnits="userSpaceOnUse" x1="167.7629" y1="634.5986" x2="-72.9039" y2="599.2647">
<stop offset="0" style="stop-color:#FFFFFF"/>
<stop offset="0.8528" style="stop-color:#CCCCCC"/>
<stop offset="0.9954" style="stop-color:#CCCCCC"/>
</linearGradient>
<polygon id="surface_center_inside_bottom_9_" fill="url(#surface_center_inside_bottom_1_)" points="137.145,620.04 68.572,578.837 0,620.04 68.572,661.233"/>
<linearGradient id="surface_right_inside_side_1_" gradientUnits="userSpaceOnUse" x1="178.8889" y1="600.1787" x2="33.103" y2="517.9229">
<stop offset="0" style="stop-color:#FFFFFF"/>
<stop offset="0.9816" style="stop-color:#A3A5A8"/>
</linearGradient>
<polygon id="surface_right_inside_side_3_" fill="url(#surface_right_inside_side_1_)" points="136.526,620.374 68.359,578.501 68.572,493.837 137.358,535.37"/>
<linearGradient id="surface_right_inside_side_2_" gradientUnits="userSpaceOnUse" x1="126.2664" y1="563.249" x2="-28.4" y2="621.916">
<stop offset="0" style="stop-color:#FF0000"/>
<stop offset="0.6698" style="stop-color:#00FFFF"/>
<stop offset="1" style="stop-color:#FF0000"/>
</linearGradient>
<polygon id="surface_right_inside_side_5_" fill="url(#surface_right_inside_side_2_)" points="68.573,661.239 0,620.036 0,535.036 68.573,576.231"/>
<linearGradient id="surface_center_outside_top_1_" gradientUnits="userSpaceOnUse" x1="167.3728" y1="533.5059" x2="-47.9608" y2="536.8394">
<stop offset="0.0016" style="stop-color:#FF0000"/>
<stop offset="0.6735" style="stop-color:#00FFFF"/>
<stop offset="1" style="stop-color:#FF0000"/>
</linearGradient>
<polygon id="surface_center_outside_top_3_" fill="url(#surface_center_outside_top_1_)" points="137.145,535.041 68.572,493.837 0,535.041 68.572,576.233"/>
</g>
И вот код SVG для меньшего, который мне нужно развернуть:
<g>
<linearGradient id="surface_right_inside_side_4_" gradientUnits="userSpaceOnUse" x1="273.4377" y1="319.251" x2="78.0696" y2="209.0197">
<stop offset="0" style="stop-color:#FFFFFF"/>
<stop offset="0.9816" style="stop-color:#A3A5A8"/>
</linearGradient>
<polygon id="surface_right_inside_side_9_" fill="url(#surface_right_inside_side_4_)" points="205.112,366.797 136.945,324.924 137.157,156.261 205.731,197.464"/>
<linearGradient id="SVGID_1_" gradientUnits="userSpaceOnUse" x1="247.2952" y1="408.1992" x2="-103.1108" y2="356.7538">
<stop offset="0" style="stop-color:#FFFFFF"/>
<stop offset="0.8528" style="stop-color:#CCCCCC"/>
<stop offset="0.9954" style="stop-color:#CCCCCC"/>
</linearGradient>
<polygon fill="url(#SVGID_1_)" points="205.731,366.465 137.157,325.262 0.021,407.536 68.592,448.729"/>
<linearGradient id="surface_right_inside_side_7_" gradientUnits="userSpaceOnUse" x1="160.3313" y1="296.623" x2="-52.0119" y2="377.1676">
<stop offset="0" style="stop-color:#FF0000"/>
<stop offset="0.6698" style="stop-color:#00FFFF"/>
<stop offset="1" style="stop-color:#FF0000"/>
</linearGradient>
<polygon id="surface_right_inside_side_6_" fill="url(#surface_right_inside_side_7_)" points="68.532,448.767 0,407.497 0.021,238.536 68.592,279.729"/>
<linearGradient id="SVGID_2_" gradientUnits="userSpaceOnUse" x1="248.4749" y1="215.7417" x2="-75.5139" y2="220.7572">
<stop offset="0.0016" style="stop-color:#FF0000"/>
<stop offset="0.6735" style="stop-color:#00FFFF"/>
<stop offset="1" style="stop-color:#FF0000"/>
</linearGradient>
<polygon fill="url(#SVGID_2_)" points="205.731,197.464 137.157,156.261 68.592,197.333 0.021,238.536 68.592,279.729"/>
</g>
@dignifiedquire возьмите эту проблему
Я реализовал предложенный алгоритм @dignifiedquire на тестовом сайте: Здесь тестовая ссылка. Я сделал абсолютное относительное преобразование самостоятельно, и он просто показывает тот же результат, который я обычно добавлял бы таким же значениям полигона x и y в градиент x и y. Это основная проблема - как преобразовать эти значения в такое значение, которое преобразует градиент, как в моих примерах выше?
Требуется дополнительная помощь.