Created
October 4, 2008 06:22
-
-
Save ombran/14728 to your computer and use it in GitHub Desktop.
drag and page scroll
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 DragScroll | |
// @namespace http://github.com/ombran | |
// @include * | |
// ==/UserScript== | |
(function(){ | |
function DragScroll(){ | |
this.initialize.apply(this, arguments); | |
} | |
DragScroll.prototype = { | |
draw: false, | |
speed: 50, | |
maxStep: 150, | |
brakeK: 3, | |
hash: null, | |
currentBlock: null, | |
requestedX: 0, | |
requestedY: 0, | |
initialize: function(){ | |
var ds = document.createElement("canvas"); | |
ds.id = "drag-scroll"; | |
document.body.appendChild(ds); | |
var canvas = document.getElementById("drag-scroll"); | |
var ctx = canvas.getContext("2d"); | |
canvas.width = 128; | |
canvas.height = 128; | |
this.canvas = canvas; | |
this.ctx = ctx; | |
this.canvasStyle(); | |
var self = this; | |
addEventToListener(canvas, 'mouseup', function(event) { self.catchMouseEvent(event); }, false); | |
addEventToListener(canvas, 'mousedown', function(event) { self.catchMouseEvent(event); }, false); | |
addEventToListener(canvas, 'mouseover', function(event) { self.catchMouseEvent(event); }, false); | |
addEventToListener(canvas, 'mouseout', function(event) { self.catchMouseEvent(event); }, false); | |
addEventToListener(canvas, 'mousemove', function(event) { self.catchMouseEvent(event); }, false); | |
addEventToListener(window, 'scroll', function(event) { self.catchMouseEvent(event); }, false); | |
addEventToListener(window, 'resize', function(event) { self.catchMouseEvent(event); }, false); | |
this.offDrawRader(); | |
}, | |
canvasStyle: function(){ | |
this.dragWidth = this.canvas.width * ( getScroll().winW / getScroll().docW ); | |
this.dragHeight = this.canvas.height * ( getScroll().winH / getScroll().docH ); | |
this.canvas.style.position = "fixed"; | |
this.canvas.style.top = getScroll().winH - this.canvas.height - 10 + "px"; | |
this.canvas.style.left = getScroll().winW - this.canvas.width - 10 + "px"; | |
this.canvas.style.zIndex = "100"; | |
}, | |
offDrawRader: function(){ | |
this.clearCanvas(); | |
var hx, hy, pw, ph, px, py; | |
if (this.canvas.getContext){ | |
px = this.canvas.width * ( getScroll().scrollX / getScroll().docW ); | |
py = this.canvas.height * ( getScroll().scrollY / getScroll().docH ); | |
pw = this.dragWidth; | |
ph = this.dragHeight; | |
this.ctx.fillStyle = "rgba(200,220,255,0.5)"; | |
this.ctx.fillRect(0, 0, this.canvas.width, this.canvas.height); | |
this.ctx.fillStyle = "rgba(220,180,200,0.5)"; | |
this.ctx.fillRect(px, py, pw, ph); | |
} | |
}, | |
onDrawRader: function(){ | |
this.clearCanvas(); | |
var hx, hy, pw, ph, px, py; | |
if (this.canvas.getContext){ | |
px = this.canvas.width * ( getScroll().scrollX / getScroll().docW ); | |
py = this.canvas.height * ( getScroll().scrollY / getScroll().docH ); | |
pw = this.dragWidth; | |
ph = this.dragHeight; | |
this.ctx.fillStyle = "rgba(200,220,255,0.8)"; | |
this.ctx.fillRect(0, 0, this.canvas.width, this.canvas.height); | |
this.ctx.fillStyle = "rgba(220,180,200,0.8)"; | |
this.ctx.fillRect(px, py, pw, ph); | |
} | |
}, | |
clearCanvas: function(){ | |
if (this.canvas.getContext){ | |
this.ctx.clearRect(0, 0, this.canvas.width, this.canvas.height); | |
} | |
}, | |
catchMouseEvent: function(event){ | |
var x, y, ww, hh; | |
x = event.clientX - this.canvas.offsetLeft - this.dragWidth/2; | |
y = event.clientY - this.canvas.offsetTop - this.dragHeight/2; | |
ww = getScroll().docW / this.canvas.width; | |
hh = getScroll().docH / this.canvas.height; | |
x = x * ww; | |
y = y * hh; | |
switch(event.type) { | |
case 'mouseover': | |
this.onDrawRader(); | |
break; | |
case 'mouseup': | |
this.draw = false; | |
this.initSmoothScroll(x, y); | |
this.onDrawRader(); | |
break; | |
case 'mousedown': | |
this.draw = true; | |
this.onDrawRader(); | |
break; | |
case 'mouseout': | |
this.draw = false; | |
this.offDrawRader(); | |
break; | |
case 'mousemove': | |
if (this.draw == true) { | |
window.scroll(x, y); | |
this.onDrawRader(); | |
} | |
break; | |
case 'scroll': | |
if (this.draw == false) { | |
this.offDrawRader(); | |
} | |
break; | |
case 'resize': | |
this.canvasStyle(); | |
break; | |
} | |
}, | |
/* smooth scroll 機構 */ | |
initSmoothScroll: function(x, y){ | |
this.requestedX = x; | |
this.requestedY = y; | |
this.smoothScroll(); | |
return false; | |
}, | |
smoothScroll: function(){ | |
var top = getScroll().scrollY; | |
var left = getScroll().scrollX; | |
var winW = getScroll().winW; | |
var winH = getScroll().winH; | |
var docW = getScroll().docW; | |
var docH = getScroll().docH; | |
var endDistance, offsetX, offsetY; | |
if(this.requestedY > top) { | |
endDistance = Math.round((docH - (top + winH)) / this.brakeK); | |
endDistance = Math.min(Math.round((this.requestedY-top)/ this.brakeK), endDistance); | |
offsetY = Math.max(2, Math.min(endDistance, this.maxStep)); | |
} else { | |
offsetY = - Math.min(Math.abs(Math.round((this.requestedY-top)/ this.brakeK)), this.maxStep); | |
} | |
if(this.requestedX > left) { | |
endDistance = Math.round((docW - (left + winW)) / this.brakeK); | |
endDistance = Math.min(Math.round((this.requestedX-left)/ this.brakeK), endDistance); | |
offsetX = Math.max(2, Math.min(endDistance, this.maxStep)); | |
} else { | |
offsetX = - Math.min(Math.abs(Math.round((this.requestedX-left)/ this.brakeK)), this.maxStep); | |
} | |
window.scrollTo(left + offsetX, top + offsetY); | |
if((Math.abs(top-this.requestedY) <= 1 || getScroll().scrollY == top) && | |
(Math.abs(left-this.requestedX) <= 1 || getScroll().scrollX == left)) { | |
// window.scrollTo(this.requestX, this.requestedY); | |
} else { | |
var self = this; | |
setTimeout(function(){ self.smoothScroll(); }, this.speed); | |
} | |
} | |
} | |
function addEventToListener(element, event, func, capture){ | |
if (element.addEventListener) { | |
element.addEventListener(event, func, capture); | |
} | |
else if (element.attachEvent) { | |
element.attachEvent("on"+event, func); | |
} | |
else { | |
alert("no support browser."); | |
return(false); | |
} | |
} | |
function getScroll(){ | |
var Obj = new Object(); | |
var scrollX1 = scrollX2 = scrollX3 = scrollY1 = scrollY2 = scrollY3 = 0; | |
var docW1 = docW2 = docH1 = docH2 = 0; | |
var winW1 = winW2 = winW3 = winH1 = winH2 = winH3 = 0; | |
if (document.documentElement) { | |
scrollX1 = document.documentElement.scrollLeft || 0; | |
scrollY1 = document.documentElement.scrollTop || 0; | |
docW1 = document.documentElement.scrollWidth || 0; | |
docH1 = document.documentElement.scrollHeight || 0; | |
winW1 = document.documentElement.clientWidth; | |
winH1 = document.documentElement.clientHeight; | |
} | |
if (document.body) { | |
scrollX2 = document.body.scrollLeft || 0; | |
scrollY2 = document.body.scrollTop || 0; | |
docW2 = document.body.scrollWidth || 0; | |
docH2 = document.body.scrollHeight || 0; | |
winW2 = document.body.clientWidth; | |
winH2 = document.body.clientHeight; | |
} | |
scrollX3 = window.scrollX || 0; | |
scrollY3 = window.scrollY || 0; | |
winW3 = window.innerWidth; | |
winH3 = window.innerHeight; | |
Obj.scrollX = Math.max(scrollX1, Math.max(scrollX2, scrollX3)); | |
Obj.scrollY = Math.max(scrollY1, Math.max(scrollY2, scrollY3)); | |
Obj.docW = Math.max(docW1, docW2); | |
Obj.docH = Math.max(docH1, docH2); | |
Obj.winW = Math.min(winW1, Math.min(winW2, winW3)); | |
Obj.winH = Math.min(winH1, Math.min(winH2, winH3)); | |
return Obj; | |
} | |
addEventToListener(window, 'load', function(){ new DragScroll(); }, false); | |
})(); |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment