使用HTML5 canvas 標籤進行圖片裁剪、旋轉、縮放
阿新 • • 發佈:2019-02-13
程式碼使用到的js外掛:jquery、bootstrap、lrz。
jquery就不說了,基本都知道。bootstrap是一個響應式的前端ui框架。使用它是為了在手機端檢視頁面時能夠自適應寬高。lrz是一個前端的js壓縮圖片的外掛。
效果圖:
截圖後的圖片:
原始碼下載:點選下載
HTML頁面程式碼:
<html lang="zh-CN">
<head>
<meta http-equiv="content-type" content="text/html; charset=UTF-8" />
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1">
<title>圖片裁剪</title>
<link href="css/bootstrap.min.css" rel="stylesheet">
<link href="css/imgUpload.css" rel="stylesheet">
</head>
<body class="container" style="background-color: #C0C0C0;">
<div class="row-fluid">
<input type="file" class="btn btn-default" />
<div class="row-fluid col-sm-12 col-md-12 item" id="canvasDivId">
<canvas id="myCanvas" width="400" height="550" class="img-responsive"
style ="border:1px solid #d3d3d3;display:none;">
你的瀏覽器不支援HTML5. </canvas>
</div>
<div class="row-fluid col-sm-12 col-md-12">
<canvas id="myCanvasTow" width="320" height="400" class="img-responsive"
style="border:1px solid #d3d3d3;display:none;">
你的瀏覽器不支援HTML5. </canvas>
</div>
<div class="row-fluid col-sm-12 col-md-12" id="anniuDiv"
style="display:none;">
<button type="button" class="btn btn-success" id="affirmId">確認</button>
<!--<img alt="逆時針旋轉" title="逆時針旋轉" style="width: 30px;height: 30px;" id="rotateLeft" src="imageUpload/left.png">-->
<img alt="順時針旋轉" title="順時針旋轉" style="width: 30px;height: 30px;" id="rotateRight" src="imageUpload/right.png">
<img alt="縮小" title="縮小" style="width: 30px;height: 30px;" id="scale" src="imageUpload/rrrr.png">
<img alt="放大" title="放大" style="width: 30px;height: 30px;" id="little" src="imageUpload/pppp.png">
<button type="button" class="btn btn-primary" id="buttonId">預覽</button>
<button type="button" class="btn btn-danger" style="display: none;" id="resetId">重置</button>
</div>
<div class="row-fluid col-sm-12 col-md-12">
<img id="cutImgId" class="img-responsive" src=""
style="width: 320;height: 400;display:none;">
</div>
</div>
<script type="text/javascript" src="js/jquery-1.11.1.js"></script>
<script src="js/bootstrap.min.js"></script>
<script type="text/javascript" src="js/img2.js"></script>
<script type="text/javascript" src="js/lrz.pc.min.js"></script>
<script type="text/javascript" src="js/lrz.mobile.min.js"></script>
<script type="text/javascript">
var ics = new imgStroke();
$('input[type=file]').change(function(){
var file=this.files[0];
var reader=new FileReader();
reader.onload=function(){
// 通過 reader.result 來訪問生成的 DataURL
var url=reader.result;
ics.init({"canvasId":"myCanvas","url":url,"x":20,"y":20});
demo_report();
};
reader.readAsDataURL(file);
});
</script>
</body>
</html>
img2.js的js程式碼:
var tempContext = null, //全域性Context物件
canvas = null, /**畫布**/
imageObj = null, //全域性圖片物件
imageRotate = null, //旋轉後的圖片
oX=null, //矩形框X座標
oY=null, //矩形框Y座標
started=false, //標識滑鼠移動時是否重繪
n = 0, //旋轉步驟
width = 0, //矩形裁剪框寬度
height = 0, //矩形裁剪框高度
imgW = 400, //圖片的寬
imgH = 550, //圖片的高
canvasW = 400, //畫布的寬
canvasH = 550, //畫布的高
moveSwitch = false; //全域性開關
var imgStroke = (function(){
//建構函式
function ics(){
canvas = null;
oX = 20; /**載入時矩形左上角的 x 座標**/
oY = 20; /**載入時矩形左上角的 y 座標**/
width = 320; /**載入時初始化矩形框的寬**/
height = 400; /**載入時初始化矩形框的高**/
imageRotate = null;
moveSwitch = true;
}
/**
* 初始化
*/
ics.prototype.init = function(obj){
/**如果畫布有內容則清除**/
if(tempContext){
clearCanvas();
}
canvas = document.getElementById(obj.canvasId); /**畫布**/
canvas.width = canvasW;
canvas.height = canvasH;
tempContext = canvas.getContext("2d");
var imageUrl = new Image();
imageUrl.src = obj.url;
imageObj = imageUrl; /**圖片**/
if(obj.x)
oX = obj.x; /**矩形左上角的 x 座標**/
if(obj.y)
oY = obj.y; /**矩形左上角的 y 座標**/
if(obj.width)
width = obj.width;
if(obj.height)
height = obj.height;
$("#"+obj.canvasId).show();
/**載入圖片並繪製矩形框**/
loadImgRect(oX,oY,"load");
// 滑鼠事件
canvas.addEventListener("mousedown", doMouseDown, false);
canvas.addEventListener('mousemove', doMouseMove, false);
canvas.addEventListener('mouseup', doMouseUp, false);
// 觸屏事件
canvas.addEventListener("touchstart",doMouseDown,false);
canvas.addEventListener("touchmove",doMouseMove,false);
canvas.addEventListener("touchend",doMouseUp,false);
}
/**
* 載入圖片並繪製矩形框
*/
function loadImgRect(x,y,type){
if(!moveSwitch){
return;
}
/**
* 判斷移動是否超出畫布
* 畫布的寬度減去裁剪框的寬度得到x座標在畫布中的最大值
* 畫布的高度減去裁剪框的高度得到y座標在畫布中的最大值
*/
if(x>(canvasW-width)){ x= (canvasW-width); }
if(y>(canvasH-height)){ y= (canvasH-height); }
if(x<0)x=0;if(y<0)y=0;
if((!type||type!="load")&&imageRotate){
imageObj = imageRotate;
}
oX = x; oY = y;
clearCanvas();
/**從新設定透明度為1**/
tempContext.globalAlpha = 1;
tempContext.drawImage(imageObj, 0, 0, imgW, imgH);
tempContext.globalAlpha=0.7;
tempContext.fillStyle='#F8F8F8';
tempContext.fillRect(x,y,width,height);
}
/**
* 座標換算
* 相對頁面來講:上下為y軸 左右為x軸
* 用當前頁面的x座標減去畫布與頁面左邊的距離從而得到當前滑鼠在畫布中的x座標
* 用當前頁面的y座標減去畫布與頁面頭部的距離從而得到當前滑鼠在畫布中的y座標
* 乘以(canvas.width / bbox.width)跟(canvas.height / bbox.height)是為了綜合畫布實際大小而做的一個誤差填補計算。畫寬高的誤差值在2px左右
*/
function getPointOnCanvas(canvas, x, y) {
var bbox = canvas.getBoundingClientRect();
return { x: x - bbox.left * (canvas.width / bbox.width),
y: y - bbox.top * (canvas.height / bbox.height) };
}
/**
* 清除畫布
*/
function clearCanvas() {
tempContext.clearRect(0, 0, canvasW,canvasH);
}
/**
* 滑鼠按下事件
*/
function doMouseDown(event) {
event.preventDefault();
event.stopPropagation();
var x = null,y = null;
/**獲取滑鼠相對於文件(頁面)的位置**/
if(event.changedTouches){
x=event.changedTouches[0].pageX;
y=event.changedTouches[0].pageY;
}else{
x=event.pageX;
y=event.pageY;
}
var canvas = event.target;
var loc = getPointOnCanvas(canvas, x, y);
/**載入圖片並繪製矩形框**/
loadImgRect(loc.x, loc.y);
started = true;
}
/**
* 滑鼠移動事件
*/
function doMouseMove(event) {
event.preventDefault();
event.stopPropagation();
var x = null,y = null;
/**獲取滑鼠相對於文件(頁面)的位置**/
if(event.changedTouches){
x=event.changedTouches[0].pageX;
y=event.changedTouches[0].pageY;
}else{
x=event.pageX;
y=event.pageY;
}
var canvas = event.target;
var loc = getPointOnCanvas(canvas, x, y);
if (started) {
/**載入圖片並繪製矩形框**/
loadImgRect(loc.x, loc.y);
}
}
/**
* 滑鼠按起事件
*/
function doMouseUp(event) {
event.preventDefault();
event.stopPropagation();
if (started) {
doMouseMove(event);
started = false;
}
}
/**確認裁剪**/
ics.prototype.getImageData=function(id){
if(!moveSwitch){
return;
}
if(imageRotate){
imageObj = imageRotate;
}
/**去掉裁剪框填充背景色**/
clearCanvas();
/**恢復預設透明度為不透明**/
tempContext.globalAlpha = 1;
tempContext.drawImage(imageObj, 0, 0, imgW, imgH);
tempContext.strokeStyle="#FFFFFF";
tempContext.strokeRect(oX,oY,width,height);
/**獲取資料**/
var data = tempContext.getImageData(oX,oY,width,height);
var canvasTow = document.getElementById("myCanvasTow");
var ctxTow = canvasTow.getContext("2d");
ctxTow.putImageData(data,0,0);
var imgData = canvasTow.toDataURL();
loadImgRect(oX,oY);
lrz(imgData, {
width:width,
height:height,
// 壓縮開始
before: function() {
console.log('壓縮開始');
},
// 壓縮失敗
fail: function(err) {
console.error(err);
},
// 壓縮結束(不論成功失敗)
always: function() {
console.log('壓縮結束');
},
// 壓縮成功
done: function (results) {
$("#"+id).show();
$("#"+id).attr("src",results.base64);
moveSwitch = false;
$("#buttonId").hide();
$("#resetId").show();
}
});
}
/**旋轉**/
ics.prototype.rotate=function(arr){
if(!moveSwitch){
alert('請點選重置按鈕');
return;
}
imgRotate(arr);
}
/**
* 旋轉圖片並繪製矩形框
*/
function imgRotate(arr){
clearCanvas();
if(n== null) n=0;
if(arr=='left'){
(n==0)? n=3:n--;
}else if(arr=='right'){
(n==3)? n=0:n++;
}
switch(n) {
default :
case 0 :
canvas.width = canvasW;
canvas.height = canvasH;
tempContext.rotate(0 * Math.PI / 180);
tempContext.drawImage(imageObj, 0, 0,canvasW,canvasH);
createCanvas(canvasW,canvasH);
break;
case 1 :
canvas.width = canvasH;
canvas.height = canvasW;
tempContext.rotate(90 * Math.PI / 180);
tempContext.drawImage(imageObj, 0, -canvasH,canvasW,canvasH);
createCanvas(canvasH,canvasW);
break;
case 2 :
canvas.width = canvasW;
canvas.height = canvasH;
tempContext.rotate(180 * Math.PI / 180);
tempContext.drawImage(imageObj, -canvasW, -canvasH,canvasW,canvasH);
createCanvas(canvasW,canvasH);
break;
case 3 :
canvas.width = canvasH;
canvas.height = canvasW;
tempContext.rotate(270 * Math.PI / 180);
tempContext.drawImage(imageObj, -canvasW, 0,canvasW,canvasH);
createCanvas(canvasH,canvasW);
break;
};
}
/**
* 將旋轉過後的畫布內容取出來並重新建立畫布
* @param {Object} w 畫布的寬
* @param {Object} h 畫布的高
*/
function createCanvas(w,h){
/**得到旋轉後的img物件 —— BUG 在獲取到img後,旋轉就錯亂了**/
var data = tempContext.getImageData(0,0,w,h);
tempContext.clearRect(0, 0, w,h);
/**重設畫布的寬高**/
canvasH = h;canvasW =w;
imgW = w, imgH = h;
/**將旋轉後的得到的圖片覆蓋以前的畫布**/
canvas = document.getElementById("myCanvas");
canvas.width = w;
canvas.height = h;
tempContext = canvas.getContext("2d");
tempContext.globalAlpha = 1;
tempContext.putImageData(data,0,0);
var img = new Image();
img.src = canvas.toDataURL();
imageRotate = img;
tempContext.globalAlpha=0.7;
tempContext.fillStyle='#F8F8F8';
tempContext.fillRect(oX, oY,width,height);
}
/**縮放**/
ics.prototype.scale=function(type){
if(!moveSwitch){
alert('請點選重置按鈕');
return;
}
if(type=="BIG"){
imgW = imgW + 10;
imgH = imgH + 10/imgW*imgH;
} else {
imgW = imgW - 10;
imgH = imgH - 10/imgW*imgH;
}
loadImgRect(oX,oY);
}
return ics;
})();
/*** 載入按鈕 */
function demo_report() {
var li = document.createElement('li');
li.className = 'item';
li.innerHTML = $("#anniuDiv").html();
var ul = document.createElement('ul');
ul.appendChild(li);
document.getElementById("canvasDivId").appendChild(ul);
$("#buttonId").click(function(){
ics.getImageData("cutImgId");
});
$("#rotateLeft").click(function(){
ics.rotate("left");
});
$("#rotateRight").click(function(){
ics.rotate("right");
});
$("#little").click(function(){
ics.scale("BIG");
});
$("#scale").click(function(){
ics.scale("little");
});
$("#affirmId").click(function(){
ics.getImageData("cutImgId");
});
$("#resetId").click(function(){
if(confirm("您確定要重置嗎?")){
window.location.reload();
}
});
}
原始碼下載:點選下載