Skip to content

Instantly share code, notes, and snippets.

@ombran
Created October 4, 2008 06:22
Show Gist options
  • Save ombran/14728 to your computer and use it in GitHub Desktop.
Save ombran/14728 to your computer and use it in GitHub Desktop.
drag and page scroll
// ==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