Как сделать "заголовок" (всплывающее, всплывающее, альт-текст) в CSS, который будет использоваться с SVG, без JavaScript

Довольно легко создать всплывающее окно с атрибутом "title" в SVG. Но как вы достигаете такого же эффекта с CSS.

Это для иллюстрации, которую я делаю для Викимедиа, и я стараюсь, чтобы большинство других википедий хотело исправлять встроенную таблицу стилей со свойствами стиля, сгруппированными по предмету реальной жизни. Большинство редакторов wikipedia являются компьютерными неграмотными, вы не можете ожидать, что они будут искать много кода, чтобы внести свои изменения, и если им нужно что-то изменить, кроме простых CSS-значений в коде, тогда вы, вероятно, получите отвратительный беспорядок, Если я сделаю это тяжело для их плохих мозгов, то рано или поздно кто-то сделает файл недостижимым, используя Inkscape, Illustrator или какой-нибудь другой ужасный редактор.

Я мог бы использовать Javascript, но это сделает иллюстрацию менее доступной и сделает код еще более запутанным для людей, которым необходимо его отредактировать. Из-за этого некоторые SVG файлы с использованием Javascript были удалены из Викимедиа, но я не уверен, что это абсолютное правило.


Я только что обнаружил, когда я подтвердил свой файл, что атрибут title в SVG не разрешен там, где я его использовал, но он работает с большинством браузеров. В соответствии со стандартом вы должны использовать элемент title, но это не работает с любыми браузерами. Кроме того, в соответствии со стандартом я мог бы дать атрибут title для элемента стиля, но, похоже, он не работает с каким-либо браузером, и мне потребовалось бы использовать 180 стилей вместо одного (код сгенерированный script, поэтому для меня не проблема создавать их, это просто то, что это сделает код намного больше и сложнее понять).


Два "ответа", которые я получил до сих пор, не были для вопроса, который я задал, и даже не отдаленно полезны.

I не имеет значения, можно ли изменить изображение в Inkscape. Inkscape - хороший инструмент для создания растровых изображений (даже если вам нужно запустить их через какую-либо другую программу, чтобы впоследствии улучшить сжатие). Inkscape всасывает при создании файлов SVG (или любых векторных файлов изображений, предназначенных для аудитории, файлы изображений на основе векторов, созданные Inkscape, действительно полезны только с Inkscape), Inkscape - действительно, действительно, действительно плохой инструмент выбирать для создания изображений SVG, предназначенных как конечный продукт; Sodipodi был хорошим инструментом для этого, но Inkscape - это не Sodipodi, основанный только на Sodipodi (к сожалению, старая C-версия Sodipodi не работает хорошо на современных компьютерных системах, и версия С++ никогда не заканчивалась). Я хочу, чтобы мое изображение было легко отредактировано с помощью текстового редактора, так что ни у кого из Википедии не возникнет соблазна использовать Inkscape и сделать файл unmaintanable (и в процессе увеличить размер от чуть менее 2 МБ до более 60 МБ, если вы сохраните его в Inkscape как "стандартное" SVG-изображение (которое не всегда дает стандартный файл-complient), Inkscapes собственный формат файла на основе svg делает даже более крупные файлы).

Я не думаю, что wikipedia разрешает javascript внутри SVG-изображений, поэтому Javascript не может быть и речи.

Я уже знаю, как создавать всплывающие подсказки с помощью javascript и два разных метода для их создания в SVG (но не в CSS, встроенном в SVG). Причина, в дополнение к уже упомянутой в исходном вопросе, что я не хочу использовать SVG-код для всплывающих подсказок, заключается в том, что ни один веб-браузер не поддерживает стандарт, но SVG-зрители делают (но не нестандартные всплывающие подсказки, которые работают с браузерами), поэтому тот, кто вручную внесет исправления в всплывающую подсказку в файле (с помощью текстового редактора), должен будет изменить текст в двух разных местах, скорее всего, со временем, в результате чего будут отображаться различные подсказки при просмотре в разных браузерах/зрителях.

Ответ 1

Я часто прибегаю к использованию атрибута (недействительного) title= "для элементов SVG, поскольку он настолько прост и, похоже, работает в большинстве браузеров. Я понимаю, что ваше требование состоит в том, что оно соответствует стандартам и что люди могут редактировать графику в InkScape прозрачно и не нарушать всплывающие подсказки - для этого вам придется использовать какой-то JavaScript. Вот быстрый пример, который, надеюсь, вы найдете полезным, он присоединяет событие mouseover к каждому <title> элемент немедленного родителя и загрузите текстовое содержимое во всплывающую подсказку, отображаемую рядом с курсором. Это при сохранении совместимости InkScape и возможности использования диалогового окна" Свойства объекта" InkScape для установки текста всплывающей подсказки.

Учитывая следующий пример SVG:

<svg xmlns="http://www.w3.org/2000/svg">
  <title>Main Title</title>
  <g id="group1">
    <title>Title One</title>
    <circle cx="120" cy="60" r="40" fill="#993333" />
  </g>
  <g id="group2">
    <title>Title Two</title>
    <circle cx="60" cy="60" r="40" fill="#339933" />
    <g id="group3">
      <circle cx="180" cy="60" r="40" fill="#333399" />
      <title>Title Three</title>
    </g>
  </g>
</svg>

Сначала добавьте фиктивный элемент подсказки:

<g id="toolTip" transform="translate(0,0)">
  <rect width="150" height="25" />
  <text x="5" y="18"> </text>
</g>

Дайте ему несколько стилей:

<style>
g#toolTip {
visibility: hidden;
}
  g#toolTip rect {
  fill: #FFCC00;
  }
  g#toolTip text {
  font-size: 16px;
  }
</style>

Затем вставьте опрыскивание JS:

<script>
  <![CDATA[
  var toolTip = document.getElementById('toolTip');
  var titles = document.getElementsByTagName('title');
  for (var i = 0; i < titles.length; i++) {
    titles.item(i).parentNode.addEventListener('mouseover', function(e) {
      showTip(this,xy(e));
    }, true);
    titles.item(i).parentNode.addEventListener('mouseout', function() {
      hideTip();
    }, true);
  }
  function showTip(element,pos) {
    var text = element.getElementsByTagName('title')[0].childNodes[0].nodeValue;
    toolTip.getElementsByTagName('text')[0].childNodes[0].nodeValue = text;
    toolTip.setAttribute('transform', 'translate(' + pos + ')');
    toolTip.style.visibility = 'visible';
  }
  function hideTip() {
    toolTip.style.visibility = 'hidden';
  }
  function xy(e) {
    if (!e) var e = window.event;
    if (e.pageX || e.pageY) {
      return [e.pageX,e.pageY]
    } else if (e.clientX || e.clientY) {
      return [e.clientX + document.body.scrollLeft + document.documentElement.scrollLeft,e.clientY + document.body.scrollTop + document.documentElement.scrollTop];
    }
    return [0,0]
  }
  ]]>
</script>

Предостережения: блок JS должен идти в нижней части файла SVG - и если вы используете редактор XML в InkScape (редко), это испортит script (это может быть разрешено путем перехода на внешний JS файл и добавление некоторого обнаружения готовности DOM).

Подход также ожидает, что a) all <title> элементы должны отображаться в виде подсказок и b) что существует только один <title> элемент на родителя (как ни странно, спецификация SVG допускает несколько) - здесь я жестко закодировал его, чтобы просто использовать первый <title> дочерний элемент, игнорируя любые последующие.

Примечание. Функция xy (e) нужна только для того, чтобы обойти несогласованность браузера, когда дело доходит до сообщения о позиции курсора - вам может и не понадобиться, или вы можете предпочесть перевернуть свой собственный.

Бонус: это можно легко расширить, чтобы использовать <desc> также, если вам нужны более сложные всплывающие подсказки с более длинными фрагментами текста.

Ответ 2

Насколько я могу вам сказать, вы не можете. Элемент SVG, кажется, ведет себя странно.

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

<style type="text/css">
acronym{
    position:relative
}
acronym:after {
    content:attr(title);
    position:absolute;
    position:absolute;
    left:100%;
    margin-left:-10px;
    top:-0.5em;
    z-index:2;
    padding:0.25em;
    width:200px;
    background-color:#f1f1f1;
    text-align:center;
    display:none;   
}
acronym:hover:after{
    display:block;
}
</style>

<acronym title="Keep It Simple Stupid"><a href="/">KISS</a></acronym>

Но селектор :after не работает над элементом SVG

Я думаю, что ваш лучший выбор - это jQuery script, который работает на $(document).ready() и делает все тяжелую работу для вас.

Ответ 3

Эта статья: http://codepen.io/recursiev/pen/zpJxs демонстрирует несколько типов подсказок с SVG.

Включая то, что вы просили: SVG + CSS.

В принципе:

<g class="tooltip css" transform="translate(200,50)">
    <rect x="-3em" y="-45" width="6em" height="1.25em"/>
    <text y="-45" dy="1em" text-anchor="middle" fill="LightSeaGreen">
        SVG/CSS Tip</text>
</g>

С некоторыми соответствующими CSS:

.tooltip {
    pointer-events:none; /*let mouse events pass through*/
    opacity:0;
    transition: opacity 0.3s;
    text-shadow:1px 1px 0px gray;
}
g.tooltip:not(.css) {
    fill:currentColor;
}
g.tooltip rect {
    fill: lightblue;
    stroke: gray;
}

Эта статья: http://www.scientificpsychic.com/etc/css-mouseover.html демонстрирует только подсказки CSS.

в основном

<span class="dropt" title="Title for the pop-up">Hot Zone Text
    <span style="width:500px;">Pop-up text</span>
</span>

с этим CSS:

span.dropt {border-bottom: thin dotted; background: #ffeedd;}
span.dropt:hover {text-decoration: none; background: #ffffff; z-index: 6; }
span.dropt span {position: absolute; left: -9999px;
  margin: 20px 0 0 0px; padding: 3px 3px 3px 3px;
  border-style:solid; border-color:black; border-width:1px; z-index: 6;}
span.dropt:hover span {left: 2%; background: #ffffff;} 
span.dropt span {position: absolute; left: -9999px;
  margin: 4px 0 0 0px; padding: 3px 3px 3px 3px; 
  border-style:solid; border-color:black; border-width:1px;}
span.dropt:hover span {margin: 20px 0 0 170px; background: #ffffff; z-index:6;}

Между ними вы сможете получить именно то, что хотите.

UPDATE: это отлично работает для меня в Chrome v44, но не в Internet Explorer v9. IE просто дает мне всплывающее название, а не всплывающее окно.