坑爹的三角形导航终于制作完成了,下面分享一下思路,先看最终效果:
http://mall.juesheng.com/act/butie3
基本思路:使用古老的 Image Mapping 技术,在图片上定义多边形锚点,然后监听每个锚点的鼠标事件,显示指定的元素,实现锚点的高亮,由于 Image Mapping 中的多边形锚点不支持样式化,需要用其他手段进行高亮,先贴出 DOM 结构:
<div class='map-box'>
<div class='map-layout-0'></div>
<div class='map-layout-1' id='mapNodeList'>
<div class='map-node map-node-0'>
<img src='<!--#echo var='v_dir_img'-->/mall/act/butie3/tri_lt.png' width='110' height='109'>
<em>古筝</em>
</div>
<div class='map-node map-node-1'>
<img src='<!--#echo var='v_dir_img'-->/mall/act/butie3/tri_rb.png' width='114' height='114'>
<em>钢琴</em>
</div>
<div class='map-node map-node-2'>
<img src='<!--#echo var='v_dir_img'-->/mall/act/butie3/tri_lt.png' width='147' height='147'>
<em>瑜伽</em>
</div>
<div class='map-node map-node-3'>
<img src='<!--#echo var='v_dir_img'-->/mall/act/butie3/tri_lt.png' width='147' height='147'>
<em>雅思</em>
</div>
<div class='map-node map-node-4'>
<img src='<!--#echo var='v_dir_img'-->/mall/act/butie3/tri_rb.png' width='147' height='147'>
<em>英语思维</em>
</div>
<div class='map-node map-node-5'>
<img src='<!--#echo var='v_dir_img'-->/mall/act/butie3/tri_tr.png' width='147' height='147'>
<em>舞蹈</em>
</div>
<div class='map-node map-node-6'>
<img src='<!--#echo var='v_dir_img'-->/mall/act/butie3/tri_rb.png' width='147' height='147'>
<em>吉他</em>
</div>
<div class='map-node map-node-7'>
<img src='<!--#echo var='v_dir_img'-->/mall/act/butie3/tri_lt.png' width='146' height='146'>
<em>少儿街舞</em>
</div>
<div class='map-node map-node-8'>
<img src='<!--#echo var='v_dir_img'-->/mall/act/butie3/tri_lt.png' width='147' height='147'>
<em>素描</em>
</div>
<div class='map-node map-node-9'>
<img src='<!--#echo var='v_dir_img'-->/mall/act/butie3/tri_rb.png' width='113' height='112'>
<em>艺考</em>
</div>
</div>
<img src='<!--#echo var='v_dir_img'-->/10x10.gif' width='639' height='359'
usemap='#navMap' class='map-img' alt='导航图'>
<map name='navMap' id='navMap'>
<area href='javascript:' shape='poly' coords='119,67,119,171,223,67' alt='钢琴'>
<area href='javascript:' shape='poly' coords='100,195,204,195,204,91' alt='音乐'>
<area href='javascript:' shape='poly' coords='63,199,63,338,202,199' alt='舞蹈'>
<area href='javascript:' shape='poly' coords='246,17,246,155,384,17' alt='跆拳道'>
<area href='javascript:' shape='poly' coords='208,197,348,197,348,57' alt='少儿英语'>
<area href='javascript:' shape='poly' coords='210,199,348,337,348,199' alt='架子鼓'>
<area href='javascript:' shape='poly' coords='354,178,494,178,494,38' alt='艺考'>
<area href='javascript:' shape='poly' coords='351,181,351,320,490,181' alt='寒假强化班'>
<area href='javascript:' shape='poly' coords='496,69,496,207,634,69' alt='跆拳道'>
<area href='javascript:' shape='poly' coords='447,262,553,262,553,156' alt='钢琴'>
</map>
</div>
从 DOM 结构中可以看出,我们使用了三层结构:
一、map-layout-0,空元素,但它的样式中,定义了其背景图片为:
这是一个半透明的 PNG 图片
二、map-layout-1,这一层用来高亮锚点,每一个锚点对应一个高亮元素,用脚本控制显示隐藏,其中使用的 元素,即是高亮的三角形,其中,bt3_tri_lt.png、bt3_tri_tr.png、bt3_tri_rb.png 分别为:
之所以使用 img 元素而非 background,是因为需要对这些三角形进行缩放
三、class 为 map-img 的 img 元素及 map 元素,用来定义多边形锚点(这里全部是三角形),map 中的 area 数据,是用古董级网页设计软件 Dreamweaver 生成的,如图:
另外,这一层的 img 元素的 src 为一个 10 x 10 像素的透明 gif 图片,真正用于导航的地图,是第一层的背景图片
下面看看样式,用 LESS 写成:
.map-box {
position: absolute;
right: 10px;
bottom: -3px;
width: 639px;
height: 359px;
}
.map-layout-0,
.map-layout-1,
.map-img {
position: absolute;
left: 0;
top: 0;
width: 100%;
height: 100%;
}
.map-layout-0 {
background: url('@{img}/mall/act/butie3/map.png') no-repeat;
}
.map-node {
position: absolute;
width: 169px;
height: 169px;
img {
position: absolute;
display: none;
}
em {
position: absolute;
color: #fff;
font-size: 20px;
.yahei;
}
}
.map-node-0 {
left: 119px;
top: 64px;
em {
left: 15px;
top: 20px;
}
}
.map-node-1 {
left: 94px;
top: 85px;
em {
left: 57px;
top: 67px;
}
}
.map-node-2 {
left: 61px;
top: 197px;
em {
left: 27px;
top: 28px;
}
}
.map-node-3 {
left: 243px;
top: 15px;
em {
left: 28px;
top: 26px;
}
}
.map-node-4 {
left: 204px;
top: 52px;
em {
left: 54px;
top: 99px;
}
}
.map-node-5 {
left: 204px;
top: 197px;
em {
left: 80px;
top: 26px;
}
}
.map-node-6 {
left: 349px;
top: 34px;
em {
left: 82px;
top: 89px;
}
}
.map-node-7 {
left: 350px;
top: 180px;
em {
left: 7px;
top: 28px;
}
}
.map-node-8 {
left: 494px;
top: 67px;
em {
left: 26px;
top: 28px;
}
}
.map-node-9 {
left: 443px;
top: 152px;
em {
left: 59px;
top: 64px;
}
}
上面已经解释过,样式代码就不解释了,再看看脚本:
define(function(require) {
'use strict'
var event = require('j/fn/event')
function toggle(el, act) {
var index = $(el).index()
$('#mapNodeList').find('img').eq(index)[act]()
act == 'show' && event.fire('mapIndexChange', index)
}
$('#navMap').on('mouseenter', 'area', function() {
toggle(this, 'show')
})
.on('mouseleave', 'area', function() {
toggle(this, 'hide')
})
})
define 是 SeaJS 提供的模块定义函数,SeaJS 是模块化管理前端脚本,非常 Nice 的工具,但这不是重点。
使用 jQuery 监听 map 中的 area 元素的 mouseenter 与 mouseleave 事件,然后在 mouseenter 中显示第二层中相同索引的 img 元素,从而实现高亮,mouseleave 事件用于清除高亮