鼠标移入移出效果 -- jQuery/Vue版

元素内遮罩层根据鼠标方向显示的效果比较常见,比如百度图片里的图片信息展示。自己动手实现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>
效果

原文链接:segmentfault.com

上一篇:前端每日实战:59# 视频演示如何用纯 CSS 创作彩虹背景文字(本专栏文章数过百,感谢大家的支持!)
下一篇:VSCode格式化代码功能失效的bug解决方法

相关推荐

  • 🚩Vue源码——组件如何渲染成最终的DOM

    最近参加了很多场面试,几乎每场面试中都会问到Vue源码方面的问题。在此开一个系列的专栏,来总结一下这方面的经验,如果觉得对您有帮助的,不妨点个赞支持一下呗。 前言 Vue有两个核心思想,一个是数据...

    3 天前
  • 🔥基于vue3.0.1 beta搭建仿京东淘宝的电商商城项目!

    前言 就在前段时间,vue官方发布了3.0.0-beta.1 版本,趁着五一假期有时间,就把之前的一个电商商城的项目,用最新的Composition API拿来改造一下! 👉GitHub地址请访问�...

    5 个月前
  • 🍊仿Element自定义Vue组件库

    前言 🍊 市面上目前已有各种各样的UI组件库,他们的强大毋庸置疑。但是有时候我们有必要开发一套属于自己团队的定制化组件库。还有时候原有的组件不能满足我们的各种需求,就需要在原有的组件上进行改造...

    2 个月前
  • 🌓vue页面换肤实践

    前言 最近要做一个换肤的功能,不过只是对一个页面换肤,换一下背景图呀,背景、边框、字体颜色呀之类的,并非整个项目换肤,相对比较简单,所以以下介绍的换肤方法仅适用于页面换肤而非整个项目换肤。

    17 天前
  • (源码分析)为什么 Vue 中 template 有且只能一个 root ?

    引言 今年,疫情并没有影响到各种面经的正常出现,可谓是络绎不绝(学不动...)。然后,在前段时间也看到一个这样的关于 Vue 的问题,为什么每个组件 template 中有且只能一个 root? 可能...

    5 个月前
  • (深入)使用jQuery复制数组(复制)

    Communitymorgancodes提出了一个问题:(Deep) copying an array using jQuery [duplicate],或许与您遇到的问题类似。

    3 年前
  • (小白篇)vue-cli3.0创建项目+引入element-ui

    vue-cli在2018年8月份发布了3.0版本,经过重构之后,可以说是一个船心版本! 在项目都落地之后,就想升级一下cli版本,尝一尝3.0带来的舒适,也是为后面项目的开展做一个准备。

    1 年前
  • (小小黑科技)vue+echarts实现半圆图表

    如何用echarts实现半圆图表?在echarts官方实例倒腾一波,发现官方并没有提供半圆图表的写法,那怎么办呢?官方没提供,但需求还是要实现的。 半圆图表其实就是饼图的一半,那么简单的思路如下:设置...

    1 年前
  • (原创)vue-router的Import() 异步加载模块问题的解决方案

    关注不迷路,如果解决了问题,留下个赞。 1、问题现象 2、出现问题的代码点 3、替代方案: 把import() 替换成如下: Promise.resolve().then(()=&...

    4 个月前
  • (vue框架)为element组件赋初始值以后无法更改值得问题

    情况描述:组件未加载时已有初始值,mounted里面加载数据,赋值,渲染以后,组件无法更改内容 data里面已经有这个表单对象的初始值但还是无法修改,之前有过一次,没有给表单绑定对象,所以赋值以后无法...

    1 年前

官方社区

扫码加入 JavaScript 社区