如何在CSS中创建一个"标题"(工具提示,弹出窗口,替代文本)以与SVG一起使用,而无需JavaScript

mja*_*mja 11 css svg wikipedia

使用SVG中的"title"属性创建弹出窗口非常容易.但是你如何用CSS实现同样的效果呢?

这是我为维基媒体制作的一个例子,我努力让其他维基人员想要在嵌入式样式表中纠正大部分内容,其中样式属性按照现实主题分组.大多数维基百科编辑都是计算机文盲,你不能指望他们通过大量代码进行修改以及如果他们必须在代码中改变除了简单的CSS值之外的任何东西,那么你可能会得到一个令人讨厌的混乱.如果我为他们可怜的大脑努力做到这一点,那么迟早有人会通过使用Inkscape,Illustrator或其他同样可怕的矢量编辑器来使文件无法维护.

我可以使用Javascript,但这会使插图不易访问,并使代码更容易让需要编辑它的人感到困惑.此外,由于这一点,一些使用Javascript的SVG文件已从维基媒体中删除,但我不确定这是否是绝对的规则.


我刚刚发现,当我验证我的文件时,SVG中的title-attribute不允许在我使用它的地方,但它适用于大多数浏览器.根据标准,您应该使用title-element,但这似乎不适用于任何浏览器.此外,根据标准,我可以给一个样式元素一个title-attribute,但这似乎不适用于任何浏览器,它需要我使用180个样式元素而不是一个(代码是由脚本生成,因此创建它们不是问题,只是它会使代码更大,更难理解).


到目前为止我得到的两个"答案"并不是针对我提出的问题,甚至没有用处.

不在乎图像是否可以在Inkscape中编辑.Inkscape是创建位图图像的好工具(即使你必须通过其他程序运行它们以便之后获得更好的压缩).Inkscape很难创建SVG文件(或任何面向观众的基于矢量的图像文件,Inkscape创建的基于矢量的图像文件只对Inkscape非常有用),Inkscape是一个非常非常非常糟糕的工具,可用于创建预期的SVG图像作为最终产品; Sodipodi是一个很好的工具,但是Inkscape并不是Sodipodi,只是基于Sodipodi(不幸的是,Sodipodi的旧C版本在现代计算机系统上运行不佳而且C++版本从未完成).我希望使用文本编辑器轻松编辑我的图像,这样任何维基百科都不会试图使用Inkscape并使文件无法管理(并且在此过程中将大小从略小于2 MB增加到超过60 MB,如果你将它作为"标准"SVG图像保存在Inkscape中(并不总是提供标准的兼容文件),Inkscapes自己的基于svg的文件格式可以生成更大的文件).

我不认为维基百科允许在SVG图像中使用javascript,因此Javascript是不可能.

我已经知道如何使用javascript和两种不同的方法创建工具提示来在SVG中创建它们(但不是在SVG中嵌入的CSS中).除了在原始问题中已经提到的那个之外,我不想在工具提示中使用SVG代码的原因是没有Web浏览器支持标准,但SVG查看器(但不是非标准)与浏览器一起使用的工具提示),那么手动对文件中的工具提示进行更正(使用文本编辑器)的人必须在两个不同的地方更改文本,最有可能的是,随着时间的推移,在查看时会导致不同的工具提示在不同的浏览器/查看器中.

Ola*_*son 6

我经常在 SVG 元素上使用(无效的)title="" 属性,因为它非常简单并且似乎可以在大多数浏览器中使用。我理解您的要求是它符合标准,并且人们可以在 InkScape 中透明地编辑图形,而不会破坏工具提示 - 为此,您必须使用一些 JavaScript。这是一个简单的例子,我希望你会觉得有帮助,它将鼠标悬停事件附加到每个 <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>
Run Code Online (Sandbox Code Playgroud)

首先添加一个虚拟工具提示元素:

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

给它一些样式:

<style>
g#toolTip {
visibility: hidden;
}
  g#toolTip rect {
  fill: #FFCC00;
  }
  g#toolTip text {
  font-size: 16px;
  }
</style>
Run Code Online (Sandbox Code Playgroud)

然后插入一点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>
Run Code Online (Sandbox Code Playgroud)

警告:JS 块需要位于 SVG 文件的底部 - 如果您在 InkScape 中使用 XML 编辑器(罕见),它会弄乱脚本(这可以通过移动到外部 JS 文件并添加一些 DOM 来解决)准备检测)。

该方法还期望 a)所有<title> 元素都应该呈现为工具提示和 b)每个父元素只有一个<title> 元素(奇怪的是,SVG 规范允许多个) - 在这里我已经将它硬编码为简单使用遇到的第一个 <title> 子元素,忽略任何后续元素。

注意:xy(e) 函数只需要在报告光标位置时解决浏览器不一致的问题 - 您可能不需要它,或者您可能更喜欢自己滚动。

奖励:这可以很容易地扩展为使用 <desc> 元素,如果您需要带有更长文本的更详细的工具提示。


小智 1

据我所知你不能。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>
Run Code Online (Sandbox Code Playgroud)

:after选择器似乎不适用于 SVG 元素

我认为你最好的选择是一个 jQuery 脚本,它可以运行$(document).ready()并为你完成所有繁重的工作。