作者:小5聊基础
简介:一只喜欢全栈方向的程序员,欢迎咨询,尽绵薄之力答疑解惑
编程原则:Write Less Do More
主要知识点列表
编号 | 语言或插件 | 知识点 | 说明 |
---|---|---|---|
1 | js | template | type的属性值,用于标志为html标签模板 |
2 | js | $(' ') | 操作虚拟化DOM |
3 | html | $(dom).html() | 获取dom对象的html标签,不包括自己本身 |
4 | jQuery | $(dom).css() | 获取或设置dom对象的css样式,可以设置单个和多个,font-size有横线分隔的改为第二个首字母大写,css("fontSize","16px") |
5 | jQuery | $(dom).addClass() | 添加class样式名称 |
6 | js | trim | 去掉字符串前后空格,字符串中间的空格不会去掉 |
7 | jQuery | $(dom).mouseenter | 鼠标移动进入到指定dom元素里触发的方法 |
8 | jQuery | $(dom).mousecleave | 鼠标移动离开到指定dom元素里触发的方法 |
9 | jQuery | $(dom).parent() | 获取父级元素对象,这个方法比较有意思,可以不断迭代往上获取父级元素对象,感兴趣的有小伙伴也可以思想这个是怎么实现的,可以浏览他们的jQuery代码 |
10 | jQuery | $(dom).outerWidth() | 获取dom对象的宽度,包括内边距 |
11 | jQuery | $(dom).outerHeight() | 获取dom对象的高度,包括内边距 |
12 | jQuery | $(dom).append() | 向dom元素追加内容,追加在后面 |
13 | jQuery | $(dom).offset() | 获取dom对象元素相对于文档的top和left值,offset().top/left |
1、动态化模板布局
script标签,有这样一个属性,template模板
可能大家没怎么用过,现在前端有非常多成熟的框架,用过vue的小伙伴应该不陌生
模板可以包含循环体的代码块,如下
- 部分代码
<!--模板-->
<script id="site" type="text/template">
<div class="item" style="left: 0px;top: 0px;">
<div class="line"></div>
<div class="text" style="width:100px;right: -8px;text-align:right;">
<span></span>
</div>
<div class="circular" style="left: 24px;top: 0px;"></div>
</div>
</script>
<!--换乘图标模板-->
1.1 动态参数分析
1)单元块,top和left <br/>
2)线条的旋转角度是 <br/>
3)线条的颜色,不同颜色代表不同的线路 <br/>
4)站点名称 <br/>
5)换成图标 <br/>
6)是否是最后一个站点,线条长度和圆圈大小一致 <br/>
通过上面的分析,我们可以得出如下json格式
- 部分代码
{
text: '嘉禾望岗',
position: {
left: 500,
top: 0
},
class: {
rorate: 'line-transform-45',
line: 'line-2'
},
is_rorate_line: 1
}
1.2 逻辑实现
1)通过for循环多个站点值,并使用站点模板追加到目标div里 <br/>
2)$(template),先通过jQuery虚拟化操作dom进行赋值 <br/>
这里的template不能出现前后空格,所以需要使用trim()去掉前后空格
3)通过虚拟dom即可给文本值、旋转样式、换乘图标、单元块等值进行判断和赋值
- 效果
- 部分代码
var html = '';
for (var i = 0; i < line_arr.length; i++) {
var data = line_arr[i];
var temp = site_template;
var dom = $(temp);
$(".text", dom).html(data.text);
dom.css({ "left": data.position.left, "top": data.position.top });
$(".line", dom).addClass(data.class.rorate);
$(".line", dom).addClass(data.class.line);
if (data.is_exchange_line) {
$(".circular", dom).html(exchange_template);
}
html += dom.prop('outerHTML');
}
$(".metro-map").html(html);
2、站点弹窗显示信息
2.1 实现逻辑
1)鼠标移动到站点,显示站点开始和结束的运营时间,同样可通过模板方式动态追加
2)鼠标移开站点,则隐藏,弹窗信息移除
3)json格式增加,站点运营时间等信息,起点站只有一个方向,中间站可能会有多个方向
4)弹窗位置计算方式,默认透明度为0,先获取赋值后,弹窗的整体高宽度,从而计算得出合适的位置left和top值,display:none,在隐藏的情况是无法获取高宽度
5)由于position元素会继承position父级的宽度,所以弹窗需要设置为fixed固定样式,才能不被限定宽度,此时就需要获取父级的相对html的top值
{
text: '黄边',
position: {
left: 450,
top: 50
},
class: {
rorate: 'line-transform-45',
line: 'line-2'
},
is_exchange_line: 0,
direction: [
'嘉禾望岗方向 始:06:23 末:00:16',
'广州南站方向 始:06:03 末:23:36'
]
}
<!--弹窗信息模板-->
<script id="info" type="text/template">
<div class="info" style="position:fixed;left: 0px;top: 0px;box-shadow:0 0 13px #ccc;padding:6px 8px;border-radius:10px;font-size: 13px;background:#fff;opacity:0;"></div>
</script>
3、完整代码
<!doctype html>
<html>
<head>
<meta charset="utf-8">
<title>标题</title>
<script src="jquery-2.0.0.min.js"></script>
<style>
body, html {
margin: 0;
padding: 0;
font-size: 100%;
}
.item {
position: absolute;
left: 0px;
top: 0px;
}
.line {
width: 10px;
height: 80px;
}
.line-end {
height: 10px;
}
.line-transform-45 {
right: -8px;
transform: rotate(45deg);
-ms-transform: rotate(45deg); /* Internet Explorer */
-moz-transform: rotate(45deg); /* Firefox */
-webkit-transform: rotate(45deg); /* Safari 和 Chrome */
-o-transform: rotate(45deg); /* Opera */
}
.line-2 {
background: #0066cc;
}
.text {
position: absolute;
right: 18px;
top: 0px;
}
.circular {
position: absolute;
left: -5px;
top: -5px;
background: #fff;
border: 4px solid #0066CC;
width: 12px;
height: 12px;
border-radius: 14px;
cursor: pointer;
}
.circular:hover {
border: 4px solid #4398ed;
}
.circular .icon {
width: 1.4rem;
height: 1.4rem;
vertical-align: middle;
fill: #333;
overflow: hidden;
position: absolute;
top: -5px;
left: -5px;
background: #fff;
border-radius: 1.5rem;
}
.circular:hover .icon {
fill: #4398ed !important;
}
.circular-position {
left: 24px;
top: 0px;
}
.light {
background: #aae298 !important;
border: 4px solid #44ce3f !important;
}
.light .icon {
display: none;
}
</style>
</head>
<body>
<div style="position:fixed;top:10px;right:10px;">
<div style="text-align:center;">
<svg class="icon" style="width: 2rem;height: 2rem;vertical-align: middle;fill: #333;overflow: hidden;" viewBox="0 0 1024 1024" version="1.1" xmlns="http://www.w3.org/2000/svg" p-id="2152"><path d="M255.329 231.83C212.739 142.273 153.359 65.132 77.148 0.386L267.84 0a686.133 686.133 0 0 1 149.188 218.117 685.707 685.707 0 0 1 56.011 267.446v538.418H321.49V525.925c0-103.384-22.06-201.422-66.18-294.096zM550.955 1024V485.583a685.688 685.688 0 0 1 55.991-267.466C642.466 135.883 692.183 63.177 756.154 0l190.693 0.387C870.616 65.133 811.235 142.274 768.665 231.83a677.418 677.418 0 0 0-66.16 294.077V1024h-151.55z" fill="#BE1120" p-id="2153"></path></svg>
<br />
<span>广州地铁</span>
</div>
<div style="text-align:center;">
<span style="color:#0066cc;">二号线</span>
</div>
</div>
<div class="metro-map" style="position:relative;margin-top:50px;margin-left:100px;height:1800px;">
</div>
</body>
</html>
<!--站点模板-->
<script id="site" type="text/template">
<div class="item" style="left: 0px;top: 0px;">
<div class="line"></div>
<div class="text" style="width:100px;text-align:right;">
<span></span>
</div>
<div class="circular"></div>
</div>
</script>
<!--换成图标模板-->
<script id="exchange" type="text/template">
<svg class="icon" style="" viewBox="0 0 1024 1024" version="1.1" xmlns="http://www.w3.org/2000/svg" p-id="7696"><path d="M514.56 962.56C267.776 962.56 66.56 761.344 66.56 514.56S267.776 66.56 514.56 66.56 962.56 267.776 962.56 514.56 761.344 962.56 514.56 962.56z m0-834.56C301.568 128 128 301.568 128 514.56S301.568 901.12 514.56 901.12s386.56-173.568 386.56-386.56S727.552 128 514.56 128z" p-id="7697"></path><path d="M737.28 482.816H291.84c-15.36 0-28.16-12.8-28.16-28.16s12.8-28.16 28.16-28.16h445.44c15.36 0 28.16 12.8 28.16 28.16s-12.8 28.16-28.16 28.16z" p-id="7698"></path><path d="M615.936 293.376l141.312 141.312c10.752 10.752 10.752 28.672 0 39.936-10.752 10.752-28.672 10.752-39.936 0l-141.312-141.312c-10.752-10.752-10.752-28.672 0-39.936 11.264-10.752 29.184-10.752 39.936 0zM311.808 555.008L453.12 696.32c10.752 10.752 10.752 28.672 0 39.936-10.752 10.752-28.672 10.752-39.936 0l-141.312-141.312c-10.752-10.752-10.752-28.672 0-39.936s28.672-11.264 39.936 0z" p-id="7699"></path><path d="M737.28 603.136H291.84c-15.36 0-28.16-12.8-28.16-28.16s12.8-28.16 28.16-28.16h445.44c15.36 0 28.16 12.8 28.16 28.16s-12.8 28.16-28.16 28.16z" p-id="7700"></path></svg>
</script>
<!--弹窗信息模板-->
<script id="info" type="text/template">
<div class="info" style="position:fixed;left: 0px;top: 0px;box-shadow:0 0 13px #ccc;padding:6px 8px;border-radius:10px;font-size: 13px;opacity:0;background:#fff;"></div>
</script>
<!--交互js-->
<script type="text/javascript">
$(function () {
// 模板
var site_template = $("#site").html().trim(); //获取站点模板并去掉前后空格
var exchange_template = $("#exchange").html().trim(); //获取换乘模板并去掉前后空格
var info_template = $("#info").html().trim(); //获取弹窗信息模板
// 数组 - 根据站点间的时间差可知距离长度
var line_arr = [
{
text: '嘉禾望岗',
position: {
left: 500,
top: 0
},
class: {
rorate: 'line-transform-45',
line: 'line-2',
position: 'circular-position'
},
is_exchange_line: 1,
direction: ['广州南站方向 始:06:00 末:23:35']
},
{
text: '黄边',
position: {
left: 450,
top: 50
},
class: {
rorate: 'line-transform-45',
line: 'line-2',
position: 'circular-position'
},
is_exchange_line: 0,
direction: [
'嘉禾望岗方向 始:06:23 末:00:16',
'广州南站方向 始:06:03 末:23:36'
]
},
{
text: '江夏',
position: {
left: 400,
top: 100
},
class: {
rorate: 'line-transform-45',
line: 'line-2',
position: 'circular-position'
},
is_exchange_line: 0,
direction: [
'嘉禾望岗方向 始:06:21 末:00:14',
'广州南站方向 始:06:05 末:23:38'
]
},
{
text: '萧岗',
position: {
left: 350,
top: 150
},
class: {
rorate: 'line-transform-45',
line: 'line-2',
position: 'circular-position'
},
is_exchange_line: 0,
direction: [
'嘉禾望岗方向 始:06:18 末:00:13',
'广州南站方向 始:06:07 末:23:41'
]
},
{
text: '白云文化广场',
position: {
left: 300,
top: 200
},
class: {
rorate: 'line-transform-45',
line: 'line-2',
position: 'circular-position'
},
is_exchange_line: 0,
direction: [
'',
''
]
},
{
text: '白云公园',
position: {
left: 250,
top: 250
},
class: {
rorate: 'line-transform-45',
line: 'line-2',
position: 'circular-position'
},
is_exchange_line: 0,
direction: [
'嘉禾望岗方向 始:06:14 末:00:09',
'广州南站方向 始:06:11 末:23:45'
]
},
{
text: '飞翔公园',
position: {
left: 224,
top: 314
},
class: {
rorate: '',
line: 'line-2',
position: ''
},
is_exchange_line: 0,
direction: [
'嘉禾望岗方向 始:06:12 末:00:07',
'广州南站方向 始:06:13 末:23:47'
]
},
{
text: '三元里',
position: {
left: 224,
top: 384
},
class: {
rorate: '',
line: 'line-2',
position: ''
},
is_exchange_line: 0,
direction: [
'嘉禾望岗方向 始:06:10 末:00:05',
'广州南站方向 始:06:10 末:23:49'
]
},
{
text: '广州火车站',
position: {
left: 224,
top: 464
},
class: {
rorate: '',
line: 'line-2',
position: ''
},
is_exchange_line: 1,
direction: [
'',
''
]
}
]
// 循环加载站点
var html = '';
for (var i = 0; i < line_arr.length; i++) {
var data = line_arr[i];
var temp = site_template;
var dom = $(temp);
$(".text", dom).html(data.text);
dom.css({ "left": data.position.left, "top": data.position.top });
$(".line", dom).addClass(data.class.rorate);
$(".line", dom).addClass(data.class.line);
$(".circular", dom).addClass(data.class.position);
if (data.is_exchange_line) {
$(".circular", dom).html(exchange_template);
}
html += dom.prop('outerHTML');
}
$(".metro-map").html(html);
// 绑定站点事件
$(".circular").mouseenter(function () {
var parent = $(this).parent();
var top_parent = parent.offset().top;
var left_parent = parent.offset().left;
var i = parent.index();
var data = line_arr[i];
var dom = $(info_template);
dom.html(data.direction.join('<br />'));
$(this).append(dom);
var info = $('.info', $(this));
var width = info.outerWidth();
var height = info.outerHeight();
info.css({ "left": (left_parent - (width / 2)), "top": top_parent - height - 6, "opacity": "1" });
}).mouseleave(function () {
$('.info', $(this)).remove();
});
})
</script>