最近项目里有个基于 raphael.js 的功能要进行迭代,要求要可以对画布进行缩放和移动,类似于地图那种放大缩小移动,研究了一番,发现 raphael 并没有直接实现这些功能,看了手册,我发现了 paper 的 setViewBox 方法:
经过测试,这个方法类似于一个放大镜的功能,它在不改变画布 paper 的情况下,截取某一个区域,用这个区域来铺满 paper,于是我们可以使用它来实现放大、移动的效果,代码如下:
<html>
<head>
<title>raphael缩放移动画布/</title>
<script src="https://cdn.bootcss.com/jquery/3.2.1/jquery.min.js" type="text/javascript"></script>
<script src="https://cdn.bootcss.com/raphael/2.2.7/raphael.min.js" type="text/javascript"></script>
</head>
<body>
<div id="paper"></div>
</body>
</html>
<script>
$(function () {
//一些全局参数
const paperWidth = 500; //画布宽度
const paperHeight = 500; //画布高度
const maxSize = 3; //允许放大的最大倍数
const minSize = 0.5; //允许缩小的最大倍数
var mouseOnBackGround = false; //鼠标是否悬浮在画布上
var mouseOnObject = false; //鼠标是否悬浮在画布的某个对象上
var mouseDown = false; //鼠标是否得按住状态
var lastMouseLocation = {}; //记录鼠标移动之前的坐标
//缩放相关参数
//coef:每次放大、缩小的增量;
//zoom:目前的大小与原来大小的比例;
//(x,y):目前缩放图的左上角坐标;
//w,h:以(x,y)为原点取得宽度和高度;
const scale = {coef: 0.05, zoom: 1, x: 0, y: 0, w: paperWidth, h: paperHeight};
//创建一个画布
var paper = new Raphael("paper", paperWidth, paperHeight);
//创建一个跟paper一样尺寸的rect模拟背景图
paper.rect(0, 0, paperWidth, paperHeight)
.attr({
"stroke": "blue",
"stroke-width": 4,
"fill": "#e1e1e1"
}
)
.hover(
function () {
//鼠标进入背景
mouseOnBackGround = true;
},
function () {
//鼠标移出背景
mouseOnBackGround = false;
}
);
//创建一个圆
paper.circle(150, 150, 40)
.attr({
"stroke": "red",
"stroke-width": 4,
"fill": "blue",
"opacity": 0.5
})
.hover(
function () {
//鼠标进入
mouseOnObject = true;
},
function () {
//鼠标移出
mouseOnObject = false;
}
);
//创建一个圆角方形
paper.rect(250, 250, 50, 50, 10)
.attr({
"stroke": "blue",
"stroke-width": 4,
"fill": "green"
}
)
.hover(
function () {
//鼠标进入
mouseOnObject = true;
},
function () {
//鼠标移出
mouseOnObject = false;
}
);
//更新Scale
function updateScale(x, y, w, h) {
scale.w = w;
scale.h = h;
scale.x = x;
scale.y = y;
}
//获取操作前的viewbox中心点
function getLastCenterPoint() {
var centerPoint = {};
centerPoint.x = scale.x + scale.w / 2;
centerPoint.y = scale.y + scale.h / 2;
return centerPoint;
}
/**
*鼠标滚轮缩放
*
*/
function onMouseWheeling(e) {
var dtl;
if (!mouseOnBackGround && !mouseOnObject) {
return;
}
if (e.wheelDelta) { //chrome
dtl = e.wheelDelta;
} else if (e.detail) {//firefox or others
dtl = -e.detail;
}
if (dtl < 0) {
//缩小,
if (scale.zoom < minSize) {
return;
}
scale.zoom -= scale.coef;
} else {
//放大
if (scale.zoom > maxSize) {
return;
}
scale.zoom += scale.coef;
}
//计算新的视图参数
var w = paperWidth / scale.zoom;
var h = paperHeight / scale.zoom;
var lastCenterPoint = getLastCenterPoint();
var x = lastCenterPoint.x - w / 2;
var y = lastCenterPoint.y - h / 2;
updateScale(x, y, w, h);
paper.setViewBox(x, y, w, h, false);
}
if (document.addEventListener) {
document.addEventListener('DOMMouseScroll', onMouseWheeling, false);
window.onmousewheel = document.onmousewheel = onMouseWheeling;//IE/Opera/Chrome/Safari
} else {
alert("鼠标滚轮监听事件绑定失败");
}
//监听鼠标移动
$(document).bind('mousedown', function (e) {
lastMouseLocation.x = e.clientX;
lastMouseLocation.y = e.clientY;
mouseDown = true;
}).bind('mouseup', function (e) {
lastMouseLocation = {};
mouseDown = false;
}).bind('mousemove', function (e) {
if (!mouseDown) {
return;
}
if (!mouseOnBackGround && !mouseOnObject) {
return;
}
var dx = e.clientX - lastMouseLocation.x;
var dy = e.clientY - lastMouseLocation.y;
var x = scale.x - dx;
var y = scale.y - dy;
updateScale(x, y, scale.w, scale.h);
lastMouseLocation.x = e.clientX;
lastMouseLocation.y = e.clientY;
paper.setViewBox(x, y, scale.w, scale.h, false);
})
});
</script>
欢迎来到这里!
我们正在构建一个小众社区,大家在这里相互信任,以平等 • 自由 • 奔放的价值观进行分享交流。最终,希望大家能够找到与自己志同道合的伙伴,共同成长。
注册 关于