Originalmente, eu queria criar um efeito de dicas de ferramentas que combinasse posicionamento flutuante e acompanhamento do mouse, mas descobri que o posicionamento e o acompanhamento do mouse ainda são diferentes em alguns lugares importantes, então devemos fazer isso separadamente.
Este efeito em si não é muito difícil. Colocamos principalmente algum esforço na estrutura e expansão do programa para torná-lo mais conveniente de usar e poder ser usado em mais lugares.
Recursos do programa
Download de exemplo completo (clique para baixar)
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" " http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd ">
<html xmlns=" http://www.w3.org/1999/xhtml ">
<cabeça>
<meta http-equiv="Content-Type" content="text/html; charset=gb2312" />
<title>Efeito de prompt de posicionamento flutuante JavaScript</title>
<roteiro>
var $$ = função (id) {
retornar "string" == tipo de id? document.getElementById(id): id;
};
var isIE = navigator.userAgent.indexOf('MSIE') != -1;
var isIE6 = isIE && ([/MSIE (d).0/i.exec(navigator.userAgent)][0][1] == "6");
var isChrome = navigator.userAgent.indexOf('Chrome') != -1;
var isSafari = navigator.userAgent.indexOf('AppleWebKit') != -1;
// com contribuições de Tino Zijdel, Matthias Miller, Diego Perini
// http://dean.edwards.name/weblog/2005/10/add-event/
function addEvent(elemento, tipo, manipulador) {
if (element.addEventListener) {
element.addEventListener(tipo, manipulador, falso);
} outro {
if (!handler.$$guid) manipulador.$$guid = addEvent.guid++;
if (!element.events) element.events = {};
var manipuladores = element.events[tipo];
if (! manipuladores) {
manipuladores = element.events[type] = {};
if (elemento["ligado" + tipo]) {
manipuladores[0] = elemento["on" + tipo];
}
}
manipuladores[handler.$$guid] = manipulador;
elemento["on" + tipo] = handleEvent;
}
};
addEvent.guid = 1;
function removeEvent(elemento, tipo, manipulador) {
if (element.removeEventListener) {
element.removeEventListener(tipo, manipulador, falso);
} outro {
if (element.events && element.events[tipo]) {
excluir element.events[type][handler.$$guid];
}
}
};
function handleEvent(evento) {
var returnValue = true;
evento = evento || fixEvent(((this.ownerDocument || this.document || this).parentWindow || janela).event);
var manipuladores = this.events[event.type];
for (var i em manipuladores) {
this.$$handleEvent = manipuladores[i];
if (this.$$handleEvent(event) === falso) {
valorderetorno = falso;
}
}
return valorderetorno;
};
function fixEvent(evento) {
evento.target = evento.srcElement;
if(event.type == "mouseout") {
evento.relacionadoTarget = evento.toElement;
}else if(event.type == "mouseover") {
evento.relacionadoTarget = evento.fromElement;
}
evento de retorno;
};
var Extend = function(destino, origem) {
for (var propriedade na fonte) {
destino[propriedade] = origem[propriedade];
}
destino de retorno;
}
var Contém = função(a, b){
retornar a.contains ? a != b && a.contains(b) : !!(a.compareDocumentPosition(b) & 16);
}
var Bind = function(objeto, diversão) {
var args = Array.prototype.slice.call(argumentos, 2);
função de retorno() {
return fun.apply(objeto, args.concat(Array.prototype.slice.call(argumentos)));
}
}
var BindAsEventListener = function(objeto, diversão) {
var args = Array.prototype.slice.call(argumentos, 2);
função de retorno(evento) {
return fun.apply(objeto, [evento].concat(args));
}
}
var FixedTips = function(dica, opções){
this.Tip = $$(dica);//caixa de prompt
this._trigger = null; // Objeto gatilho
this._timer = null;//Temporizador
this._cssTip = this.Tip.style;//Código simplificado
this._onshow = false; // Registra o status de exibição atual
this.SetOptions(opções);
//Objeto de dica de processo
this._cssTip.margin = 0;//Evite problemas de posicionamento
this._cssTip.position = "absoluto";
this._cssTip.visibility = "oculto";
this._cssTip.display = "bloquear";
this._cssTip.zIndex = 99;
this._cssTip.left = this._cssTip.top = "-9999px";//Evite barras de rolagem no espaço reservado
//parâmetros de correção de deslocamento
var iLeft = iTop = 0, p = this.Tip;
enquanto (p.offsetParent) {
p = p.offsetParent;iLeft += p.offsetLeft;
};
this._offsetleft = iLeft;
this._offsettop = iTop;
//Continua exibindo ao passar para o objeto Tip
addEvent(this.Tip, "mouseover", BindAsEventListener(this, function(e){
//Se um elemento externo entrar, significa que ele está atualmente no estágio de atraso de ocultação, então limpe o temporizador para cancelar a ocultação.
this.Check(e. RelatedTarget) && clearTimeout(this._timer);
}));
//ie6 manipula seleção
if (éIE6) {
this._iframe = document.createElement("<iframe style='position:absolute;filter:alpha(opacity=0);display:none;'>");
document.body.insertBefore(this._iframe, document.body.childNodes[0]);
};
//Usado para ocultar clicando
this._fCH = BindAsEventListener(this, function(e) {
if (this.Check(e.target) && this.CheckHide()) {
this.ReadyHide(this._trigger.ClickHideDelay);
};
});
//Usado para acionar o método para ocultar
this._fTH = BindAsEventListener(this, function(e) {
if (this.Check(e. RelatedTarget) && this.CheckHide()) {
this.ReadyHide(this._trigger.TouchHideDelay);
};
});
};
FixedTips.prototype = {
_doc: document.documentElement, //Simplifique o código
//Definir propriedades padrão
SetOptions: function(opções) {
this.options = {//Valor padrão
ClickShow: true, //Se exibir no modo clique
ClickShowDelay: false, //Se o atraso de exibição do clique
ClickHide: true, //Se o modo de clique está oculto
ClickHideDelay: false, //Se clicar para ocultar o atraso
TouchShow: true, //Se o modo de disparo é exibido
TouchShowDelay: true, //Se deve acionar o atraso de exibição
TouchHide: true, //Se o modo de disparo está oculto
TouchHideDelay: true, //Se deve acionar o atraso de ocultação
ShowDelay: 300, //Mostra o tempo de atraso
HideDelay: 300, //Ocultar tempo de atraso
Alinhar: "clientleft",//Posicionamento horizontal
vAlign: "clienttop",//posicionamento vertical
Personalizado: {esquerda: 0, topo: 0},//Posicionamento personalizado
Porcentagem: {esquerda: 0, topo: 0},//Posicionamento percentual personalizado
Adaptativo: falso, //Se é para posicionamento adaptativo
Redefinir: falso, //Se deve ser reposicionado durante o posicionamento adaptativo
onShow: function(){},//Executa ao exibir
onHide: function(){}//Executado quando oculto
};
Estender(this.options, opções || {});
},
//Verifica o elemento gatilho
Verifique: function(elem) {
//Retorna se é um elemento externo (ou seja, um objeto de elemento diferente do elemento gatilho e do próprio objeto Tip e seus elementos internos)
retornar !this._trigger ||
!(
this.Tip === elem || this._trigger.Elem === elem ||
Contém(this.Tip, elem) || Contém(this._trigger.Elem, elem)
);
},
//Pronto para exibir
ReadyShow: função(atraso) {
clearTimeout(this._timer);
var trigger = this._trigger;
//Clique para ocultar
trigger.ClickHide && addEvent(documento, "clique", this._fCH);
//Modo de disparo oculto
trigger.TouchHide && addEvent(this._trigger.Elem, "mouseout", this._fTH);
//Se deve atrasar o acionamento
se (atraso) {
this._timer = setTimeout(Bind(this, this.Show), trigger.ShowDelay);
} else { this.Show() };
},
//mostrar
Mostrar: função() {
clearTimeout(this._timer);
this._trigger.onShow();//Coloque na frente para facilitar a modificação dos atributos
//Calcula a esquerda e o topo com base no posicionamento predefinido e no posicionamento personalizado
var trigger = this._trigger, rect = trigger.Elem.getBoundingClientRect(),
scrolldoc = isChrome || isSafari ? documento.body : this._doc,
scrollLeft = scrolldoc.scrollLeft, scrollTop = scrolldoc.scrollTop,
customLeft = trigger.Custom.left, customTop = trigger.Custom.top,
iLeft = this.GetLeft(rect, trigger.Align) + customLeft,
iTop = this.GetTop(rect, trigger.vAlign) + customTop;
// Posicionamento percentual personalizado
if (trigger.Percent.left) { iLeft += .01 * trigger.Percent.left * trigger.Elem.offsetWidth };
if (trigger.Percent.top) { iTop += .01 * trigger.Percent.top * trigger.Elem.offsetHeight };
//Posicionamento adaptativo da janela
if (trigger.Adaptive) {
//Parâmetros de posicionamento corretos
var maxLeft = this._doc.clientWidth - this.Tip.offsetWidth,
maxTop = this._doc.clientHeight - this.Tip.offsetHeight;
if (gatilho.Redefinir) {
//Reposicionamento automático
if (iLeft > maxLeft || iLeft < 0) {
iLeft = this.GetLeft(rect, 2 * iLeft > maxLeft ? "esquerda" : "direita") + customLeft;
};
if (iTop > maxTop || iTop < 0) {
iTop = this.GetTop(rect, 2 * iTop > maxTop ? "top" : "inferior") + customTop;
};
} outro {
//Corrige para a posição apropriada
iLeft = Math.max(Math.min(iLeft, maxLeft), 0);
iTop = Math.max(Math.min(iTop, maxTop), 0);
};
};
//Definir posição e exibição
this._cssTip.left = iLeft + scrollLeft - this._offsetleft + "px";
this._cssTip.top = iTop + scrollTop - this._offsettop + "px";
this._cssTip.visibility = "visível";
//ie6 manipula seleção
if (éIE6) {
this._iframe.style.left = iLeft + scrollLeft + "px";
this._iframe.style.top = iTop + scrollTop + "px";
this._iframe.style.width = this.Tip.offsetWidth + "px";
this._iframe.style.height = this.Tip.offsetHeight + "px";
this._iframe.style.display = "";
};
//Modo de disparo oculto
trigger.TouchHide && addEvent(this.Tip, "mouseout", this._fTH);
},
//Obtém a esquerda do elemento gatilho relativo
GetLeft: function(retificar, alinhar) {
mudar (align.toLowerCase()) {
caso "esquerda":
retornar rect.left - this.Tip.offsetWidth;
caso "clientleft":
retorne ret.esquerda;
caso "centro":
return (rect.left + rect.right - this.Tip.offsetWidth)/2;
caso "direito do cliente":
retornar rect.right - this.Tip.offsetWidth;
caso "certo":
padrão :
retorne rect.right;
};
},
//Obtém o topo relativo ao elemento gatilho
GetTop: function(rect, valign) {
switch (valign.toLowerCase()) {
caso "topo":
retornar rect.top - this.Tip.offsetHeight;
caso "clienttop":
retornar rect.top;
caso "centro":
return (rect.top + rect.bottom - this.Tip.offsetHeight)/2;
caso "clientbottom":
retornar rect.bottom - this.Tip.offsetHeight;
caso "inferior":
padrão :
retornar rect.bottom;
};
},
//Prepare-se para se esconder
ReadyHide: função(atraso) {
clearTimeout(this._timer);
se (atraso) {
this._timer = setTimeout(Bind(this, this.Hide), this._trigger.HideDelay);
} else { this.Hide() };
},
//esconder
Ocultar: function() {
clearTimeout(this._timer);
//Configure para ocultar
this._cssTip.visibility = "oculto";
this._cssTip.left = this._cssTip.top = "-9999px";
//ie6 manipula seleção
if (isIE6) { this._iframe.style.display = "none" };
//Processa o objeto gatilho
if (!!this._trigger) {
this._trigger.onHide();
removeEvent(this._trigger.Elem, "mouseout", this._fTH);
}
this._trigger = null;
//remove o evento
removeEvent(this.Tip, "mouseout", this._fTH);
removeEvent(documento, "clique", this._fCH);
},
//Adiciona objeto gatilho
Adicione: function(elem, opções) {
//Cria um objeto gatilho
var elem = $$(elem), trigger = Extend(Extend({ Elem: elem }, this.options), options || {});
//Clique para exibir
addEvent(elem, "clique", BindAsEventListener(this, function(e){
if (trigger.ClickShow) {
if (this.CheckShow(trigger)) {
this.ReadyShow(trigger.ClickShowDelay);
} outro {
clearTimeout(this._timer);
};
};
}));
//Exibição do modo de disparo
addEvent(elem, "mouseover", BindAsEventListener(this, function(e){
if (trigger.TouchShow) {
if (this.CheckShow(trigger)) {
this.ReadyShow(trigger.TouchShowDelay);
} else if (this.Check(e. RelatedTarget)) {
clearTimeout(this._timer);
};
};
}));
//retorna o objeto gatilho
gatilho de retorno;
},
//Mostra verificação
CheckShow: function(trigger) {
if (gatilho! == this._trigger) {
//Se não for o mesmo objeto gatilho, execute Hide primeiro para evitar conflitos.
this.Hide(); this._trigger = trigger true;
} senão { retornar falso };
},
//ocultar verificação
CheckHide: function() {
if (this._cssTip.visibility === "oculto") {
//É originalmente um estado oculto, não há mais necessidade de executar Hide
clearTimeout(this._timer);
removeEvent(this._trigger.Elem, "mouseout", this._fTH);
this._trigger = null;
removeEvent(documento, "clique", this._fCH);
retornar falso;
} senão { retornar verdadeiro };
}
};
</script>
</head>
<corpo>
<estilo>
.trigger{borda:1px sólido #003099; cor de fundo:#e2e7ff;
.tip{border:1px sólido #c00000; cor:#c00000; fundo:#ffcccc;
</estilo>
<div style="padding:50px;">
<div id="idTip" class="tip"></div>
<div id="idTrigger1" class="trigger">
<selecionar>
<opção>teste</opção>
</selecionar>
</div>
<br>
posição horizontal:
<rótulo>
<input name="nAlign" type="radio" value="left" />
esquerda </label>
<rótulo>
<input name="nAlign" type="radio" value="clientleft" />
cliente esquerdo </label>
<rótulo>
<input name="nAlign" type="radio" value="center" />
centro </label>
<rótulo>
<input name="nAlign" type="radio" value="clientright" />
direito do cliente </label>
<rótulo>
<input name="nAlign" type="radio" value="right" verificado="verificado" />
certo </label>
<br>
Posição vertical:
<rótulo>
<input name="nVAlign" type="radio" value="top" />
topo </label>
<rótulo>
<input name="nVAlign" type="radio" value="clienttop" />
cliente superior </label>
<rótulo>
<input name="nVAlign" type="radio" value="center" />
centro </label>
<rótulo>
<input name="nVAlign" type="radio" value="clientbottom" />
parte inferior do cliente </label>
<rótulo>
<input name="nVAlign" type="radio" value="bottom" verificado="verificado" />
inferior </label>
<br>
<br>
Segmentação personalizada:
esquerda:
<input id="idLeft" type="text" size="5" value="0" maxlength="3" />
principal:
<input id="idTop" type="text" size="5" value="0" maxlength="3"/>
<br>
<br>
<input id="idClick" type="checkbox"checked="checked" />
<label for="idClick">Método de clique</label>
<input id="idTouch" type="checkbox"checked="checked" />
<label for="idTouch">Método de gatilho</label>
<br>
<br>
Tempo de atraso:
<input id="idDelayTime" type="text" size="5" value="0" maxlength="4"/>
<input id="idDelay" type="button" value="Cancelar atraso" />
<br>
<br>
Outros exemplos de aplicação: <br>
<br>
<div id="idTest1"> Use o título: <a href=" http://www.cnblogs.com/cloudgamer/archive/2008/11/17/1334778.html " title="Efeito arrastar e soltar"> Arrastar e solte o efeito</a> <a href=" http://www.cnblogs.com/cloudgamer/archive/2008/12/03/1346386.html " title="Efeito de arrastar e ampliar"> Arrastar e ampliar Efeito</a > <a href=" http://www.cnblogs.com/cloudgamer/archive/2008/07/21/1247267.html " title="Efeito de corte de imagem"> Efeito de corte de imagem</a > </div >
<br>
<br>
Efeitos populares de exibição de avatar: <br>
<br>
<div id="idTest2"> <a href=" http://www.cnblogs.com/cloudgamer/archive/2008/07/06/1236770.html " title="Efeito de mudança deslizante de imagem"> <img src= "/articleimg/2009/07/6852/r_mx1.jpg" border="0"/></a> <a href=" http://www.cnblogs.com/cloudgamer/archive/2008/05/ 23/1205642.html " title="Efeito de transformação de imagem"><img src="/articleimg/2009/07/6852/r_mx2.jpg" border="0"/></a> <a href=" http://www.cnblogs.com/cloudgamer/archive/2008/05/13/1194272.html " title="Efeito de exibição deslizante de imagem"><img src="/articleimg/2009/07/6852/r_mx3.jpg "border="0"/></a> </div>
<br>
<br>
Botão Fechar: <a id="idTest3" href=" http://www.cnblogs.com/cloudgamer/archive/2009/05/18/TableFixed.html">Efeito de posicionamento de linha da tabela </a>
</div>
<roteiro>
var forEach = function(array, retorno de chamada, thisObject){
if(array.forEach){
array.forEach(retorno de chamada, thisObject);
}outro{
for (var i = 0, len = array.length; i < len; i++) { callback.call(thisObject, array[i], i, array });
}
}
///////////////////////////////////////
var ft = new FixedTips("idTip");
///////////////////////////////////////
var trigger1 = ft.Add("idTrigger1", {
onShow: função(){
//teste de posicionamento
var sAlign = this.Align, sVAlign = this.vAlign;
forEach(document.getElementsByName("nAlign"), function(o){ if(o.checked){ sAlign = o.value; } });
forEach(document.getElementsByName("nVAlign"), function(o){ if(o.checked){ sVAlign = o.value; } });
this.Align = sAlign;
this.vAlign = sVAlign;
this.Custom.left = $$("idLeft").valor 0;
this.Custom.top = $$("idTop").valor 0;
trigger1.ShowDelay = trigger1.HideDelay = $$("idDelayTime").valor || 300;
ft.Tip.innerHTML = sAlign + "<br>" + sVAlign + "<br>" + "left: " + this.Custom.left + ", top: " + this.Custom.top;
}
});
//teste de atraso
$$("idDelayTime").value = trigger1.ShowDelay;
$$("idDelay").onclick = function(){
if(trigger1.TouchShowDelay){
trigger1.ClickShowDelay = trigger1.ClickHideDelay =
trigger1.TouchShowDelay = trigger1.TouchHideDelay = falso;
$$("idDelayTime").disabled = true;
this.value = "Definir atraso";
}outro{
trigger1.ClickShowDelay = trigger1.ClickHideDelay =
trigger1.TouchShowDelay = trigger1.TouchHideDelay = verdadeiro;
$$("idDelayTime").disabled = falso;
this.value = "Cancelar atraso";
}
}
//teste do método
$$("idClick").onclick = function(){
trigger1.ClickShow = trigger1.ClickHide = this.checked;
}
$$("idTouch").onclick = function(){
trigger1.TouchShow = trigger1.TouchHide = this.checked;
}
////////////////////////////////////////
forEach($$("idTest1").getElementsByTagName("a"), function(o){
var título = o.título; o.título = "";
ft.Add(o, { vAlign: "bottom", Percent: { left: 50, top: 0 }, onShow: function(){ ft.Tip.innerHTML = title; } });
})
////////////////////////////////////////
forEach($$("idTest2").getElementsByTagName("a"), function(o){
var img = o.getElementsByTagName("img")[0], título = o.title;
o.title = "";
ft.Add(img, { Personalizado: {esquerda: -6, topo: -6 },
onShow: função(){
var str = '<a href="' + o.href + '"><img src="' + img.src + '" style="padding-bottom:5px;" uma>';
str += '<br /><a href="' + o.href + '">' + título + '</a>';
ft.Tip.innerHTML = str;
}
});
})
////////////////////////////////////////
ft.Add("idTest3", { ClickHide: falso, TouchHide: falso, Align: "direita",
onShow: função(){
var str = ' <a href=" http://www.cnblogs.com/cloudgamer/archive/2009/03/11/1408333.html "> Gradiente de cor e efeitos de gradiente</a><br />';
str += ' <a href=" http://www.cnblogs.com/cloudgamer/archive/2008/10/20/1314766.html "> Imitação de disco de rede 163 sem sistema de upload de arquivo de atualização</a><br / >';
str += '<input type="button" onclick="ft.Hide();" value="Clique para fechar" />';
ft.Tip.innerHTML = str;
}
});
</script>
</body>
</html>
JavaScript, posicionamento, flutuante, dicas, dicas de ferramentas, FixedTips, Dica
Descrição do programa
Objeto de dica :
O objeto Tip é um contêiner usado para exibir informações de prompt e o programa é representado pelo atributo Tip. Não há requisitos para isso, algumas configurações serão feitas quando o programa for inicializado.
Primeiro faça as seguintes configurações:
this._cssTip.margin = 0;
this._cssTip.position = "absoluto";
this._cssTip.visibility = "oculto";
this._cssTip.display = "bloquear";
this._cssTip.zIndex = 99;
this._cssTip.left = this._cssTip.top = "-9999px";
A margem é definida como 0 para evitar alguns problemas de posicionamento. A visibilidade é usada para ocultar em vez de exibir porque o programa precisa obter o offsetWidth e o offsetHeight da ponta. Ele também precisa definir a esquerda e o topo para evitar que a barra de rolagem apareça devido a. a ponta ocupando o espaço.
Como a Ponta pode estar dentro de outros elementos posicionados, dois parâmetros de correção de deslocamento devem ser definidos:
var iLeft = iTop = 0, p = this.Tip.offsetParent;
while (!(p === document.body || p === document.documentElement)) {
iLeft += p.offsetLeft;
};
this._offsetleft = iLeft;
this._offsettop = iTop;
Por fim, adicione um evento ao mouseover do Tip, que será explicado mais tarde.