一.原理
当鼠标点击并移动在画布canvas中时,会显示放大后的图片一角。移除canvas,鼠标松开或是鼠标离开点击那块范围时,则不会显示。这个原理是:把这个图片放在离屏canvas上,而可视画布canvas放着这个图片的缩小版,填充画布。
当鼠标点击这个可视画布canvas中图像的位置,我们可以根据这个位置获取离屏画布canvas中图像上的位置(这个位置是=可视画布中图像的位置*图片与可视画布canvas的倍数),此时裁剪离屏canvas中的图像,显示在可视窗口中。
二.知识点
1.图片的加载:
var img=new Image();
img.src = "timg.jpg";
img.οnlοad=function (){
context.drawImage( image , 0 , 0 );
}
2. 鼠标与canvas的交互:
①.鼠标点击canvas.onmousedown = function(e){e.preventDefault();}
②鼠标移动: 当鼠标移动到某对象范围的上方时触发的事件
canvas.onmousemove = function(e){e.preventDefault();}
③鼠标按下后,松开时激发的事件
canvas.onmouseup = function(e){e.preventDefault();}
④当鼠标离开某对象范围时触发的事件
canvas.onmouseout = function(e){e.preventDefault();}
e.preventDefault();//禁止默认的响应事件
3.获取在canvas里的点坐标
getBoundingClientRect()用于获取某个元素相对于视窗的位置集合。集合中有top, right, bottom, left等属性。
function detect(event){
var x=event.clientX-canvas.getBoundingClientRect().left;
var y=event.clientY-canvas.getBoundingClientRect().top;
}
4.创建一个新的变量,用来判断鼠标是否处于点击的状态
var isMouseDown = false;
5.需要一个离屏画布canvas(离屏是用户不可见的),用来做放大镜的作用
<canvas id="offCanvas" style="display: none">您的浏览器尚不支持canvas</canvas>
这个canvas画布承载这是图像的大小
6.创建一个变量,用来放大的倍数,用来计算图片与可视画布canvas的倍数
var scale;
在这里我们不考虑不规则图像的倍数多样性问题,简单点,让图形的大小等于可视画布canvas的大小整数倍。三.代码
<!DOCTYPE html>
<html>
<head lang="en">
<meta charset="UTF-8">
<title></title>
<style type="text/css">
body{
background: black;
}
#canvas{
display:block;
margin:0 auto;
border:1px solid #aaa;
}
</style>
</head>
<body>
<canvas id="canvas">您的浏览器尚不支持canvas</canvas>
<canvas id="offCanvas" style="display: none">您的浏览器尚不支持canvas</canvas>
<script>
var canvas = document.getElementById("canvas");
var context = canvas.getContext("2d");
var offCanvas = document.getElementById("offCanvas");
var offContext = offCanvas.getContext("2d");
var image = new Image();
var isMouseDown = false;//用来判断鼠标是否处于点击的状态
var scale;
window.onload = function(){
canvas.width = 1024;
canvas.height = 750;
image.src = "img-lg.jpg";
image.onload = function(){
offCanvas.width = image.width;
offCanvas.height = image.height;
//在这里我们不考虑不规则图像的倍数问题,简单点,让图形的大小等于可视画布canvas的大小3倍
scale = offCanvas.width / canvas.width;
context.drawImage( image , 0 , 0 , canvas.width , canvas.height );//这边放着图像的缩放版,刚刚好填充可视窗口
offContext.drawImage( image , 0 , 0 );//offContext的大小应该跟图像的大小
}
}
//1.鼠标点击
canvas.onmousedown = function(e){
e.preventDefault();//禁止默认的响应事件
point = windowToCanvas( e.clientX , e.clientY );//坐标点
console.log( point.x , point.y );
isMouseDown = true;
drawCanvasWithMagnifier( true , point );
}
//3.1鼠标移动: 当鼠标移动到某对象范围的上方时触发的事件
canvas.onmousemove = function(e){
e.preventDefault();//禁止默认的响应事件
if( isMouseDown == true ){
point = windowToCanvas( e.clientX , e.clientY );
console.log( point.x , point.y );
drawCanvasWithMagnifier( true , point );
}
}
//3.2鼠标按下后,松开时激发的事件
canvas.onmouseup = function(e){
e.preventDefault();//禁止默认的响应事件
isMouseDown = false;
drawCanvasWithMagnifier( false );
}
//3.3当鼠标离开某对象范围时触发的事件
canvas.onmouseout = function(e){
e.preventDefault();
isMouseDown = false;
drawCanvasWithMagnifier( false );
}
//4放大镜绘制
//参数:isShowMagnifier是否要显示放大镜
//point要放大镜时,显示在哪里坐标
function drawCanvasWithMagnifier( isShowMagnifier , point ){
context.clearRect( 0 , 0 , canvas.width , canvas.height );
context.drawImage( image , 0 , 0 , canvas.width , canvas.height );
if( isShowMagnifier == true ){
drawMagnifier( point );
}
}
//5.要放大镜时,显示在哪里坐标
function drawMagnifier( point ){
var mr = 200;//设置半径值
//离屏画布canvas中图像上的位置imageLG_cx,imageLG_cy=可视画布中图像的位置*图片与可视画布canvas的倍数
var imageLG_cx = point.x * scale;
var imageLG_cy = point.y * scale;
var sx = imageLG_cx - mr;
var sy = imageLG_cy - mr;
var dx = point.x - mr;
var dy = point.y - mr;
context.save();
context.lineWidth = 10.0
context.strokeStyle = "#069"
context.beginPath();
context.arc( point.x , point.y , mr , 0 , Math.PI*2 , false );
context.stroke();
context.clip();
context.drawImage( offCanvas , sx , sy , 2*mr , 2*mr , dx , dy , 2*mr , 2*mr );
context.restore();
}
//2.获取在canvas里的点坐标
//canvas在屏幕在的坐标,getBoundingClientRect()用于获取某个元素相对于视窗的位置集合。
//集合中有top, right, bottom, left等属性。
function windowToCanvas( x , y ){
var bbox = canvas.getBoundingClientRect();
return {x:x-bbox.left , y:y-bbox.top};
}
</script>
</body>
</html>
代码跟之前差不多,只要修改
//5.要放大镜时,显示在哪里坐标
function drawMagnifier( point ){
context.save();
var mr = 200;//设置半径值
//离屏画布canvas中图像上的位置imageLG_cx,imageLG_cy=可视画布中图像的位置*图片与可视画布canvas的倍数
var imageLG_cx = point.x * scale;
var imageLG_cy = point.y * scale;
var sx = imageLG_cx - mr;
var sy = imageLG_cy - mr;
var dx = point.x - mr;
var dy = point.y - mr;
context.save();
context.lineWidth = 10.0;
context.translate(point.x ,point.y);
context.scale(mr,mr);
starPath(context);
context.fillStyle="#fff";
context.fill();
context.restore();
context.clip();
context.drawImage( offCanvas , sx , sy , 2*mr , 2*mr , dx , dy , 2*mr , 2*mr );
context.restore();
}
//五角星
function starPath(ctx){//参数:canvas的内容传递,小圆半径,大圆半径,原点坐标的转移位置x,y,旋转的角度
ctx.beginPath();
for(var i=0;i<5;i++){
ctx.lineTo(Math.cos(2*(18+i*72)*Math.PI / 360),
-Math.sin(2*(18+i*72)*Math.PI / 360));
ctx.lineTo(Math.cos(2*(54+i*72)*Math.PI / 360)*0.5,
-Math.sin(2*(54+i*72)*Math.PI / 360)*0.5);
}
context.closePath();
}
如果是用户上传图像,这时图像大小就不确定,倍数得情况就多样性了,而此项目并没有考虑这些而是简单化了,事先就把图像大小设计成可视画布canvas的整数倍(3倍),。
欢迎大家一起讨论,解决这些不足,使其项目更加完整。