html与svg中js交互
Quite some time ago a reader asked for my help in creating a special UI effect for a German skateboard club: mouseover (or touch) any skater in the photo above to see the effect.
相当一段时间以前,一位读者在我的帮助下为德国滑板俱乐部创建了特殊的UI效果:将鼠标悬停在(或触摸)上图中的任何溜冰者以查看效果。
The creative process was unique enough to deserve a two-part series: this article analyses the workflow and code for the effect, while a follow-up will detail the information popups for each skater.
创作过程非常独特,值得分两部分进行:本文分析了效果的工作流程和代码,而后续活动将详细介绍每个溜冰者的信息弹出窗口。
命中地区 (Making The Hit Areas)
The core of the effect required two copies of the image: one in SVG, and the other as a background. The “hotspot” areas for each skater would serve two functions: a general hit area for the skater, and a mask that would be applied to that portion of the image.
效果的核心需要图像的两份副本:一份在SVG中 ,另一份作为背景。 每个滑冰者的“热点”区域将具有两个功能:滑冰者的常规打击区域和将应用于图像的该部分的蒙版。

Creating the paths by hand in Adobe Illustrator wouldn’t work well: the image was a little too complex for Trace
to work. Instead, I used PhotoShop’s Magnetic Lasso tool. The selection made for each skater was saved as a path, and the paths exported to Illustrator, adjusted to fit on top of the background image, and then exported to SVG. (If using the latest version of Adobe PhotoShop CC, you could also export the PSD directly to SVG.)
在Adobe Illustrator中手动创建路径效果不佳:图像太复杂,无法使用Trace
。 相反,我使用了PhotoShop的Magnetic Lasso工具。 为每个滑手所做的选择都保存为路径,并且路径导出到Illustrator,进行调整以适合背景图像的顶部,然后导出到SVG。 (如果使用最新版本的Adobe PhotoShop CC,您还可以将PSD直接导出到SVG 。)
放置SVG (Placing The SVG)
After cleanup, the exported SVG paths are given appropriate id
values, placed inside links, and the SVG itself placed inside a <div>
:
清理后,将为导出的SVG路径提供适当的id
值 ,并将其放置在链接中,并将SVG本身放置在<div>
:
<div id="skateclub">
<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" viewBox="0 0 2074 1382">
<image width="2074" height="1382" xlink:href="team-photo.jpg">
</image>
<a id="konni" xlink:href="#">
<title>Konni</title>
<path id="konni-mask-path" d="M427.7,450.3c26.5-0.7…"/>
</a>
…
</svg>
</div>
The <title>
element inside each link creates the pop-up text over each link.
每个链接内的<title>
元素在每个链接上创建弹出文本。
增强CSS (Enhancing With CSS)
The initial CSS places the image correctly in the background of the <div>
element; font-size: 0
is used to ensure that the SVG image and the background image remain perfectly matched. Note that the exact same image is used in both the SVG and the background; rather than making a greyscale copy, we’ll change the appearance of the background-image
using blend modes.
初始CSS将图像正确放置在<div>
元素的背景中; font-size: 0
用于确保SVG图像和背景图像保持完美匹配。 注意SVG和背景都使用完全相同的图像 ; 而不是进行灰度复制,我们将使用混合模式更改background-image
的外观。
#skateclub {
background-image: url(team-photo.jpg);
background-position: center center;
background-size: cover;
font-size: 0;
background-blend-mode: luminosity;
transition: 1s;
}
#skateclub path { opacity: 0; }
Because there’s no background-color
applied to the #skateclub
element, the background-blend-mode
has no effect at this point. The SVG paths are automatically filled with black; to make them disappear, I’ve set their opacity
to 0
.
因为没有background-color
应用于#skateclub
元素,所以background-blend-mode
在这一点上无效。 SVG路径会自动填充为黑色; 为了使它们消失,我将其opacity
设置为0
。
Returning to the SVG, a series of clipPath
elements reference the earlier paths:
返回到SVG,一系列clipPath
元素引用了先前的路径:
<clipPath id="konni-clip">
<use xlink:href="#konni-mask-path" />
</clipPath>
…
These clipPaths are not applied automatically; we’re going to do that via CSS and JavaScript.
这些clipPath 不会自动应用。 我们将通过CSS和JavaScript做到这一点。
增加互动 (Adding Interactivity)
Before turning to the rollover effects, one more style declaration is added to the CSS:
在转向过渡效果之前,向CSS添加了另一个样式声明:
.hovered {
background-color: #000;
}
This will be activated via JavaScript added to the bottom of the page:
这将通过添加到页面底部JavaScript激活:
var clubcontainer = document.getElementById("skateclub"),
skateclub = clubcontainer.querySelector("svg"),
shapeLinks = skateclub.querySelectorAll("a");
for (var i=0; i < shapeLinks.length; i++) {
shapeLinks[i].addEventListener("mouseenter", trackEnter, false);
shapeLinks[i].addEventListener("mouseleave", trackLeave, false);
}
After gathering all the SVG links, two functions (trackEnter
and trackLeave
) are added to each:
收集所有SVG链接后,向每个函数添加了两个函数( trackEnter
和trackLeave
):
function trackEnter(evt) {
skater = evt.target.id;
skateclub.style.cssText = "clip-path:url(#"+skater+"-clip)";
clubcontainer.classList.add("hovered");
}
function trackLeave() {
skateclub.style.cssText = "";
clubcontainer.classList.remove("hovered");
}
When the mouse (or touch) enters the area, the current id
of the link is gained and concatenated with the word “clip” to get the appropriate clipPath
, which is then applied to the SVG, making everything disappear in the SVG disappear except for the current skater. At the same time, the .hovered
class is added to the <div>
, adding a background-color
. In combination with the background-blend-mode
, this turns the background image black-and-white, completing the effect. To see the complete code, check out the CodePen repo.
当鼠标(或触摸)进入该区域时,将获取链接的当前id
,并将其与单词“ clip”连接起来以获取适当的clipPath
,然后将其应用到SVG,从而使除SVG之外的所有内容消失当前的溜冰者。 同时,将.hovered
类添加到<div>
,并添加了background-color
。 与background-blend-mode
结合使用,可以将背景图像变成黑白,从而完成效果。 要查看完整的代码,请签出CodePen存储库。
However, this UI is not yet complete: each of the skaters deserves their own profile information popup, which I’ll detail in the next article.
但是,此UI尚未完成:每个滑冰者都应该拥有自己的个人资料信息弹出窗口,我将在下一篇文章中详细介绍。
html与svg中js交互