最近在写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. 初识:LevelDB

    初识:LevelDB 上篇文章缘起:BigTable可以说是已经把论文Bigtable: A Distributed Storage System for Structured Data中的内容掰扯的 ...

  2. [Qt2D绘图]-05绘图设备-QPixmap&&QBitmap&&QImage&&QPicture

    这篇笔记记录的是QPainterDevice(绘图设备,可以理解为一个画板) 大纲:     绘图设备相关的类:QPixmap QBitmap QImage QPicture     QPixmap ...

  3. Java继承多态

    一. 父类引用指向子类对象父类名(接口名) 对象名=new 子类(接口)名称() 二. 父子继承关系中,成员变量重名1.直接通过子类对象访问成员变量 =左边是谁,就优先用谁2.间接通过成员方法访问成员 ...

  4. 华为云如何使用二次验证码/虚拟MFA/两步验证/谷歌验证器?

    一般点账户名——设置——安全设置中开通虚拟MFA两步验证 具体步骤见链接  华为云如何使用二次验证码/虚拟MFA/两步验证/谷歌验证器? 二次验证码小程序于谷歌身份验证器APP的优势 1.无需下载ap ...

  5. java 成员变量和局部变量的区别

    将对象的存储在数组中会报错 public static void main(String[] args) { ArrayList<Goods> arrayList = new ArrayL ...

  6. 互联网找的e是无理数的初等证明

    e的两种计算方式 \(e=lim_{n \to \infty}(1+\frac{1}{n})^n\) \(e=\sum_{n=0}^{+\infty}\frac{1}{n!}\) \(即,e=\fra ...

  7. ANDROID自定义视图——onMeasure,MeasureSpec源码 流程 思路详解

    简介: 在自定义view的时候,其实很简单,只需要知道3步骤: 1.测量--onMeasure():决定View的大小 2.布局--onLayout():决定View在ViewGroup中的位置 3. ...

  8. 看完这篇,再也不怕被问到 AsyncTask 的原理了

    本文很多资料基于Google Developer官方对AsyncTask的最新介绍. AsyncTask 是什么 AsyncTask is designed to be a helper class ...

  9. jmeter单接口和多接口测试

    @@@@@@@@@@@@@@@ # 路漫漫其修远 最近接触到了多接口串联,接口串联的技术会在其他帖子有说明,其核心技术点就是通过正则表达式和变量来实现接口的关联.目前为止呢笔者用到的地方还只有一个,就 ...

  10. 社交网站的数据挖掘与分析pdf版本|网盘下载地址附提取码|

    点击此处进入网盘下载地址 提取码:btqx 作者介绍: 马修·罗塞尔(MatthewA.Russell),DigitalReasoningSystems公司的技术副总裁和Zaffra公司的负责人,是热 ...