获取视频秒数对应的热度数据(Y轴最大值是100):
function timeToSeconds(time) {
const parts = time.split(':');
let hours = 0;
let minutes = 0;
let seconds = 0;
if (parts.length === 3) {
hours = +parts[0];
minutes = +parts[1];
seconds = +parts[2];
} else if (parts.length === 2) {
minutes = +parts[0];
seconds = +parts[1];
} else {
seconds = +parts[0];
}
return hours * 3600 + minutes * 60 + seconds;
}
function pathToPoints(path, total) {
const commands = path.split(/(?=[LMC])/);
const points = [];
for (const command of commands) {
const [type, ...args] = command.split(/[\s,]+/);
if (type === 'M' || type === 'L') {
points.push([Math.round(+args[0]), Math.round((100 - +args[1]) * 100) / 100]);
} else if (type === 'C') {
points.push(
[Math.round(+args[0]), Math.round((100 - +args[1]) * 100) / 100],
[Math.round(+args[2]), Math.round((100 - +args[3]) * 100) / 100],
[Math.round(+args[4]), Math.round((100 - +args[5]) * 100) / 100]
);
}
}
const lastX = points[points.length - 1][0];
const ratio = total / lastX;
return points
.map(([x, y]) => [Math.round(x * ratio), Math.round(y * 100) / 100])
.filter(([x], i, arr) => x <= total && (!arr[i + 1] || arr[i + 1][0] !== x));
}
var totalTimeStr = document.getElementsByClassName("ytp-time-duration")[0].textContent
var totalSeconds = timeToSeconds(totalTimeStr)
var path = document.getElementsByClassName("ytp-heat-map-path")[0].getAttribute("d")
var points = pathToPoints(path, totalSeconds)
原SVG绘图时的Y轴从下到上是100-0,即Y轴值越低,热度越高,100代表的热度最低(是0),这反常识(便于绘制SVG),因此我给改了,将Y轴变为0-100,值越高热度越高,最高100
X轴在结束时,因为画的是C曲线(三次贝塞尔曲线),所以有的点会故意超过总长度,因此我把这些点删除了
一个小问题:视频最后一秒会有两个热度数据,因为热点数据以0开始,以0结尾,最后一个是0,如有干扰,可以删除最后一个数据
如果只关注C曲线的最终点,就不会出现这些问题了,但会导致热度数据的残缺:
if (type === 'M' || type === 'L') {
points.push([Math.round(+args[0]), Math.round((100 - +args[1]) * 100) / 100]);
} else if (type === 'C') {
points.push(
[Math.round(+args[4]), Math.round((100 - +args[5]) * 100) / 100]
);
}