前端切图学习-双击点赞

Double Click Heart

Posted by R1NG on August 31, 2021 Viewed Times

双击点赞 Double Click Heart

1. 概述

项目本体展示了一个可对某张图片双击进行点赞操作的组件.

本项目中涉及的知识点:

  1. 使用box-shadow 语法叠加多个不同的阴影构造复杂的阴影效果
  2. 使用计时器构造防抖函数

效果:

20210831093354


2. 结构和切图

网页的基本结构如下:

1
2
3
4
5
<body>
    <h3>Double click the avatar to <i class="fas fa-heart"></i> it</h3>
    <small>You liked it <span id="times">114514</span> times</small>
    <div class="loveMe"></div>
</body>


3. 编写 CSS 样式

由于在本项目中仅需使用一个容器容纳图片, 我们首先将 body 的文字排版方式设为 center:

1
2
3
4
5
6
7
8
body {
    font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, Oxygen, Ubuntu, Cantarell, 'Open Sans', 'Helvetica Neue', sans-serif;
    text-align: center;
    overflow: hidden;
    margin: 0;
    user-select: none;
    -webkit-user-select: none;
}

我们随后设定文字格式:

1
2
3
4
5
6
7
8
9
10
11
12
h3 {
    text-align: center;
    margin-bottom: 0;
}
small {
    display: block;
    text-align: center;
    margin-bottom: 20px;
}
.fa-heart {
    color: red;
}

注意此处对 fontawesome 字体的颜色定义方式.

下面定义主体-图片展示框的样式:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
.loveMe {
    height: 440px;
    width: 300px;
    background: url('../expanding-cards/avatar1.JPG') no-repeat center center/cover;
    margin: auto;
    cursor: pointer;
    max-width: 100%;
    position: relative;
    box-shadow: 0 14px 28px rgba(0, 0, 0, 0.25), 0 10px 10px rgba(0, 0, 0, 0.22);
    overflow: hidden;
    transition: ease .3s;
    border-radius: 6px;
}
.loveMe:active {
    transform: scale(.98);
}

注意此处对 box-shadow 阴影的两层叠加.

然后定义点击图片时以点击处为中心所需要展示的爱心的初始样式和动画关键帧:

1
2
3
4
5
6
7
8
9
10
11
12
.loveMe .fa-heart {
    position: absolute;
    animation: grow .6s linear;
    transform: translate(-50%, -50%) scale(0);
}

@keyframes grow {
    to {
        transform: translate(-50%, -50%) scale(10);
        opacity: 0;
    }
}

最后, 完整的 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
40
41
42
43
44
45
46
47
48
49
50
51
* {
    box-sizing: border-box;
}
body {
    font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, Oxygen, Ubuntu, Cantarell, 'Open Sans', 'Helvetica Neue', sans-serif;
    text-align: center;
    overflow: hidden;
    margin: 0;
    user-select: none;
    -webkit-user-select: none;
}
h3 {
    text-align: center;
    margin-bottom: 0;
}
small {
    display: block;
    text-align: center;
    margin-bottom: 20px;
}
.fa-heart {
    color: red;
}
.loveMe {
    height: 440px;
    width: 300px;
    background: url('../expanding-cards/avatar1.JPG') no-repeat center center/cover;
    margin: auto;
    cursor: pointer;
    max-width: 100%;
    position: relative;
    box-shadow: 0 14px 28px rgba(0, 0, 0, 0.25), 0 10px 10px rgba(0, 0, 0, 0.22);
    overflow: hidden;
    transition: ease .3s;
    border-radius: 6px;
}
.loveMe:active {
    transform: scale(.98);
}
.loveMe .fa-heart {
    position: absolute;
    animation: grow .6s linear;
    transform: translate(-50%, -50%) scale(0);
}

@keyframes grow {
    to {
        transform: translate(-50%, -50%) scale(10);
        opacity: 0;
    }
}


4. JavaScript

最后编写 JavaScript 函数:

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
const loveMe = document.querySelector('.loveMe');
const times = document.querySelector('#times');
let clickTime = 0;
let timesClicked = 0;

// check whether we need to create a new floating heart
// everytime we DOUBLE click the avatar
loveMe.addEventListener('click', (e) => {
    // record the time when client clicked first
    if (clickTime === 0) {
        clickTime = new Date().getTime();
    } else {
        // we set the double-click interval to be 800 ms
        // create a new heart elem only if the user clicked twice within 
        // the time interval
        if (new Date().getTime() - clickTime < 800) {    
            createHeart(e);
            clickTime = 0;
        } else {
            clickTime = new Date().getTime()
        }
    }
})

const createHeart = (e) => {    
    const heart = document.createElement('i');
    heart.classList.add('fas');
    heart.classList.add('fa-heart');
    
    const x = e.clientX;
    const y = e.clientY;
    const leftOffset = e.target.offsetLeft;
    const topOffset = e.target.offsetTop;

    const xInside = x - leftOffset;
    const yInside = y - topOffset;

    heart.style.top = `${yInside}px`
    heart.style.left = `${xInside}px`

    loveMe.appendChild(heart);

    times.innerHTML = ++timesClicked;

    setTimeout(() => heart.remove(), 1000);
}

最后, 完整的网页演示可见 此处