canvas 缩放/拖动/还原/封装和实例--开箱即用
canvas 缩放/拖动/还原/封装和实例一、预览二、使用2.1 创建和配置2.2 方法三、重点说明3.1 配置里有2个宽高设置3.2 分开设置事件四、源码一、预览最近需要用到canvas的缩放、拖动、还原等操作,网上有些资料,但用起来都不太方便,自己重新写了一个操作类,能满足上述使用情况,而且用起来很方便,也很灵活,画布尺寸和css尺寸不一致情况也考虑到,拖动支持触摸和鼠标。效果如下:二、使用2
·
canvas 缩放/拖动/还原/封装和实例
一、预览
如果是小程序,可以看这里小程序canvas缩放/拖动/还原/封装和实例
最近需要用到canvas的缩放、拖动、还原等操作,网上有些资料,但用起来都不太方便,自己重新写了一个操作类,能满足上述使用情况,而且用起来很方便,也很灵活。
- 支持画布尺寸和css尺寸不一致
- 支持触摸/鼠标拖拽
- 支持滚轮/按钮缩放
- 支持还原、清除画布等操作
效果如下:
二、使用
2.1 创建和配置
// 创建对象并进行配置
var canvas = new CanvasOperation({
ele: document.getElementById("canvas"), // 画布对象
draw: userDraw, // 用户绘图方法
width: 500, // 画布宽
height: 500, // 画布高
cssWidth: 500, // css设置的宽(对应css style的width)
cssHeight: 500, // css设置的高(对应css style的height)
maxScale: 8, // 缩放最大倍数(缩放比率倍数)
minScale: 0.4, // 缩放最小倍数(缩放比率倍数)
scaleStep: 0.2, // 缩放比率
});
canvas.addMusewheelEvent(); // 添加滚轮放大缩小事件
canvas.addDragEvent(); // 添加拖动事件
canvas.draw(); // 开始绘图
// 用户绘图(这里写你的绘图方法)
function userDraw() {
this.ctx.fillStyle = "#f00";
this.ctx.fillRect(0, 0, 100, 100);
this.ctx.fillStyle = "#00f";
this.ctx.fillRect(150, 150, 200, 200);
this.ctx.fillStyle = "#0f0";
this.ctx.fillRect(400, 400, 100, 100);
}
2.2 方法
canvas.addMusewheelEvent(); // 添加滚轮放大缩小事件
canvas.addDragEvent(); // 添加拖动事件
canvas.draw(); // 绘图
canvas.zoomIn(); // 中心放大
canvas.zoomOut(); // 中心缩小
canvas.reset(); // 还原
canvas.clear(); // 清除画布
三、重点说明
3.1 配置里有2个宽高设置
width: 500, // 画布宽
height: 500, // 画布高
cssWidth: 500, // css设置的宽(对应css style的width)
cssHeight: 500, // css设置的高(对应css style的height)
<canvas id="canvas" width="500" height="500" style="width: 500px; height: 500px"></canvas>
对应canvas元素的2个宽高属性,分别是画布和css。
二者可以不一致,也就是说画布也可以1000px,但css设置为500px,你实际看到的是画布缩小了1倍来显示,主要方便css的页面布局
3.2 分开设置事件
canvas.addMusewheelEvent(); // 添加滚轮放大缩小事件
canvas.addDragEvent(); // 添加拖动事件
你可以根据实际情况只添加滚轮事件或者拖动事件,或者都不添加
四、源码
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<meta http-equiv="X-UA-Compatible" content="IE=edge" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>canvas 缩放/拖动/还原/封装和实例</title>
</head>
<body>
<div class="container">
<h1>canvas 缩放/拖动/还原/封装和实例 -- 大话主席</h1>
<div class="btns">
<button onclick="zoomIn()">放大</button>
<button onclick="zoomOut()">缩小</button>
<button onclick="reset()">还原</button>
</div>
<canvas
id="canvas"
width="500"
height="500"
style="width: 500px; height: 500px"
></canvas>
</div>
<script type="text/javascript">
// 创建对象并进行配置
var canvas = new CanvasOperation({
ele: document.getElementById("canvas"), // 画布对象
draw: userDraw, // 用户绘图方法
width: 500, // 画布宽
height: 500, // 画布高
cssWidth: 500, // css设置的宽(对应css style的width)
cssHeight: 500, // css设置的高(对应css style的height)
maxScale: 8, // 缩放最大倍数(缩放比率倍数)
minScale: 0.4, // 缩放最小倍数(缩放比率倍数)
scaleStep: 0.2, // 缩放比率
});
canvas.addMusewheelEvent(); // 添加滚轮放大缩小事件
canvas.addDragEvent(); // 添加拖动事件
canvas.draw();
// 用户绘图
function userDraw() {
this.ctx.fillStyle = "#f00";
this.ctx.fillRect(0, 0, 100, 100);
this.ctx.fillStyle = "#00f";
this.ctx.fillRect(150, 150, 200, 200);
this.ctx.fillStyle = "#0f0";
this.ctx.fillRect(400, 400, 100, 100);
}
// 放大
function zoomIn() {
canvas.zoomIn();
}
// 缩小
function zoomOut() {
canvas.zoomOut();
}
// 还原
function reset() {
canvas.reset();
}
// canvas操作类
function CanvasOperation(option) {
if (!option.ele || !option.draw) return;
this.ele = option.ele; // 画布对象
this.userDraw = option.draw; // 用户绘图方法
this.width = option.width || 500; // 画布宽
this.height = option.height || 500; // 画布高
this.cssWidth = option.cssWidth || this.width; // css设置的宽
this.cssHeight = option.cssHeight || this.height; // css设置的高
this.maxScale = option.maxScale || 8; // 缩放最大倍数(缩放比率倍数)
this.minScale = option.minScale || 0.4; // 缩放最小倍数(缩放比率倍数)
this.scaleStep = option.scaleStep || 0.2; // 缩放比率
this.ctx = this.ele.getContext("2d");
var _this = this;
var scale = 1; // 当前缩放
var preScale = 1;
var offset = { x: 0, y: 0 }; // 拖动偏移
var curOffset = { x: 0, y: 0 }; // 当前偏移
var mousePos = { x: 0, y: 0 }; // 鼠标位置
var widthRatio = this.width / this.cssWidth; // 画布和css宽比率
var heightRatio = this.height / this.cssHeight; // 画布和css高比率
console.log(widthRatio);
console.log(heightRatio);
// 判断是否移动端,移动端使用触摸事件
var isTouchPad = /hp-tablet/gi.test(navigator.appVersion);
var hasTouch = "ontouchstart" in window && !isTouchPad;
var touchStart = hasTouch ? "touchstart" : "mousedown";
var touchMove = hasTouch ? "touchmove" : "mousemove";
var touchEnd = hasTouch ? "touchend" : "mouseup";
// 绘图(会进行缩放和位移)
this.draw = function () {
this.clearCanvas();
this.ctx.translate(offset.x, offset.y);
this.ctx.scale(scale, scale);
_this.userDraw();
};
// 放大
this.zoomIn = function (isMouse) {
scale += this.scaleStep;
if (scale > this.maxScale) {
scale = this.maxScale;
return;
}
zoom.call(this, isMouse);
};
// 缩小
this.zoomOut = function (isMouse) {
scale -= this.scaleStep;
if (scale < this.minScale) {
scale = this.minScale;
return;
}
zoom.call(this, isMouse);
};
/**
* 缩放操作
* isMouse 是否鼠标为中心缩放,true:鼠标中心缩放 false:画布中间缩放
*/
zoom = function (isMouse) {
// 是否居中放大
if (isMouse) {
mousePos.x *= widthRatio;
mousePos.y *= heightRatio;
} else {
mousePos.x = this.width / 2;
mousePos.y = this.height / 2;
}
offset.x = mousePos.x - ((mousePos.x - offset.x) * scale) / preScale;
offset.y = mousePos.y - ((mousePos.y - offset.y) * scale) / preScale;
this.draw();
preScale = scale;
curOffset.x = offset.x;
curOffset.y = offset.y;
};
// 还原
this.reset = function () {
this.clear();
this.draw();
};
// 仅清除地图
this.clearCanvas = function () {
// 重设canvas尺寸会清空地图并重置canvas内置的scale等
this.ele.width = this.width;
};
// 清除地图并还原对象所有设置
this.clear = function(){
this.clearCanvas()
scale = 1; // 当前缩放
preScale = 1; // 当前缩放
offset = { x: 0, y: 0 }; // 拖动偏移
curOffset = { x: 0, y: 0 }; // 当前偏移
mousePos = { x: 0, y: 0 }; //
},
// 添加滚轮事件
this.addMusewheelEvent = function () {
// 兼容FireFox
const eventType = document.mozFullScreen
? "DOMMouseScroll"
: "mousewheel";
this.ele.addEventListener(eventType, mouseWheel);
function mouseWheel(e) {
mousePos.x = e.offsetX;
mousePos.y = e.offsetY;
var b = true;
if (e.wheelDelta) {
b = e.wheelDelta > 0;
} else {
b = e.detail < 0;
}
if (b) {
_this.zoomIn(true);
} else {
_this.zoomOut(true);
}
if (e.preventDefault) {
e.preventDefault();
}
return false;
}
};
// 添加拖动事件
this.addDragEvent = function () {
this.ele.addEventListener(touchStart, dragStart);
let x = 0;
let y = 0;
function dragMove(e) {
offset.x = curOffset.x + (e.x - x) * widthRatio;
offset.y = curOffset.y + (e.y - y) * heightRatio;
_this.draw();
}
function dragEnd() {
curOffset.x = offset.x;
curOffset.y = offset.y;
window.removeEventListener(touchMove, dragMove);
window.removeEventListener(touchEnd, dragEnd);
}
function dragStart(e) {
x = e.x;
y = e.y;
window.addEventListener(touchMove, dragMove);
window.addEventListener(touchEnd, dragEnd);
}
};
}
</script>
<style type="text/css">
* {
margin: 0;
padding: 0;
}
body {
background: #ccc;
}
h1 {
padding: 30px;
}
.btns button {
margin: 10px;
padding: 3px 10px;
cursor: pointer;
}
.container {
text-align: center;
}
#canvas {
margin: 0 auto;
background: #fff;
cursor: move;
}
</style>
</body>
</html>
https://gitee.com/dhzx/canvas-operation
兄弟,如果帮到你,点个赞再走
开放原子开发者工作坊旨在鼓励更多人参与开源活动,与志同道合的开发者们相互交流开发经验、分享开发心得、获取前沿技术趋势。工作坊有多种形式的开发者活动,如meetup、训练营等,主打技术交流,干货满满,真诚地邀请各位开发者共同参与!
更多推荐
所有评论(0)