canvas图片编辑操作:缩放、移动、保存(PC端+移动端)
最近在写canvas关于图片的操作,看了网上的代码基本都是不行的,于是就自己写了一个。
html代码
<canvas id="myCanvas" width="375px" height="500px"></canvas>
<a id="save">
点击保存
</a>
移动端操作: Js代码
var canvas = document.getElementById('myCanvas'); //画布对象
var context = canvas.getContext('2d'); //画布显示二维图片
var saveBtn = document.getElementById('save');
var img, //图片是否加载完成;
imgX = 0,
imgY = 0,
dragging = false,
posl = {},
scale = 1,
pos = {
x: 0,
y: 0
},
newPos = {
x: 0,
y: 0
};
loadImg();
function drawImage(params) {
context.clearRect(0, 0, canvas.width, canvas.height);
// 保证 imgX 在 [img.width*(1-scale),0] 区间内
if (imgX < img.width * (1 - scale)) {
imgX = img.width * (1 - scale);
} else if (imgX > 0) {
imgX = 0
}
// 保证 imgY 在 [img.height*(1-scale),0] 区间内
if (imgY < img.height * (1 - scale)) {
imgY = img.height * (1 - scale);
} else if (imgY > 0) {
imgY = 0
}
context.drawImage(
img, //规定要使用的图像、画布或视频。
0, 0, //开始剪切的 x 坐标位置。
img.width, img.height, //被剪切图像的高度。
imgX, imgY, //在画布上放置图像的 x 、y坐标位置。
img.width * scale, img.height * scale //要使用的图像的宽度、高度
);
}
function loadImg() {
img = new Image();
img.onload = function () {
drawImage();
}
img.src = './test.jpg'
}
var start, end = 0;
canvas.addEventListener('touchstart', function (e) {
e.preventDefault()
if (e.touches.length === 1) {
dragging = true;
pos = windowToCanvas(e.touches[0].clientX, e.touches[0].clientY); //坐标转换,将窗口坐标转换成canvas的坐标
}
if (e.touches.length === 2) {
var t1 = e.touches[0];
var t2 = e.touches[1];
var pos1 = {
x: t1.clientX,
y: t1.clientY
}
var pos2 = {
x: t2.clientX,
y: t2.clientY
}
pos = windowToCanvas((pos1.x + pos2.x) / 2, (pos1.y + pos2.y) / 2);
}
});
canvas.addEventListener('touchmove', function (e) {
e.preventDefault()
if (e.touches.length === 1) {
// 加上dragging区分pos和posl的值,一个为双指,这里为单指的值
if (dragging) {
posl = windowToCanvas(e.touches[0].clientX, e.touches[0].clientY);
var x = posl.x - pos.x;
var y = posl.y - pos.y;
imgX += x;
imgY += y;
pos = JSON.parse(JSON.stringify(posl));
drawImage(); //重新绘制图片
}
}
// 双指中有可能存在移动,所以不加dragging判断,都是用的同一个中心点
if (e.touches.length === 2) {
posl = JSON.parse(JSON.stringify(pos));
var s1 = end;
var t1 = e.touches[0];
var t2 = e.touches[1];
var pos1 = {
x: t1.clientX,
y: t1.clientY
}
var pos2 = {
x: t2.clientX,
y: t2.clientY
}
pos = windowToCanvas((pos1.x + pos2.x) / 2, (pos1.y + pos2.y) / 2);
end = Math.sqrt(Math.pow((pos1.x - pos2.x), 2) + Math.pow((pos1.y - pos2.y), 2));
var pianX = posl.x - pos.x;
var pianY = posl.y - pos.y;
newPos = {
x: ((pos.x - imgX + pianX) / scale),
y: ((pos.y - imgY + pianY) / scale)
};
// 缩小
if (s1 > end) {
scale = scale - 0.05;
imgX = (1 - scale) * newPos.x + (pos.x -
newPos.x);
imgY = (1 - scale) * newPos.y + (pos.y - newPos.y);
if (scale < 1) { //最小缩放1
scale = 1;
drawImage(); //重新绘制图片
return
}
// drawImage(); //重新绘制图片
// 放大
} else {
scale = scale + 0.05;
imgX = (1 - scale) * newPos.x + (pos.x -
newPos.x);
imgY = (1 - scale) * newPos.y + (pos.y - newPos.y);
// drawImage();
}
drawImage();
}
});
canvas.addEventListener('touchend', function (e) {
e.preventDefault()
if (e.touches.length === 1) {
dragging = false;
}
})
saveBtn.addEventListener('click', function (e) {
var imgUrl = canvas.toDataURL();
var imgName = prompt('下载的图片名称:');
if (imgName != null) {
saveBtn.download = imgName;
saveBtn.href = imgUrl;
}
})
function windowToCanvas(x, y) {
var box = canvas.getBoundingClientRect();
//这个方法返回一个矩形对象,包含四个属性:left、top、right和bottom。分别表示元素各边与页面上边和左边的距离
return {
x: x - box.left - (box.width - canvas.width) / 2,
y: y - box.top - (box.height - canvas.height) / 2
};
}
PC端操作: Js代码
var canvas = document.getElementById('scaleDragCanvas'); //画布对象
var context = canvas.getContext('2d'); //画布显示二维图片
var saveBtn = document.getElementById('save');
var img, imgX = 0,
imgY = 0,
imgScale = 1;
var MINIMUM_SCALE = 1.0,
pos = {},
posl = {},
dragging = false;
loadImg();
canvasEventsInit();
function loadImg() {
img = new Image();
img.onload = function () {
drawImage();
}
img.src =
'./test.jpg';
}
function drawImage() {
context.clearRect(0, 0, canvas.width, canvas.height);
// 保证 imgX 在 [img.width*(1-imgScale),0] 区间内
if (imgX < img.width * (1 - imgScale)) {
imgX = img.width * (1 - imgScale);
} else if (imgX > 0) {
imgX = 0
}
// 保证 imgY 在 [img.height*(1-imgScale),0] 区间内
if (imgY < img.height * (1 - imgScale)) {
imgY = img.height * (1 - imgScale);
} else if (imgY > 0) {
imgY = 0
}
context.drawImage(
img, //规定要使用的图像、画布或视频。
0, 0, //开始剪切的 x 坐标位置。
img.width, img.height, //被剪切图像的高度。
imgX, imgY, //在画布上放置图像的 x 、y坐标位置。
img.width * imgScale, img.height * imgScale //要使用的图像的宽度、高度
);
}
/*事件注册*/
function canvasEventsInit() {
canvas.onmousedown = function (event) {
dragging = true;
pos = windowToCanvas(event.clientX, event.clientY); //坐标转换,将窗口坐标转换成canvas的坐标
};
saveBtn.addEventListener('click', function (e) {
var imgUrl = canvas.toDataURL();
var imgName = prompt('下载的图片名称:');
if (imgName != null) {
saveBtn.download = imgName;
saveBtn.href = imgUrl;
}
})
canvas.onmousemove = function (evt) { //移动
if (dragging) {
posl = windowToCanvas(evt.clientX, evt.clientY);
var x = posl.x - pos.x,
y = posl.y - pos.y;
imgX += x;
imgY += y;
pos = JSON.parse(JSON.stringify(posl));
drawImage(); //重新绘制图片
}
};
canvas.onmouseup = function () {
dragging = false;
};
canvas.onmousewheel = canvas.onwheel = function (event) { //滚轮放大缩小
var pos = windowToCanvas(event.clientX, event.clientY);
console.log(pos)
event.wheelDelta = event.wheelDelta ? event.wheelDelta : (event.deltalY * (-40)); //获取当前鼠标的滚动情况
var newPos = {
x: ((pos.x - imgX) / imgScale).toFixed(2),
y: ((pos.y - imgY) / imgScale).toFixed(2)
};
if (event.wheelDelta > 0) { // 放大
imgScale += 0.1;
imgX = (1 - imgScale) * newPos.x + (pos.x - newPos.x);
imgY = (1 - imgScale) * newPos.y + (pos.y - newPos.y);
} else { // 缩小
imgScale -= 0.1;
if (imgScale < MINIMUM_SCALE) { //最小缩放1
imgScale = MINIMUM_SCALE;
}
imgX = (1 - imgScale) * newPos.x + (pos.x - newPos.x);
imgY = (1 - imgScale) * newPos.y + (pos.y - newPos.y);
console.log(imgX, imgY);
}
drawImage(); //重新绘制图片 }; } /*坐标转换*/
}
}
function windowToCanvas(x, y) {
var box = canvas.getBoundingClientRect();
//这个方法返回一个矩形对象,包含四个属性:left、top、right和bottom。分别表示元素各边与页面上边和左边的距离
return {
x: x - box.left - (box.width - canvas.width) / 2,
y: y - box.top - (box.height - canvas.height) / 2
};
}
canvas图片编辑操作:缩放、移动、保存(PC端+移动端)的更多相关文章
- Canvas动画(PC端 移动端)
Canvas动画(PC端 移动端) 一,介绍与需求 1.1,介绍 canvas是HTML5中新增一个HTML5标签与操作canvas的javascript API,它可以实现在网页中完成动态的2D与3 ...
- 兼顾pc和移动端的textarea字数监控的实现方法
概述 pc端移动端中文本框监控字数的功能的一种较为简单的实现,考虑到安卓和IOS输入法输入过程中是否触发keyup的差异.利用监听compositionstart判断是否开启了输入法.从而实现体验较为 ...
- 把图片画到画布上,适应PC和移动端
画一张图片到画布上 <canvas id="myCanvas" width="1000px" height="200px" >您 ...
- 用react开发一个新闻列表网站(PC和移动端)
最近在学习react,试着做了一个新闻类的网站,结合ant design框架, 并且可以同时在PC和移动端运行: 主要包含登录和注册组件.头部和脚部组件.新闻块类组件.详情页组件.评论和收藏组件等: ...
- JS判断PC和移动端设备
1.方法一 function IsPC() { var userAgentInfo = navigator.userAgent; var Agents = ["Android", ...
- 前端分辨pc和移动端导入不同css
通过navigator获取浏览器,根据浏览器的不同判断出pc和移动端然后设置不同的css 分辨不同屏幕导入不同的css文件: function loadCSS() { if((navigator.us ...
- 判断PC机大小端
判断PC机大小端 #include<stdio.h> #include<stdlib.h> int main() { short a = 0x0102; char *p = ( ...
- js判断是pc还是移动端
//判断pc还是移动端 var isM = function () { var ua = navigator.userAgent; /* navigator.userAgent 浏览器发送的用户代理标 ...
- 一个 VUE 组件:实现子元素 scroll 父元素容器不跟随滚动(兼容PC、移动端)
介绍 我们经常遇到一种情况.当滑动滚动条区域时,子元素滚动条到底部或顶部时就会触发父级滚动条,父级滚动条同理会继续向上触发,直至body容器.这是浏览器默认的滚动行为. 但是很多情况,我们想要子元素滚 ...
随机推荐
- 导出数据到Excel的时候报JAVA.LANG.NOSUCHMETHODERROR: ORG.APACHE.POI.SS.USERMODEL.CELLSTYLE.SETVERTICALALIGNMENT(LORG/APACHE/POI/SS/USERMODEL/VERTICALALIGNMENT;)V
JAVA.LANG.NOSUCHMETHODERROR: ORG.APACHE.POI.SS.USERMODEL.CELLSTYLE.SETVERTICALALIGNMENT(LORG/APACHE/ ...
- nginx: command not found
nginx 正常启动,可以访问服务器地址:welcome to nginx 使用nginx -t 等命令时 报错:nginx: command not found 这是环境变量未配置 配置环境变量 v ...
- Ethical Hacking - NETWORK PENETRATION TESTING(5)
Deauthentication Attacks Theory This attack is used to disconnect any device from any network within ...
- Bootstrap 3 -> 4 : 居中布局的变化
我们知道,Bootstrap布局的核心是栅格系统,一行有12个栅格. 比如,我想让两个宽度400px左右的div居中显示. 这个时候,我们可以利用栅格的列偏移功能. <div class=&qu ...
- spring tx——TransactionManger
TransactionDefinition--事务定义 定义事务属性,包括传播级别.隔离级别.名称.超时.只读等 TransactionStatus--事务状态 事务状态,包含事务对象(jdbc为Da ...
- goroutine间的同步&协作
Go语言中的同步工具 基础概念 竞态条件(race condition) 一份数据被多个线程共享,可能会产生争用和冲突的情况.这种情况被称为竞态条件,竞态条件会破坏共享数据的一致性,影响一些线程中代码 ...
- 给Django Admin添加验证码和多次登录尝试限制
Django自带的Admin很好用,但是放到生产环境总还差了点什么= = 看看admin的介绍: Django奉行Python的内置电池哲学.它自带了一系列在Web开发中用于解决常见问题或需求的额外的 ...
- Python延迟初始化(lazy property)
转自:https://blog.csdn.net/azsx02/article/details/77649527 Python 对象的延迟初始化是指,当它第一次被创建时才进行初始化,或者保存第一次创建 ...
- 友好城市dp
// // Created by Arc on 2020/4/27. //对了,这篇题解的代码是小白自己写的.有啥错误还请各位大佬多多包涵. /* * 某国有一条大河(一条大河~~~~,波浪宽~~~~ ...
- 阿里云ecs轻量级服务器node镜像部署
这个是自带安装pm2,nginx,node,mongodb的环境的,目录在控制台有给出, server端的配置按照开发手册去操作即可. 而静态的页面.需要修改nginx的配置文件,找到nginx的ng ...