jQuery - mousemove 在元素外不起作用
jQuery - mousemove does not work outside of element
我用 mousedown
和 mousemove
为我的 <audio>
元素制作了一个 slider/seeker。我的问题是,一旦用户在按住鼠标按钮的同时离开该元素,它就不会注册 mousemove
。这是我的代码:
/** Variables **/
isPlaying = false;
isBuffering = false;
isScrubbing = false;
isScrubberHolding = false;
tempProgress = 0;
time = playerE.currentTime;
dur = playerE.duration;
/** Binds and Properties **/
player.bind("timeupdate", timeUpdate);
scrubber.bind("mousemove", scrubberGrab);
scrubber.bind("mousedown", scrubberClick);
/** Progress and Buffer **/
function progressWidth(progress) {
var calcProgress = ((progress * 100) + "%");
$(".progress").width(calcProgress);
}
/** Time events **/
function timeUpdate(e) {
/** Update Variables **/
time = playerE.currentTime;
dur = playerE.duration;
/** Update Progress and Buffer **/
if (isScrubbing === false) {
var progress = time / dur;
}
var buffered = playerE.buffered.end(0) / dur;
timeConvert(time);
progressWidth(progress);
}
function setPlayerTime(timeset) {
playerE.currentTime = timeset * dur;
}
function timeConvert(s) {
var h = Math.floor(s / 3600);
s -= h * 3600;
var m = Math.floor(s / 60);
s -= m * 60;
var resultSubstring = ((m < 10 ? '0' + m : m) + ":" + (s < 10 ? '0' + s : s)).substring(0, 5);
$('#playerTime').text(resultSubstring);
}
/** Scrubber **/
$(".player-small").mouseenter(function () {
knob.stop().fadeIn(200);
});
setTimeout(function () {
$(".player-small").mouseleave(function () {
knob.stop().fadeOut(200);
});
}, 3000);
function scrubberClick(e) {
isScrubberHolding = true;
isScrubbing = true;
player.trigger('pause');
var $this = $(this);
var x = e.pageX - $this.offset().left;
var percent = x / $this.width();
progressWidth(percent);
tempProgress = percent;
}
$(document).mouseup(function () {
if (isScrubberHolding === true) {
isScrubberHolding = false;
isScrubbing = false;
setPlayerTime(tempProgress)
player.trigger('play');
} else {
isScrubberHolding = false;
}
})
function scrubberGrab(e) {
if (isScrubberHolding === true) {
var $this = $(this);
var x = e.pageX - $this.offset().left;
var percent = x / $this.width();
tempProgress = percent;
progressWidth(percent);
setPlayerTime(percent)
} else {}
}
查看实际效果:
var player = $('audio');
var playerE = $('audio')[0];
var playerE = $('audio').get(0);
var canvasviz = $('canvas');
var playbutton = $("#playButton");
var buffering = $("#buffering");
var scrubber = $(".scrubber-con");
var progress = $(".progress");
var buffered = $(".buffered");
var knob = $(".knob");
var analyser = $("#analyzer");
var currentAlbum = "";
var countElement = $('#playlistCount');
var titleElement = $('#trackTitle');
/** Variables **/
isPlaying = false;
isBuffering = false;
isScrubbing = false;
isScrubberHolding = false;
tempProgress = 0;
time = playerE.currentTime;
dur = playerE.duration;
/** Binds and Properties **/
player.bind("timeupdate", timeUpdate);
scrubber.bind("mousemove", scrubberGrab);
scrubber.bind("mousedown", scrubberClick);
/** Progress and Buffer **/
function progressWidth(progress) {
var calcProgress = ((progress * 100) + "%");
$(".progress").width(calcProgress);
}
/** Time events **/
function timeUpdate(e) {
/** Update Variables **/
time = playerE.currentTime;
dur = playerE.duration;
/** Update Progress and Buffer **/
if (isScrubbing === false) {
var progress = time / dur;
}
var buffered = playerE.buffered.end(0) / dur;
timeConvert(time);
progressWidth(progress);
}
function setPlayerTime(timeset) {
playerE.currentTime = timeset * dur;
}
function timeConvert(s) {
var h = Math.floor(s / 3600);
s -= h * 3600;
var m = Math.floor(s / 60);
s -= m * 60;
var resultSubstring = ((m < 10 ? '0' + m : m) + ":" + (s < 10 ? '0' + s : s)).substring(0, 5);
$('#playerTime').text(resultSubstring);
}
/** Scrubber **/
$(".player-small").mouseenter(function () {
knob.stop().fadeIn(200);
});
setTimeout(function () {
$(".player-small").mouseleave(function () {
knob.stop().fadeOut(200);
});
}, 3000);
function scrubberClick(e) {
isScrubberHolding = true;
isScrubbing = true;
player.trigger('pause');
var $this = $(this);
var x = e.pageX - $this.offset().left;
var percent = x / $this.width();
progressWidth(percent);
tempProgress = percent;
}
$(document).mouseup(function () {
if (isScrubberHolding === true) {
isScrubberHolding = false;
isScrubbing = false;
setPlayerTime(tempProgress)
player.trigger('play');
} else {
isScrubberHolding = false;
}
})
function scrubberGrab(e) {
if (isScrubberHolding === true) {
var $this = $(this);
var x = e.pageX - $this.offset().left;
var percent = x / $this.width();
tempProgress = percent;
progressWidth(percent);
setPlayerTime(percent)
} else {}
}
.player-small {
height: 55px;
width: 100%;
background: #ff4081;
}
.player-height-anim {}
.player-small .left {
height: 55px;
float: left;
width: 56%;
overflow: hidden;
}
.player-small .right {
height: 40px;
position: relative;
top: 8px;
float: right;
width: calc(44% - 2px);
overflow: hidden;
border-left: solid 2px rgba(0, 0, 0, .05);
}
.transport {
overflow: auto;
}
.play-button-con {
height: 55px;
width: 55px;
float: left;
overflow: hidden;
}
#buffering {
height: 55px;
width: 55px;
animation: rotating 900ms ease infinite;
background-image: url(img/player-buffering.svg);
background-size: contain;
display: none;
}
@-webkit-keyframes rotating {
from {
-ms-transform: rotate(0deg);
-moz-transform: rotate(0deg);
-webkit-transform: rotate(0deg);
-o-transform: rotate(0deg);
transform: rotate(0deg);
}
to {
-ms-transform: rotate(360deg);
-moz-transform: rotate(360deg);
-webkit-transform: rotate(360deg);
-o-transform: rotate(360deg);
transform: rotate(360deg);
}
}
@keyframes rotating {
from {
-ms-transform: rotate(0deg);
-moz-transform: rotate(0deg);
-webkit-transform: rotate(0deg);
-o-transform: rotate(0deg);
transform: rotate(0deg);
}
to {
-ms-transform: rotate(360deg);
-moz-transform: rotate(360deg);
-webkit-transform: rotate(360deg);
-o-transform: rotate(360deg);
transform: rotate(360deg);
}
}
.rotating {
-webkit-animation: rotating 2s linear infinite;
-moz-animation: rotating 2s linear infinite;
-ms-animation: rotating 2s linear infinite;
-o-animation: rotating 2s linear infinite;
animation: rotating 2s linear infinite;
}
#playButton {
width: 55px;
height: 55px;
font-size: 18px;
text-align: center;
background-image: url(img/player-play.svg);
background-size: contain;
image-rendering: crisp-edges;
-webkit-image-rendering: crisp-edges;
}
.playFailed {
pointer-events: none;
}
.next-button-con {
height: 55px;
width: 55px;
float: left;
}
#nextButton {
width: 55px;
height: 55px;
text-align: center;
font-size: 11px;
background-image: url(img/player-next.svg);
background-size: contain;
}
.scrubber-con {
margin: auto;
margin-top: 12px;
height: 30px;
width: calc(100% - 40px);
overflow: visible;
cursor: pointer;
}
.scrubber-container {
float: left;
height: 55px;
width: calc(100% - 154px);
overflow: hidden;
}
.scrubber {
margin: auto;
height: 5px;
background: rgba(0, 0, 0, .04);
position: relative;
top: 13px;
}
.scrubber .knob {
float: right;
height: 13px;
width: 13px;
position: relative;
bottom: 4px;
left: 5px;
background: white;
border-radius: 50px;
display: none;
}
.scrubber .knob:hover {
cursor: grab;
}
.scrubber .knob:active {
cursor: grabbing;
}
.scrubber .progress {
height: 100%;
float: left;
background: white;
width: 0%;
position: relative;
z-index: 1;
}
.scrubber .buffered {
height: 5px;
position: relative;
width: 0%;
background: rgba(0, 0, 0, .2);
transition: ease 1000ms;
}
.time-con {
float: left;
width: 30px;
height: 55px;
}
.time {
position: relative;
top: 20px;
color: white;
font-size: 13px;
}
.player-small .button {
color: white;
float: left;
cursor: pointer;
}
.player-small .button:hover {
background: rgba(0, 0, 0, .12);
}
.analyzer-con {
float: left;
position: relative;
margin-left: 235px;
width: calc(100% - 650px);
height: 60px;
}
#analyzer {
width: 100%;
height: 45px;
margin-top: 8px;
display: none;
}
audio {
display: block;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div class="player-small">
<div class="w-ctrl">
<div class="controls">
<div class="left">
<div class="transport">
<div class="play-button-con">
<div class="button playFailed" id="playButton" onclick="togglePlay()">
</div>
<div id="buffering">
</div>
</div>
<div class="next-button-con">
<div class="button" id="nextButton" onclick="next()"></div>
</div>
<div class="scrubber-container" nmousedown="event.preventDefault ? event.preventDefault() : event.returnValue = false">
<div class="scrubber-con" nmousedown="event.preventDefault ? event.preventDefault() : event.returnValue = false">
<div class="scrubber" draggable="false" nmousedown="event.preventDefault ? event.preventDefault() : event.returnValue = false">
<div class="progress" draggable="false" onmousedown="event.preventDefault ? event.preventDefault() : event.returnValue = false">
<div class="knob" draggable="false" onmousedown="event.preventDefault ? event.preventDefault() : event.returnValue = false"></div>
</div>
<div class="buffered"></div>
</div>
</div>
</div>
<div class="time-con">
<div class="time" id="playerTime">0:00</div>
</div>
</div>
</div>
<div class="right">
<audio id="player" src="your track here" controls="controls" preload="none"></audio>
<div class="info">
<div class="count" id="playlistCount">0/0</div>
<div class="title" id="trackTitle">Track title</div>
</div>
</div>
</div>
</div>
</div>
抓住我的自定义导引头(左)并将鼠标移出粉红色区域。现在对音频元素(右)做同样的事情,你需要一个轨道来播放,以便能够移动它的导引头。看看即使鼠标不在其中也可以拖动它?
那么我怎样才能让我的自定义导引头有这种行为呢?
由于您将 mousemove
绑定到 scrubber,当鼠标悬停在 scrubber
元素上时,scrubberGrab()
只会 运行。
改变
scrubber.bind("mousemove", scrubberGrab);
至
$(document).bind("mousemove", scrubberGrab);
function scrubberGrab(e) {
if (isScrubberHolding === true) {
var x = e.pageX - scrubber.offset().left;
var percent = Math.min(Math.max(x / scrubber.width(), 0), 1.0);
tempProgress = percent;
progressWidth(percent);
setPlayerTime(percent);
} else {}
}
我用 mousedown
和 mousemove
为我的 <audio>
元素制作了一个 slider/seeker。我的问题是,一旦用户在按住鼠标按钮的同时离开该元素,它就不会注册 mousemove
。这是我的代码:
/** Variables **/
isPlaying = false;
isBuffering = false;
isScrubbing = false;
isScrubberHolding = false;
tempProgress = 0;
time = playerE.currentTime;
dur = playerE.duration;
/** Binds and Properties **/
player.bind("timeupdate", timeUpdate);
scrubber.bind("mousemove", scrubberGrab);
scrubber.bind("mousedown", scrubberClick);
/** Progress and Buffer **/
function progressWidth(progress) {
var calcProgress = ((progress * 100) + "%");
$(".progress").width(calcProgress);
}
/** Time events **/
function timeUpdate(e) {
/** Update Variables **/
time = playerE.currentTime;
dur = playerE.duration;
/** Update Progress and Buffer **/
if (isScrubbing === false) {
var progress = time / dur;
}
var buffered = playerE.buffered.end(0) / dur;
timeConvert(time);
progressWidth(progress);
}
function setPlayerTime(timeset) {
playerE.currentTime = timeset * dur;
}
function timeConvert(s) {
var h = Math.floor(s / 3600);
s -= h * 3600;
var m = Math.floor(s / 60);
s -= m * 60;
var resultSubstring = ((m < 10 ? '0' + m : m) + ":" + (s < 10 ? '0' + s : s)).substring(0, 5);
$('#playerTime').text(resultSubstring);
}
/** Scrubber **/
$(".player-small").mouseenter(function () {
knob.stop().fadeIn(200);
});
setTimeout(function () {
$(".player-small").mouseleave(function () {
knob.stop().fadeOut(200);
});
}, 3000);
function scrubberClick(e) {
isScrubberHolding = true;
isScrubbing = true;
player.trigger('pause');
var $this = $(this);
var x = e.pageX - $this.offset().left;
var percent = x / $this.width();
progressWidth(percent);
tempProgress = percent;
}
$(document).mouseup(function () {
if (isScrubberHolding === true) {
isScrubberHolding = false;
isScrubbing = false;
setPlayerTime(tempProgress)
player.trigger('play');
} else {
isScrubberHolding = false;
}
})
function scrubberGrab(e) {
if (isScrubberHolding === true) {
var $this = $(this);
var x = e.pageX - $this.offset().left;
var percent = x / $this.width();
tempProgress = percent;
progressWidth(percent);
setPlayerTime(percent)
} else {}
}
查看实际效果:
var player = $('audio');
var playerE = $('audio')[0];
var playerE = $('audio').get(0);
var canvasviz = $('canvas');
var playbutton = $("#playButton");
var buffering = $("#buffering");
var scrubber = $(".scrubber-con");
var progress = $(".progress");
var buffered = $(".buffered");
var knob = $(".knob");
var analyser = $("#analyzer");
var currentAlbum = "";
var countElement = $('#playlistCount');
var titleElement = $('#trackTitle');
/** Variables **/
isPlaying = false;
isBuffering = false;
isScrubbing = false;
isScrubberHolding = false;
tempProgress = 0;
time = playerE.currentTime;
dur = playerE.duration;
/** Binds and Properties **/
player.bind("timeupdate", timeUpdate);
scrubber.bind("mousemove", scrubberGrab);
scrubber.bind("mousedown", scrubberClick);
/** Progress and Buffer **/
function progressWidth(progress) {
var calcProgress = ((progress * 100) + "%");
$(".progress").width(calcProgress);
}
/** Time events **/
function timeUpdate(e) {
/** Update Variables **/
time = playerE.currentTime;
dur = playerE.duration;
/** Update Progress and Buffer **/
if (isScrubbing === false) {
var progress = time / dur;
}
var buffered = playerE.buffered.end(0) / dur;
timeConvert(time);
progressWidth(progress);
}
function setPlayerTime(timeset) {
playerE.currentTime = timeset * dur;
}
function timeConvert(s) {
var h = Math.floor(s / 3600);
s -= h * 3600;
var m = Math.floor(s / 60);
s -= m * 60;
var resultSubstring = ((m < 10 ? '0' + m : m) + ":" + (s < 10 ? '0' + s : s)).substring(0, 5);
$('#playerTime').text(resultSubstring);
}
/** Scrubber **/
$(".player-small").mouseenter(function () {
knob.stop().fadeIn(200);
});
setTimeout(function () {
$(".player-small").mouseleave(function () {
knob.stop().fadeOut(200);
});
}, 3000);
function scrubberClick(e) {
isScrubberHolding = true;
isScrubbing = true;
player.trigger('pause');
var $this = $(this);
var x = e.pageX - $this.offset().left;
var percent = x / $this.width();
progressWidth(percent);
tempProgress = percent;
}
$(document).mouseup(function () {
if (isScrubberHolding === true) {
isScrubberHolding = false;
isScrubbing = false;
setPlayerTime(tempProgress)
player.trigger('play');
} else {
isScrubberHolding = false;
}
})
function scrubberGrab(e) {
if (isScrubberHolding === true) {
var $this = $(this);
var x = e.pageX - $this.offset().left;
var percent = x / $this.width();
tempProgress = percent;
progressWidth(percent);
setPlayerTime(percent)
} else {}
}
.player-small {
height: 55px;
width: 100%;
background: #ff4081;
}
.player-height-anim {}
.player-small .left {
height: 55px;
float: left;
width: 56%;
overflow: hidden;
}
.player-small .right {
height: 40px;
position: relative;
top: 8px;
float: right;
width: calc(44% - 2px);
overflow: hidden;
border-left: solid 2px rgba(0, 0, 0, .05);
}
.transport {
overflow: auto;
}
.play-button-con {
height: 55px;
width: 55px;
float: left;
overflow: hidden;
}
#buffering {
height: 55px;
width: 55px;
animation: rotating 900ms ease infinite;
background-image: url(img/player-buffering.svg);
background-size: contain;
display: none;
}
@-webkit-keyframes rotating {
from {
-ms-transform: rotate(0deg);
-moz-transform: rotate(0deg);
-webkit-transform: rotate(0deg);
-o-transform: rotate(0deg);
transform: rotate(0deg);
}
to {
-ms-transform: rotate(360deg);
-moz-transform: rotate(360deg);
-webkit-transform: rotate(360deg);
-o-transform: rotate(360deg);
transform: rotate(360deg);
}
}
@keyframes rotating {
from {
-ms-transform: rotate(0deg);
-moz-transform: rotate(0deg);
-webkit-transform: rotate(0deg);
-o-transform: rotate(0deg);
transform: rotate(0deg);
}
to {
-ms-transform: rotate(360deg);
-moz-transform: rotate(360deg);
-webkit-transform: rotate(360deg);
-o-transform: rotate(360deg);
transform: rotate(360deg);
}
}
.rotating {
-webkit-animation: rotating 2s linear infinite;
-moz-animation: rotating 2s linear infinite;
-ms-animation: rotating 2s linear infinite;
-o-animation: rotating 2s linear infinite;
animation: rotating 2s linear infinite;
}
#playButton {
width: 55px;
height: 55px;
font-size: 18px;
text-align: center;
background-image: url(img/player-play.svg);
background-size: contain;
image-rendering: crisp-edges;
-webkit-image-rendering: crisp-edges;
}
.playFailed {
pointer-events: none;
}
.next-button-con {
height: 55px;
width: 55px;
float: left;
}
#nextButton {
width: 55px;
height: 55px;
text-align: center;
font-size: 11px;
background-image: url(img/player-next.svg);
background-size: contain;
}
.scrubber-con {
margin: auto;
margin-top: 12px;
height: 30px;
width: calc(100% - 40px);
overflow: visible;
cursor: pointer;
}
.scrubber-container {
float: left;
height: 55px;
width: calc(100% - 154px);
overflow: hidden;
}
.scrubber {
margin: auto;
height: 5px;
background: rgba(0, 0, 0, .04);
position: relative;
top: 13px;
}
.scrubber .knob {
float: right;
height: 13px;
width: 13px;
position: relative;
bottom: 4px;
left: 5px;
background: white;
border-radius: 50px;
display: none;
}
.scrubber .knob:hover {
cursor: grab;
}
.scrubber .knob:active {
cursor: grabbing;
}
.scrubber .progress {
height: 100%;
float: left;
background: white;
width: 0%;
position: relative;
z-index: 1;
}
.scrubber .buffered {
height: 5px;
position: relative;
width: 0%;
background: rgba(0, 0, 0, .2);
transition: ease 1000ms;
}
.time-con {
float: left;
width: 30px;
height: 55px;
}
.time {
position: relative;
top: 20px;
color: white;
font-size: 13px;
}
.player-small .button {
color: white;
float: left;
cursor: pointer;
}
.player-small .button:hover {
background: rgba(0, 0, 0, .12);
}
.analyzer-con {
float: left;
position: relative;
margin-left: 235px;
width: calc(100% - 650px);
height: 60px;
}
#analyzer {
width: 100%;
height: 45px;
margin-top: 8px;
display: none;
}
audio {
display: block;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div class="player-small">
<div class="w-ctrl">
<div class="controls">
<div class="left">
<div class="transport">
<div class="play-button-con">
<div class="button playFailed" id="playButton" onclick="togglePlay()">
</div>
<div id="buffering">
</div>
</div>
<div class="next-button-con">
<div class="button" id="nextButton" onclick="next()"></div>
</div>
<div class="scrubber-container" nmousedown="event.preventDefault ? event.preventDefault() : event.returnValue = false">
<div class="scrubber-con" nmousedown="event.preventDefault ? event.preventDefault() : event.returnValue = false">
<div class="scrubber" draggable="false" nmousedown="event.preventDefault ? event.preventDefault() : event.returnValue = false">
<div class="progress" draggable="false" onmousedown="event.preventDefault ? event.preventDefault() : event.returnValue = false">
<div class="knob" draggable="false" onmousedown="event.preventDefault ? event.preventDefault() : event.returnValue = false"></div>
</div>
<div class="buffered"></div>
</div>
</div>
</div>
<div class="time-con">
<div class="time" id="playerTime">0:00</div>
</div>
</div>
</div>
<div class="right">
<audio id="player" src="your track here" controls="controls" preload="none"></audio>
<div class="info">
<div class="count" id="playlistCount">0/0</div>
<div class="title" id="trackTitle">Track title</div>
</div>
</div>
</div>
</div>
</div>
抓住我的自定义导引头(左)并将鼠标移出粉红色区域。现在对音频元素(右)做同样的事情,你需要一个轨道来播放,以便能够移动它的导引头。看看即使鼠标不在其中也可以拖动它?
那么我怎样才能让我的自定义导引头有这种行为呢?
由于您将 mousemove
绑定到 scrubber,当鼠标悬停在 scrubber
元素上时,scrubberGrab()
只会 运行。
改变
scrubber.bind("mousemove", scrubberGrab);
至
$(document).bind("mousemove", scrubberGrab);
function scrubberGrab(e) {
if (isScrubberHolding === true) {
var x = e.pageX - scrubber.offset().left;
var percent = Math.min(Math.max(x / scrubber.width(), 0), 1.0);
tempProgress = percent;
progressWidth(percent);
setPlayerTime(percent);
} else {}
}