1:Cause
improve zoom functionality of html5 imageviewer. zoom in the picture by the mouse.
2:Bring in the Scalable Vector Graphics (SVG)
Before: Canvas is based on the bitmap image, it can not change the size, scale display only. SVG is an earlier standard for drawing shapes in browsers. SVG is based on the vector at the same time, all it can to change the size of good graphics processing.
3:Canvas track transform to SVG use js
var svg = document.createElementNS("http://www.w3.org/2000/svg",'svg');
var xform = svg.createSVGMatrix();
ctx.getTransform = function(){ return xform; };
var savedTransforms = [];
var save = ctx.save;
ctx.save = function(){
savedTransforms.push(xform.translate(0,0));
return save.call(ctx);
};
var restore = ctx.restore;
ctx.restore = function(){
xform = savedTransforms.pop();
return restore.call(ctx);
};
var scale = ctx.scale;
ctx.scale = function(sx,sy){
xform = xform.scaleNonUniform(sx,sy);
return scale.call(ctx,sx,sy);
};
var rotate = ctx.rotate;
ctx.rotate = function(radians){
xform = xform.rotate(radians*180/Math.PI);
return rotate.call(ctx,radians);
};
var translate = ctx.translate;
ctx.translate = function(dx,dy){
xform = xform.translate(dx,dy);
return translate.call(ctx,dx,dy);
};
var transform = ctx.transform;
ctx.transform = function(a,b,c,d,e,f){
var m2 = svg.createSVGMatrix();
m2.a=a; m2.b=b; m2.c=c; m2.d=d; m2.e=e; m2.f=f;
xform = xform.multiply(m2);
return transform.call(ctx,a,b,c,d,e,f);
};
var setTransform = ctx.setTransform;
ctx.setTransform = function(a,b,c,d,e,f){
xform.a = a;
xform.b = b;
xform.c = c;
xform.d = d;
xform.e = e;
xform.f = f;
return setTransform.call(ctx,a,b,c,d,e,f);
};
var pt = svg.createSVGPoint();
ctx.transformedPoint = function(x,y){
pt.x=x; pt.y=y;
return pt.matrixTransform(xform.inverse());
}
4: The standard method of Canvas
1:save() : Saves the entire state of the canvas.
2:restore(): Restores the most recently saved canvas state.
3:translate(x,y): Move the canvas and its origin on the grid. x is the horizontal distance to move, y is the vertical distance to move.
4:rotate(angle): Rotate around the current origin by the angle number of radians.
5:scaling(x,y): Scales the units by x horizontal and y vertically. default is x=1 and y =1.
6:setTransform(a,b,c,d,e,f): Multiplies the current transformation matrix with the matrix described by its arguments. the default is setTransform(1, 0, 0, 1, 0, 0).
a: Horizontal scaling.
b:Horizontal skewing.
c:Vertical skewing.
d:Vertical scaling.
e:Horizontal moving.
f: Vertical moving.
7:drawImage(img,sx,sy,swidth,sheight,x,y,width,height): Draw the image in the canvas.
parameter description
img image source
sx optional. the x coordinate of shear the image
sy optional. the y coordinate of shear the image
swidth optional. the y coordinate of shear the image
sheight optional. the y coordinate of shear the image
x the begin x coordinate of image
y the begin y coordinate of image
width optional. display image width
height optional. display image height
5: In Image Viewer Case
1:set the origin of coordinates.
default image position
//translate the coordinate.
//we need set the coordinate original point to the canvas center.
Canvas.prototype.tanslateCoordinate = function(canvas){
if(!this.isTranslated){
this.context.translate(canvas.width/2,canvas.height/2);
this.isTranslated = true;
}
}
//draw the image.
Canvas.prototype.drawContextImage = function(image,canvas){
// dirtyFlag = false means it is a new image, but the medavisCanvas is null, the first time to draw image on the canvas, no state existed yet
// if the canvas marked as dirty, then no need to load the image,
$(canvas).attr("dirty", "true");
if(this.fitFlag){
//parameter 1:image data 2:image x coordinate 3:image y coordinate 4:image x width 5:image height
//we need draw the image in the original point.
this.context.drawImage(image, -image.width*this.multiple/2,-image.height*this.multiple/2,image.width*this.multiple,image.height*this.multiple); // draw the image
}else{
this.context.drawImage(image,-image.width/2,-image.height/2); // draw the original image
}
}
4:Zoom in by the mouse
./**----image zoom in out function----*/
Canvas.prototype.zoomInOut = function(image,canvas,scale,lastX,lastY){
this.clearRect(image,canvas);
this.tanslateCoordinate(canvas);
var pt = this.context.transformedPoint(lastX,lastY);
//get the x and y
this.dragStart = this.context.transformedPoint(lastX,lastY);
//translate
this.context.translate(pt.x,pt.y);
//scale
var factor = 1 + scale;
this.context.scale(factor,factor);
this.scaleFactor =this.scaleFactor * factor;
// revert. this.context.translate(-pt.x/factor,-pt.y/factor); this is the true revert.
if(MedicalViewerAPI.selectSeries){
this.context.translate(-pt.x/factor,-pt.y/factor);
}else{
this.context.translate(-pt.x,-pt.y);
}
this.drawContextImage(image,canvas)
};
5:Pan mode move image.
get the mouse down x and y position and get the move position.
// get mouse down x and y coordinate value.
Canvas.prototype.mouseDown = function(image,canvas,e){
this.lastX = e.offsetX || (e.pageX - canvas.offsetLeft);
this.lastY = e.offsetY || (e.pageY - canvas.offsetTop);
// save the mouse down coordinate for after move envet to calculate the distance.
this.dragStart = this.context.transformedPoint(this.lastX,this.lastY);
//for move series when mouse is out of the canvas need to reset the flag .
if(MedicalViewerAPI.selectSeries){
this.setFirstDragStart();
}
};
//It's depend on the coordinate status
Canvas.prototype.moveImage=function(e,image,canvas){
var lastX = e.offsetX || (e.pageX - canvas.offsetLeft);
var lastY = e.offsetY || (e.pageY - canvas.offsetTop);
var pt = this.context.transformedPoint(lastX,lastY);
this.clearRect(image,canvas);
this.context.translate(pt.x-this.dragStart.x,pt.y-this.dragStart.y);
this.tanslateCoordinate(canvas);
this.drawContextImage(image,canvas);
};
6:Rotate and Flip
Canvas.prototype.drawRotated = function (image,canvas,degrees){
this.clearRect(image,canvas);
this.tanslateCoordinate(canvas);
this.rotatedCanvas(canvas,degrees);
this.drawContextImage(image,canvas);
}
Canvas.prototype.rotatedCanvas = function (canvas,degrees){
this.context.rotate(degrees*Math.PI/180);
}
Canvas.prototype.rotateLeft=function(image,canvas){
var flipHorFlag = this.flipHor ? -1 : 1;
var flipVorFlag = this.flipVor ? -1 : 1;
//when in fliph or flipv rotate left and rotate right need to reversal.
this.angleInDegrees-=90*flipHorFlag*flipVorFlag;
this.angleInDegrees = this.angleInDegrees%360
this.drawRotated(image,canvas,-90*flipHorFlag*flipVorFlag);
//push it in the rotateAndFlipSteps to use in original and revert function.
this.rotateAndFlipSteps.push(0);
};
Canvas.prototype.rotateRight=function(image,canvas){
var flipHorFlag = this.flipHor ? -1 : 1;
var flipVorFlag = this.flipVor ? -1 : 1;
this.angleInDegrees+=90*flipHorFlag*flipVorFlag;
this.angleInDegrees = this.angleInDegrees%360
this.drawRotated(image,canvas,90*flipHorFlag*flipVorFlag);
this.rotateAndFlipSteps.push(1);
};
/**---------------rotate function end---------------------**/
/**---------------flip image function---------------------**/
Canvas.prototype.flipH=function(image,canvas){
this.flipHor = !this.flipHor;
this.clearRect(image,canvas);
this.tanslateCoordinate(canvas);
if((Math.abs(this.angleInDegrees) ==90 || Math.abs(this.angleInDegrees) ==270)){
this.context.scale(1, -1); // Set scale to flip.
}else{
this.context.scale(-1, 1);
}
this.drawContextImage(image,canvas);
this.rotateAndFlipSteps.push(3);
};
Canvas.prototype.flipV=function(image,canvas){
//need to save this image is flip or not.
this.flipVor = !this.flipVor;
this.clearRect(image,canvas);
this.tanslateCoordinate(canvas);
if((Math.abs(this.angleInDegrees) ==90 || Math.abs(this.angleInDegrees) ==270)){
this.context.scale(-1, 1); // Set scale to flip.
}else{
this.context.scale(1, -1);
}
this.drawContextImage(image,canvas);
this.rotateAndFlipSteps.push(2);
};