Как изменить цвет заливки SVG с помощью внешнего CSS [duplicate]

Что такое «неопределенный ссылочный / неразрешенный внешний символ»

Я попытаюсь объяснить, что такое «неопределенный ссылочный / неразрешенный внешний символ».

note : я использую g ++ и Linux, и все примеры для него

Например, у нас есть некоторый код

// src1.cpp
void print();

static int local_var_name; // 'static' makes variable not visible for other modules
int global_var_name = 123;

int main()
{
    print();
    return 0;
}

и

// src2.cpp
extern "C" int printf (const char*, ...);

extern int global_var_name;
//extern int local_var_name;

void print ()
{
    // printf("%d%d\n", global_var_name, local_var_name);
    printf("%d\n", global_var_name);
}

Создание объектных файлов

$ g++ -c src1.cpp -o src1.o
$ g++ -c src2.cpp -o src2.o

После фазы ассемблера у нас есть объектный файл, который содержит любые экспортируемые символы. Посмотрите на символы

$ readelf --symbols src1.o
  Num:    Value          Size Type    Bind   Vis      Ndx Name
     5: 0000000000000000     4 OBJECT  LOCAL  DEFAULT    4 _ZL14local_var_name # [1]
     9: 0000000000000000     4 OBJECT  GLOBAL DEFAULT    3 global_var_name     # [2]

Я отклонил некоторые строки из вывода, потому что они не имеют значения

Итак, мы видим следующие символы для экспорта.

[1] - this is our static (local) variable (important - Bind has a type "LOCAL")
[2] - this is our global variable

src2.cpp ничего не экспортирует, и мы не видели его символов

Свяжите наши объектные файлы

$ g++ src1.o src2.o -o prog

и запустите его

$ ./prog
123

Linker видит экспортированные символы и связывает их. Теперь мы пытаемся раскомментировать строки в src2.cpp, как здесь

// src2.cpp
extern "C" int printf (const char*, ...);

extern int global_var_name;
extern int local_var_name;

void print ()
{
    printf("%d%d\n", global_var_name, local_var_name);
}

, и перестроить объектный файл

$ g++ -c src2.cpp -o src2.o

OK (нет ошибок), потому что мы только строим объектный файл, связь еще не завершена. Попробуйте установить ссылку

$ g++ src1.o src2.o -o prog
src2.o: In function `print()':
src2.cpp:(.text+0x6): undefined reference to `local_var_name'
collect2: error: ld returned 1 exit status

Это произошло потому, что наше local_var_name статично, то есть оно не отображается для других модулей. Теперь глубже. Получить выход фазы перевода

$ g++ -S src1.cpp -o src1.s

// src1.s
look src1.s

    .file   "src1.cpp"
    .local  _ZL14local_var_name
    .comm   _ZL14local_var_name,4,4
    .globl  global_var_name
    .data
    .align 4
    .type   global_var_name, @object
    .size   global_var_name, 4
global_var_name:
    .long   123
    .text
    .globl  main
    .type   main, @function
main:
; assembler code, not interesting for us
.LFE0:
    .size   main, .-main
    .ident  "GCC: (Ubuntu 4.8.2-19ubuntu1) 4.8.2"
    .section    .note.GNU-stack,"",@progbits

Итак, мы видели, что для local_var_name нет метки, поэтому линкер не нашел его. Но мы хакеры :), и мы можем это исправить. Откройте src1.s в текстовом редакторе и измените

.local  _ZL14local_var_name
.comm   _ZL14local_var_name,4,4

на

    .globl  local_var_name
    .data
    .align 4
    .type   local_var_name, @object
    .size   local_var_name, 4
local_var_name:
    .long   456789

i.e. вам должно быть как ниже

    .file   "src1.cpp"
    .globl  local_var_name
    .data
    .align 4
    .type   local_var_name, @object
    .size   local_var_name, 4
local_var_name:
    .long   456789
    .globl  global_var_name
    .align 4
    .type   global_var_name, @object
    .size   global_var_name, 4
global_var_name:
    .long   123
    .text
    .globl  main
    .type   main, @function
main:
; ...

мы изменили видимость local_var_name и установили его значение в 456789. Попробуйте построить из него объектный файл

$ g++ -c src1.s -o src2.o

ok, см.

$ readelf --symbols src1.o
8: 0000000000000000     4 OBJECT  GLOBAL DEFAULT    3 local_var_name

В настоящее время local_var_name имеет привязку GLOBAL (LOCAL)

link

$ g++ src1.o src2.o -o prog

и запускает ее

$ ./prog 
123456789

ok, мы взломаем его:)

Итак, в результате - «неопределенная ссылка / неразрешенная внешняя ошибка символа» происходит, когда компоновщик не может найти глобальные символы в объектных файлах.

62
задан Joey 25 August 2013 в 22:50
поделиться

11 ответов

Ваш файл main.css повлияет только на содержимое SVG, если SVG-файл включен в HTML:

https://developer.mozilla.org/ ru / docs / SVG_In_HTML_Introduction

<html>
  <body>
  <svg version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" viewBox="0 0 56.69 56.69">
    <g>
      <path d="M28.44......./>
    </g>
  </svg>
</html>

Если вы хотите сохранить SVG в файлах, CSS необходимо определить внутри SVG-файла.

Вы можете сделать это с помощью тега стиля:

http://www.w3.org/TR/SVG/styling.html#StyleElementExample

<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" 
  "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
<svg xmlns="http://www.w3.org/2000/svg" version="1.1"
     width="50px" height="50px" viewBox="0 0 50 50">
  <defs>
    <style type="text/css"><![CDATA[
      .socIcon g {
        fill:red;
      }
    ]]></style>
  </defs>
  <g>
    <path d="M28.44......./>
  </g>
</svg>

Вы можете использовать инструмент на стороне сервера для обновления тега стиля в зависимости от активного стиля. В рубине вы могли добиться этого с Нокогири. SVG - это просто XML. Таким образом, возможно, существует много доступных XML-библиотек, которые, возможно, могут это достичь.

Если вы не можете этого сделать, вам придется просто использовать их, как если бы они были PNG; создавая набор для каждого стиля и сохраняя их встроенные стили.

61
ответ дан Paul D. Waite 23 August 2018 в 19:03
поделиться

Вы можете делать то, что хотите, с одним (важным) предупреждением: пути внутри вашего символа не могут быть созданы независимо через внешний CSS - вы можете только установить свойства для всего символа с помощью этого метода. Итак, если у вас есть два пути в вашем символе и хотите, чтобы у них были разные цвета заливки, это не сработает, но если вы хотите, чтобы все ваши пути были одинаковыми, это должно работать.

В вашем html, вы хотите что-то вроде этого:

<style>
  .fill-red { fill: red; }
  .fill-blue { fill: blue; }
</style>

<a href="//www.example.com/">
  <svg class="fill-red">
    <use xlink:href="images/icons.svg#example"></use>
  </svg>
</a>

И во внешнем SVG-файле вы хотите что-то вроде этого:

<svg xmlns="http://www.w3.org/2000/svg">
   <symbol id="example" viewBox="0 0 256 256">
    <path d="M120.... />
  </symbol>
</svg>

Поменяйте класс на теге svg (в вашем html) с fill-red до fill-blue и ta-da ... у вас есть синий, а не красный.

Вы можете частично преодолеть ограничение возможности таргетинга на пути отдельно с помощью внешний CSS путем смешивания и сопоставления внешнего CSS с некоторым встроенным CSS на определенных путях, поскольку встроенный CSS будет иметь приоритет. Такой подход будет работать, если вы делаете что-то вроде белого значка на цветном фоне, где вы хотите изменить цвет фона через внешний CSS, но сам значок всегда белый (или наоборот). Итак, с тем же HTML, что и раньше, и что-то вроде этого кода svg, вы получите красный фон и белый путь переднего плана:

<svg xmlns="http://www.w3.org/2000/svg">
  <symbol id="example" viewBox="0 0 256 256">
    <path class="background" d="M120..." />
    <path class="icon" style="fill: white;" d="M20..." />
  </symbol>
</svg>
31
ответ дан Adam Korman 23 August 2018 в 19:03
поделиться

«Я действительно собираюсь изменить цвета этих изображений на основе той цветовой схемы, которую пользователь выбрал для моего сайта». - Jordan 10 часов назад

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

<?php

    header('Content-Type: image/svg+xml');
    echo '<?xml version="1.0" encoding="utf-8"?>';
    $color = $_GET['color'];

?>
<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">

<svg version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" viewBox="0 0 56.69 56.69">
    <g>
        <path fill="<?php echo $color; ?>" d="M28.44..."/>
    </g>
</svg>

И позже вы можете использовать этот файл как filename.php?color=#ffffff, чтобы получить файл svg в желаемом цвете.

1
ответ дан Community 23 August 2018 в 19:03
поделиться

Я знаю его старое сообщение, но просто для устранения этой проблемы ... вы просто используете свои классы не в том месте: D

Прежде всего вы можете использовать

svg { fill: red; }

в вашем main.css, чтобы он был красным. Это имеет эффект. Вы также можете использовать селектора узлов, чтобы получить конкретные патчи.

Во-вторых, вы объявили класс в img -Tag.

<img class='socIcon'....

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

<?xml version="1.0" encoding="utf-8"?>
<?xml-stylesheet href="stylesheets/main.css" type="text/css"?>
<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">

<svg version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" viewBox="0 0 56.69 56.69">
<g>
    <path class="myClassForMyPath" d="M28.44......./>
</g>
</svg>

теперь вы можете изменить цвет в своем main.css, например

.myClassForMyPath {
    fill: yellow;
}
1
ответ дан Dwza 23 August 2018 в 19:03
поделиться

Что работает для меня: тег стиля с правилом @import

<defs>
    <style type="text/css">
        @import url("svg-common.css");
    </style>
</defs>
1
ответ дан Fordi 23 August 2018 в 19:03
поделиться

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

-1
ответ дан HTMLGUY1999 23 August 2018 в 19:03
поделиться

Это должно быть возможно сделать, сначала вставив внешние изображения svg. Посмотрите здесь, например:

Заменить все изображения Svg с помощью Inline Svg | JAVASCRIPT | Библиотека фрагмента кода Джесс Фразель

3
ответ дан Leo 23 August 2018 в 19:03
поделиться

Можно создать стиль SVG путем динамического создания элемента стиля в JavaScript и добавления его в элемент SVG. Hacky, но он работает.

<object id="dynamic-svg" type="image/svg+xml" data="your-svg.svg">
    Your browser does not support SVG
</object>
<script>
    var svgHolder = document.querySelector('object#dynamic-svg');
    svgHolder.onload = function () {
        var svgDocument = svgHolder.contentDocument;
        var style = svgDocument.createElementNS("http://www.w3.org/2000/svg", "style");

        // Now (ab)use the @import directive to load make the browser load our css
        style.textContent = '@import url("/css/your-dynamic-css.css");';

        var svgElem = svgDocument.querySelector('svg');
        svgElem.insertBefore(style, svgElem.firstChild);
    };
</script>

Вы можете генерировать JavaScript динамически на PHP, если хотите - тот факт, что это возможно в JavaScript, открывает множество возможностей.

5
ответ дан Pete 23 August 2018 в 19:03
поделиться

При использовании в теге <image> SVG должен содержаться в одном файле по соображениям конфиденциальности. Эта ошибка bugzilla содержит более подробную информацию о том, почему это так. К сожалению, вы не можете использовать другой тег, такой как <iframe>, потому что это не будет работать как ссылка, поэтому вам придется встроить CSS в тег <style> внутри самого файла.

Еще один способ сделать это - иметь SVG-данные в основном файле html, т. Е.

<a href='http://youtube.com/...' target='_blank'>
  <svg id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" viewBox="0 0 56.69 56.69">
    <g>
        <path d="M28.44......./>
    </g>
  </svg>
</a>

. Вы можете создать стиль с помощью внешнего файла CSS с использованием тега HTML <link>.

2
ответ дан Robert Longson 23 August 2018 в 19:03
поделиться

Один из подходов, который вы можете предпринять, - это просто использовать фильтры CSS, чтобы изменить внешний вид графики SVG в браузере.

Например, если у вас есть SVG-графический файл, который использует цвет заливки красного цвета внутри SVG-код, вы можете включить его фиолетовым с настройкой поворота оттенка на 180 градусов:

#theIdOfTheImgTagWithTheSVGInIt {
    filter: hue-rotate(180deg);
    -webkit-filter: hue-rotate(180deg);
    -moz-filter: hue-rotate(180deg);
    -o-filter: hue-rotate(180deg);
    -ms-filter: hue-rotate(180deg);
}

Экспериментируйте с другими настройками поворота, чтобы найти нужные цвета.

Чтобы быть ясным, приведенный выше CSS идет в CSS, который применяется к вашему HTML-документу. Вы ставите тег img в HTML-код, не устраивая код SVG.

И обратите внимание, что это не будет работать с графикой, заполненной черным или белым или серым цветом. Вы должны иметь фактический цвет, чтобы вращать оттенок этого цвета.

3
ответ дан Simon White 23 August 2018 в 19:03
поделиться

Очень быстрое решение для динамического стиля с внешней таблицей стилей CSS, если вы используете тэг <object> для вставки вашего svg.

В этом примере добавится класс к корню <svg> при нажатии на родительский элемент.

file.svg:

<?xml-stylesheet type="text/css" href="../svg.css"?>
 <svg xmlns="http://www.w3.org/2000/svg" viewBox="">
  <g>
   <path/>
  </g>
 </svg>

html:

<a class="parent">
  <object data="file.svg"></object>
</a>

JQuery:

$(function() {
  $(document).on('click', '.parent', function(){
    $(this).find('object').contents().find('svg').attr("class","selected");
  }
});

на родительском элементе click:

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

, тогда вы можете управлять своим css

svg.css:

path {
 fill:none;
 stroke:#000;
 stroke-miterlimit:1.41;
 stroke-width:0.7px;
}

.selected path {
 fill:none;
 stroke:rgb(64, 136, 209);
 stroke-miterlimit:1.41;
 stroke-width:0.7px;
}
2
ответ дан vhanahrni 23 August 2018 в 19:03
поделиться