微信小程序图片热点区域计算

微信小程序图片热点区域计算

有时我们会遇到需求,要求下图中的四个文字区域是可以被点击的,那我们要怎么实现呢?

我们先把基本的页面给实现出来。

pages\index\index.wxml

1
2
3
4
5
6
<!--index.wxml-->
<view class="container">
<view class="images">
<image src="https://hongfs-test-20200314.oss-cn-shenzhen.aliyuncs.com/20210515/24b7e7.png" mode="widthFix" bindload="handleLoadImage" />
</view>
</view>

pages\index\index.wxss

1
2
3
4
5
6
7
8
9
10
11
12
13
14
/**index.wxss**/
page {
background-color: #3273dc;
}

.container {
display: flex;
align-items: center;
height: 100vh;
}

.container .images image {
width: 100vw;
}

pages\index\index.js

1
2
3
4
5
6
7
8
9
// index.js

Page({
data: {
},
handleLoadImage() {
console.log('handleLoadImage');
},
});

页面实现好了,我们需要通过 PS 等工具测量出具体位置。

通过辅助线我们可以更好的进行测量,但实际上我们可能不需要那么精确的结果,毕竟我只是个写代码的。

从测量结果可以看出,第一个区域左上角 X=341 Y=17,右上角 X=898 Y=133。然后我们重复操作得出四个区域的结果。

1
2
3
4
5
6
const list = [
[341, 17, 898, 133],
[67, 294, 626, 408],
[1562, 382, 2192, 502],
[1542, 690, 2022, 811],
];

开始计算前我们还需要知道当前测量的图片宽度像素是多少。

1
const image_width = 2250;
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
// 获取图片在小程序内的节点信息
wx.createSelectorQuery().in(this).select('.container > .box > .images').boundingClientRect(box => {
if(box === null) {
setTimeout(() => {
this.handleLoadImage();
}, 50);
return;
}

// box = {
// width: 375,
// };

// 计算出测量图片和小程序图片实际的比率
const image_rate = image_width / box.width;

const data = list.map(item => {
return {
// 计算出定位左边位置
left: parseInt(item[0] / image_rate),
// 计算出定位上边位置
top: parseInt(item[1] / image_rate),
// 计算出宽度
width: parseInt((item[2] - item[0]) / image_rate),
// 计算出高度
height: parseInt((item[3] - item[1]) / image_rate),
};
});

console.table(data);
}).exec();

计算出来后,则需要应用上去,最终实际代码:

pages\index\index.wxml

1
2
3
4
5
6
7
<!--index.wxml-->
<view class="container">
<view class="box">
<image class="images" src="https://hongfs-test-20200314.oss-cn-shenzhen.aliyuncs.com/20210515/24b7e7.png" mode="widthFix" bindload="handleLoadImage" />
<view wx:for="{{ list }}" class="item" style="top: {{ item.top }}px; left: {{ item.left }}px; width: {{ item.width }}px; height: {{ item.height }}px;"></view>
</view>
</view>

pages\index\index.wxss

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
/**index.wxss**/
page {
background-color: #3273dc;
}

.container {
display: flex;
align-items: center;
height: 100vh;
}

.container .box {
position: relative;
}

.container .box .images {
width: 100vw;
}

.container .box .item {
position: absolute;
/* background-color: #ccc; */
}

pages\index\index.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
// index.js

Page({
data: {
list: [],
},
handleLoadImage() {
console.log('handleLoadImage');

const list = [
[341, 17, 898, 133],
[67, 294, 626, 408],
[1562, 382, 2192, 502],
[1542, 690, 2022, 811],
];

const image_width = 2250;

// 获取图片在小程序内的节点信息
wx.createSelectorQuery().in(this).select('.container > .box > .images').boundingClientRect(box => {
if(box === null) {
setTimeout(() => {
this.handleLoadImage();
}, 50);
return;
}

// box = {
// width: 375,
// };

// 计算出测量图和小程序图片实际的比率
const image_rate = image_width / box.width;

const data = list.map(item => {
return {
// 计算出定位左边位置
left: parseInt(item[0] / image_rate),
// 计算出定位上边位置
top: parseInt(item[1] / image_rate),
// 计算出宽度
width: parseInt((item[2] - item[0]) / image_rate),
// 计算出高度
height: parseInt((item[3] - item[1]) / image_rate),
};
});

this.setData({
list: data,
});
}).exec();
},
});

往上