leader-line-vue移动svg(指示线元素)到另外一个容器中(定位基准)
leader-line-vue移动svg(指示线元素)到另外一个容器中(定位基准)
leader-line 绘制的svg指示线是利用相对于 body 的 absolute 定位。而在移动端给body的布局高度为 height:100%,页面是在body局部滚动的,所以指示线的位置相对body始终是固定的,在屏幕上看起来也就是固定不变的。leader-line 绘制的svg指示线是利用相对于 body 的 absolute 定位。而在移动端给body的布局高度为 height:100%,页面是在body局部滚动的,所以指示线的位置相对body始终是固定的,在屏幕上看起来也就是固定不变的。
点击查看代码
<template>
<div class="HelloWorld">
<div id="frame">
<div id="container">
<div id="terminal-1" class="terminal"></div>
<div id="terminal-2" class="terminal"></div>
<div id="terminal-3" class="terminal"></div>
</div>
</div>
<svg version="1.1" id="svg-clip">
<defs>
<rect id="clip-rect" />
<clipPath id="clip-1">
<use xlink:href="#clip-rect" />
</clipPath>
<clipPath id="clip-2">
<use xlink:href="#clip-rect" />
</clipPath>
</defs>
</svg>
</div>
</template>
<script>
import LeaderLine from "leader-line-vue";
import AnimEvent from "anim-event";
export default {
name: "HelloWorld",
data() {
return {};
},
mounted() {
this.$nextTick(() => {
this.InitFun();
});
},
beforeDestroy() {
/**
* 离开页面时销毁所有line
*/
// this.ClearAllLine();
},
methods: {
InitFun() {
var elmFrame = document.getElementById("frame"),
rectFrame = elmFrame.getBoundingClientRect(),
elmClipRect = document.getElementById("clip-rect"),
line1 = LeaderLine.setLine(
document.getElementById("terminal-1"),
document.getElementById("terminal-2")
),
elmLine1 = document.querySelector(".leader-line:last-of-type"),
elmRefClipRect1 = document.querySelector("#clip-1>use"),
line2 = LeaderLine.setLine(
document.getElementById("terminal-3"),
line1.end
),
elmLine2 = document.querySelector(".leader-line:last-of-type"),
elmRefClipRect2 = document.querySelector("#clip-2>use");
function update() {
line1.position();
line2.position();
// Adjust clip position
var rectLine = elmLine1.getBoundingClientRect();
elmRefClipRect1.x.baseVal.value = rectFrame.left - rectLine.left;
elmRefClipRect1.y.baseVal.value = rectFrame.top - rectLine.top;
rectLine = elmLine2.getBoundingClientRect();
elmRefClipRect2.x.baseVal.value = rectFrame.left - rectLine.left;
elmRefClipRect2.y.baseVal.value = rectFrame.top - rectLine.top;
}
// Init clip size
elmClipRect.width.baseVal.value = elmFrame.clientWidth;
elmClipRect.height.baseVal.value = elmFrame.clientHeight;
elmLine1.style.clipPath = "url(#clip-1)";
elmLine2.style.clipPath = "url(#clip-2)";
elmFrame.addEventListener("scroll", AnimEvent.add(update), false);
update();
},
/**
* 监听滚动条变化各部分连线跟随变化
*/
AddEventListenerSrollFun() {
window.addEventListener(
"scroll",
AnimEvent.add(() => {
d3.selectAll(".leader-line").remove();
this.lines1 = [];
this.lines2 = [];
this.lines3 = [];
this.DrawLeaderLine1();
this.DrawLeaderLine2();
this.DrawLeaderLine3();
}),
false
);
let scrollableBox1 = document.getElementsByClassName("FirstContent")[0];
scrollableBox1.addEventListener(
"scroll",
AnimEvent.add(() => {
d3.selectAll(".leader-line").remove();
this.lines1 = [];
this.lines2 = [];
this.lines3 = [];
this.DrawLeaderLine1();
this.DrawLeaderLine2();
this.DrawLeaderLine3();
}),
false
);
let scrollableBox2 = document.getElementsByClassName("SecondContent")[0];
scrollableBox2.addEventListener(
"scroll",
AnimEvent.add(() => {
d3.selectAll(".leader-line").remove();
this.lines1 = [];
this.lines2 = [];
this.lines3 = [];
this.DrawLeaderLine1();
this.DrawLeaderLine2();
this.DrawLeaderLine3();
}),
false
);
let scrollableBox3 = document.getElementsByClassName("ThirdContent")[0];
scrollableBox3.addEventListener(
"scroll",
AnimEvent.add(() => {
d3.selectAll(".leader-line").remove();
this.lines1 = [];
this.lines2 = [];
this.lines3 = [];
this.DrawLeaderLine1();
this.DrawLeaderLine2();
this.DrawLeaderLine3();
}),
false
);
let scrollableBox4 = document.getElementsByClassName("FourContent")[0];
scrollableBox4.addEventListener(
"scroll",
AnimEvent.add(() => {
d3.selectAll(".leader-line").remove();
this.lines1 = [];
this.lines2 = [];
this.lines3 = [];
this.DrawLeaderLine1();
this.DrawLeaderLine2();
this.DrawLeaderLine3();
}),
false
);
},
ClearAllLine() {
if (this.lines1 && this.lines1.length) {
this.lines1.forEach((line) => {
line.remove();
});
}
if (this.lines2 && this.lines2.length) {
this.lines2.forEach((line) => {
line.remove();
});
}
if (this.lines3 && this.lines3.length) {
this.lines3.forEach((line) => {
line.remove();
});
}
},
},
};
</script>
<style lang="scss" scoped>
.HelloWorld {
display: flex;
flex-flow: row nowrap;
justify-content: center;
align-items: center;
width: 100%;
height: 100%;
background: #1f4760;
}
#frame {
margin: 64px;
width: 540px;
height: 540px;
overflow: scroll;
}
#container {
width: 880px;
height: 880px;
position: relative;
background-color: beige;
}
.terminal {
width: 32px;
height: 32px;
position: absolute;
background-color: blue;
}
#terminal-1 {
left: 32px;
top: 32px;
}
#terminal-2 {
left: 416px;
top: 320px;
}
#terminal-3 {
left: 64px;
top: 180px;
}
#svg-clip {
width: 1px; /* for Gecko bug */
height: 1px; /* for Gecko bug */
}
</style>