См. ОБНОВЛЕНИЕ в конце!
Мой оригинальный ответ:
У меня нет mac и не «гладкая» мышь, но я проверил ваш фрагмент как на Chrome и Firefox на Windows и Linux коробки.
Отлично работает на Chrome как на Windows и Linux , но ...
выглядит как коэффициентне подходит для Firefox ... он работает лучше (не так хорошо, как в Chrome ) с 200
.
Еще одна вещь:
Тестировали ли вы модную мышь mac на Windows и наоборот?Может ли это быть mac проблема?
ОБНОВЛЕНИЕ:
Другие ответы - это здорово, но я был озадачен вашим вопросом и многому научился скод и то, на что указывали другие ответы, но что-то запомнилось мне как ошибка.
В поисках этой темы я нашел этот вопрос очень информативным.В этот ответ включен возможный скрипт калибровки прокрутки мыши и функция getScrollLineHeight
для Определение высоты строки, используемой событиями прокрутки DOM_DELTA_LINE .
Я скопировал эту функцию в фрагмент для полноты, но в конце она не нужна для того, что я думал.Я закомментировал строку, которая вызывает getScrollLineHeight
, потому что она не работает на этом сайте по соображениям безопасности, но работает в этой скрипке .
Моя путаница заключалась в том, что прокруткаЯ обычно делаю, с точки зрения пикселей на странице.Но ваш код действительно не заботится об этом.Я имею в виду, не волнует колесо прокрутки мыши event.deltaY
величина.Только если оно положительное или отрицательное, и рассмотрите один шаг вперед или назад по временной шкале видео.
Так что это не решает проблему «сенсорных мыши с прокруткой», но легко решает Firefox / Chrome и любые другиеPixel / Line / Page deltaMode
также.Теперь он работает как в Chrome, так и в Firefox.Я не могу проверить в другом браузере из-за видео формата WEBM, и я не смог создать видео в любом формате, который работает (посмотрите на мой PD в конце).
Итак, каждый вызовэто всего лишь один шаг: -1 или 1. Хотя кажется, что только Firefox возвращает что-либо, кроме «пикселей» для deltaMode
.Я использовал эту скрипку для проверки ... Теперь вы можете сосредоточиться на этой плавно прокручивающейся мыши и увидеть как быстро она отправляет каждый вызов, вот что действительно имеет значение в данном конкретном случае (примечаниечто у многих компьютеров Mac есть программное обеспечение с плавной прокруткой или перевернутая прокрутка).
Я прокомментировал каждую строку вашего кода и свои модификации для себя, но может быть полезен для других.
// detect if browser firefox as it appears to be the only
// browser that return deltaModes different than DOM_DELTA_PIXEL
// Ref: https://stackoverflow.com/a/37474225/4146962
var FF = !(window.mozInnerScreenX == null);
// Function grabbed from the reference above
// It tries to read current line-height of document (for 'lines' deltaMode)
function getScrollLineHeight() {
var r;
var iframe = document.createElement('iframe');
iframe.src = '#';
document.body.appendChild(iframe);
var iwin = iframe.contentWindow;
var idoc = iwin.document;
idoc.open();
idoc.write('<!DOCTYPE html><html><head></head><body><span>a</span></body></html>');
idoc.close();
var span = idoc.body.firstElementChild;
r = span.offsetHeight;
document.body.removeChild(iframe);
return r;
}
// html5 elements
var vid = document.getElementById("v"); // HTML5 video element
var canvas = document.getElementById("c"); // HTML5 canvas element
var context = canvas.getContext('2d'); // Canvas context
var momentum = document.getElementById('m'); // Current momentum display
var delta = document.getElementById('d'); // Current deltaMode display
var lineheight = document.getElementById('l'); // Current deltaMode display
// global variables
var ch = 120; // canvas with (could be window.innerHeight)
var cw = Math.round(ch * (16 / 9)); // 16/9 proportion width
var targetOffset = 0; // Video offset target position when scrolling
// deltaY to FPS coefficients (for fine tuning)
// Possible mouse scroll wheel 'event.deltaMode'
// modes are: 0:'pixels', 1:'lines', 2:'page'
var pc = 1000; // 'pixels' deltaY coefficient
var lh = "disabled"; //getScrollLineHeight(); // get line-height of deltaMode 'lines'
lineheight.value = lh; // display current document line height
coefficient = 30;
var deltaModes = ['pixels', 'lines', 'page']; // For deltaMode display
// Sets canvas dimensions
canvas.width = cw;
canvas.height = ch;
// Pauses video (this also starts to load the video)
vid.pause();
// Listens video changes time position
vid.addEventListener('seeked', function() {
// Updates canvas with current video frame
context.drawImage(vid, 0, 0, cw, ch);
});
// Listens mouse scroll wheel
window.addEventListener('wheel', function(e) {
// Don't do what scroll wheel normally does
e.preventDefault();
// You don't need an amount, just positive or negative value: -1, 1
var deltabs = 1;
if (e.deltaY<0) deltabs = -1;
// Disable page scrolling, modes[e.deltaMode]=='page'
if (e.deltaMode>1) return false;
delta.value = deltaModes[e.deltaMode];
// Normally scrolling this should be a subtraction
// not a sum but "I like it like this!"
// targetOffset = targetOffset + (e.deltaY / coefficient); // e.deltaY is the thing!!
targetOffset = targetOffset + (deltabs/coefficient);
// Shows current momentum
momentum.value = targetOffset;
return false;
});
// Updates canvas on a loop (both for play or pause state)
var renderLoop = function() {
requestAnimationFrame(function() {
// This parts updates canvas when video is paused
// Needs 'seeked' listener above
if (vid.paused || vid.ended) {
// Reduce target offset gradually
targetOffset = targetOffset * 0.9;
// Show current momentum
momentum.value = Math.round(targetOffset * 100) / 100;
// this part joins start and end of video when scrolling
// forward & backwards
var vct = vid.currentTime - targetOffset;
if (vct < 0) {
vct = vid.duration + vct;
} else if (vct > vid.duration) {
vct = vct - vid.duration;
}
vid.currentTime = vct;
// This parts updates canvas when video is playing
} else {
// update canvas with current video frame
context.drawImage(vid, 0, 0, cw, ch);
}
renderLoop(); // Recursive call to loop
});
};
renderLoop(); // Initial call to loop
input {
width: 50px;
}
.column {
float: left;
width: 50%;
}
/* Clear floats after the columns */
.row:after {
content: "";
display: table;
clear: both;
}
<h3>
mouse scroll video
</h3>
<div class="row">
<div class="column">
<div>
Video element:
</div>
<video controls height="120" id="v" tabindex="-1" autobuffer="auto" preload="auto">
<source type="video/webm" src="https://www.html5rocks.com/tutorials/video/basics/Chrome_ImF.webm"/>
</video>
</div>
<div class="column">
<div>
Canvas element:
</div>
<canvas id="c"></canvas>
<div>
Momentum: <input type=text id="m">
</div>
<div>
deltaMode: <input type=text id="d">
</div>
<div>
lineHeight: <input type=text id="l">
</div>
</div>
</div>
PD У меня есть вопрос (слишком конкретный для объяснения в другом месте) ... Я протестировал свои собственные видео и получил очень плохие результаты... это почему?Что-то связанное с конкретными настройками кодирования видео?Знаете ли вы, какой кодировочный cmd понадобится для преобразования FFMPEG в формат WEBM, как видео, использованное в вашем примере?