วันพฤหัสบดีที่ 28 กุมภาพันธ์ พ.ศ. 2556

Web วาดรูปด้วย canvas จาก HTML5



ใน HTML5 นั้นจะมี Element ที่ชื่อว่า canvas ที่เราสามารถใช้ jQuery หรือ JavaScript ควบคุมการทำงานของมันได้ ไม่ว่าจะวาดภาพ วาดวงกลม ใส่รูป เราก็สามารถใส่เข้าไปใน canvas ได้

ถ้าเพื่อนๆที่เคยใช้พวก Java applet คงจะพอนึกภาพออกนะครับว่า Canvas นั้นมันก็เป็นพื้นที่สี่เหลี่ยมที่เอาไว้ใช้แสดงผลกราฟฟิก ที่เราสามารถจะควบคุมได้ สามารถควบคุมในระดับ pixel ได้เลยทีเดียว

Canvas นั้นก็เหมือนๆกับ Element อื่นๆครับ สามารถกำหนด Style ให้ได้ไม่ว่าจะเป็นสี ขนาดความกว้าง ความสูง กำหนดทำแหน่งได้ด้วย

ผมก็เลยเอาตัวอย่างเว็บที่ผมเขียนขึ้นมาให้ดูว่ามันเป็นอย่างไร 
ผมไม่ได้เขียนขึ้นเองมาทั้งหมด นำมาจากหลายที่ แก้ไขและเพิ่มเติม 
ก็เลยจะนำมาแบ่งให้เพื่อนๆศึกษากันดู ^^



------------------------------------------------------------------------------------------------------------

canvas.html


<html>
<head>
<script type="text/javascript" src="canvas2image.js"> </script>
</head>
<body>
<center>
<button id="pencil" onclick="Default()"> Default </button>
<input type="color" name="favcolor" id="favcolor" onchange="selectColor()"/>
<button id="sizeP" onclick="sizeP()"> + </button>
<button id="sizeD" onclick="sizeD()"> - </button>
<input type="file" NAME="Files" onchange="preview(this)" />
<button id="Submit" onclick="Submit()"> Submit </button>

</br>
<button id="clears" onclick="Pencil()"> Pencil </button>
<button id="Circle" onclick="Circle()"> Circle </button>
<button id="Rectangle" onclick="Rectangle()"> Rectangle </button>
<button id="Ellipse" onclick="Ellipse()"> Ellipse </button>
<button id="export" onclick="exportImage()"> Export </button>
<button id="eraser" onclick="eraser()"> Eraser </button>
<button id="clears" onclick="Clear_image()"> Clear </button></br>
<canvas id="canvas" width="800" height="500" style="border: 1px solid black;"></canvas>
<div id="coord"></div></center>



<script> 
var mouse = {x: 0, y: 0};
var start_mouse = {x: 0, y: 0};
var radius = 5;
var canvas = document.getElementById('canvas'),
    coord = document.getElementById('coord'),
    context = canvas.getContext('2d'), // get 2D context
    rect = {},
    drag = false;
imgCat = new Image();

/*********** draw image *************/
imgCat.src = 'Untitled.jpg';
imgCat.onload = function() { // wait for image load
    context.drawImage(imgCat, 0, 0); // draw imgCat on (0, 0)
context.lineWidth = radius;
context.strokeStyle = '#000000';
context.lineWidth = 5;
};

function getPath(){
      var str = document.getElementById('blaat').value;
      // lastIndexOf('\\') you need to use two \\'s because you use \ to escape
      str = str.substring(0, str.lastIndexOf('\\'));
      //if you want a closing \ just add a \ to the str (str += '\')
      document.getElementById('verborgenBlaat').value = str;
      // alert to proof it sets the directory 
      alert(document.getElementById('verborgenBlaat').value)
}

function preview(test){
    var source=test.value;
    alert(source);
}


function fileSelected(){
alert( document.forms[0].files.value);

}
function Submit(){
alert(document.forms[0].getElementById('files').value);

}


/*********** handle mouse events on canvas **************/
function Pencil(){
context.strokeStyle = document.getElementById("favcolor").value;
var mousedown = false;
canvas.onmousedown = function(e) {
    var pos = fixPosition(e, canvas);
    mousedown = true;
    context.beginPath();
    context.moveTo(pos.x, pos.y);
    return false;
};

canvas.onmousemove = function(e) {
    var pos = fixPosition(e, canvas);
    coord.innerHTML = '(' + pos.x + ',' + pos.y + ')';
    if (mousedown) {
        context.lineTo(pos.x, pos.y);
        context.stroke();
    }
};

canvas.onmouseup = function(e) {
    mousedown = false;
};

}
/********** utils ******************/
// Thanks to http://stackoverflow.com/questions/55677/how-do-i-get-the-coordinates-of-a-mouse-click-on-a-canvas-element/4430498#4430498
function fixPosition(e, gCanvasElement) {
    var x;
    var y;
    if (e.pageX || e.pageY) { 
      x = e.pageX;
      y = e.pageY;
    }
    else { 
      x = e.clientX + document.body.scrollLeft +
          document.documentElement.scrollLeft;
      y = e.clientY + document.body.scrollTop +
          document.documentElement.scrollTop;
    } 
    x -= gCanvasElement.offsetLeft;
    y -= gCanvasElement.offsetTop;
    return {x: x, y:y};
}


function exportImage() {
window.open(canvas.toDataURL(),'_blank','width=800,height=600');
//window.open("http://www.w3schools.com")
}
function Default(){
   context.strokeStyle = document.getElementById("favcolor").value;
   context.lineWidth = 5;
}

function Clear_image() {
context.clearRect(0, 0, canvas.width, canvas.height);

function sizeP() {
radius++;
                context.lineWidth = radius;

function sizeD() {
if(radius==1){}
else{
radius--;
                context.lineWidth = radius;
}

function eraser(){
Pencil();
   context.strokeStyle = "#FFFFFF";
  
}
function showR(){
   document.write(radius);
}

//////////////////////////////////////////////////////

function Rectangle(){
context.strokeStyle = document.getElementById("favcolor").value;
      var mousedown = false;
canvas.onmousedown = function(e) {
var pos = fixPosition(e, canvas);
mousedown = true;
context.drawImage(canvas, 0, 0);
context.beginPath();
rect.startX = e.pageX - this.offsetLeft;
rect.startY = e.pageY - this.offsetTop;
return false;
};

canvas.onmousemove = function(e) {
    var pos = fixPosition(e, canvas);
    coord.innerHTML = '(' + pos.x + ',' + pos.y + ')';
    
/* if (mousedown) {
    rect.w = (e.pageX - this.offsetLeft) - rect.startX;
    rect.h = (e.pageY - this.offsetTop) - rect.startY ;
    context.clearRect(0,0,canvas.width,canvas.height);
    context.strokeRect(rect.startX, rect.startY, rect.w, rect.h);
  }
*/
};



canvas.onmouseup = function(e) {
if (mousedown) {
    rect.w = (e.pageX - this.offsetLeft) - rect.startX;
    rect.h = (e.pageY - this.offsetTop) - rect.startY ;
    
    context.strokeRect(rect.startX, rect.startY, rect.w, rect.h);
  }
    mousedown = false;
};
}


function Circle(){
context.strokeStyle = document.getElementById("favcolor").value;
var mousedown = false;
canvas.onmousedown = function(e) {
var pos = fixPosition(e, canvas);
mousedown = true;
context.drawImage(canvas, 0, 0);
context.beginPath();
rect.startX = e.pageX - this.offsetLeft;
rect.startY = e.pageY - this.offsetTop;
return false;
};

canvas.onmousemove = function(e) {
    var pos = fixPosition(e, canvas);
    coord.innerHTML = '(' + pos.x + ',' + pos.y + ')';
    
/* if (mousedown) {
    rect.w = (e.pageX - this.offsetLeft) - rect.startX;
    rect.h = (e.pageY - this.offsetTop) - rect.startY ;
    context.clearRect(0,0,canvas.width,canvas.height);
    context.strokeRect(rect.startX, rect.startY, rect.w, rect.h);
  }
*/
};



canvas.onmouseup = function(e) {
if (mousedown) {
    rect.w = (e.pageX - this.offsetLeft) - rect.startX;
    rect.h = (e.pageY - this.offsetTop) - rect.startY ;
    
var radius = Math.max(
Math.abs(rect.w),
Math.abs(rect.h)
) / 2;
    context.arc(rect.startX, rect.startY, radius, 0, Math.PI*2, false);
context.stroke();
context.closePath();
  }
    mousedown = false;
};

}





</script>

</body>
</html>

------------------------------------------------------------------------------------------------------------

canvas2image.js


var Canvas2Image = (function() {

// check if we have canvas support
var bHasCanvas = false;
var oCanvas = document.createElement("canvas");
if (oCanvas.getContext("2d")) {
bHasCanvas = true;
}

// no canvas, bail out.
if (!bHasCanvas) {
return {
saveAsBMP : function(){},
saveAsPNG : function(){},
saveAsJPEG : function(){}
}
}

var bHasImageData = !!(oCanvas.getContext("2d").getImageData);
var bHasDataURL = !!(oCanvas.toDataURL);
var bHasBase64 = !!(window.btoa);

var strDownloadMime = "image/octet-stream";

// ok, we're good
var readCanvasData = function(oCanvas) {
var iWidth = parseInt(oCanvas.width);
var iHeight = parseInt(oCanvas.height);
return oCanvas.getContext("2d").getImageData(0,0,iWidth,iHeight);
}

// base64 encodes either a string or an array of charcodes
var encodeData = function(data) {
var strData = "";
if (typeof data == "string") {
strData = data;
} else {
var aData = data;
for (var i=0;i<aData.length;i++) {
strData += String.fromCharCode(aData[i]);
}
}
return btoa(strData);
}

// creates a base64 encoded string containing BMP data
// takes an imagedata object as argument
var createBMP = function(oData) {
var aHeader = [];
var iWidth = oData.width;
var iHeight = oData.height;

aHeader.push(0x42); // magic 1
aHeader.push(0x4D); 
var iFileSize = iWidth*iHeight*3 + 54; // total header size = 54 bytes
aHeader.push(iFileSize % 256); iFileSize = Math.floor(iFileSize / 256);
aHeader.push(iFileSize % 256); iFileSize = Math.floor(iFileSize / 256);
aHeader.push(iFileSize % 256); iFileSize = Math.floor(iFileSize / 256);
aHeader.push(iFileSize % 256);

aHeader.push(0); // reserved
aHeader.push(0);
aHeader.push(0); // reserved
aHeader.push(0);

aHeader.push(54); // dataoffset
aHeader.push(0);
aHeader.push(0);
aHeader.push(0);

var aInfoHeader = [];
aInfoHeader.push(40); // info header size
aInfoHeader.push(0);
aInfoHeader.push(0);
aInfoHeader.push(0);

var iImageWidth = iWidth;
aInfoHeader.push(iImageWidth % 256); iImageWidth = Math.floor(iImageWidth / 256);
aInfoHeader.push(iImageWidth % 256); iImageWidth = Math.floor(iImageWidth / 256);
aInfoHeader.push(iImageWidth % 256); iImageWidth = Math.floor(iImageWidth / 256);
aInfoHeader.push(iImageWidth % 256);
var iImageHeight = iHeight;
aInfoHeader.push(iImageHeight % 256); iImageHeight = Math.floor(iImageHeight / 256);
aInfoHeader.push(iImageHeight % 256); iImageHeight = Math.floor(iImageHeight / 256);
aInfoHeader.push(iImageHeight % 256); iImageHeight = Math.floor(iImageHeight / 256);
aInfoHeader.push(iImageHeight % 256);
aInfoHeader.push(1); // num of planes
aInfoHeader.push(0);
aInfoHeader.push(24); // num of bits per pixel
aInfoHeader.push(0);
aInfoHeader.push(0); // compression = none
aInfoHeader.push(0);
aInfoHeader.push(0);
aInfoHeader.push(0);
var iDataSize = iWidth*iHeight*3; 
aInfoHeader.push(iDataSize % 256); iDataSize = Math.floor(iDataSize / 256);
aInfoHeader.push(iDataSize % 256); iDataSize = Math.floor(iDataSize / 256);
aInfoHeader.push(iDataSize % 256); iDataSize = Math.floor(iDataSize / 256);
aInfoHeader.push(iDataSize % 256); 
for (var i=0;i<16;i++) {
aInfoHeader.push(0); // these bytes not used
}
var iPadding = (4 - ((iWidth * 3) % 4)) % 4;

var aImgData = oData.data;

var strPixelData = "";
var y = iHeight;
do {
var iOffsetY = iWidth*(y-1)*4;
var strPixelRow = "";
for (var x=0;x<iWidth;x++) {
var iOffsetX = 4*x;

strPixelRow += String.fromCharCode(aImgData[iOffsetY+iOffsetX+2]);
strPixelRow += String.fromCharCode(aImgData[iOffsetY+iOffsetX+1]);
strPixelRow += String.fromCharCode(aImgData[iOffsetY+iOffsetX]);
}
for (var c=0;c<iPadding;c++) {
strPixelRow += String.fromCharCode(0);
}
strPixelData += strPixelRow;
} while (--y);

var strEncoded = encodeData(aHeader.concat(aInfoHeader)) + encodeData(strPixelData);

return strEncoded;
}


// sends the generated file to the client
var saveFile = function(strData) {
document.location.href = strData;
}

var makeDataURI = function(strData, strMime) {
return "data:" + strMime + ";base64," + strData;
}

// generates a <img> object containing the imagedata
var makeImageObject = function(strSource) {
var oImgElement = document.createElement("img");
oImgElement.src = strSource;
return oImgElement;
}

var scaleCanvas = function(oCanvas, iWidth, iHeight) {
if (iWidth && iHeight) {
var oSaveCanvas = document.createElement("canvas");
oSaveCanvas.width = iWidth;
oSaveCanvas.height = iHeight;
oSaveCanvas.style.width = iWidth+"px";
oSaveCanvas.style.height = iHeight+"px";

var oSaveCtx = oSaveCanvas.getContext("2d");

oSaveCtx.drawImage(oCanvas, 0, 0, oCanvas.width, oCanvas.height, 0, 0, iWidth, iHeight);
return oSaveCanvas;
}
return oCanvas;
}

return {

saveAsPNG : function(oCanvas, bReturnImg, iWidth, iHeight) {
if (!bHasDataURL) {
return false;
}
var oScaledCanvas = scaleCanvas(oCanvas, iWidth, iHeight);
var strData = oScaledCanvas.toDataURL("image/png");
if (bReturnImg) {
return makeImageObject(strData);
} else {
saveFile(strData.replace("image/png", strDownloadMime));
}
return true;
},

saveAsJPEG : function(oCanvas, bReturnImg, iWidth, iHeight) {
if (!bHasDataURL) {
return false;
}

var oScaledCanvas = scaleCanvas(oCanvas, iWidth, iHeight);
var strMime = "image/jpeg";
var strData = oScaledCanvas.toDataURL(strMime);
// check if browser actually supports jpeg by looking for the mime type in the data uri.
// if not, return false
if (strData.indexOf(strMime) != 5) {
return false;
}

if (bReturnImg) {
return makeImageObject(strData);
} else {
saveFile(strData.replace(strMime, strDownloadMime));
}
return true;
},

saveAsBMP : function(oCanvas, bReturnImg, iWidth, iHeight) {
if (!(bHasImageData && bHasBase64)) {
return false;
}

var oScaledCanvas = scaleCanvas(oCanvas, iWidth, iHeight);

var oData = readCanvasData(oScaledCanvas);
var strImgData = createBMP(oData);
if (bReturnImg) {
return makeImageObject(makeDataURI(strImgData, "image/bmp"));
} else {
saveFile(makeDataURI(strImgData, strDownloadMime));
}
return true;
}
};

})();

------------------------------------------------------------------------------------------------------------

ไม่มีความคิดเห็น:

แสดงความคิดเห็น