2016年9月24日 星期六

HTML5 - canvas : imagData

HTML
<!--使用crossOrigin="anonymous"解決跨域存取圖片的問題,
參考連結https://developer.mozilla.org/zh-CN/docs/Web/HTML/CORS_enabled_image-->
<img src="https://c2.staticflickr.com/1/437/18634993201_10aa53d5ef_k.jpg" width="200" 
crossOrigin="anonymous">
<canvas id="myCanvas" width="200" height="133"></canvas>

JQuery 1.9.1
$(function() {
  function drawImg(imgObj) {
    var ctx = $('#myCanvas')[0].getContext('2d');
    var _iow = imgObj.width;//呼叫的圖形寬度
    var _ioh = imgObj.height;//呼叫的圖形高度
    var _iox = 0;//將要複製的圖形之起始x基準點
    var _ioy = 0;//將要複製的圖形之起始y基準點
    ctx.drawImage(imgObj, _iox, _ioy, _iow, _ioh);//將呼叫的物件寫入畫布中
    var cImg = ctx.getImageData(_iox, _ioy, _iow, _ioh);//設定要複製的資料範圍
    for (var i = 0; i <= cImg.data.length; i += 4) {//每四筆就loop一次
      cImg.data[i] = 255 - cImg.data[i];//Rad-用255色去剪掉Red原本的值
      cImg.data[i + 1] = 255 - cImg.data[i + 1];//green-用255色去剪掉green原本的值
      cImg.data[i + 2] = 255 - cImg.data[i + 2];//blue-用255色去剪掉blue原本的值
      cImg.data[i + 3] = 255;//alpha-維持原樣不變
    }
    ctx.putImageData(cImg, 0, 0);//將改變過顏色的圖片於原位覆蓋上去
  }
  $('img').load(function() {
    drawImg(this);//這邊的this=$('#img')
  }).each(function() {//執行完$('#img')的載入後,就遍歷$('#img')
    if (this.complete) $(this).load();//如果html的這張圖片載入成功,$('img')就再執行load內容一次
  });
});



主要使用function :
  1. crossOrigin - 結合合適的CROS響應頭,就可實踐跨域使用<img>,這裡有更想詳細的說明https://developer.mozilla.org/zh-CN/docs/Web/HTML/CORS_enabled_image
  2. complete - HTML DOM complete 屬性,可返回瀏覽器是否已完成圖片的加載。
  3. getImageData - 複製畫布上指定的像素範圍,getImageData(將要拷貝的起始x位置, 將要拷貝的起始y位置, 將要拷貝的寬度, 將要拷貝的高度)。
  4. imageData - getImageData拷貝的圖片中每個像素的值,imageData.data[red:value,green:value,blue:value,alpha:value]。
    語法 解說
    rad 0 ~ 255
    green 0 ~ 255
    blue 0 ~ 255
    alpha 0 ~ 255(0為全透明,255為不透明)
  5. putImageData - 將從getImageData取的的資料放回畫布,putimageData(要放回畫布的物件名稱, 要放回畫布上的x座標, 要放回畫布上的y座標, 以自身為基準的左移幅度-可選, 以自身為基準的下移幅度-可選, 放上畫布時的寬度-可選, 放上畫布時的高度-可選)

Result


JSFiddle
https://jsfiddle.net/MickeyChen/v6jyutdt/

2016年9月15日 星期四

HTML5 - canvas : operations

這個範例的運作方式是,先把圖型效果在tempCanvas畫好一個就以單張圖片的方式複製到mainCanvas上面,然後tempCanvas裡原先的圖形就會被移除,並用來預備繪製下一個圖形效果。

如果多個效果都寫在一個畫布上,容易出現效果錯亂的問題,所以這個範例是使用畫一個存出來一個的方式執行。

參考網站:http://www.html5canvastutorials.com/advanced/html5-canvas-global-composite-operations-tutorial/

HTML
<!--Original source http://www.html5canvastutorials.com/advanced/html5-canvas-global-composite-operations-tutorial/-->
<canvas id="tempCanvas" width="600" height="400" style="display:none;"></canvas>
<canvas id="mainCanvas" width="600" height="400"></canvas>

JQuery 1.9.1
$(function(){
  var tempCtx=$('#tempCanvas')[0].getContext('2d');//形成圖形相加效果的畫布
  var temp=$('#tempCanvas');
  var bCtx=$('#mainCanvas')[0].getContext('2d');//tempCtx圖形繪製出來後,擺放圖形的畫布
  var bCtxW=$('#mainCanvas').width();//消除已經複製過的圖形時所需要使用的寬
  var bCtxH=$('#mainCanvas').height();//消除已經複製過的圖形時所需要使用的高
  var sW=50;//第一層的方形寬高
  var cR=30;//第二層的圓形半徑
  var offset=45;//兩個圖相疊時的差距
  var operationOffset=140;//下一個圖形擺放的間距
  var i=[];//放效果指令的陣列

  //將所有的交疊效果放入i陣列中
  i.push('source-atop');
  i.push('source-in');
  i.push('source-out');
  i.push('source-over');
  i.push('destination-atop');
  i.push('destination-in');
  i.push('destination-out');
  i.push('destination-over');
  i.push('lighter');
  i.push('darker');
  i.push('xor');
  i.push('copy');
  console.log(i);
  
  for(var n=0; n < i.length; n++){
    tempCtx.save();//將每次繪製圖前的空值狀態存下,以便繪製完成後恢復到空值狀態
    tempCtx.clearRect(0,0,bCtxW,bCtxH);//清除tempCtx上的上一個交疊效果圖形
    
    tempCtx.beginPath();//繪製上層的方形
    tempCtx.rect(0,0,sW,sW);
    tempCtx.fillStyle="#62EACB";
    tempCtx.fill();
    
    tempCtx.globalCompositeOperation=i[n];//把效果從陣列中取出放入驅動效果
    console.log(i[n]);
    
    tempCtx.beginPath();//繪製下層的圓形
    tempCtx.arc(offset,offset,cR,0,2*Math.PI);
    tempCtx.fillStyle='#E177EA';
    tempCtx.fill();
    tempCtx.restore();//回復到空值的狀態
    
    tempCtx.font='14px arial';
    tempCtx.fillStyle='#666';
    tempCtx.fillText(i[n],0,sW+45);//把效果的名稱列在圖形下面
    
    if(n > 0){
     if(n % 4 === 0){//圖形寫入mainCanavs食,每4個一排
       bCtx.translate(operationOffset*-3,operationOffset);//當遇到4能整除的那個就往下折行
      }else{
       bCtx.translate(operationOffset,0);//如果無法整除就直接往右增加
      }
    }
    bCtx.drawImage(tempCanvas,0,0);//把tempCanvas用image的方式繪製到mainCanvas上面
  }
});


主要使用function :
  1. clearRect() - 刪除畫布上的一個區域,clearRect(要刪除的起始點x軸,要刪除的起始點y軸,要刪除的寬度,要刪除的高度)。
  2. globalCompositeOperation - 控制兩個互相覆蓋的圖形使用何種覆蓋效果。
    解說
    source-over 預設值,正常順序的上下圖形覆蓋。
    source-in 保留兩個圖形交疊的區域且保留上層圖形的樣式。
    source-out 只保留非交疊的上層圖形的形狀與樣式。
    source-atop 兩個圖形的樣式都保留但是只使用下層圖形的形狀。
    destination-over 兩個圖形的上下層級互換。
    destination-in 保留兩個圖形交疊的區域且保留下層圖形的樣式。
    destination-out 只保留非交疊的下層圖形的形狀與樣式。
    destination-atop 兩個圖形的樣式都保留但是只使用上層圖形的形狀。
    lighter 兩個圖形交疊處的顏色由兩個圖形的色相加而成。
    darker 已移除的值,兩個圖形交疊處的顏色由兩個圖形的色碼相減而成。
    xor 兩個圖形交疊區為透明。
    copy 移除其他圖形,只保留最上層的圖形。

Result


JSFiddle
https://jsfiddle.net/MickeyChen/krjLs085/

HTML5 - canvas : clip

HTML
<canvas id="myCanvas" width="210" height="210"></canvas>

JQuery 1.9.1
$(function(){
  var ctx=$('#myCanvas')[0].getContext('2d');
  var _x=$('#myCanvas').width()/2;//設定圓心的x軸
  var _y=$('#myCanvas').height()/2;//設定圓心的y軸
  var radius=100;//設定半徑
  var offset=65;//設定位移距離
  ctx.save();//設定這個斷點以上的code為起始儲存點
  
  //遮罩範圍
  ctx.beginPath();//開始繪製遮罩
  ctx.arc(_x,_y,radius,0,2*Math.PI,false);//繪製一個正圓形的遮罩
  ctx.clip();//設定遮罩功能
  
  //繪製A圖
  ctx.beginPath();//開始繪製A圖
  ctx.arc(_x-offset,_y-offset,radius,0,2*Math.PI,false);//繪製一個向左上角偏移的圓形
  ctx.fillStyle='#0D4351';//設定為深藍
  ctx.fill();//填色

  //繪製B圖
  ctx.beginPath();//開始繪製B圖
  ctx.arc(_x+offset,_y,radius,0,2*Math.PI,false);//繪製一個向右偏移的圓形
  ctx.fillStyle='#EA4881';//設定為桃紅
  ctx.fill();//填色

  //繪製C圖
  ctx.beginPath();//開始繪製C圖
  ctx.arc(_x,_y+offset,radius,0,2*Math.PI,false);//繪製一個向下偏移的圓形
  ctx.fillStyle='#6BD1EA';//設定為天空藍
  ctx.fill();//填色
  
  ctx.restore();//回復起始設定
  ctx.beginPath();//開始繪製外框線
  ctx.arc(_x,_y,radius,0,2*Math.PI,false);//繪製一個正圓為外框線,包覆遮罩邊框
  ctx.lineWidth=5;//設定外框限寬度
  ctx.strokeStyle='#66B79B';//設定為綠色
  ctx.stroke();//繪製線段
});


主要使用function :
  1. clip() - 用來剪裁畫布的可見範圍。

Result


JSFiddle
https://jsfiddle.net/MickeyChen/f9qrbvsd/

2016年9月9日 星期五

HTML5 - canvas : shadow & globalAlpha

HTML
<canvas id="myCanvas" width="340" height="200"></canvas>

JQuery 1.9.1
$(function(){
  var ctx=$('#myCanvas')[0].getContext('2d');
  ctx.rect(10,10,100,100);//繪製一個正方形。
  ctx.fillStyle='#E9EA6B';//給予填色。
  ctx.shadowColor="#B7A766";//設定陰影顏色。
  ctx.shadowBlur=10;//設定陰影霧化程度。
  ctx.shadowOffsetX=5;//設定陰影x座標。
  ctx.shadowOffsetY=5;//設定陰影y座標。
  ctx.fill();//
  
  ctx.beginPath();//繪製第一層的圓形。
  ctx.arc(200,60,50,0,2*Math.PI);
  ctx.fillStyle='#50510D';
  ctx.fill();
  
  ctx.beginPath();//繪製第二層的圓形。
  ctx.globalAlpha=0.5;//設定第二層圓形的透明度。
  ctx.arc(250,60,50,0,2*Math.PI);
  ctx.fillStyle='#758CC0';
  ctx.fill();
});


主要使用function :
  1. globalAlpha - 用來設定物件的透明度,可設定值為:0 ~ 1。
  2. shadow -
    語法 解說
    shadowColor 設定陰影顏色,需與shadowBlur合用。
    shadowBlur 設定陰影物化程度,值:0 ~ 100。
    shadowOffsetX 設定對應生成陰影物件的x軸定位,正數向右移,負數向左移。
    shadowOffsetY 設定對應生成陰影物件的y軸定位,正數向下移,負數向上移。

Result


JSFiddle
https://jsfiddle.net/MickeyChen/naxsrvej/

2016年9月7日 星期三

HTML5 - canvas : transformations

這篇所有綠色的方框都是個別效果的基本樣式,然後每一個範例都有先回復到上一個樣式再將已經回復的樣式存起來,所以每個樣式的繪圖起始樣式都是用base的樣式去做複製延伸,如果沒有這個儲存回覆的動作,就會因為<canvas>的樣式繼承特性,在同一個<canvas>裡面的繪圖物件都會繼承上一個繪圖物件的樣式,繪製出來的物件就會亂跑。

HTML
<canvas id="myCanvas1" width="600" height="300"></canvas>

JQuery 1.9.1
$(function(){
  var cxt=$('#myCanvas1')[0].getContext('2d');

  //basic style
  cxt.strokeStyle="#91B766";
  cxt.strokeRect(10,10,100,100);
  cxt.save();//保存這個basic樣式的設定。
  
  //translate
  cxt.restore();//回復到上一個save的basic樣式設定狀態。
  cxt.save();//保存這個回復成basic樣式的設定。
  cxt.strokeRect(120,10,100,100);
  cxt.translate(120,10);//重製一個x:120,y:10的這個物件在畫布的x:120,y:10的地方。
  cxt.strokeStyle="#926BEA";
  cxt.strokeRect(10,10,100,100);
  
  //scale
  cxt.restore();//回復到上一個save的basic樣式設定狀態。
  cxt.save();//保存這個回復成basic樣式的設定。
  cxt.strokeRect(300,10,100,100);
  cxt.scale(0.5,0.5);//重製一個x:300,y:10的這個物件在畫布上,並按照比例縮放50%。
  cxt.strokeStyle="#926BEA";
  cxt.strokeRect(600,20,100,100);
  
  //rotate
  cxt.restore();//回復到上一個save的basic樣式設定狀態。
  cxt.save();//保存這個回復成basic樣式的設定。
  cxt.strokeRect(499,10,100,100);
  cxt.translate(499,10);//給予選轉的物件新的x軸與y軸。
  cxt.rotate(5*Math.PI/180);//旋轉正5度。
  cxt.strokeStyle="#926BEA";
  cxt.strokeRect(499,10,100,100);//這個物件的x,y就是這個物件選轉的圓心。
  
  //transform
  cxt.restore();//回復到上一個save的basic樣式設定狀態。
  cxt.save();//保存這個回復成basic樣式的設定。
  cxt.strokeRect(10,150,100,100);
  cxt.transform(1,0,0.5,1,-75,0);//繪製一個平行垂直傾斜90*0.5度的平行四邊形。
  cxt.strokeStyle="#926BEA";
  cxt.strokeRect(10,150,100,100);
  //setTransform
  cxt.setTransform(1,0,0,1,0,0);//不會繼承到上一個平行四邊形的樣式,直接重新繪製一個正方形。
  cxt.strokeStyle='#B09BC0';
  cxt.strokeRect(110,150,100,100);
  
  //Mirror
  cxt.restore();//回復到上一個save的basic樣式設定狀態。
  cxt.save();//保存這個回復成basic樣式的設定。
  cxt.scale(1,-1);//用y軸的-1將Hello!垂直反轉成倒過來的文字。
  cxt.font='50px Arial';
  //因為文字被整個垂直反轉,所以y軸必須使用負值讓文字重新回到<canvas>裡面,不然文字會跑出<canvas>外面。
  cxt.fillText('Hello!',350,-180);
});


主要使用function :
  1. save() - 保存當前環境狀態,會以堆存的方式被放進保存清單裡面,如果存入過多資料,會造成系統負擔。
  2. restore() - 回復到上一個保存過的路徑狀態跟屬性。
  3. transformations -
    語法 解說
    translate(新物件在畫布上的x軸, 新物件在畫布上的x軸); 重新複製物件在對照畫布(0,0)的地方。
    scale(縮放的寬比例, 縮放的高比例); 縮放的比例以1為原比例,0.5為50%的比例,2為200%的比例,以此類推,負值為將物件鏡射。
    rotate(角度*Math.PI/180); 需要以(角度*Math.PI/180)的公式照計算出圓弧的弧度,並依照弧度轉動角度,圓心座標為繪製出這個物件的座標軸減掉放置這個物件的容器的座標軸所得出的(x,y)。
    transform(水平縮放,水平傾斜,垂直縮放,垂直傾斜,水平移動,垂直移動); 縮放、旋轉與移動繪製物件。可以在保持物件已繪製過的樣式,再增加縮放、旋轉與移動的效果。
    setTransform(水平縮放,水平傾斜,垂直縮放,垂直傾斜,水平移動,垂直移動); 與transform一樣的效果,不同處為這個語法只會影響到在這個語法之後編寫的繪圖樣式。

Result


JSFiddle
https://jsfiddle.net/MickeyChen/bzLbttwy/

2016年9月6日 星期二

HTML5 - canvas : font(2)

HTML
<!--Original source http://www.html5canvastutorials.com/tutorials/html5-canvas-wrap-text-tutorial/-->
<canvas id="myFont" width="500" height="400"></canvas>

JQuery 1.9.1
$(function(){
  function wrapText(cxt,txt,x,y,maxWidth,lineHeight){
  //cxt:<canvas>,txt:文案,x:文案的起始x軸,y:文案的起始y軸,maxWidth:文案的最大寬度,lineHeight:文案行高

    var words=txt.split(' ');//把文案用空白字元為依據來分割並給予words。
    var line='';//擷取出來的單字將要存入的容器。
    
    for(var n=0; n < words.length; n++){//按照擷取出來的單字總數來循環執行。
      var txtLine=line+words[n]+' ';//每個單字加上一個空白字元並放入txLine。
      var metrics=cxt.measureText(txtLine).width;//計算每一次執行時txtLine長度是多少。
      if(metrics > maxWidth && n > 0){//判斷當txtLine長度超過maxWidth且文字多於0個。
       cxt.fillText(line,x,y);//新增一行文字。
        line=words[n]+' ';//改變該行文字的第一個字為使txtLine超出maxWidth的那個文字。
        y+=lineHeight;//y軸往下移動一個LineHeight的高度。
      }else{
       line=txtLine;//直接蓋過原本的當行的文字。
      };
    };
    cxt.fillText(line,x,y);//創建第一行文字。
  };
  var article='The greatest test of courage on earth is to bear defeat without losing heart. 
               世界上對勇氣的最大考驗是忍受失敗而不喪失信心。';
  var cxt=$('#myFont')[0].getContext('2d');
  cxt.font='20px Calibri';
  cxt.fillStyle='#666';
  wrapText(cxt,article,10,20,490,30);
});


主要使用function :
  1. wrapText() - 此function的作用為,繪製一個規定範圍內按照英文書寫習慣,文案自動折行。
  2. split() - 把一段文字分割成多個單一文字,'文字物件'.split('字符串或正則表達式,按照這個值去分割文字物件 - 必填', '返回分割的最大返回分割的最大長度,以1為起始計算點,無設定以全文字物件長度返回 - 非必填')。
    範例 解說
    "Hi! How was today?".split( '' ); 結果//H,i,!, ,H,o,w, ,w,a,s, ,t,o,d,a,y,?
    每一個字元包含空白字元都會被分割列出。
    "Hi! How was today?".split( ' ' ); 結果//Hi!,How,was,today?
    使用'空白字元'會以空白字元為分割點分割列出,空白字元會被省略掉。
    "Hi! How was today?".split( ' ', 2 ); 結果//Hi!,How
    只抓取第1、2個單字。
    ":1:2:3".split( ':' ); 結果// ,1,2,3
    以:作為分割點分割列出,:會被省略掉。
    var words = sentence.split( ' / \s+/ ' ); 把句子分割成單字。

Result


JSFiddle
https://jsfiddle.net/MickeyChen/84cuwtos/

2016年9月5日 星期一

HTML5 - canvas : font(1)

HTML
<canvas id="myFont" width="300" height="200" style="border:1px solid #999;"></canvas>

JQuery 1.9.1
$(function(){
  var cxt=$('#myFont')[0].getContext('2d');
  var txt='BEAST';//設定文字文案。
  var _x=$('#myFont').width()/2;//取得畫布的橫向中心點。
  var _y=$('#myFont').height()/2;//取的畫布的直向中心點。
  cxt.font='oblique 40px Arial';//設定文字樣式。
  cxt.textAlign='center';//設定文字居中對齊。
  cxt.textBaseline='middle';//設定文字垂直置中對齊。
  cxt.fillStyle='#ccc';
  cxt.fillText(txt,_x,_y-20);//設定填色文字的文案與位置。
  cxt.strokeStyle='#664746';
  cxt.strokeText(txt,_x,_y-20);//設定線框文字的文案與位置。
  
  var txtW=cxt.measureText(txt).width;//取得繪製文字的寬度。
  cxt.font='normal 20px Calibri';
  cxt.fillStyle='#333';
  cxt.fillText(txtW+'PX',_x,_y+20);
});


主要使用function :
  1. textAling - 設定文字左右對齊依據。
    屬性
    start 預設值,內文在指定位置開始。
    end 內文在指定位置結束。
    right 內文以指定位置居右對齊。
    center 內文以指定位置居中對齊。
    left 內文以指定位置居左對齊。

  2. textBaseLine - 設定文字垂直對齊的基線,以1em為高度基準。
    圖片來源:http://www.w3school.com.cn/i/textBaseline.gif
    屬性
    alphabetic 預設值,文字位在普通字母基線。
    top 文字位在以1em平方為單位的方框上端。
    hanging 文字位在懸掛基線。
    middle 文字位在以1em平方為單位的方框中間。
    ideographic 文字位在表意基線。
    bottom 文字位在以1em平方的方框下端。

  3. fillText() - 把填色文字寫入<canvas>,fillText('要寫入的文案',起始x軸,起始y軸)。
  4. strokeText() - 把線框文字寫入<canvas>,strokeText('要寫入的文案',起始x軸,起始y軸)。
  5. font - 在畫布上寫一段文案,默認值為10px sans-serif。最少需填寫font='font-size,font-family'兩個值。
    屬性
    font-style 字體樣式:normal正常 / italic斜體 / oblique斜體
    font-variant 字體變體:normal正常 / small-caps小型大寫字體
    font-weight 字體粗細:normal正常 / bold粗體 / bolder特粗體 / lighter細體 / 100 ~ 900自訂粗細
    font-size / line-height 字體大小與行高,以px為單位。
    font-family 字型,常用的為: Arial / courier New / Times New Roman 等等。
    caption 使用標題控制元件<caption>的字體EX:button、drop-downs等等。
    icon 使用於標記圖示的字體。
    menu 使用於菜單的字體。
    message-box 使用於對話框的字體。
    small-caption 使用於小型控制元件的字體。
    status-bar 使用在window視窗狀態欄的字體。
    initial 將此屬性設置為默認值。
    inherit 繼承父元件的文字屬性。

  6. measureText().width - measureText(要測量的文本).width,取的畫布上的文字寬度。

Result


JSFiddle
https://jsfiddle.net/MickeyChen/bbryzekb/