Last active
November 2, 2017 18:32
-
-
Save ishitsuka/10175564 to your computer and use it in GitHub Desktop.
Visualize comments upsurge for Nicovideo
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// ==UserScript== | |
// @name HistogramHeatGraph.user.js | |
// @namespace https://gist.github.com/ishitsuka/10175564 | |
// @version 0.20160204 | |
// @description ニコニコ動画でコメントの盛り上がりをグラフで表示 | |
// @match http://www.nicovideo.jp/watch/* | |
// @include http://www.nicovideo.jp/watch/* | |
// @grant none | |
// ==/UserScript== | |
/** | |
* Firefoxで動画上のコメントリストを半透明で表示できない。 | |
* Firefoxで最後の棒がまれにずれる。 | |
* 動画総時間がちょうど1分などの場合に最後の棒が表示されない。 | |
* いくつか棒の上1pxがにじむ。 | |
* 一部の動画で棒の下1pxが見えない。 | |
* 関数setContentに遅延処理がないと棒がずれる。 | |
* グラフを再表示するたび表示に要する時間が倍増する。 | |
* 横スクロールバーがまれに表示される。 | |
* 提供有無確認が不正確。 | |
* Watch.jsのAPI仕様が謎。 | |
* Flexboxはコンテンツなしだと効かない。 | |
*/ | |
(function() { | |
function setStyle() {/* | |
#playerContainer { | |
text-align: left; | |
} | |
#playerTabWrapper + div { | |
background: repeating-linear-gradient(to top, #000, #222 10px); | |
border: 1px solid #000; | |
border-top: 0; | |
float: left; | |
font-size: 0; | |
white-space: nowrap; | |
width: 670px; | |
} | |
#playerTabWrapper + div div { | |
display: inline-block; | |
} | |
#playerTabWrapper + div div:hover { | |
background: rgba(255, 255, 255, .1); | |
-webkit-filter: hue-rotate(180deg); | |
filter: hue-rotate(180deg); | |
} | |
#playerContainer > a { | |
cursor: pointer; | |
margin-left: 10px; | |
text-shadow: rgba(0, 0, 0, .2) 0 1px; | |
} | |
#comment-list { | |
background: #000; | |
color: #fff; | |
font-size: 12px; | |
line-height: 1.25; | |
padding: 4px 4px 0; | |
pointer-events: none; | |
position: absolute; | |
z-index: 9999; | |
} | |
.size_normal #playerTabWrapper + div { | |
transform: scaleX(1.336); | |
transform-origin: 0; | |
} | |
.size_normal #playerContainer > a { | |
margin-left: 236px; | |
} | |
.size_small #playerTabWrapper + div, | |
.size_small #playerContainer > a, | |
#comment-list:empty { | |
display: none; | |
} | |
*/} | |
const style = document.createElement('style'); | |
const styleText = setStyle.toString().match(/\/\*([^]*)\*\//)[1]; | |
style.appendChild(document.createTextNode(styleText)); | |
document.body.appendChild(style); | |
function setScript() { | |
function setElement() { | |
$('#playerContainer') | |
.append('<div>') | |
.append('<a>'); | |
$('<div>') | |
.attr('id', 'comment-list') | |
.appendTo('body'); | |
} | |
function setContent(barTimeInterval) { | |
// constだとFirefoxでエラー | |
var videoTotalTime = $('#external_nicoplayer')[0].ext_getTotalTime(); | |
const barIndex = Math.ceil(videoTotalTime / barTimeInterval); | |
const listMessages = []; | |
const listCounts = []; | |
const listTimes = []; | |
const lastBarTimeIntervalGap = barTimeInterval - Math.floor(videoTotalTime % barTimeInterval); | |
var barTimePoint = 0; | |
var comments = require('watchapp/init/PlayerInitializer').rightSidePanelViewController; | |
comments = comments.getPlayerPanelTabsView()._commentPanelView.getComments().getData(); | |
comments.some(val => { | |
if (val.vpos / 1000 > videoTotalTime + 1) { | |
videoTotalTime += 10; | |
return true; | |
} | |
}); | |
for (var i = 0; i < barIndex; i++) { | |
listMessages[i] = []; | |
listCounts[i] = 0; | |
comments.forEach(val => { | |
var thisTimePoint = val.vpos / 1000; | |
if (barTimePoint <= thisTimePoint && thisTimePoint < barTimeInterval + barTimePoint) { | |
listMessages[i].push(val); | |
listCounts[i]++; | |
} | |
}); | |
listMessages[i] | |
.sort((a, b) => a.vpos - b.vpos) | |
.forEach((val, j) => { | |
listMessages[i][j] = val.message.replace(/"|<|</g, ' ').replace(/\n/g, '<br>'); | |
}); | |
listMessages[i] = listMessages[i].join('<br>'); | |
var min = Math.floor(barTimePoint / 60); | |
var sec = barTimePoint - min * 60; | |
if (sec < 10) { | |
sec = `0${sec}`; | |
} | |
listTimes[i] = `${min}:${sec}-`; | |
if (i > barIndex - 2) { | |
barTimePoint -= lastBarTimeIntervalGap; | |
} | |
min = Math.floor((barTimeInterval + barTimePoint) / 60); | |
sec = barTimeInterval + barTimePoint - min * 60; | |
if (sec < 10) { | |
sec = `0${sec}`; | |
} | |
listTimes[i] += `${min}:${sec}`; | |
barTimePoint += barTimeInterval; | |
} | |
const listCountMax = Math.max(...listCounts); | |
const graphHeight = listCountMax > 10 ? listCountMax : 10; | |
const playerWidth = 670; | |
const barColors = [ | |
'126da2', '1271a8', '1275ae', '1279b4', '137dba', | |
'1381c0', '1385c6', '1489cc', '148dd2', '1491d8' | |
]; | |
const barColorRatio = (barColors.length - 1) / listCountMax; | |
const lastBarWidthRatio = videoTotalTime % barTimeInterval / barTimeInterval; | |
const $graph = $('#playerTabWrapper').next(); | |
const $list = $('#comment-list'); | |
var barWidth = playerWidth / (lastBarWidthRatio + barIndex - 1); | |
$('#playerContainerWrapper').css('padding-bottom', graphHeight + 11); | |
$('.miniBannerAdCloseButton').trigger('click'); | |
$graph.empty(); | |
for (i = 0; i < barIndex; i++) { | |
var barColor = barColors[Math.floor(listCounts[i] * barColorRatio)]; | |
var barBackground = `linear-gradient(to top, #${barColor}, #${barColor} ` + | |
`${listCounts[i]}px, transparent ${listCounts[i]}px, transparent)`; | |
var barText = listCounts[i] ? | |
`${listMessages[i]}<br><br>${listTimes[i]} コメ ${listCounts[i]}` : ''; | |
if (i > barIndex - 2) { | |
barWidth *= lastBarWidthRatio; | |
} | |
$('<div>') | |
.css('background-image', barBackground) | |
.data('text', barText) | |
.height(graphHeight) | |
.width(barWidth) | |
.appendTo($graph); | |
} | |
$graph.children().on({ | |
'mouseenter': function(val) { | |
$list | |
.css({ | |
'left': val.pageX, | |
'top': $graph.offset().top - $list.height() - 10 | |
}) | |
.html($(this).data('text')); | |
}, | |
'mousemove': function(val) { | |
$list.offset({ | |
'left': val.pageX, | |
'top': $graph.offset().top - $list.height() - 10 | |
}); | |
}, | |
'mouseleave': function() { | |
$list.empty(); | |
} | |
}); | |
const $lastBar = $graph.children().eq(-1); | |
const foo = $graph.offset().left - $lastBar.offset().left; | |
const lastBarWidth = $('#playerNicoplayer').width() < 898 ? foo + 671 : (foo + 897) * 672 / 898; | |
$lastBar.width(lastBarWidth > 1 ? lastBarWidth : 1); | |
$graph.next() | |
.on('click', function(val) { | |
setContent(val.ctrlKey ? 60 : 10); | |
}) | |
.text(`コメ ${comments.length}`); | |
navigator.userAgent.match(/Chrome/) && $list.css('background', 'rgba(0, 0, 0, .5)'); | |
} | |
const npc = require('watchapp/model/player/NicoPlayerConnector'); | |
require('advice').after(npc, 'onCommentListInitialized', function() { | |
!$('#comment-list')[0] && setElement(); | |
setTimeout(setContent, 1000, 10); | |
}); | |
} | |
setTimeout(function() { | |
const script = document.createElement('script'); | |
script.appendChild(document.createTextNode('(' + setScript + ')()')); | |
document.body.appendChild(script); | |
}, 100); | |
})(); |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment