<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<meta name="viewport" content="width=device-width,initial-scale=0.5,minimum-scale=0.5,maximum-scale=0.5,user-scalable=no" />
<title>Title</title>
<style>
body {
position: fixed;
width: 100%;
height: 100%;
margin: 0px;
background-color: black;
}
.cover-top {
font-size: 50px;
color: white;
text-align: center;
width: 100%;
padding:5px;
border: solid 0px;
background-color: black;
position: absolute;
opacity: 0.5;
top: 0px;
z-index: 1;
}
.cover-top input {
font-size: 50px;opacity: 0;position: absolute;right: 0;top: 0;
}
.cover-middle {
width: 100%;
padding:5px;
border: solid 0px;
position: absolute;
transform: translateY(-50%);
top: 50%;
z-index: 1;
}
.cover-down {
font-size: 28px;
color: white;
text-align: center;
width: 100%;
padding:5px;
border: solid 0px;
background-color: black;
position: absolute;
opacity: 0.5;
bottom: 0px;
z-index: 1;
}
button {
padding: 20px;position: absolute;left: 0px;
}
.image {
display:block;width: 100%;overflow: scroll;transform: translate(0px,50%);position: absolute;
}
</style>
</head>
<body>
<form id="cutImage" action="htpp://localhost/product/upload_pic" enctype="multipart/form-data" method="post">
<div id="cover-top" class="cover-top">
<a href="javascript:">
<input id="imageFile" name="image" type="file" accept="image/gif, image/jpeg, image/jpg" onchange="loadImage()">點選上傳
</a>
<button onclick="selectImage()">選擇圖檔</button>
<input id="x", name="x" style="display: none">
<input id="y", name="y" style="display: none">
<input id="width" name="width" style="display: none">
<input id="height" name="height" style="display: none">
</div>
<div id="cover-middle" class="cover-middle"></div>
<div id="cover-down" class="cover-down">
<button type="button" onclick="cutParams()">獲得裁剪參數</button><span id="params">12121</span>
</div>
<img id="image" class="image" draggable="true" src="./23123.jpeg" onload="init()">
</form>
</body>
<script>
//圖檔的尺寸({寬,高, 真實的寬,真實的高})
var imageParams={width:0, height:0, naturalWidth:0, naturalHeight:0};
//螢幕的寬高
var containSize={width:0, height:0};
//滑鼠觸摸時滑鼠坐标
var mouseOnCrd={x1:0, y1:0, x2:0, y2:0}
//圖檔的坐标(其實就是偏移的位置)
var imageCrd = {x:0, y:0};
//頁面加載時候需要初始化的參數
window.onload = function () {
containSize.width = document.body.offsetWidth;
containSize.height = document.body.offsetHeight;
//設定遮罩層的寬高
var coverMiddle = document.getElementById("cover-middle");
coverMiddle.style.width=containSize.width + "px";
coverMiddle.style.height=containSize.width + "px";
var coverTop = document.getElementById("cover-top");
coverTop.style.height=(containSize.height-containSize.width)/2 + "px";
var coverDown = document.getElementById("cover-down");
coverDown.style.height=(containSize.height-containSize.width)/2 + "px";
init()
}
//獲得目前的參數(必須要通過綁定img 的onload事件,不然讀取到的參數不準确)
function init() {
//設定初始參數
var image = document.getElementById("image")
imageParams.width = image.width;
imageParams.height = image.height;
imageParams.naturalWidth = image.naturalWidth;
imageParams.naturalHeight = image.naturalHeight;
//配置圖檔的位置
configImage();
}
/**
* 配置圖檔的位置
*/
function configImage() {
var image = document.getElementById("image");
imageCrd.x = 0; // 初始位置橫向從零開始
imageCrd.y = parseInt((containSize.height - imageParams.height)/2); // 設定縱向居中
image.style.transform = "translate(" + imageCrd.x + "px," + imageCrd.y + "px)"; // 完成偏移操作
}
//點選選擇圖檔
function selectImage() {
document.getElementById("imageFile").click();
}
//選擇圖檔之後加載圖檔
function loadImage() {
var files = document.getElementById("imageFile").files;
var reader = new FileReader();
reader.readAsDataURL(files[0]);
reader.onload = function() {
document.getElementById("image").setAttribute('src', reader.result);
};
}
//觸摸移動事件
document.addEventListener("touchmove", function (ev) {
if(ev.touches.length == 2) { //放大
zoom(ev.touches[0], ev.touches[1])
}
if(ev.touches.length == 1) { //移動
move(ev.touches[0]); //由于手機是多點觸控,是以很可能有多個事件
}
})
//螢幕觸摸事件
document.addEventListener("touchstart", function (ev) {
//雙點觸摸(即放大或者縮小圖檔)
if(ev.touches.length == 2) {
mouseOnCrd.x1 = ev.touches[0].pageX;
mouseOnCrd.y1 = ev.touches[0].pageY;
mouseOnCrd.x2 = ev.touches[1].pageX;
mouseOnCrd.y2 = ev.touches[1].pageY;
}
//單點觸摸(即移動圖檔)
if(ev.touches.length == 1) {
var e = ev.touches[0];
mouseOnCrd.x1 = e.pageX;
mouseOnCrd.y1 = e.pageY;
}
});
//縮放圖檔
function zoom(touch1, touch2) {
var touchCrd1 = getMouseCrd(touch1);
var touchCrd2 = getMouseCrd(touch2);
//計算新舊兩點的距離,判斷是縮小還是放大(false:縮小;true:放大)
var zoomFlag = (Math.pow((mouseOnCrd.x1 - mouseOnCrd.x2), 2) + Math.pow((mouseOnCrd.y1 - mouseOnCrd.y2), 2)) -
(Math.pow((touchCrd1.x - touchCrd2.x), 2) + Math.pow((touchCrd1.y - touchCrd2.y), 2)) > 0 ? false : true;
// alert("運作到這裡" + zoomFlag);
//設定圖檔的寬度,高度是自适應,是以不用擷取
var image = document.getElementById("image");
image.style.width = (zoomFlag ? (imageParams.width + 15) : (imageParams.width - 15) )+ "px";
//重新獲得圖檔的dom元素,并擷取寬高
imageParams.width = image.width;
imageParams.height = image.height;
// document.getElementById("cover-down").innerHTML= imageParams.width + "px" + ":" +imageParams.height + "px";
}
//移動圖檔
function move(touch) {
var touchCrd = getMouseCrd(touch);
//和初始坐标比較,在每個坐标上發生的位移
console.log("發生了位移:", touchCrd.x-mouseOnCrd.x1, touchCrd.y-mouseOnCrd.y1);
delPicCoordinate({x:touchCrd.x-mouseOnCrd.x1, y: touchCrd.y-mouseOnCrd.y1});
//獲得位移量之後,重新指派給初始坐标,以備下次比較
mouseOnCrd.x1 = touchCrd.x;
mouseOnCrd.y1 = touchCrd.y;
}
//根據位移計算圖檔的坐标
function delPicCoordinate(shifting) {
var image = document.getElementById("image");
//目前的圖檔的坐标
var x = imageCrd.x;
var y = imageCrd.y;
x = checkX(x, parseInt(shifting.x));
y = checkY(y, parseInt(shifting.y))
console.log("即将偏移的量:", shifting.x, shifting.y);
image.style.transform = "translate(" + x + "px," + y + "px)";
// document.getElementById("cover-down").innerHTML=x + "px:" + y + "px";
console.log("偏移之後的偏移:", x, y);
imageCrd.x = x;
imageCrd.y = y;
}
//判斷是否可以在x軸上移動
function checkX(x, shiftingX) {
if(shiftingX < 0) { //向左
if((x + shiftingX) < (containSize.width- imageParams.width)) {
//如果轉行前已經比他小,保持原樣
if(x < (containSize.width- imageParams.width)){
return x;
}
return (containSize.width- imageParams.width);
}
}else {
if((x + shiftingX) > 0) { //向右
//如果轉行前已經比他大,保持原樣
if(x > shiftingX) {
return y;
}
return 0
}
}
return x+ shiftingX
}
//判斷是否可以在x軸上移動
function checkY(y, shiftingY) {
if(shiftingY < 0) { //向上
if((y + shiftingY) < ((containSize.width+containSize.height)/2 - imageParams.height)) {
console.log("==============向上:", y+shiftingY, ((containSize.width+containSize.height)/2 - imageParams.height));
//如果已經是比這個小,保持原樣
if(y < ((containSize.width+containSize.height)/2 - imageParams.height)) {
return y;
}
return parseInt((containSize.width+containSize.height)/2 - imageParams.height);
}
}else { //向下
if((y + shiftingY) > (containSize.height-containSize.width)/2) {//這裡隻是長寬都比頁面高
//如果已經是比這個大,保持原樣
if(y > (containSize.height-containSize.width)/2) {
return y;
}
return parseInt((containSize.height-containSize.width)/2);
}
}
return y+ shiftingY
}
//獲得滑鼠坐标
function getMouseCrd(touch) {
//滑鼠移動的位置
if(touch.pageX || touch.pageY){
return {x:touch.pageX, y:touch.pageY};
}
return{
x:touch.clientX + document.body.scrollLeft - document.body.clientLeft,
y:touch.clientY + document.body.scrollTop - document.body.clientTop
};
}
//計算最後的切割其實坐标,寬度和高度
function cutParams() {
var x;
var y;
var width;
var height;
if(imageParams.width > containSize.width) {
x = 0 - imageCrd.x;
width = containSize.width;
}else {
x = 0;
width = containSize.width;
}
if(imageParams.height > containSize.width) {
y = (containSize.height - containSize.width)/2 - imageCrd.y;
height = containSize.width;
}else {
y = 0;
height = imageParams.height;
}
var canvas = document.createElement("canvas"); // 畫布
canvas.width = width;
canvas.height = height;
var zoomRate = imageParams.width / imageParams.naturalWidth; // 縮放比例
// 擷取圖檔的真實切割起始坐标和寬高
x = parseInt(x / zoomRate);
y = parseInt(y / zoomRate);
width = parseInt(width / zoomRate);
height = parseInt(height / zoomRate);
var ctx = canvas.getContext('2d'); // 擷取畫布
ctx.drawImage(imageOrigin,x,y,width,height,0,0,canvas.width,canvas.height); // 裁剪并畫入畫布
saveimg(canvas);
}
// base64資料轉換為位圖
function b64ToUint8Array(b64Image) {
let img = atob(b64Image.split(',')[1]);
let img_buffer = [];
let i = 0;
while (i < img.length) {
img_buffer.push(img.charCodeAt(i));
i++;
}
return new Uint8Array(img_buffer);
}
// 儲存圖檔到伺服器
function saveimg(canvas){
// canva轉換為base64資料
let b64Image = canvas.toDataURL('image/jpeg');
// base64資料轉換為位圖
let u8Image = b64ToUint8Array(b64Image);
// 組裝form表單資料
let formData = new FormData();
formData.append("image", new Blob([ u8Image ], {type: "image/jpg"}));
// ajax送出
let xhr1 = new XMLHttpRequest();
xhr1.open("POST", HREF_PREFIX+"/api/updateHeadImg.php", true);
xhr1.onreadystatechange = function(){
if(xhr1.readyState === XMLHttpRequest.DONE && xhr1.status === 200) {
document.getElementsByClassName("updateHeadImg")[0].style.display = "none";
document.getElementById("updateHeadImg").getElementsByTagName("img")[0].src = xhr1.responseText;
}
}
xhr1.send(formData);
}
</script>
</html>
引用 https://gitee.com/sanpy/h5-demo/tree/master
增加了本地裁剪功能