Canvas实现画布的缩放
主要介绍三种方式:
首先创建一个index.html文件

<!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>iot</title>
</head>
<body>
<canvas id="canvas" width="800" height="800" style="width: 800px;height: 800px;border: 1px solid gray;margin: auto;display: flex;"></canvas>
</body>
</html>
<script type="module">
import index from './index.js';
window.onload = (() => {
index.init();
})
</script>
index.html
一、使用canvas style属性和 width以及height属性实现缩放效果
优点:代码简单、易开发
缺点:当放大活缩小到一定倍数时容易失真,且只能围绕画布左上角缩放,效果不好,且不能实现编辑等功能
原理:canvas中style样式的height和width属性修饰的是DOM元素的样式,而canvas自有的height和width属性描述的是画布的大小,当这两种样式等比例关系时,就可以实现放大和缩小
/**
* 通过改变canvas的样式来实现缩放,原理是通过canvas的style中height和width 以及自带的width和height属性不同的比例实现缩放
* flag true:放大 false: 缩小
*/
function zoom1(flag = true) {
const curH = Number(canvas.getAttribute('height'));
const curW = Number(canvas.getAttribute('width'));
canvas.setAttribute('width', flag ? curW * scale : curW / scale);
canvas.setAttribute('height', flag ? curH * scale : curH / scale);
}

二、使用canvas API scale方法实现图形的缩放
优点:代码简洁,可以按照鼠标所在位置进行缩放
缺点:图形边框等会随着缩放,且有一定的失真;缩放后,图形原始坐标点会随着缩放等比例变化,不方便实现编辑功能
/**
* 通过改变canvas的样式来实现缩放,原理是通过canvas的scale属性缩放横纵轴
* flag true:放大 false: 缩小
*/
function zoom2(flag = true) {
const beta = flag ? 1 / scale : scale;
ctx.scale(beta, beta);
}

三、根据缩放比例重新计算点坐标,首推这种方式
优点:图形边框等不会随着缩放而变化,图形不会失真,可以根据缩放后的坐标点实现一些编辑功能(比如选中高亮)
缺点:需要针对不同的图形元素动态计算坐标点,逻辑较为繁琐
已缩小为例,原理图如下:
缩小时需要同时考虑图形距离鼠标位置更近以及图形大小也同比例缩小,所以最好办法是:
1. 计算缩小后图形中心点距离鼠标的位置B,可以根据缩小前图形中心点A的横纵坐标乘以一个比例得到。
2. 再根据位置B计算各个顶点的坐标,计算时要注意各个顶点之间的距离也要等比例缩小

/**
* 通过改变坐标点信息实现缩放,可以设置缩放的中心点
* flag true:放大 false: 缩小
*/
function zoom3(flag = true, event) {
// 记录当前鼠标的相对位置
initX = event.offsetX;
initY = event.offsetY;
// 计算放大缩小的比例
multi = 1 * (flag ? 1 / scale : scale); // 获取图形中心点
const center = getCenter();
// 获取图形最大最小的顶点坐标
const maxMin = getMaxMin();
// 计算缩放后的中心点坐标
const newC = [center[0] - (initX - center[0]) * (multi - 1), center[0] - (initY - center[1]) * (multi - 1)]; // 根据缩放后的中心点计算各个顶点信息
coordinates = coordinates.map(e => {
const operateX = center[0] - e[0] > 0 ? 1 : -1;
const operateY = center[1] - e[1] > 0 ? 1 : -1;
return [newC[0] - (maxMin.maxX - maxMin.minX) * multi / 2 * operateX, newC[1] - (maxMin.maxY - maxMin.minY) * multi / 2 * operateY];
})
}

下面附上完整的JS代码

let canvas;
let ctx;
let coordinates = [[50, 50], [250, 50], [250, 250], [50, 250]];
const scale = 0.8;
let [initX, initY] = [0, 0]; let multi = 1;
function init() {
canvas = document.getElementById('canvas');
ctx = canvas.getContext('2d');
draw();
drawText();
addEvent();
} function draw () {
ctx.lineWidth = 4;
ctx.strokeStyle = 'rgba(153, 153, 153, 1)';
ctx.moveTo(...coordinates[0]);
ctx.beginPath();
for (let i = 0; i < coordinates.length; i++) {
ctx.lineTo(...coordinates[i]);
}
ctx.closePath();
ctx.stroke();
} function getMaxMin() {
const x = coordinates.map(e => e[0]);
const y = coordinates.map(e => e[1]); return {
maxX: Math.max(...x),
minX: Math.min(...x),
maxY: Math.max(...y),
minY: Math.min(...y),
}
} function getCenter() {
const maxMin = getMaxMin();
return [(maxMin.maxX + maxMin.minX) / 2, (maxMin.minY + maxMin.maxY) / 2];
} /**
* 绘制文本内容
*/
function drawText() {
const maxMin = getMaxMin();
ctx.save();
ctx.translate((maxMin.maxX + maxMin.minX) / 2, (maxMin.maxY + maxMin.minY) / 2);
ctx.font = '20px serif';
ctx.fillStyle = '#333';
ctx.textAlign = 'center';
ctx.fillText('测试Canvas缩放功能', 0, 0, maxMin.maxX - maxMin.minX);
ctx.restore();
} /**
* 通过改变canvas的样式来实现缩放,原理是通过canvas的style中height和width 以及自带的width和height属性不同的比例实现缩放
* flag true:放大 false: 缩小
*/
function zoom1(flag = true) {
const curH = Number(canvas.getAttribute('height'));
const curW = Number(canvas.getAttribute('width'));
canvas.setAttribute('width', flag ? curW * scale : curW / scale);
canvas.setAttribute('height', flag ? curH * scale : curH / scale);
} /**
* 通过改变canvas的样式来实现缩放,原理是通过canvas的scale属性缩放横纵轴
* 优点:代码量少
* 缺点:会改变数据的原始属性
* flag true:放大 false: 缩小
*/
function zoom2(flag = true) {
const beta = flag ? 1 / scale : scale;
ctx.scale(beta, beta);
} /**
* 通过改变坐标点信息实现缩放,可以设置缩放的中心点
* 优点:代码量较大,需要修改每个要素的坐标点
* 缺点:会改变数据的原始属性
* flag true:放大 false: 缩小
*/
function zoom3(flag = true, event) {
// 记录当前鼠标的相对位置
initX = event.offsetX;
initY = event.offsetY;
// 计算放大缩小的比例
multi = 1 * (flag ? 1 / scale : scale); // 获取图形中心点
const center = getCenter();
// 获取图形最大最小的顶点坐标
const maxMin = getMaxMin();
// 计算缩放后的中心点坐标
const newC = [center[0] - (initX - center[0]) * (multi - 1), center[0] - (initY - center[1]) * (multi - 1)]; // 根据缩放后的中心点计算各个顶点信息
coordinates = coordinates.map(e => {
const operateX = center[0] - e[0] > 0 ? 1 : -1;
const operateY = center[1] - e[1] > 0 ? 1 : -1;
return [newC[0] - (maxMin.maxX - maxMin.minX) * multi / 2 * operateX, newC[1] - (maxMin.maxY - maxMin.minY) * multi / 2 * operateY];
})
} function addEvent() {
ctx.beginPath();
ctx.arc(0, 0, 5, 0, Math.PI * 2);
ctx.stroke();
const minMax = getMaxMin(coordinates);
canvas.addEventListener('mousewheel', event => {
ctx.clearRect(0, 0, 1600, 1600);
// zoom1(event.wheelDelta > 0); // zoom2(event.wheelDelta > 0); zoom3(event.wheelDelta > 0, event);
draw();
drawText(); ctx.restore();
});
} export default { init, addEvent };
Canvas实现画布的缩放的更多相关文章
- 通过Canvas及File API缩放并上传图片
原文地址:Resize an Image Using Canvas, Drag and Drop and the File API 示例地址:Canvas Resize Demo 原文作者:Dr. T ...
- 通过Canvas及File API缩放并上传图片完整演示样例
创建一个只管的用户界面,并同意你控制图片的大小.上传到server端的数据,并不须要处理enctype为 multi-part/form-data 的情况.只一个简单的POST表单处理程序就能够了. ...
- 安卓自定义View进阶-Canvas之画布操作 转载
安卓自定义View进阶-Canvas之画布操作 转载 https://www.gcssloop.com/customview/Canvas_Convert 本来想把画布操作放到后面部分的,但是发现很多 ...
- 通过Canvas及File API缩放并上传图片完整示例
<!DOCTYPE html> <html> <head> <title>通过Canvas及File API缩放并上传图片</title> ...
- HTML5 Canvas(画布)实战编程初级篇:基本介绍和基础画布元素
欢迎大家阅读HTML5 Canvas(画布)实战编程初级篇系列,在这个系列中,我们将介绍最简单的HTML5画布编程.包括: 画布元素 绘制直线 绘制曲线 绘制路径 绘制图形 绘制颜色,渐变和图案 绘制 ...
- Canvas对画布及文字控制基础API学习
这次纯API练习,比较简单,但是是为了之后的结合项目打基础的,所以也不能忽视它,下面开始: Canvas的平移.旋转.缩放 这里还是以上次画那个青春痘的DEMO为例[http://www.cnblog ...
- canvas图片编辑操作:缩放、移动、保存(PC端+移动端)
最近在写canvas关于图片的操作,看了网上的代码基本都是不行的,于是就自己写了一个. html代码 <canvas id="myCanvas" width="37 ...
- canvas实例:旋转缩放的方块
首先在页面中创建一个canvas标签: <body> <canvas id="c1" width="500" height="500 ...
- (网页)html5 canvas清空画布方法(转)
总结以下三种清空canvas画布的方式: 1. 最简单的方法:由于canvas每当高度或宽度被重设时,画布内容就会被清空,因此可以用以下方法清空: function clearCanvas() { v ...
- WPF 中Canvas图形移动、缩放代码
从Flash转C#,很多内容一知半解,边摸索边前进,代码粗糙,权当留个脚印. 只是想得到一个基础的移动和缩放功能的界面,找了很久都是画线.画矩形等基础形状的代码,移动和缩放说的并不清晰,只能自己努力来 ...
随机推荐
- serdes调试常见功能汇总
初始化流程 CORE复位流程 FW手动加载 FW版本自生成(可选) lane复位流程 TX复位流程 RX复位流程 TX,RX使能,disable(可选)关闭数据通道 速率频点配置,CPU模式配置,PL ...
- Django笔记四十四之Nginx+uWSGI部署Django以及Nginx负载均衡操作
本文首发于公众号:Hunter后端 原文链接:Django笔记四十四之Nginx+uWSGI部署Django以及Nginx负载均衡操作 这一篇笔记介绍如何使用 Nginx + uWSGI 来部署 Dj ...
- 企业u盘禁止访问如何解锁
如果您遇到了U盘禁止访问的问题,可能是由于系统设置.安全策略或第三方工具导致的.以下是一些可能的解锁方法,具体的操作可能因具体情况而异: 管理员权限: 确保您有足够的管理员权限来解锁U盘.有时,系统管 ...
- linux文件和文件夹的筛选、查找及用户和组管理命令
1.列出当前系统上所有已经登陆的用户的用户名, 注意:同一个用户登录多次,则只显示一次即可. 查看系统用户的命令为: (1)getent passwd 查看系统上的所有用户信息 (2)w 查看登录用户 ...
- Cesium渲染一帧中用到的图形技术
译者注:本文翻译自Cesium官方博文<Graphics Tech in Cesium - Rendering a Frame>,May 14, 2015 by Patrick Cozzi ...
- GaussDB(for Redis)双活容灾支持4大应用场景,为业务安全保驾护航
摘要:GaussDB(for Redis)的双活解决方案,支持同域主备.同域双主.异地主备.异地双主四大应用场景,提供了安全可靠的容灾能力. 一场火灾引发的思考 2021年3月10日,欧洲某云服务提供 ...
- 互斥锁Mutex:鸿蒙轻内核中处理临界资源独占的“法官”
摘要:本文带领大家一起剖析鸿蒙轻内核的互斥锁模块的源代码,包含互斥锁的结构体.互斥锁池初始化.互斥锁创建删除.申请释放等. 本文分享自华为云社区<鸿蒙轻内核M核源码分析系列十 互斥锁Mutex& ...
- Springboot中,如何读取配置文件中的属性
摘要:在比较大型的项目的开发中,比较经常修改的属性我们一般都是不会在代码里面写死的,而是将其定义在配置文件中,之后如果修改的话,我们可以直接去配置文件中修改,那么在springboot的项目中,我们应 ...
- SEAL 0.3 正式发布:国内首个全链路软件供应链安全管理平台
12月1日,软件供应链安全管理平台 SEAL 0.3 正式发布(以下简称"SEAL"),这是国内首个以全链路视角保护软件供应链的安全管理平台.两个月前 SEAL 0.2 发布,该版 ...
- 火山引擎DataLeap数据调度实例的 DAG 优化方案(三):技术实现
在原始数据中,是以一个数组的形式返回节点信息及依赖关系.所以,需要对数据进行处理形成图所需要的数据,同时,利用多个 map 对数据进行存储,方便后续对数据进行检索,减少时间复杂度. 实例节点的样式需要 ...