原生JS实现会拖动弹跳的公告栏插件
dengjianbin
12年前
原生JS实现会拖动弹跳的公告栏插件是一款功能很强大的特效,一开始渐渐的显示在屏幕的中间,显示完之后就从上面掉到最底部跳来跳去,你也可以拖拽它扔来扔去,撞到边上就会反弹回来,就像玩游戏一样的感觉,太棒了,点击关闭还可以隐藏到左上角图标,当点击左上角图标时,公告栏又像炮弹一样的发射出来跳来跳去,不说了,看效果吧
效果如下:
插件源代码如下:
function onLoad(fn) { var old = window.onload; window.onload = function() { old && old(); fn() } } if (typeof DockType == "undefined") { DockType = { LEFT: 1, RIGHT: 2, TOP: 4, BOTTOM: 8 } } function Dock(oEle, iDirection, oDistance, fnOnBrowserChecked, fnOnResizeOrScroll) { var bIsIe6 = false; var obj = this; this.__oEle__ = oEle; this.__iDir__ = iDirection; this.__oDis__ = oDistance; this.fnOnResizeOrScroll = fnOnResizeOrScroll; if ( - 1 != window.navigator.userAgent.indexOf('MSIE 6.0')) { if ( - 1 != window.navigator.userAgent.indexOf('MSIE 7.0') || -1 != window.navigator.userAgent.indexOf('MSIE 8.0')) { bIsIe6 = false } else { bIsIe6 = true } } else { bIsIe6 = false } this.bIsIe6 = bIsIe6; if (fnOnBrowserChecked) { fnOnBrowserChecked(bIsIe6) } if (bIsIe6) { oEle.style.position = 'absolute' } else { oEle.style.position = 'fixed' } if (bIsIe6) { miaovAppendEventListener(window, "scroll", function() { obj.fixItem() }) } miaovAppendEventListener(window, "resize", function() { obj.fixItem() }); this.fixItem() } Dock.prototype.getScreen = function() { var t = document.body.scrollTop || document.documentElement.scrollTop; return { left: 0, right: document.documentElement.clientWidth, top: t, bottom: t + document.documentElement.clientHeight } }; Dock.prototype.move = function(oDistance) { this.__oDis__ = oDistance; this.fixItem() }; Dock.prototype.fixItem = function() { var t = document.body.scrollTop || document.documentElement.scrollTop; if (this.__iDir__ & DockType.LEFT) { this.__oEle__.style.left = this.__oDis__.left + 'px' } else if (this.__iDir__ & DockType.RIGHT) { this.__oEle__.style.left = document.documentElement.clientWidth - this.__oDis__.right - this.__oEle__.offsetWidth + 'px' } else if (this.__iDir__ & DockType.BOTTOM) { if (this.bIsIe6) { this.__oEle__.style.top = t + document.documentElement.clientHeight - this.__oDis__.bottom - this.__oEle__.offsetHeight } else { this.__oEle__.style.top = document.documentElement.clientHeight - this.__oDis__.bottom - this.__oEle__.offsetHeight } } else if (this.__iDir__ & DockType.TOP) { if (this.bIsIe6) { this.__oEle__.style.top = t + this.__oDis__.top + 'px' } else { this.__oEle__.style.top = this.__oDis__.top + 'px' } } if (this.fnOnResizeOrScroll) { this.fnOnResizeOrScroll({ left: 0, right: document.documentElement.clientWidth, top: t, bottom: t + document.documentElement.clientHeight }) } }; function EffectBuffer(fDistanceCoefficient, iMinSpeed) { this.distanceCoefficient = fDistanceCoefficient; this.iMinSpeed = iMinSpeed } EffectBuffer.prototype.initMotion = function(aMotionData) {}; EffectBuffer.prototype.next = function(aMotionData) { var motion = null; var i = 0; var complete = true; for (i = 0; i < aMotionData.length; i++) { motion = aMotionData[i]; motion.speed = (motion.target - motion.cur) / this.distanceCoefficient; motion.speed = ceilSpeed(motion.speed); if (Math.abs(motion.speed) < this.iMinSpeed) { motion.speed = this.iMinSpeed > 0 ? this.iMinSpeed: -this.iMinSpeed } if (Math.abs(motion.speed) > motion.speedMax) { motion.speed = (motion.speed > 0) ? motion.speedMax: -motion.speedMax } motion.cur += motion.speed; if (motion.cur != motion.target) { complete = false } } if (complete) { for (i = 0; i < aMotionData.length; i++) { aMotionData[i].cur = aMotionData[i].target; aMotionData[i].speed = 0 } return true } return false }; function initQuirkyPopup() { var oDiv = document.getElementById('messageBoardContainer'); var oDivContent = oDiv.getElementsByTagName('div')[0]; var oText = oDiv.getElementsByTagName('div')[2]; var aSpan = oText.getElementsByTagName('span'); var oCloseBtn = oDiv.getElementsByTagName('a')[0]; var oBtnShow = document.getElementById('quirkyPopupShowBtn'); var w = 354; var h = 294; var i = 0; var t = document.body.scrollTop || document.documentElement.scrollTop; oDiv.style.left = (document.documentElement.clientWidth - w) / 2 + 'px'; oDiv.style.top = t + (document.documentElement.clientHeight) / 2 + 'px'; for (i = 0; i < aSpan.length; i++) { aSpan[i].onmousedown = function(ev) { miaovCancelBubble(window.event || ev); return false } } var oQP = new QuirkyPopup(oDiv, oDiv, oBtnShow, oCloseBtn, { x: w, y: h }, function() { return { x: oDiv.offsetLeft, y: oDiv.offsetTop } }, function() { return { x: oDiv.offsetWidth, y: oDiv.offsetHeight } }, function(x, y) { oDiv.style.left = x + 'px'; oDiv.style.top = y + 'px' }, function(x, y) { oDivContent.style.top = (y - h) / 2 + 'px'; oDivContent.style.left = (x - w) / 2 + 'px'; oDiv.style.width = x + 'px'; oDiv.style.height = y + 'px' }); setTimeout(function() { oQP.initShow() }, 1000); if (/msie 6/i.test(navigator.userAgent) && !/msie 7/i.test(navigator.userAgent) && !/msie 8/i.test(navigator.userAgent)) { oBtnShow.style.position = 'absolute'; miaovAppendEventListener(window, 'scroll', function() { var scrollTop = document.documentElement.scrollTop || document.body.scrollTop; oBtnShow.style.top = scrollTop + 'px' }) } } function miaovCancelBubble(oEvent) { if (oEvent.stopPropagation) { oEvent.stopPropagation() } else { oEvent.cancelBubble = true } } function QuirkyPopup(oEleMove, oEleDrag, oEleBtn, oCloseBtn, oMaxSize, fnGetPos, fnGetSize, fnDoMove, fnDoResize, fnOnShowEnd, fnOnHideEnd) { var obj = this; var oSize = fnGetSize(); var oPos = fnGetPos(); this.__oEleMove__ = oEleMove; this.__oEleDrag__ = oEleDrag; this.__oEleBtn__ = oEleBtn; this.__oMaxSize__ = oMaxSize; this.__fnGetPos__ = fnGetPos; this.__fnGetSize__ = fnGetSize; this.__fnDoMove__ = fnDoMove; this.__fnDoResize__ = fnDoResize; this.__fnOnShowEnd__ = fnOnShowEnd; this.__fnOnHideEnd__ = fnOnHideEnd; this.__oDivOuter__ = document.createElement('div'); this.__oDivOuter__.style.display = 'none'; this.__oDivOuter__.style.background = 'white'; this.__oDivOuter__.style.width = '100%'; this.__oDivOuter__.style.filter = 'alpha(opacity=0)'; this.__oDivOuter__.style.opacity = '0'; this.__oDivOuter__.style.top = '0px'; this.__oDivOuter__.style.left = '0px'; this.__oDivOuter__.style.position = 'absolute'; this.__oDivOuter__.style.zIndex = '3003'; this.__oDivOuter__.style.overflow = 'hidden'; this.__oDivOuter__.style.height = document.body.offsetHeight + "px"; document.body.appendChild(this.__oDivOuter__); this.__oDrag__ = new PerfectDrag(oEleDrag, fnGetPos, function(x, y) { var top = document.body.scrollTop || document.documentElement.scrollTop; if (x < 0) { x = 0 } else if (x + obj.__oMaxSize__.x > document.body.offsetWidth) { x = document.body.offsetWidth - obj.__oMaxSize__.x } if (y < top) { y = top } else if (y + obj.__oMaxSize__.y > top + document.documentElement.clientHeight) { y = top + document.documentElement.clientHeight - obj.__oMaxSize__.y } oEleMove.style.left = x + 'px'; oEleMove.style.top = y + 'px'; obj.__oSpeed__.x = x - obj.__oLastPos__.x; obj.__oSpeed__.y = y - obj.__oLastPos__.y; obj.__oLastPos__.x = x; obj.__oLastPos__.y = y }, function() { obj.__oLastPos__ = obj.__fnGetPos__(); obj.stopMove(); obj.__oDivOuter__.style.display = 'block' }, function() { obj.startMove(); obj.__oDivOuter__.style.display = 'none' }); this.__oDrag__.disable(); this.__oLastPos__ = { x: 0, y: 0 }; this.__oSpeed__ = { x: 0, y: 0 }; this.__oMoveTimer__ = null; this.__oMLResize__ = new MoveLib([oSize.x, oSize.y], [60, 60], function(arr) { obj.__fnDoMove__(oPos.x, oPos.y - arr[1].cur / 2); obj.__fnDoResize__(arr[0].cur, arr[1].cur) }, function() { obj.__oDrag__.enable(); obj.startMove(); oCloseBtn.onmousedown = function() { obj.hide(); return false } }, MoveLibType.BUFFER); this.__oMLMove__ = new MoveLib([0, 0], [40, 40], function(arr) { obj.__fnDoMove__(arr[0].cur, arr[1].cur) }, function() { obj.startShowBtn(); obj.__oDock__.fnOnResizeOrScroll = function(oPos) { obj.__oEleMove__.left = -obj.__oMaxSize__.x + 'px' } }, MoveLibType.BUFFER); this.__oMLBtn__ = new MoveLib([0], [40], function(arr) { obj.__oDock__.move({ left: arr[0].cur, top: 0 }) }, function() { if (this.isOpening) { obj.__oSpeed__.x = 150 + Math.ceil(Math.random() * 150); obj.__oSpeed__.y = 0; obj.startMove(); obj.__oDrag__.enable(); this.isOpening = false } }, MoveLibType.BUFFER); this.__oMLBtn__.isOpening = false; this.iAcc = 3; this.fScale = -0.7; this.__oEleBtn__.style.display = 'block'; this.__oDock__ = new Dock(oEleBtn, DockType.LEFT | DockType.TOP, { left: -oEleBtn.offsetWidth, top: 0 }, null, null); this.__oEleBtn__.onclick = function() { var top = document.body.scrollTop || document.documentElement.scrollTop; oEleMove.style.top = top + 'px'; obj.show() } } QuirkyPopup.prototype.initShow = function() { var obj = this; this.__oMLResize__.setTarget([this.__oMaxSize__.x, this.__oMaxSize__.y]) }; QuirkyPopup.prototype.show = function() { this.__oDrag__.disable(); this.stopMove(); this.__oMLBtn__.setCurrent([0]); this.__oMLBtn__.setTarget([ - this.__oEleBtn__.offsetWidth]); this.__oMLBtn__.isOpening = true }; QuirkyPopup.prototype.hide = function() { var obj = this; var oPos = this.__fnGetPos__(); var oSize = this.__oDock__.getScreen(); var top = document.body.scrollTop || document.documentElement.scrollTop; this.__oDrag__.disable(); this.stopMove(); this.__oMLMove__.setCurrent([oPos.x, oPos.y]); this.__oMLMove__.setTarget([ - this.__oMaxSize__.x, oSize.top]); this.__oDock__.fnOnResizeOrScroll = function(oSize) { obj.__oMLMove__.setTarget([ - obj.__oMaxSize__.x, oSize.top]) } }; QuirkyPopup.prototype.startShowBtn = function() { this.__oMLBtn__.setCurrent([ - this.__oEleBtn__.offsetWidth]); this.__oMLBtn__.setTarget([0]) }; QuirkyPopup.prototype.startMove = function() { var obj = this; if (this.__oMoveTimer__) { clearInterval(this.__oMoveTimer__) } this.__oMoveTimer__ = setInterval(function() { obj.__doMove__() }, 30) }; QuirkyPopup.prototype.stopMove = function() { clearInterval(this.__oMoveTimer__); this.__oMoveTimer__ = null }; QuirkyPopup.prototype.__doMove__ = function() { var oPos = this.__fnGetPos__(); var r = document.body.offsetWidth - this.__oMaxSize__.x; var t = document.body.scrollTop || document.documentElement.scrollTop; var b = t + document.documentElement.clientHeight - this.__oMaxSize__.y; this.__oSpeed__.y += this.iAcc; oPos.x += this.__oSpeed__.x; oPos.y += this.__oSpeed__.y; if (Math.abs(this.__oSpeed__.x) < 1) { this.__oSpeed__.x = 0 } if (Math.abs(this.__oSpeed__.y) < 1) { this.__oSpeed__.y = 0 } if (oPos.x <= 0) { oPos.x = 0; this.__oSpeed__.x *= this.fScale } else if (oPos.x >= r) { oPos.x = r; this.__oSpeed__.x *= this.fScale } if (oPos.y <= t) { oPos.y = t; this.__oSpeed__.y *= this.fScale } else if (oPos.y >= b) { oPos.y = b; this.__oSpeed__.y *= this.fScale; this.__oSpeed__.x *= -this.fScale } if (Math.abs(this.__oSpeed__.x) > 0 || Math.abs(this.__oSpeed__.y) > 0) { this.__fnDoMove__(oPos.x, oPos.y) } }; if (typeof MoveLibType == "undefined") { MoveLibType = { COLLISION: 1, ELASTICITY: 2, BUFFER: 3, DIRECT: 4, DIRECT_SLOW: 5, DIRECT_FAST: 6, BUFFER_CUSTOM: 7 } } if (typeof ceilSpeed == "undefined") { ceilSpeed = function(fSpeed) { return fSpeed > 0 ? Math.ceil(fSpeed) : -Math.ceil( - fSpeed) } } function MoveLib(aCur, aSpeedMax, fnDoMove, fnMoveEnd, iEffectType) { var i = 0; switch (iEffectType) { case MoveLibType.COLLISION: this.__oEffect__ = new EffectCollision( - 0.6, 3); break; case MoveLibType.ELASTICITY: this.__oEffect__ = new EffectElasticity(4, 0.65); break; case MoveLibType.BUFFER: this.__oEffect__ = new EffectBuffer(8); break; case MoveLibType.DIRECT: this.__oEffect__ = new EffectDirect(10); break; case MoveLibType.DIRECT_SLOW: this.__oEffect__ = new EffectDirect(20); break; case MoveLibType.DIRECT_FAST: this.__oEffect__ = new EffectDirect(5); break; case MoveLibType.BUFFER_CUSTOM: this.__oEffect__ = new EffectBuffer(parseInt(arguments[5]), parseInt(arguments[6])); break; default: alert('未知的类型' + iEffectType); return } this.motionDatas = []; for (i = 0; i < aCur.length; i++) { this.motionDatas[i] = { target: aCur[i], speed: 0, speedMax: aSpeedMax[i], cur: aCur[i] } } this.fnDoMove = fnDoMove; this.fnMoveEnd = fnMoveEnd; this.interval = 40; this.timer = null; this.lastTimer = 0; this.enabled = true; this.pause = false } MoveLib.prototype.setTarget = function(aValue) { var t = (new Date()).getTime(); var allSame = true; var i = 0; for (i = 0; i < aValue.length; i++) { this.motionDatas[i].target = parseInt(aValue[i]); if (this.motionDatas[i].target != this.motionDatas[i].cur) { allSame = false } } if (allSame) { if (!this.timer) { this.start() } return } this.__oEffect__.initMotion(this.motionDatas); if (this.enabled) { if (!this.timer) { this.start() } if (t - this.lastTimer > this.interval) { this.__timerHandler__(); this.lastTimer = t } } }; MoveLib.prototype.setCurrent = function(aValue) { var i = 0; for (i = 0; i < aValue.length; i++) { this.motionDatas[i].cur = parseInt(aValue[i]) } }; MoveLib.prototype.start = function() { var obj = this; if (!this.enabled) { return } if (this.timer) { clearInterval(this.timer) } else { this.timer = setInterval(function() { obj.__timerHandler__() }, this.interval) } this.iStartTime = ((new Date()).getTime()); this.iCounter = 0 }; MoveLib.prototype.stop = function() { if (this.timer) { clearInterval(this.timer); this.timer = null } }; MoveLib.prototype.__timerHandler__ = function() { var bEnd = false; if (this.pause) { return } bEnd = this.__oEffect__.next(this.motionDatas); if (bEnd) { if (this.fnMoveEnd) { this.fnMoveEnd(this.motionDatas) } this.fnDoMove(this.motionDatas); this.stop() } else { this.iCounter++; this.fnDoMove(this.motionDatas) } this.lastTimer = ((new Date()).getTime()) }; function miaovAppendEventListener(obj, sEventName, fnEvent) { if (obj.attachEvent) { obj.attachEvent('on' + sEventName, fnEvent) } else { obj.addEventListener(sEventName, fnEvent, false) } } function miaovRemoveEventListener(obj, sEventName, fnEvent) { if (obj.detachEvent) { obj.detachEvent('on' + sEventName, fnEvent) } else { obj.removeEventListener(sEventName, fnEvent, false) } } function miaovCancelBubble(oEvent) { if (oEvent.stopPropagation) { oEvent.stopPropagation() } else { oEvent.cancelBubble = true } } function PerfectDrag(oElementDrag, fnGetPos, fnDoMove, fnOnDragStart, fnOnDragEnd) { var obj = this; this.oElement = oElementDrag; this.oElement.style.overflow = 'hidden'; this.fnGetPos = fnGetPos; this.fnDoMove = fnDoMove; this.fnOnDragStart = fnOnDragStart; this.fnOnDragEnd = fnOnDragEnd; this.__oStartOffset__ = { x: 0, y: 0 }; this.oElement.onmousedown = function(ev) { obj.startDrag(window.event || ev); return false }; this.fnOnMouseUp = function(ev) { obj.stopDrag(window.event || ev) }; this.fnOnMouseMove = function(ev) { obj.doDrag(window.event || ev) } } PerfectDrag.prototype.enable = function() { var obj = this; this.oElement.onmousedown = function(ev) { obj.startDrag(window.event || ev); return false } }; PerfectDrag.prototype.disable = function() { this.oElement.onmousedown = null }; PerfectDrag.prototype.startDrag = function(oEvent) { var oPos = this.fnGetPos(); var x = oEvent.clientX; var y = oEvent.clientY; if (this.fnOnDragStart) { this.fnOnDragStart() } this.__oStartOffset__.x = x - oPos.x; this.__oStartOffset__.y = y - oPos.y; if (this.oElement.setCapture) { this.oElement.setCapture(); this.oElement.onmouseup = this.fnOnMouseUp; this.oElement.onmousemove = this.fnOnMouseMove } else { document.addEventListener("mouseup", this.fnOnMouseUp, true); document.addEventListener("mousemove", this.fnOnMouseMove, true); window.captureEvents(Event.MOUSEMOVE | Event.MOUSEUP) } }; PerfectDrag.prototype.stopDrag = function(oEvent) { if (this.oElement.releaseCapture) { this.oElement.releaseCapture(); this.oElement.onmouseup = null; this.oElement.onmousemove = null } else { document.removeEventListener("mouseup", this.fnOnMouseUp, true); document.removeEventListener("mousemove", this.fnOnMouseMove, true); window.releaseEvents(Event.MOUSE_MOVE | Event.MOUSE_UP) } if (this.fnOnDragEnd) { if (oEvent.clientX == this.__oStartOffset__.x && oEvent.clientY == this.__oStartOffset__.y) { this.fnOnDragEnd(false) } else { this.fnOnDragEnd(true) } } }; PerfectDrag.prototype.doDrag = function(oEvent) { var x = oEvent.clientX; var y = oEvent.clientY; this.fnDoMove(x - this.__oStartOffset__.x, y - this.__oStartOffset__.y) };