给你们推荐一下 这是一个大牛直播传授知识 你们可以学习一下人家怎么学习的 想学习的可以来
直播时间: 晚8点
听课方式: 感兴趣的同学可以加Q群:439107211 点击链接加入群【前端技术交流群】:https://jq.qq.com/?_wv=1027&k=4696DcP
直播方式: 实时观看直播者屏幕,实时互动
是否免费: 免费
由项目需要,原生写了个详情页图片放大镜的效果,扔上代码供学习分享,也作为日常笔记…
效果如图(例子中偷偷链了张天猫的图片,希望没啥事 -。-):
实现过程教简单,但我们还是从css开始分析,过程如下(图片已正方形为例):
css:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
|
/* 图片容器 */
.imgBox
{
width
:
200px
;
/* 各位大老爷们看着办 */
height
:
200px
;
/* 各位大老爷们看着办 */
position
:
relative
;
/* 必需 */
}
/* 图片标签 */
.mainImg
{
width
:
100%
;
/* 各位大老爷们看着办,尽量100%好看些[斜眼笑] */
height
:
100%
;
/* 各位大老爷们看着办,尽量100%好看些[斜眼笑] */
}
/* 遮罩层-既放大区域 */
.glass
{
position
:
absolute
;
/* 必需 */
width
:
50px
;
/* 遮罩层宽度 此处是放大4倍,所以为200/4=50 */
height
:
50px
;
/* 遮罩层高度 此处是放大4倍,所以为200/4=50 */
top
:
-9999px
;
/* 绝对位置,先放远些 */
left
:
-9999px
;
/* 绝对位置,先放远些 */
cursor
:
move
;
/* 鼠标样式,好看些 */
background
:
rgba
(
0,0,180,0.5
)
;
/* 遮罩层样式,好看些 */
}
/* 大图所在的容器 */
.imgMax
{
position
:
absolute
;
/* 必需 */
overflow
:
hidden
;
/* 必需,盖掉超出的大图[斜眼笑] */
left
:
210px
;
/* 必需,此处为距原图左边10像素 */
top
:
0
;
/* 必需,此处为距上边0像素 */
width
:
200px
;
/* 放大图片容器的宽度 此处此处是放大4倍,为200,保持和原图容器一般大,若此处为400,则是放大2*4倍,那么相应的放大图片应该是200*4*2=1600 */
height
:
200px
;
/* 放大图片容器的高度 此处此处是放大4倍,为200,保持和原图容器一般大,若此处为400,则是放大2*4倍,那么相应的放大图片应该是200*4*2=1600 */
display
:
none
;
/* 先隐藏 */
}
.maxImg
{
position
:
absolute
;
/* 必需 */
width
:
800px
;
/* 此处是放大4倍,所以为200*4=800 受放大图片所在的容器影响,规则如上 */
height
:
800px
;
/* 此处是放大4倍,所以为200*4=800 受放大图片所在的容器影响,规则如上 */
}
|
上面css中需要注意的就是几个position和缩放比例,注意调整下即可
写完样式,来看看布局:
html:
1
2
3
4
5
6
7
8
9
10
11
12
|
<!-- 图片容器 -->
<div
class
=
"J_imgBox imgBox"
>
<!-- 需要放大的图片-原始图 -->
<img
class
=
"J_mainImg mainImg"
src
=
"http://img.alicdn.com/bao/uploaded/i7/TB1Xpe_NXXXXXXRXFXXGTq09XXX_035318.jpg_430x430q90.jpg"
/>
<!-- 遮罩-既放大的区域 -->
<div
class
=
"J_glass glass"
>
</div>
<!-- 大图的容器 -->
<div
class
=
"J_imgMax imgMax"
>
<!-- 大图 -->
<img
class
=
"J_maxImg maxImg"
/>
</div>
</div>
|
接下来是主要的js代码,一如既往的带注解:
js:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
|
(
function
(
)
{
/* 放大镜函数
** @imgContainer 需要实现放大镜效果的图片容器 此处是 class 为 J_imgBox 的 div
*/
function
imgZoom
(
imgContainer
)
{
// 取大图url,不知道淘宝图片规则如何,反正看了详情页的大图和小图url对比,随便写了个替换
var
imgUrl
=
imgContainer
.
querySelector
(
'.J_mainImg'
)
.
src
.
replace
(
/
.
(
jpg
|
jpeg
|
png
|
gif
)
(
_
)
(
d
+
)
(
x
)
(
d
+
)
(
q90
)
?
/
g
,
''
)
;
// 取大图标签的节点
var
maxImg
=
imgContainer
.
querySelector
(
'.J_maxImg'
)
;
// 给该节点的src属性赋值为大图的url
maxImg
.
src
=
imgUrl
;
// 取大图所在的容器
var
maxImgContainer
=
imgContainer
.
querySelector
(
'.J_imgMax'
)
;
// 取遮罩块
var
glassBlock
=
imgContainer
.
querySelector
(
'.J_glass'
)
;
// 取消放大镜效果
var
hideMaxImg
=
function
(
)
{
glassBlock
.
style
.
top
=
'-9999px'
;
glassBlock
.
style
.
left
=
'-9999px'
;
maxImgContainer
.
style
.
display
=
'none'
;
}
// 鼠标移出图片区域,取消放大镜效果
imgContainer
.
onmouseout
=
function
(
event
)
{
event
.
stopPropagation
(
)
;
hideMaxImg
(
)
;
}
;
// 鼠标在图片区域内移动事件
imgContainer
.
onmousemove
=
function
(
event
)
{
event
.
stopPropagation
(
)
;
// 取图片容器的大小及其相对于视口的位置,需要实时取,所以放在move事件里
var
clientRect
=
event
.
currentTarget
.
getBoundingClientRect
(
)
;
// 获取距鼠标距的上和左的坐标
var
leftX
=
event
.
clientX
-
clientRect
.
left
;
var
leftY
=
event
.
clientY
-
clientRect
.
top
;
// 动态设置遮罩块的left和top位置 这里需要减去遮罩层的一半,因为鼠标位于遮罩块中心点
var
pointerLeft
=
leftX
-
25
;
var
pointerTop
=
leftY
-
25
;
// 如果鼠标坐标移动超出原始图片区域边缘 则取消放大镜效果 因为这里存在快速移动鼠标到大图区域时,鼠标仍处在外层的图片区域内,并不会触发mouseout事件(虽然中间隔了小小的间距,但是快速移动仍能产生这个bug,如代码下面的图所示)
if
(
(
pointerLeft
+
25
)
>
clientRect
.
width
||
pointerLeft
clientRect
.
height
||
pointerTop
)
{
hideMaxImg
(
)
;
return
!
1
;
}
;
// 遮罩块在最左边的时候,鼠标仍在图片区域内,可在遮罩块左边缘至中心线区域内移动,且这时遮罩块为距左0像素
if
(
pointerLeft
)
{
pointerLeft
=
0
;
}
;
// 同上 右边限制
if
(
pointerLeft
>
clientRect
.
width
-
50
)
{
pointerLeft
=
clientRect
.
width
-
50
;
}
;
// 同上 顶部限制
if
(
pointerTop
)
{
pointerTop
=
0
;
}
;
// 同上 底部限制
if
(
pointerTop
>
clientRect
.
height
-
50
)
{
pointerTop
=
clientRect
.
height
-
50
;
}
;
// 设置遮罩块的位置
glassBlock
.
style
.
left
=
pointerLeft
;
glassBlock
.
style
.
top
=
pointerTop
;
// 取遮罩快距离左边的位置和图片区域的宽高比,用于计算大图偏移距离,展示遮罩块所对应的图片区域
var
percentLeft
=
pointerLeft
/
clientRect
.
width
;
var
percentHeight
=
pointerTop
/
clientRect
.
height
;
// 设置大图偏移距离 因为其父元素存在 overflow:hidden 所以只会展示对应区块
maxImg
.
style
.
left
=
-
(
percentLeft*
maxImg
.
clientWidth
)
+
'px'
;
maxImg
.
style
.
top
=
-
(
percentHeight*
maxImg
.
clientHeight
)
+
'px'
;
}
;
}
var
elem
=
document
.
querySelectorAll
(
'.J_imgBox'
)
;
elem
.
forEach
(
function
(
item
,
idx
)
{
imgZoom
(
item
)
}
)
}
)
(
)
|
补bug图:
看完后是不是觉得简直不要太简单,接下来就来理一理以上代码中能够抽取出来在平常开发中比较实用的知识点:
Element.getBoundingClientRect()
Element.getBoundingClientRect()方法返回元素的大小及其相对于视口的位置
例子:
1
2
3
4
5
6
7
8
9
10
11
|
<body
style
=
"width:1400;height:1000"
>
<div
id
=
"testDiv"
style
=
"width:10px;height:20px;background:#f00"
>
</div>
<script>
(
function
(
)
{
var
elem
=
document
.
getElementById
(
'testDiv'
)
;
document
.
body
.
addEventListener
(
'click'
,
function
(
)
{
console
.
log
(
elem
.
getBoundingClientRect
(
)
)
}
,
false
)
}
)
(
)
</script>
</body>
|
效果如图:
从效果图上不难看出,当我移动视图后再点击body,打印的对象都能够正确返回元素的大小及其相对于视口的位置
这个方法也可以用于实现当某元素滚动到底/顶部时触发对应事件,相当方便。
Event
1.event.target 和 event.currentTarget
target:指向触发事件的元素
currentTarget:指向被绑定事件句柄的元素
只有当绑定的事件处理程序与触发该事件处理程序都为同一个对象的时候,两者相同
例子代码:
html:
1
2
3
4
|
<
div
id
=
"aDiv"
>
123
<
div
id
=
"bDiv"
>
456
<
/
div
>
<
/
div
>
|
js:
1
2
3
4
5
6
7
8
9
|
document
.
getElementById
(
'aDiv'
)
.
addEventListener
(
'click'
,
function
(
e
)
{
if
(
e
.
target
===
e
.
currentTarget
)
{
console
.
log
(
'target === currentTarget'
)
}
else
{
console
.
log
(
'target !== currentTarget'
)
}
console
.
log
(
'target'
,
e
.
target
)
console
.
log
(
'currentTarget'
,
e
.
currentTarget
)
}
,
false
)
|
效果图:
从效果图中,我们可以看到,当点击456时,target指向的是456所在的bDiv,currentTarget则指向aDiv,因为事件是绑定在aDiv上,但触发是在bDiv上,而且bDiv又在aDiv内,当点击123时,则target与currentTarget一致,绑定和触发都在aDiv上。
2.event.preventDefault() & event.stopPropagation()
preventDefault:如果事件可取消,则取消该事件,而不停止事件的进一步传播
stopPropagation:阻止捕获和冒泡阶段中当前事件的进一步传播
3.event.stopPropagation() & event.stopImmediatePropagation()
stopPropagation:阻止捕获和冒泡阶段中当前事件的进一步传播
stopImmediatePropagation:阻止元素上调用相同事件的其他事件监听并阻止冒泡
两者区别的例子:
html:
1
2
3
4
|
<div
id
=
"aDiv"
>
123
<div
id
=
"bDiv"
>
456
</div>
</div>
|
js:
1
2
3
4
5
6
7
8
9
10
|
document
.
getElementById
(
'aDiv'
)
.
addEventListener
(
'click'
,
function
(
)
{
console
.
log
(
'click aDiv'
)
}
,
false
)
document
.
getElementById
(
'bDiv'
)
.
addEventListener
(
'click'
,
function
(
e
)
{
e
.
stopImmediatePropagation
(
)
;
console
.
log
(
'click bDiv'
)
}
,
false
)
document
.
getElementById
(
'bDiv'
)
.
addEventListener
(
'click'
,
function
(
)
{
console
.
log
(
'click me too'
)
}
,
false
)
|
上面代码执行结果为:
1
|
click
bDiv
|
注释掉 e.stopImmediatePropagation(); 的结果为:
1
2
3
|
click
bDiv
click
me
too
click
aDIV
|
虽然都是些简单的知识点,在平常开发中也是很实用的,希望能从细节出发,没事多复习复习 -。-~