主要介绍三种方式:

首先创建一个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实现画布的缩放的更多相关文章

  1. 通过Canvas及File API缩放并上传图片

    原文地址:Resize an Image Using Canvas, Drag and Drop and the File API 示例地址:Canvas Resize Demo 原文作者:Dr. T ...

  2. 通过Canvas及File API缩放并上传图片完整演示样例

    创建一个只管的用户界面,并同意你控制图片的大小.上传到server端的数据,并不须要处理enctype为 multi-part/form-data 的情况.只一个简单的POST表单处理程序就能够了. ...

  3. 安卓自定义View进阶-Canvas之画布操作 转载

    安卓自定义View进阶-Canvas之画布操作 转载 https://www.gcssloop.com/customview/Canvas_Convert 本来想把画布操作放到后面部分的,但是发现很多 ...

  4. 通过Canvas及File API缩放并上传图片完整示例

    <!DOCTYPE html> <html> <head> <title>通过Canvas及File API缩放并上传图片</title> ...

  5. HTML5 Canvas(画布)实战编程初级篇:基本介绍和基础画布元素

    欢迎大家阅读HTML5 Canvas(画布)实战编程初级篇系列,在这个系列中,我们将介绍最简单的HTML5画布编程.包括: 画布元素 绘制直线 绘制曲线 绘制路径 绘制图形 绘制颜色,渐变和图案 绘制 ...

  6. Canvas对画布及文字控制基础API学习

    这次纯API练习,比较简单,但是是为了之后的结合项目打基础的,所以也不能忽视它,下面开始: Canvas的平移.旋转.缩放 这里还是以上次画那个青春痘的DEMO为例[http://www.cnblog ...

  7. canvas图片编辑操作:缩放、移动、保存(PC端+移动端)

    最近在写canvas关于图片的操作,看了网上的代码基本都是不行的,于是就自己写了一个. html代码 <canvas id="myCanvas" width="37 ...

  8. canvas实例:旋转缩放的方块

    首先在页面中创建一个canvas标签: <body> <canvas id="c1" width="500" height="500 ...

  9. (网页)html5 canvas清空画布方法(转)

    总结以下三种清空canvas画布的方式: 1. 最简单的方法:由于canvas每当高度或宽度被重设时,画布内容就会被清空,因此可以用以下方法清空: function clearCanvas() { v ...

  10. WPF 中Canvas图形移动、缩放代码

    从Flash转C#,很多内容一知半解,边摸索边前进,代码粗糙,权当留个脚印. 只是想得到一个基础的移动和缩放功能的界面,找了很久都是画线.画矩形等基础形状的代码,移动和缩放说的并不清晰,只能自己努力来 ...

随机推荐

  1. C++ Qt开发:Qt的安装与配置

    Qt是一种C++编程框架,用于构建图形用户界面(GUI)应用程序和嵌入式系统.Qt由Qt公司(前身为Nokia)开发,提供了一套跨平台的工具和类库,使开发者能够轻松地创建高效.美观.可扩展的应用程序. ...

  2. 2023年奔走的总结---吉特日化MES 制药项目 篇二

    书接上文,反正今年也就折腾一下了,索性好好整理一下思绪写写文章,当做工作笔记.今年工作中遇到了各种各样的事情,可能是由于今年项目压力像无头苍蝇一样瞎撞,也打发一下按耐不住的心.本篇将记录一下<吉 ...

  3. 记录一个MySQL中order by 和 limit 连用导致分页查询不生效的坑

    具体现象和这位同学的一致,具体的解决办法也是参考这位同学的做法 参考文章地址:https://www.cnblogs.com/yuluoxingkong/p/10681583.html

  4. TCP/IP协议---三次握手和四次挥手

    TCP首部的数据格式 其中, 源端口号和目的端口号各占16位,端口范围1~65535.1024以下为知名端口,1024~65535是供用户使用.源端口,目的端口,源ip,目的ip这四个值唯一确定一个T ...

  5. 【UniApp】-uni-app-处理项目输入数据(苹果计算器)

    前言 上一篇文章完成了项目的基本布局,这一篇文章我们来处理一下项目的输入数据 项目的输入数据主要是通过按键来输入的,所以我们需要对按键进行处理 那么我们就来看一下 uni-app-处理项目输入数据 步 ...

  6. [转]NLog学习笔记

    配置文件 NLog所有的配置信息都可以写到一个单独的xml文件中,也可以在程序代码中进行配置. 配置文件位置 启动的时候,NLog会试图查找配置文件完成自动配置,查找的文件依次如下(找到配置信息则结束 ...

  7. javaScript正则截取自定义标签-javascript-zheng-ze-jie-qu-zi-ding-yi-biao-qian

    title: javaScript正则截取自定义标签 date: 2021-12-29 17:31:48.448 updated: 2021-12-29 17:31:48.448 url: https ...

  8. linux内核initcall放置在各个section中函数执行流程

    前言 linux以及嵌入式一些代码,我们看到core_initcall.device_initcall等等需要链接器分配各个section,并且在启动该模块时候执行.下面我们详细追溯一下执行过程. 作 ...

  9. HDU 6203 ping ping ping 最近公共祖先 树状数组

    原题链接 题意 给我们一棵n+1节点,n条边的树,然后给我们p条路径(每条路径给出两个端点).我们需要从树上选出一些点,使得每条路径都至少包含我们选出的一个点.求最少选多少点. 思路 以1为根,我们可 ...

  10. Spring Boot3 系列:Spring Boot3 跨域配置 Cors

    目录 什么是CORS? Spring Boot 如何配置CORS? 前端代码 注解配置 全局配置 过滤器配置 注意事项 什么是CORS? CORS,全称是"跨源资源共享"(Cros ...