如何在没有JavaScript的情况下在CSS中制作"title"(工具提示,弹出窗口,替代文本)以与SVG一起使用



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

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

我可以使用Javascript,但这会使插图更难访问,并且使需要编辑它的人更容易混淆代码。此外,一些使用Javascript的svg文件也因此从维基媒体上删除了,但我不确定这是否是绝对的规则。


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


到目前为止,我得到的两个"答案"都不是针对我所问的问题,甚至一点用处都没有。

不关心图像在Inkscape中是否可编辑。Inkscape是一个创建位图图像的好工具(即使您必须通过其他程序运行它们以获得更好的压缩效果)。Inkscape在创建SVG文件方面很糟糕(或者任何面向受众的基于矢量的图像文件,Inkscape创建的基于矢量的图像文件只有在Inkscape中才真正有用),Inkscape对于创建作为最终产品的SVG图像来说是一个非常非常糟糕的工具;Sodipodi是一个很好的工具,但是Inkscape不是Sodipodi,只是基于Sodipodi(不幸的是,旧的C版本的Sodipodi不能在现代计算机系统上很好地运行,而c++版本从未完成)。我想让我的图像易于用文本编辑器编辑,这样维基人就不会试图使用Inkscape并使文件无法维护(并且在此过程中将大小从略低于2mb增加到超过60mb,如果您将其保存为Inkscape中的"标准"SVG图像(并不总是提供标准的辅助文件),Inkscape自己的基于SVG的文件格式可以生成更大的文件)。

我认为维基百科不允许在svg图像中使用javascript,所以 javascript是不可能的

我已经知道如何用javascript和两种不同的方法在SVG中创建工具提示(但不是在SVG中嵌入的CSS中)。除了在原始问题中已经提到的原因之外,我不想使用SVG代码作为工具提示的原因是没有web浏览器支持该标准,但是SVG查看器支持(但不支持与浏览器一起工作的非标准工具提示),因此手动更正文件中的工具提示的人(使用文本编辑器)将不得不在两个不同的地方更改文本,最有可能的是,随着时间的推移。

在不同的浏览器/查看器中显示不同的工具提示。

我经常在SVG元素上使用(无效的)title="属性,因为它非常简单,似乎在大多数浏览器中都能工作。我理解你的要求是它是符合标准的,人们可以在InkScape中透明地编辑图形,而不会破坏工具提示——为此,你将不得不使用一些JavaScript。这里有一个快速的例子,我希望你会发现有用的,它将鼠标悬停事件附加到每个<标题>元素的直接父元素,并在光标旁边显示的工具提示中加载文本内容。同时保留了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文件的底部——如果你使用InkScape中的XML编辑器(很少见),它会弄乱脚本(这可以通过移动到外部JS文件并添加一些DOM就绪检测来解决)。

方法还期望a) all

元素应该呈现为工具提示和b)只有一个<strong></strong><title>元素每个父元素(奇怪的是,SVG规范允许多个)—这里我硬编码它,只使用第一个<title>遇到的子元素,忽略任何后续元素。<p>注意:xy(e)函数只需要在报告光标位置时解决浏览器不一致的问题-您可能不需要它,或者您可能更喜欢自己滚动。</p><p>附加:这可以很容易地扩展以使用<desc>元素,如果您需要更详细的工具提示和更长的文本。</desc></p>

据我所知你不能。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元素上工作

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

本文: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;}

在这两者之间,你应该能够得到你想要的。

更新:这在Chrome v44中对我很好,但在Internet Explorer v9中不行。IE只给我弹出窗口的标题,而不是弹出窗口本身。

最新更新