最近在写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端+移动端)的更多相关文章

  1. Canvas动画(PC端 移动端)

    Canvas动画(PC端 移动端) 一,介绍与需求 1.1,介绍 canvas是HTML5中新增一个HTML5标签与操作canvas的javascript API,它可以实现在网页中完成动态的2D与3 ...

  2. 兼顾pc和移动端的textarea字数监控的实现方法

    概述 pc端移动端中文本框监控字数的功能的一种较为简单的实现,考虑到安卓和IOS输入法输入过程中是否触发keyup的差异.利用监听compositionstart判断是否开启了输入法.从而实现体验较为 ...

  3. 把图片画到画布上,适应PC和移动端

    画一张图片到画布上 <canvas id="myCanvas" width="1000px" height="200px" >您 ...

  4. 用react开发一个新闻列表网站(PC和移动端)

    最近在学习react,试着做了一个新闻类的网站,结合ant design框架, 并且可以同时在PC和移动端运行: 主要包含登录和注册组件.头部和脚部组件.新闻块类组件.详情页组件.评论和收藏组件等: ...

  5. JS判断PC和移动端设备

    1.方法一 function IsPC() { var userAgentInfo = navigator.userAgent; var Agents = ["Android", ...

  6. 前端分辨pc和移动端导入不同css

    通过navigator获取浏览器,根据浏览器的不同判断出pc和移动端然后设置不同的css 分辨不同屏幕导入不同的css文件: function loadCSS() { if((navigator.us ...

  7. 判断PC机大小端

    判断PC机大小端 #include<stdio.h> #include<stdlib.h> int main() { short a = 0x0102; char *p = ( ...

  8. js判断是pc还是移动端

    //判断pc还是移动端 var isM = function () { var ua = navigator.userAgent; /* navigator.userAgent 浏览器发送的用户代理标 ...

  9. 一个 VUE 组件:实现子元素 scroll 父元素容器不跟随滚动(兼容PC、移动端)

    介绍 我们经常遇到一种情况.当滑动滚动条区域时,子元素滚动条到底部或顶部时就会触发父级滚动条,父级滚动条同理会继续向上触发,直至body容器.这是浏览器默认的滚动行为. 但是很多情况,我们想要子元素滚 ...

随机推荐

  1. 一个简单的Maven小案例

    Maven是一个很好的软件项目管理工具,有了Maven我们不用再费劲的去官网上下载Jar包. Maven的官网地址:http://maven.apache.org/download.cgi 要建立一个 ...

  2. web自动化测试实战之生成测试报告

    同志们,老铁们,继上篇文章 web自动化测试实战之批量执行测试用例 之后我们接着继续往下走,有人说我们运行了所有测试用例,控制台输入的结果,如果很多测试用例那也不能够清晰快速的知道多少用例通过率以及错 ...

  3. CondenseNet:可学习分组卷积,原作对DenseNet的轻量化改造 | CVPR 2018

    CondenseNet特点在于可学习分组卷积的提出,结合训练过程进行剪枝,不仅能准确地剪枝,还能继续训练,使网络权重更平滑,是个很不错的工作   来源:晓飞的算法工程笔记 公众号 论文:Neural ...

  4. 设计模式:visitor模式

    核心:将数据结构和数据的处理分开 注意:注意函数的参数传递和调用关系 例子: class Element; class Visitor { public: virtual void Visit(Ele ...

  5. python如何编写win程序

    python可以编写win程序.win程序的格式是exe,下面我们就来看一下使用python编写exe程序的方法. 编写好python程序后py2exe模块即可将其打包为exe程序. 实际操作过程: ...

  6. 组件缓存注意事项 ---keep-alive

  7. .net core options 依赖注入的方式

    options 依赖注入的方式 public class JwtSettingsOptions { public const string JwtSettings = "JwtSetting ...

  8. Python 3爬虫、数据清洗与可视化实战PDF高清完整版免费下载|百度云盘

    百度云盘:Python 3爬虫.数据清洗与可视化实战PDF高清完整版免费下载 提取码: 内容简介 <Python 3爬虫.数据清洗与可视化实战>是一本通过实战教初学者学习采集数据.清洗和组 ...

  9. 将ip加入到防火墙

    五分钟内访问次数最多的ip加入到防火墙 #!/bin/bash cat /etc/httpd/logs/access_log|grep `date -d '1-minute-ago' +%d/%b/% ...

  10. js控制语句练习(回顾)

    1.一个小球从100米空中落下,每次反弹一半高度,小球总共经过多少米,请问第10次反弹的高度是多少? //定义初始下落过程高度 var sum1= 0; //定义初始上升高度 var sum2= 0; ...