如何准确地将SVG标签响应式排列到video标签的真实播放区域上方?
How to responsively arrange an SVG tag to the above of the video tag's real playing area exactly?
<video id="video" width="100%" height="100%" controls src="test.mp4"></video>
<svg id="svg" width="100%" height="100%" style="position: absolute; left:0px; background:gray; opacity:0.5; pointer-events: none;"></svg>
<script>
//some test code
let v = document.getElementById("video");
const testHandler = () => {
let v_w = v.videoWidth;
let v_h = v.videoHeight;
let c_w = v.clientWidth;
let c_h = v.clientHeight;
console.log(v_w, v_h, c_w, c_h);
}
v.addEventListener('loadeddata', testHandler);
</script>
我的目的是响应式地在video标签的真实播放区域上方准确地安排一个SVG标签。
为了轻松了解当前情况,我将 SVG 区域设置为灰色背景和 0.5 的不透明度。
绿色矩形是视频和 SVG 标签区域,红色矩形是真正的播放区域。也就是说,这是我的目标区域。
首先,我想知道一个有效的获取真实比赛区域(红色矩形)坐标的方法。
其次,我想知道一个响应式设计的技巧,就是把一个SVG标签准确的排到真实游戏区域的上面。
我解决了这个问题。
只需要计算视频的比例和标签的一些偏移值即可。
<video id="video" width="100%" height="100%" controls src="test.mp4"></video>
<svg id="svg" width="100%" height="100%" style="position: absolute; left:0px; background:gray; opacity:0.5; pointer-events: none;"></svg>
<script>
const svgHandler = (e) => {
let v = document.getElementById("video");
let v_w = v.videoWidth;
let v_h = v.videoHeight;
let c_w = v.clientWidth;
let c_h = v.clientHeight;
let v_rate = v_h / v_w;
let c_rate = c_h / c_w;
// 1. get real playing area
let r_w;
let r_h;
if (v_rate < c_rate) {
r_w = c_w;
r_h = c_w * v_rate;
} else {
r_h = c_h;
r_w = parseInt(r_h / v_rate);
}
// 2. arrange an SVG tag to the above of the real playing area
let v_off = getOffset(v);
let left_padding = (c_w - r_w) / 2 + v_off.left;
if (e.type == "loadeddata") {
let v_panel_off = getOffset(document.body);
left_padding += v_panel_off.left;
}
let top_padding = (c_h - r_h) / 2 + v_off.top;
let s = document.getElementById("svg");
s.style.position = 'absolute';
s.style.top = parseInt(top_padding);
s.style.left = parseInt(left_padding);
s.style.width = parseInt(r_w);
s.style.height = parseInt(r_h);
s.style.pointerEvents = "none";
}
const getOffset = (el) => {
const rect = el.getBoundingClientRect();
return {
left: rect.left + window.scrollX,
top: rect.top + window.scrollY
};
}
document.getElementById("video").addEventListener('loadeddata', svgHandler);
window.onresize = svgHandler;
</script>
<video id="video" width="100%" height="100%" controls src="test.mp4"></video>
<svg id="svg" width="100%" height="100%" style="position: absolute; left:0px; background:gray; opacity:0.5; pointer-events: none;"></svg>
<script>
//some test code
let v = document.getElementById("video");
const testHandler = () => {
let v_w = v.videoWidth;
let v_h = v.videoHeight;
let c_w = v.clientWidth;
let c_h = v.clientHeight;
console.log(v_w, v_h, c_w, c_h);
}
v.addEventListener('loadeddata', testHandler);
</script>
我的目的是响应式地在video标签的真实播放区域上方准确地安排一个SVG标签。 为了轻松了解当前情况,我将 SVG 区域设置为灰色背景和 0.5 的不透明度。 绿色矩形是视频和 SVG 标签区域,红色矩形是真正的播放区域。也就是说,这是我的目标区域。
首先,我想知道一个有效的获取真实比赛区域(红色矩形)坐标的方法。 其次,我想知道一个响应式设计的技巧,就是把一个SVG标签准确的排到真实游戏区域的上面。
我解决了这个问题。 只需要计算视频的比例和标签的一些偏移值即可。
<video id="video" width="100%" height="100%" controls src="test.mp4"></video>
<svg id="svg" width="100%" height="100%" style="position: absolute; left:0px; background:gray; opacity:0.5; pointer-events: none;"></svg>
<script>
const svgHandler = (e) => {
let v = document.getElementById("video");
let v_w = v.videoWidth;
let v_h = v.videoHeight;
let c_w = v.clientWidth;
let c_h = v.clientHeight;
let v_rate = v_h / v_w;
let c_rate = c_h / c_w;
// 1. get real playing area
let r_w;
let r_h;
if (v_rate < c_rate) {
r_w = c_w;
r_h = c_w * v_rate;
} else {
r_h = c_h;
r_w = parseInt(r_h / v_rate);
}
// 2. arrange an SVG tag to the above of the real playing area
let v_off = getOffset(v);
let left_padding = (c_w - r_w) / 2 + v_off.left;
if (e.type == "loadeddata") {
let v_panel_off = getOffset(document.body);
left_padding += v_panel_off.left;
}
let top_padding = (c_h - r_h) / 2 + v_off.top;
let s = document.getElementById("svg");
s.style.position = 'absolute';
s.style.top = parseInt(top_padding);
s.style.left = parseInt(left_padding);
s.style.width = parseInt(r_w);
s.style.height = parseInt(r_h);
s.style.pointerEvents = "none";
}
const getOffset = (el) => {
const rect = el.getBoundingClientRect();
return {
left: rect.left + window.scrollX,
top: rect.top + window.scrollY
};
}
document.getElementById("video").addEventListener('loadeddata', svgHandler);
window.onresize = svgHandler;
</script>