元素内遮罩层根据鼠标方向显示的效果比较常见,比如百度图片里的图片信息展示。自己动手实现jQuery插件版和Vue组件版效果。
实现思路
1、根据鼠标的位置定位在元素内出现的方向
2、根据方向动态设置遮罩层样式
3、设置动画移动遮罩层
jQuery版
jQuery插件可以通过$.fn.extend方法进行拓展。
html
<div class="container">
<div class="content" style="background:aqua">
<div class="shade">
<p>mouse hover</p>
</div>
</div>
<div class="content" style="background:bisque">
<div class="shade">
<p>mouse hover</p>
</div>
</div>
<div class="content" style="background:cadetblue">
<div class="shade">
<p>mouse hover</p>
</div>
</div>
<div class="content" style="background:chocolate">
<div class="shade">
<p>mouse hover</p>
</div>
</div>
<div class="content" style="background:cornflowerblue">
<div class="shade">
<p>mouse hover</p>
</div>
</div>
<div class="content" style="background:darkkhaki">
<div class="shade">
<p>mouse hover</p>
</div>
</div>
</div>
css
.container {
width: 600px;
margin: auto;
margin-top: 100px;
}
.content {
float: left;
position: relative;
height: 150px;
width: 150px;
margin: 20px;
overflow: hidden;
background: #ccc;
}
.content .shade {
position: absolute;
top: 0;
display: none;
width: 100%;
height: 100%;
line-height: 100px;
color: #fff;
background: rgba(0, 0, 0, 0.7);
}
js
<script>
(function ($) {
$.fn.extend({
"mouseMove": function (child) {
$(this).hover(function (e) {
$this = $(this);
var ele = $this.find(child);
var clientX = e.clientX;
var clientY = e.clientY;
var top = parseInt($this.offset().top);
var bottom = parseInt(top + $this.height());
var left = parseInt($this.offset().left);
var right = parseInt(left + $this.width());
var absTop = Math.abs(clientY - top);
var absBottom = Math.abs(clientY - bottom);
var absLeft = Math.abs(clientX - left);
var absRight = Math.abs(clientX - right);
var min = Math.min(absTop, absBottom, absLeft, absRight);
var eventType = e.type;
switch (min) {
case absTop:
animate("top", eventType, ele);
break;
case absBottom:
animate("bottom", eventType, ele);
break;
case absLeft:
animate("left", eventType, ele);
break;
case absRight:
animate("right", eventType, ele)
}
})
}
});
function animate(direction, type, ele) {
var timer = 200;
var $target = $(ele);
if (type == "mouseenter") {
$target.stop(true, true);
}
if (direction == "top") {
if (type == "mouseenter") {
$target.css({
display: "block",
top: "-100%",
left: "0"
}).animate({
top: 0,
left: 0
}, timer)
} else {
$target.animate({
display: "block",
top: "-100%",
left: "0"
}, timer)
}
} else if (direction == "left") {
if (type == "mouseenter") {
$target.css({
display: "block",
top: "0",
left: "-100%"
}).animate({
left: 0,
top: 0
}, timer)
} else {
$target.animate({
display: "block",
left: "-100%"
}, timer)
}
} else if (direction == "bottom") {
if (type == "mouseenter") {
$target.css({
display: "block",
top: "100%",
left: "0"
}).animate({
top: 0,
left: 0
}, timer)
} else {
$target.animate({
display: "block",
top: "100%",
left: "0"
}, timer)
}
} else if (direction == "right") {
if (type == "mouseenter") {
$target.css({
display: "block",
top: 0,
left: "100%"
}).animate({
left: "0%",
top: 0
}, timer)
} else {
$target.animate({
display: "block",
left: "100%"
}, timer)
}
}
}
$('.content').mouseMove('.shade')
})(window.jQuery);
</script>
Vue版
通用Vue的组件实现判断元素内鼠标的位置,利用插槽的方式显示遮罩层内容。
html
<div id="app">
<mouse-hover style="background:aqua">
<div slot>mouse hover</div>
</mouse-hover>
<mouse-hover style="background:bisque">
<div slot>mouse hover</div>
</mouse-hover>
<mouse-hover style="background:cadetblue">
<div slot>mouse hover</div>
</mouse-hover>
<mouse-hover style="background:chocolate">
<div slot>mouse hover</div>
</mouse-hover>
<mouse-hover style="background:cornflowerblue">
<div slot>mouse hover</div>
</mouse-hover>
<mouse-hover style="background:darkkhaki">
<div slot>mouse hover</div>
</mouse-hover>
</div>
css
<style>
html,
body {
text-align: center;
color: #000;
background-color: #353535;
}
* {
box-sizing: border-box;
}
#app {
width: 600px;
margin: auto;
margin-top: 100px;
}
.content {
float: left;
position: relative;
height: 150px;
width: 150px;
margin: 20px;
overflow: hidden;
background: #ccc;
}
.content .shade {
position: absolute;
top: 0;
left: -100%;
width: 100%;
height: 100%;
line-height: 100px;
color: #fff;
background: rgba(0, 0, 0, 0.7);
}
</style>
js
<script src="https://cdn.bootcss.com/vue/2.5.17-beta.0/vue.min.js"></script>
<script>
(function () {
const mouseHover = {
name: 'mouseHover',
template: `
<div class="content" @mouseenter="handleIn" @mouseleave="handleOut">
<div class="shade" ref="shade">
<slot></slot>
</div>
</div>
`,
data: () => {
return {}
},
methods: {
handleIn: function (e) {
const direction = this.direction(e);
this.animate(direction, 'in');
},
handleOut: function (e) {
const direction = this.direction(e);
this.animate(direction, 'out');
},
direction: function (e, type) {
const clientX = e.clientX;
const clientY = e.clientY;
const top = e.target.offsetTop;
const bottom = parseInt(top + e.target.offsetHeight);
const left = e.target.offsetLeft;
const right = parseInt(left + e.target.offsetWidth);
const absTop = Math.abs(clientY - top);
const absBottom = Math.abs(clientY - bottom);
const absLeft = Math.abs(clientX - left);
const absRight = Math.abs(clientX - right);
const min = Math.min(absTop, absBottom, absLeft, absRight);
let direction;
switch (min) {
case absTop:
direction = "top";
break;
case absBottom:
direction = "bottom";
break;
case absLeft:
direction = "left";
break;
case absRight:
direction = "right";
break;
};
return direction;
},
animate: function (direction, type) {
let top = 0,
left = 0;
if (type == 'in') {
this.$refs.shade.style.transition = 'none';
if (direction == 'top') {
top = '-100%';
left = 0;
} else if (direction == 'right') {
top = 0;
left = '100%';
} else if (direction == 'bottom') {
top = '100%';
left = 0;
} else if (direction == 'left') {
top = 0;
left = '-100%';
}
this.$refs.shade.style.top = top;
this.$refs.shade.style.left = left;
setTimeout(() => {
this.$refs.shade.style.transition = 'all .2s ease 0s';
this.$refs.shade.style.top = 0;
this.$refs.shade.style.left = 0;
}, 0)
} else if (type == 'out') {
if (direction == 'top') {
top = '-100%';
left = 0;
} else if (direction == 'right') {
top = 0;
left = '100%';
} else if (direction == 'bottom') {
top = '100%';
left = 0;
} else if (direction == 'left') {
top = 0;
left = '-100%';
}
this.$refs.shade.style.top = top;
this.$refs.shade.style.left = left;
}
}
}
}
Vue.component(mouseHover.name, mouseHover)
new Vue({
el: '#app'
})
})();
</script>
**粗体** _斜体_ [链接](http://example.com) `代码` - 列表 > 引用
。你还可以使用@
来通知其他用户。