1、图片上传
2、图片放大、缩小、移动
3、截图生成新的图片
canvas和input的基础我就不多说了,不懂得可以先自行学习一下基本操作
我参考了这个博主的文章,大家不会的可以先看看:
https://blog.csdn.net/cysear/article/details/89185239#comments_13156603
<div>
<div class="custom_box">
<p>此商品需要進行定制,需要添加圖片才能下單;上傳不大於15MB的JPEG或PNG格式檔案;p>
<div class="img">
<img id="img_preview">
div>
<div class="clipContent">
上传图片
<input type="file" id="file">
div>
div>
<div class="cover-wrap" id="content">
<div class="clipBgn" >
<div class="closeB">
<div class="close">div>
div>
<div class="canvas_box">
<div class="can_wrap">
<canvas id="canvas" width="335" height="340">canvas>
div>
div>
<div>注意:顯示內容是大致預覽div>
<div class="clipButton">
<div id="clipBtn">保存圖片div>
div>
div>
div>
div>
body {
margin: 0px;
padding: 0;
}
.custom_box {
margin: 10px 20px;
border: 1px #D5D9D9 solid;
border-radius: 6px;
text-align: center;
padding: 10px 20px;
font-size: 12px;
}
.custom_box .img {
height: 150px;
margin: 10px 0;
}
.custom_box .img img {
width: 100%;
height: 100%;
box-sizing: border-box;
border: 1px solid;
}
.custom_box .clipContent {
width: 100%;
height: 36px;
line-height: 36px;
position: relative;
border-radius: 4px;
background-color: #b4282d;
color: #FFFFFF;
font-size: 14px;
}
.custom_box .clipContent input[type=file] {
position: absolute;
left: 0;
top: 0;
background-color: aqua;
line-height: 36px;
right: 0;
width: 100%;
opacity: 0;
}
.cover-wrap {
position: fixed;
width: 100%;
text-align: center;
min-height: 150px;
top: 0;
left: 0;
z-index: 2;
display: none;
}
.cover-wrap .clipBgn {
margin-top: 40px;
background-color: #fff;
padding: 10px 0;
font-size: 12px;
}
.cover-wrap .clipBgn .closeB {
position: relative;
height: 25px;
}
.cover-wrap .clipBgn .closeB .close {
background-image: url(../images/close.png);
background-repeat: no-repeat;
background-size: 22px;
width: 22px;
height: 22px;
position: absolute;
right: 5px;
top: 5px;
}
.cover-wrap .clipBgn .canvas_box {
margin-top: 15px;
}
.cover-wrap .clipBgn .canvas_box .can_wrap {
position: relative;
user-select: none;
margin: 0 auto;
}
.cover-wrap .clipBgn .canvas_box .can_wrap #scaleDragCanvas {
margin-top:20px;
touch-action: manipulation;
user-select: none;
cursor: move;
}
.cover-wrap .clipBgn .clipButton {
text-align: center;
}
.cover-wrap .clipBgn .clipButton #clipBtn {
width: 120px;
height: 36px;
border-radius: 4px;
background-color: #b4282d;
color: #FFFFFF;
font-size: 14px;
text-align: center;
line-height: 36px;
outline: none;
margin: 15px auto;
}
$(function(){
// 首先做图片上传事件
var imgs ;
$('#file').change(function(){
//console.log('事件响应');
var file = $("#file").get(0).files[0];
// 处理图片的格式和大小
var size = file.size/1024 ;
var type = file.type.substring(file.type.lastIndexOf("/")+1);
if(size > 15000)
alert('上傳文件過大!');
else if( type !== "jpeg" && type !=="jpg" && type !== "png")
alert('上傳圖片的格式不正確!');
else{
var reader = new FileReader();
reader.onload = function(e){
imgs.src = e.target.result;
}
reader.readAsDataURL(file);
int();
}
});
var myCanvas, context;
var imgX = 0, imgY = 0, imgScale = 0.2, MINIMUM_SCALE = 0.2;
var posl= {
}, dragging = false;
var pcFlag = true;
function int(){
myCanvas = document.getElementById('scaleDragCanvas'); //画布对象
context = myCanvas.getContext('2d');//画布显示二维图片
isPc();
loadImg();
canvasEventsInit();
};
function loadImg() {
imgs = new Image();
imgs.onload = function () {
console.log(imgs);
// imgs的尺寸对比canvas进行等比例的多小
if(imgs.width < 80 || imgs.height < 80 || imgs.width > 10000 || imgs.height > 10000){
alert('图片宽度和高度必须在80 x 80像素到10000 x 10000像素范围内!');
}else{
show();
// 设置居中位置摆放
if(imgs.width* imgScale < myCanvas.width){
imgX = (myCanvas.width - imgs.width* imgScale)/2;
}
if(imgs.height* imgScale < myCanvas.height){
imgY = (myCanvas.height - imgs.height* imgScale)/2;
}
drawImage();
}
}
};
function drawImage() {
context.clearRect(0, 0, myCanvas.width, myCanvas.height);
context.drawImage(
imgs, //规定要使用的图像、画布或视频。
0, 0, //开始剪切的 x 坐标位置。
imgs.width, imgs.height, //被剪切图像的高度。
imgX, imgY,//在画布上放置图像的 x 、y坐标位置。
imgs.width * imgScale, imgs.height * imgScale //要使用的图像的宽度、高度
);
};
/*事件注册*/
function canvasEventsInit() {
var pageX, pageY, initX, initY;
var start = [], pos ={
};
if(pcFlag){
myCanvas.onmousedown = function (event) {
dragging = true;
pos = windowToCanvas(event.clientX, event.clientY); //坐标转换,将窗口坐标转换成canvas的坐标
};
myCanvas.onmousemove = function (evt) {
//移动
if(dragging){
posl = windowToCanvas(evt.clientX, evt.clientY);
var x = posl.x - pos.x;
var y = posl.y - pos.y;
imgX += x;
imgY += y;
pos = JSON.parse(JSON.stringify(posl));
drawImage(); //重新绘制图片
}
};
myCanvas.onmouseup = function () {
dragging = false;
};
myCanvas.onmousewheel = myCanvas.onwheel = function (event) {
//滚轮放大缩小
var pos = windowToCanvas (event.clientX, event.clientY);
//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.05;
imgX = (1-imgScale)*newPos.x+(pos.x-newPos.x);
imgY = (1-imgScale)*newPos.y+(pos.y-newPos.y);
} else {
// 缩小
imgScale -= 0.05;
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);
}
drawImage(); //重新绘制图片
};
}else{
// 兼容移动端
myCanvas.ontouchstart = function (event) {
dragging = true;
if(event.touches && event.touches.length < 2) {
let touch = event.touches[0];
pos = windowToCanvas(touch.clientX, touch.clientY); //坐标转换,将窗口坐标转换成canvas的坐标
}else{
let touches = event.touches;
//手指按下时的手指所在的X,Y坐标
pageX = touches[0].pageX;
pageY = touches[0].pageY;
//初始位置的X,Y 坐标
initX = event.target.offsetLeft;
initY = event.target.offsetTop;
//记录初始 一组数据 作为缩放使用
if (touches.length >= 2) {
//判断是否有两个点在屏幕上
start = touches; //得到第一组两个点
};
}
};
myCanvas.ontouchmove = function (evt) {
//移动
if(dragging ){
if(evt.touches && evt.touches.length < 2) {
let touch = evt.touches[0];
posl = windowToCanvas(touch.clientX, touch.clientY);
var x = posl.x - pos.x; var y = posl.y - pos.y;
imgX += x;
imgY += y;
pos = JSON.parse(JSON.stringify(posl));
}else{
let touches = evt.touches;
// 2 根 手指执行 目标元素放大操作
//得到第二组两个点
var now = touches;
pos = windowToCanvas (now[0].clientX, now[0].clientY);
var newPos = {
x:((pos.x-imgX)/imgScale).toFixed(2) ,
y:((pos.y-imgY)/imgScale).toFixed(2)
};
// Math.abs(touches[0].pageX-touches[1].pageX)
//当前距离变小, getDistance 是勾股定理的一个方法
if(getDistance(now[0], now[1]) < getDistance(start[0], start[1])){
// 缩小
imgScale -=0.03;
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);
}else if(getDistance(now[0], now[1]) > getDistance(start[0], start[1])){
// 放大
if(imgScale < 1) {
imgScale +=0.03;
imgX = (1-imgScale)*newPos.x+(pos.x-newPos.x);
imgY = (1-imgScale)*newPos.y+(pos.y-newPos.y);
}
}
start = now;
}
drawImage(); //重新绘制图片
}
};
myCanvas.ontouchend = function () {
dragging = false;
};
}
};
/*坐标转换*/
function windowToCanvas(x,y) {
var box = myCanvas.getBoundingClientRect(); //这个方法返回一个矩形对象,包含四个属性:left、top、right和bottom。分别表示元素各边与页面上边和左边的距离
return {
x: x - box.left - (box.width - myCanvas.width) / 2,
y: y - box.top - (box.height - myCanvas.height) / 2
};
};
//缩放 勾股定理方法-求两点之间的距离
function getDistance(p1, p2) {
var x = p2.pageX - p1.pageX,
y = p2.pageY - p1.pageY;
return Math.sqrt((x * x) + (y * y));
};
function isPc(){
// 判断pc或者移动端
var userAgentInfo = navigator.userAgent;
var Agents = ["Android", "iPhone",
"SymbianOS", "Windows Phone",
"iPad", "iPod"];
for (var i = 0; i < Agents.length ; i++){
if(userAgentInfo.indexOf(Agents[i]) > 0){
pcFlag = false;
break;
}
};
return pcFlag;
};
$('#clipBtn').click(function(){
// canvas截图
dataURL = context.canvas.toDataURL('image/png');
$('#img_preview').attr("src", dataURL)
var bb = document.getElementById("img_preview");
$('#img_preview').attr("src", dataURL);
if(dataURL){
close();
}
});
function show(){
$('.toast').css('display', 'inline-block');
$('.cover-wrap').css('display', 'inline-block');
$('body').attr('style','overflow:hidden');
};
function close (){
$('.toast').css('display', 'none');
$('.cover-wrap').css('display', 'none');
$('body').removeAttr('style');
};
$('.close').click(function(){
close();
});
})
结尾: 新手小白也就只能看着大神写的改改,还有很多需要修改的地方,希望有人能给我指点一二。