根据自定义的一些点, 按顺序连成一个闭环, 并赋予不同的class展示
HTML:
<div class="city">
当前点亮城市:{{ cityList.find((v) => v.id === currentLightCityId).name }}
<div v-html="lines"></div>
<div :style="{
position: 'absolute',
top: item.top,
right: item.right
}"
:class="[{
'city-lighting': item.id === currentLightCityId }, {
'city-lighted': item.id < currentLightCityId }, {
}]"
:ref="`city${item.id}`"
v-for="(item, index) in cityList"
:key="index">
{{item.name}}
</div>
</div>
JS:
data() {
return {
cityList: [
{
id: 1,
name: '星星城',
top: '120px',
right: '30px',
},
{
id: 2,
name: '月亮城',
top: '70px',
right: '170px',
},
{
id: 3,
name: '太阳城',
top: '220px',
right: '300px',
},
{
id: 4,
name: '柳城',
top: '320px',
right: '220px',
},
],
lines: '',
currentLightCityId: 1,
};
}
created() {
this.$nextTick(() => {
const lineArray = [];
for (let i = 1; i <= this.cityList.length; i += 1) {
let className = 'unlight';
// 最新点亮的城市与上一个城市之间的连线
if (this.currentLightCityId > 1 && i === this.currentLightCityId - 1) {
className = 'lighting';
} else if (this.currentLightCityId > i) {
className = 'lighted';
}
if (i === this.cityList.length) {
// 最后一个城市与第一个城市之间的连线
lineArray.push(this.drawLine(this.$refs[`city${i}`][0], this.$refs.city1[0], className));
} else {
lineArray.push(this.drawLine(this.$refs[`city${i}`][0], this.$refs[`city${i + 1}`][0], className));
}
}
this.lines = lineArray.join('');
this.$forceUpdate();
});
},
methods: {
drawLine(startObj, endObj, className) {
// 起点元素中心坐标
// console.log(this.getOffset(startObj));
const startObjOffset = this.getOffset(startObj);
const endObjOffset = this.getOffset(endObj);
const xStart = startObjOffset.height / 2 + startObjOffset.left;
const yStart = startObjOffset.height / 2 + startObjOffset.top;
// console.log(yStart);
// console.log(xStart);
// 终点元素中心坐标
const xEnd = endObjOffset.height / 2 + endObjOffset.left;
const yEnd = endObjOffset.height / 2 + endObjOffset.top;
// console.log(yEnd);
// console.log(xEnd);
// 用勾股定律计算出斜边长度及其夹角(即连线的旋转角度)
const lx = xEnd - xStart;
const ly = yEnd - yStart;
// 计算连线长度
const length = Math.sqrt(lx * lx + ly * ly);
// 弧度值转换为角度值
const c = (360 * Math.atan2(ly, lx)) / (2 * Math.PI);
// 连线中心坐标
const midX = (xEnd + xStart) / 2;
const midY = (yEnd + yStart) / 2;
const deg = c <= -90 ? (360 + c) : c; // 负角转换为正角
// console.log('length', length);
// console.log('c', c);
// console.log('midX', midX);
// console.log('midY', midY);
// console.log('deg', deg);
// console.log(`<div class='line'
// style='top:${midY}px;left:${(midX - length / 2).toFixed(2)}px;width:${length.toFixed(2)}px;transform:rotate(${deg.toFixed(2)}deg);'>
// </div>`);
return `<div class='line ${className}'
style='top:${midY}px;left:${(midX - length / 2).toFixed(2)}px;width:${length.toFixed(2)}px;transform:rotate(${deg.toFixed(2)}deg);'>
</div>`;
},
}