id="BAIDU_DUP_fp_iframe" src="https://pos.baidu.com/wh/o.htm?ltr=" style="width: 0px; height: 0px; visibility: hidden; display: none;">
登錄?|?注冊 收藏成功 確定 收藏失敗,請重新收藏 確定 src="about:block" frameborder="0" allowtransparency="true" style="z-index:-1;position:absolute;top:0;left:0;width:100%;height:100%;background:transparent"> 分享資訊 傳PPT/文檔 提問題 寫博客 傳資源 創(chuàng)建項目 創(chuàng)建代碼片 設(shè)置昵稱 編輯自我介紹,讓更多人了解你 帳號設(shè)置 退出 社區(qū) 博客 論壇 下載 知識庫 技術(shù)問答 極客頭條 英雄會 服務(wù) JOB 學(xué)院 CODE 活動 CSTO C幣兌換 俱樂部 CTO俱樂部 高校俱樂部
Ajian_studio 學(xué)問積年而成,而每日不自知! <script type="text/javascript">var username = "tianjian4592"; var _blogger = username; var blog_address = "http://blog.csdn.net/tianjian4592"; var static_host = "http://static.blog.csdn.net"; var currentUserName = "";</script>
移動信息安全的漏洞和逆向原理 ???
【觀點】世界上最好的語言是什么 ???
Get IT技能知識庫,50個領(lǐng)域一鍵直達 <script>document.getElementById('location_parent').parentNode.style.height='1px';document.getElementById('location_parent').parentNode.style.width='1px';document.getElementById('location_parent').parentNode.style.position='fixed';document.getElementById('location_parent').parentNode.style.right='10px';document.getElementById('location_parent').parentNode.style.bottom='10px';document.getElementById('location_parent').parentNode.style.zIndex=999;document.getElementById('location_parent').parentNode.style.backgroundColor='transparent';</script> id="iframeu2392861_0" src="http://pos.baidu.com/acrm?sz=300x250&rdid=2392861&dc=2&di=u2392861&dri=0&dis=0&dai=1&ps=1008x1818&coa=at%3D3%26rsi0%3D300%26rsi1%3D250%26pat%3D17%26tn%3DbaiduCustNativeAD_xuanfu%26rss1%3D%2523FFFFFF%26conBW%3D1%26adp%3D1%26ptt%3D0%26titFF%3D%2525E5%2525BE%2525AE%2525E8%2525BD%2525AF%2525E9%25259B%252585%2525E9%2525BB%252591%26titFS%3D14%26rss2%3D%2523000000%26titSU%3D0&dcb=BAIDU_SSP_define&dtm=HTML_POST&dvi=0.0&dci=-1&dpt=none&tsr=0&tpr=1478326006940&ti=Canvas%E4%B9%8Btranslate%E3%80%81scale%E3%80%81rotate%E3%80%81skew%E6%96%B9%E6%B3%95%E8%AE%B2%E8%A7%A3%EF%BC%81%20-%20Ajian_studio%20-%20%E5%8D%9A%E5%AE%A2%E9%A2%91&ari=2&dbv=2&drs=3&pcs=1829x1019&pss=1829x19885&cfv=0&cpl=4&chi=3&cce=true&cec=UTF-8&tlm=1478326006&rw=1019<u=http%3A%2F%2Fblog.csdn.net%2Ftianjian4592%2Farticle%2Fdetails%2F45234419&ecd=1&psr=1920x1080&par=1846x1080&pis=-1x-1&ccd=24&cja=false&cmi=6&col=zh-CN&cdo=-1&tcn=1478326007&qn=846792b09ec303f7&tt=1478326006861.94.97.114" width="300" height="250" align="center,center" vspace="0" hspace="0" marginwidth="0" marginheight="0" scrolling="no" frameborder="0" style="border:0; vertical-align:bottom;margin:0;" allowtransparency="true"> 關(guān)閉 <script type="text/javascript">(window['cproStyleApi'] = window['cproStyleApi'] || {})['u2392861']={at:'3',rsi0:'300',rsi1:'250',pat:'17',tn:'baiduCustNativeAD_xuanfu',rss1:'#FFFFFF',conBW:'1',adp:'1',ptt:'0',titFF:'%E5%BE%AE%E8%BD%AF%E9%9B%85%E9%BB%91',titFS:'14',rss2:'#000000',titSU:'0'};/*服務(wù)器頻道首頁置頂Banner960*90,創(chuàng)建于2014-7-3*/(window.cproArray = window.cproArray || []).push({id:'u2392861'});</script> <script src="http://cpro.baidustatic.com/cpro/ui/f.js" type="text/javascript"></script> href="http://static.blog.csdn.net/css/comment1.css" type="text/css" rel="stylesheet" /> href="http://static.blog.csdn.net/css/style1.css" type="text/css" rel="stylesheet" /><script language="JavaScript" type="text/javascript" src="http://download.csdn.net/js/jquery.cookie.js"></script><script type="text/javascript" src="http://c.csdnimg.cn/rabbit/search-service/main.js"></script> rel="stylesheet" href="http://static.blog.csdn.net/public/res-min/markdown_views.css?v=1.0" /> rel="stylesheet" href="http://static.blog.csdn.net/css/category.css?v=1.0" /><script type="text/javascript" src="http://static.blog.csdn.net/public/res/bower-libs/MathJax/MathJax.js?config=TeX-AMS_HTML"></script><script type="text/javascript" src="http://static.blog.csdn.net/scripts/web-storage-cache.min.js"></script><script type="text/javascript" src="http://static.blog.csdn.net/scripts/replace.min.js"></script> <script type="text/ecmascript">window.quickReplyflag = true; var isBole = false;</script>
[置頂] Canvas之translate、scale、rotate、skew方法講解! 標(biāo)簽: Canvasandroid畫布canvas.translatecanvas.scalecanvas.rotate 2015-05-07 13:49 8987人閱讀 收藏 舉報 本文章已收錄于: .embody{padding:10px 10px 10px;margin:0 -20px;border-bottom:solid 1px #ededed; }.embody_b{margin:0 ;padding:10px 0;}.embody .embody_t,.embody .embody_c{display: inline-block;margin-right:10px;}.embody_t{font-size: 12px;color:#999;}.embody_c{font-size: 12px;}.embody_c img,.embody_c em{display: inline-block;vertical-align: middle; }.embody_c img{ width:30px;height:30px;}.embody_c em{margin: 0 20px 0 10px;color:#333;font-style: normal;} <script type="text/javascript">$(function () { try { var lib = eval("("+$("#lib").attr("value")+")"); var html = ""; if (lib.err == 0) { $.each(lib.data, function (i) { var obj = lib.data[i]; //html += ' ' + obj.name + "??"; html += ' 分類: android動效篇(12) 作者同類文章 X
<script type="text/javascript" src="http://static.blog.csdn.net/scripts/category.js"></script>
版權(quán)聲明:本文為博主原創(chuàng)文章,未經(jīng)博主允許不得轉(zhuǎn)載。
尊重原創(chuàng),歡迎轉(zhuǎn)載,轉(zhuǎn)載請注明: FROM ? GA_studio ? ?http://blog.csdn.net/tianjian4592 ??
前面說Canvas大致可以分為三類:
1. save、restore 等與層的保存和回滾相關(guān)的方法;
2. scale、rotate、clipXXX 等對畫布進行操作的方法;
3. drawXXX 等一系列繪畫相關(guān)的方法;
前面主要講了drawBitmap方法,并舉了一個星球浮動的栗子,在那個例子中,星球有大有小,需要移動,有時候可能需求上還需要旋轉(zhuǎn)或錯切,有了這些需求,我們就需要使用到與Canvas相關(guān)的translate、scale、rotate、skew這幾個方法,平移、縮放、旋轉(zhuǎn)、錯切,這四個詞聽起來是如此的熟悉,我們在做一些基本動畫的時候經(jīng)常會與這幾個詞打交道,現(xiàn)在我們一個個看下當(dāng)把這幾個家伙和Canvas(畫布)結(jié)合能產(chǎn)生什么效果;
當(dāng)然在看之前得先明確兩個基本概念:
1.Canvas 的左上角是(0,0);
2.基于左上角往右 X 為正,往下 Y 為正,反之為負(fù);
一、canvas.translate() - 畫布的平移:
首先咱們在畫布上畫一個400 X 400 紅色的矩形
[html] view plain copy print ?
canvas.drawRect(new?Rect(0,?0,?400,?400),?mPaint);?? canvas.drawRect(new Rect(0, 0, 400, 400), mPaint);
此時整個畫布的左上角出現(xiàn)了一個紅色的矩形(為了更清楚,藍色打個底)該矩形大小為400 X 400 ,效果如下:
接下來我們canvas.translate( )玩玩
[html] view plain copy print ?
@Override?? protected?void?onDraw(Canvas?canvas)?{?? ????super.onDraw(canvas);?? ????canvas.drawColor(Color.BLUE);?? ????canvas.translate(100,?100);?? ????canvas.drawRect(new?Rect(0,?0,?400,?400),?mPaint);?? }?? @Overrideprotected void onDraw(Canvas canvas) {super.onDraw(canvas);canvas.drawColor(Color.BLUE);canvas.translate(100, 100);canvas.drawRect(new Rect(0, 0, 400, 400), mPaint);}
看下效果:
此時可以看到,雖然是繪制同樣的矩形,但矩形在畫布上的位置已經(jīng)向右和向下各移動了100px;
既然如此,這個時候如果我們再將canvas 平移(translate)(100,100),再繪制一個同樣的矩形會出現(xiàn)什么情況呢?會與之前的矩形重疊嗎?咱們拭目以待:
[html] view plain copy print ?
@Override?? protected?void?onDraw(Canvas?canvas)?{?? ????super.onDraw(canvas);?? ????canvas.drawColor(Color.BLUE);?? ????canvas.translate(100,?100);?? ????canvas.drawRect(new?Rect(0,?0,?400,?400),?mPaint);?? ????canvas.translate(100,?100);?? ????canvas.drawRect(new?Rect(0,?0,?400,?400),?mPaint);?? }?? @Overrideprotected void onDraw(Canvas canvas) {super.onDraw(canvas);canvas.drawColor(Color.BLUE);canvas.translate(100, 100);canvas.drawRect(new Rect(0, 0, 400, 400), mPaint);canvas.translate(100, 100);canvas.drawRect(new Rect(0, 0, 400, 400), mPaint);}
從效果上看,兩次translate 進行了疊加,繪制第二個矩形的時候畫布已經(jīng)偏移了(200,200);
好了,了解到這里,咱們利用canvas.translate( )一起來做個小栗子,繪制一個生活中比較常用的刻度尺;
咱們先從網(wǎng)上找個用于參考的刻度尺圖片:
從圖上看,刻度尺的元素有:外框、刻度線(不同的數(shù)值刻度線長短不一)、數(shù)字
所以我們所要做的就是對上面的元素在onDraw里分別繪制:
[html] view plain copy print ?
@Override?? protected?void?onDraw(Canvas?canvas)?{?? ????super.onDraw(canvas);?? ????//?繪制外框?? ????drawOuter(canvas);?? ????//?繪制刻度線?? ????drawLines(canvas);?? ????//?繪制數(shù)字?? ????drawNumbers(canvas);?? }?? @Overrideprotected void onDraw(Canvas canvas) {super.onDraw(canvas);// 繪制外框drawOuter(canvas);// 繪制刻度線drawLines(canvas);// 繪制數(shù)字drawNumbers(canvas);}
咱們先簡單分析一下,刻度尺有個外框,外框距離左右都有一定的邊距,第一根和最后一根刻度線距離邊框也有一定的邊距,其余刻度線之間距離相同,另外一些特殊的刻度線長短不一;
有了上面的分析,咱們一個一個來,先繪制外框,外框也就是一個矩形,只需要確定邊框的位置和大小,然后使用canvas.drawRect( )繪制即可:
咱們先定義幾個需要的數(shù)據(jù),為了屏幕適配,數(shù)據(jù)均為dp:
[html] view plain copy print ?
//?刻度尺高度?? private?static?final?int?DIVIDING_RULE_HEIGHT ?=?70 ;?? //?距離左右間?? private?static?final?int?DIVIDING_RULE_MARGIN_LEFT_RIGHT ?=?10 ;?? ?? //?第一條線距離邊框距離?? private?static?final?int?FIRST_LINE_MARGIN ?=?5 ;?? //?打算繪制的厘米數(shù)?? private?static?final?int?DEFAULT_COUNT ?=?9 ;?? // 刻度尺高度private static final int DIVIDING_RULE_HEIGHT = 70;// 距離左右間private static final int DIVIDING_RULE_MARGIN_LEFT_RIGHT = 10;// 第一條線距離邊框距離private static final int FIRST_LINE_MARGIN = 5;// 打算繪制的厘米數(shù)private static final int DEFAULT_COUNT = 9;
然后將以上數(shù)據(jù)轉(zhuǎn)為對應(yīng)像素值:
[html] view plain copy print ?
private?void?initData()?{?? ????mDividRuleHeight ?=?(int)?TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP,?? ????????????DIVIDING_RULE_HEIGHT,?mResources.getDisplayMetrics());?? ????mHalfRuleHeight ?=?mDividRuleHeight ?/?2;?? ?? ????mDividRuleLeftMargin ?=?(int)?TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP,?? ????????????DIVIDING_RULE_MARGIN_LEFT_RIGHT,?mResources.getDisplayMetrics());?? ????mFirstLineMargin ?=?(int)?TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP,?? ????????????FIRST_LINE_MARGIN,?mResources.getDisplayMetrics());?? ?? }?? private void initData() {mDividRuleHeight = (int) TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP,DIVIDING_RULE_HEIGHT, mResources.getDisplayMetrics());mHalfRuleHeight = mDividRuleHeight / 2;mDividRuleLeftMargin = (int) TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP,DIVIDING_RULE_MARGIN_LEFT_RIGHT, mResources.getDisplayMetrics());mFirstLineMargin = (int) TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP,FIRST_LINE_MARGIN, mResources.getDisplayMetrics());}
有了以上數(shù)據(jù),則可以確定外邊框的Rect為:
[html] view plain copy print ?
mOutRect ?=?new ?Rect(mDividRuleLeftMargin,?top,?mTotalWidth?-?mDividRuleLeftMargin,??????????????????mRuleBottom);?? mOutRect = new Rect(mDividRuleLeftMargin, top, mTotalWidth - mDividRuleLeftMargin,mRuleBottom);
接下來看刻度線的繪制,根據(jù)厘米可以計算出中間的格數(shù),根據(jù)厘米占用屏幕寬度和所占格數(shù)可以計算出每一格所占屏幕寬度:
[html] view plain copy print ?
mLineInterval ?=?(mTotalWidth?-?2?*?mDividRuleLeftMargin?-?2?*?mFirstLineMargin)??????????????????/?(DEFAULT_COUNT?*?10?-?1);?? mLineInterval = (mTotalWidth - 2 * mDividRuleLeftMargin - 2 * mFirstLineMargin)/ (DEFAULT_COUNT * 10 - 1);
有了每一格所占寬度,我們只需要在繪制刻度線的時候不斷將畫布右移對應(yīng)寬度即可:
[html] view plain copy print ?
/**?? ?*?繪制刻度線?? ?*?@param?canvas?? ?*/?? private?void?drawLines(Canvas?canvas)?{?? ????canvas.save();?? ????canvas.translate(mLineStartX,?0);?? ????int?top ?=?mMaxLineTop ;?? ????for?(int?i ?=?0 ;?i?< =?DEFAULT_COUNT?*?10;?i++)?{?? ????????if?(i?%?10 ?==?0)?{?? ????????????top ?=?mMaxLineTop ;?? ????????}?else?if?(i?%?5 ?==?0)?{?? ????????????top ?=?mMiddleLineTop ;?? ????????}?else?{?? ????????????top ?=?mMinLineTop ;?? ????????}?? ?? ????????canvas.drawLine(0,?mRuleBottom,?0,?top,?mLinePaint);?? ????????canvas.translate(mLineInterval,?0);?? ?? ????}?? ????canvas.restore();?? ?? }?? /*** 繪制刻度線* @param canvas*/private void drawLines(Canvas canvas) {canvas.save();canvas.translate(mLineStartX, 0);int top = mMaxLineTop;for (int i = 0; i <= DEFAULT_COUNT * 10; i++) {if (i % 10 == 0) {top = mMaxLineTop;} else if (i % 5 == 0) {top = mMiddleLineTop;} else {top = mMinLineTop;}canvas.drawLine(0, mRuleBottom, 0, top, mLinePaint);canvas.translate(mLineInterval, 0);}canvas.restore();}
由于刻度尺上分三種長短的刻度線,我們也做對應(yīng)處理,10的整數(shù)倍的刻度線最長,5的整數(shù)倍的刻度線中等長度,其余較短; 此時繪制出的刻度尺效果為:
此時刻度尺的基本樣子就出來了,對應(yīng)文字大家有興趣可以自己加上;
俗話說,條條大路通羅馬,我們除了使用canvas.translate ,還能不能使用別的方式進行實現(xiàn)呢,答案當(dāng)然是可以,比如在繪制的時候根據(jù)for循環(huán)里的 i 值也可以直接計算出每一根刻度線的位置,然后直接進行繪制,相比之下,這兩種方式的優(yōu)劣大家也可以自行比較一下,好了,canvas.translate() 就說這么多;
二、canvas.scale( ) - 畫布的縮放:
關(guān)于scale,Android 提供了以下兩個接口:
[html] view plain copy print ?
/**?? ?*?Preconcat?the?current?matrix?with?the?specified?scale.?? ?*?? ?*?@param?sx?The?amount?to?scale?in?X?? ?*?@param?sy?The?amount?to?scale?in?Y?? ?*/?? public?native?void?scale(float?sx,?float?sy);?? ?? /**?? ?*?Preconcat?the?current?matrix?with?the?specified?scale.?? ?*?? ?*?@param?sx?The?amount?to?scale?in?X?? ?*?@param?sy?The?amount?to?scale?in?Y?? ?*?@param?px?The?x-coord?for?the?pivot?point?(unchanged?by?the?scale)?? ?*?@param?py?The?y-coord?for?the?pivot?point?(unchanged?by?the?scale)?? ?*/?? public?final?void?scale(float?sx,?float?sy,?float?px,?float?py)?{?? ????translate(px,?py);?? ????scale(sx,?sy);?? ????translate(-px,?-py);?? }?? /*** Preconcat the current matrix with the specified scale.** @param sx The amount to scale in X* @param sy The amount to scale in Y*/public native void scale(float sx, float sy);/*** Preconcat the current matrix with the specified scale.** @param sx The amount to scale in X* @param sy The amount to scale in Y* @param px The x-coord for the pivot point (unchanged by the scale)* @param py The y-coord for the pivot point (unchanged by the scale)*/public final void scale(float sx, float sy, float px, float py) {translate(px, py);scale(sx, sy);translate(-px, -py);}
我們先看下scale(float sx , float sy),我們還是以上面的正方形作為栗子,調(diào)用canvas.scale(float sx , float sy)之后看下效果;
[html] view plain copy print ?
@Override?? protected?void?onDraw(Canvas?canvas)?{?? ????super.onDraw(canvas);?? ????canvas.drawColor(Color.BLUE);?? ????canvas.drawRect(new?Rect(0,?0,?400,?400),?mPaint);?? ????canvas.scale(0.5f,?0.5f);?? ????mPaint.setColor(Color.YELLOW);?? ????canvas.drawRect(new?Rect(0,?0,?400,?400),?mPaint);?? }?? @Overrideprotected void onDraw(Canvas canvas) {super.onDraw(canvas);canvas.drawColor(Color.BLUE);canvas.drawRect(new Rect(0, 0, 400, 400), mPaint);canvas.scale(0.5f, 0.5f);mPaint.setColor(Color.YELLOW);canvas.drawRect(new Rect(0, 0, 400, 400), mPaint);}
我們將畫布在x,y方向上均縮放為 0.5 倍,使用默認(rèn)基準(zhǔn)點(原點 0,0),效果如下:
效果就相當(dāng)于用個釘子釘在(0,0)處,然后把矩形的x,y縮放為一半,我們再來看看第二個接口scale(float sx , float sy, float px,float py):
前兩個參數(shù)為將畫布在x、y方向上縮放的倍數(shù),而px和py 分別為縮放的基準(zhǔn)點,從源碼上可以非常清楚的看出和scale(float sx , float sy)的差別:
[html] view plain copy print ?
translate(px,?py);?? scale(sx,?sy);?? translate(-px,?-py);?? translate(px, py);
scale(sx, sy);
translate(-px, -py);
即先將畫布平移px,py,然后scale,scale結(jié)束之后再將畫布平移回原基準(zhǔn)點;
我們再在之前的基礎(chǔ)上繪制一個同樣的矩形,x , y 均縮放為 0.5 倍,縮放中心為矩形的中心:
[html] view plain copy print ?
@Override?? protected?void?onDraw(Canvas?canvas)?{?? ????super.onDraw(canvas);?? ????canvas.drawColor(Color.BLUE);?? ????canvas.drawRect(new?Rect(0,?0,?400,?400),?mPaint);?? ?? ????//?保存畫布狀態(tài)?? ????canvas.save();?? ????canvas.scale(0.5f,?0.5f);?? ????mPaint.setColor(Color.YELLOW);?? ????canvas.drawRect(new?Rect(0,?0,?400,?400),?mPaint);?? ????//?畫布狀態(tài)回滾?? ????canvas.restore();?? ?? ????canvas.scale(0.5f,?0.5f,?200,?200);?? ????mPaint.setColor(Color.BLACK);?? ????canvas.drawRect(new?Rect(0,?0,?400,?400),?mPaint);?? }?? @Overrideprotected void onDraw(Canvas canvas) {super.onDraw(canvas);canvas.drawColor(Color.BLUE);canvas.drawRect(new Rect(0, 0, 400, 400), mPaint);// 保存畫布狀態(tài)canvas.save();canvas.scale(0.5f, 0.5f);mPaint.setColor(Color.YELLOW);canvas.drawRect(new Rect(0, 0, 400, 400), mPaint);// 畫布狀態(tài)回滾canvas.restore();canvas.scale(0.5f, 0.5f, 200, 200);mPaint.setColor(Color.BLACK);canvas.drawRect(new Rect(0, 0, 400, 400), mPaint);}
一起來看下效果:
效果就相當(dāng)于用個釘子釘在矩形的中心,然后進行縮放;
根據(jù)上面android 的實現(xiàn),我們其實可以使用以下代碼實現(xiàn)同樣的效果:
[html] view plain copy print ?
//?先將畫布平移到矩形的中心?? canvas.translate(200,?200);?? //?將畫布進行縮放?? canvas.scale(0.5f,?0.5f);?? //?將畫布移回原基準(zhǔn)點?? canvas.translate(-200,?-200);?? mPaint.setColor(Color.BLACK);?? canvas.drawRect(new?Rect(0,?0,?400,?400),?mPaint);?? // 先將畫布平移到矩形的中心canvas.translate(200, 200);// 將畫布進行縮放canvas.scale(0.5f, 0.5f);// 將畫布移回原基準(zhǔn)點canvas.translate(-200, -200);mPaint.setColor(Color.BLACK);canvas.drawRect(new Rect(0, 0, 400, 400), mPaint);
到此為止,我們也就了解了對畫布的縮放,基于canvas.scale(),我們一起完成一個小例子:
上面是網(wǎng)絡(luò)上找的一張讓人產(chǎn)生視覺誤差的靜態(tài)圖,我們模擬繪制出上面的效果;
思路非常的簡單:
1. 繪制一個和屏幕等寬的正方形;
2. 將畫布以正方形中心為基準(zhǔn)點進行縮放;
3. 在縮放的過程中繪制原正方形;
注:每次繪制都得使用canvas.save() ?和 canvas.restore()進行畫布的鎖定和回滾,以免除對后面繪制的影響(后面會單獨講)
先初始化畫筆,注意此時畫筆需要設(shè)置成空心:
[html] view plain copy print ?
/**?? ?*?初始化畫筆?? ?*/?? private?void?initPaint()?{?? ????mPaint ?=?new ?Paint(Paint.ANTI_ALIAS_FLAG);?? ????//?將畫筆設(shè)置為空心?? ????mPaint.setStyle(Style.STROKE);?? ????//?設(shè)置畫筆顏色?? ????mPaint.setColor(Color.BLACK);?? ????//?設(shè)置畫筆寬度?? ????mPaint.setStrokeWidth(mLineWidth);?? }?? /*** 初始化畫筆*/private void initPaint() {mPaint = new Paint(Paint.ANTI_ALIAS_FLAG);// 將畫筆設(shè)置為空心mPaint.setStyle(Style.STROKE);// 設(shè)置畫筆顏色mPaint.setColor(Color.BLACK);// 設(shè)置畫筆寬度mPaint.setStrokeWidth(mLineWidth);}
然后循環(huán)的將畫布縮放的同時繪制原正方形:
[html] view plain copy print ?
/**?? ?*?繪制正方形?? ?*??? ?*?@param?canvas?? ?*/?? private?void?drawSquare(Canvas?canvas)?{?? ????for?(int?i ?=?0 ;?i?< ?TOTAL_SQUARE_COUNT ;?i++)?{?? ????????//?保存畫布?? ????????canvas.save();?? ????????float?fraction ?=?(float)?i?/?TOTAL_SQUARE_COUNT;?? ????????//?將畫布以正方形中心進行縮放?? ????????canvas.scale(fraction,?fraction,?mHalfWidth,?mHalfHeight);?? ????????canvas.drawRect(mSquareRect,?mPaint);?? ????????//?畫布回滾?? ????????canvas.restore();?? ????}?? }?? /*** 繪制正方形* * @param canvas*/private void drawSquare(Canvas canvas) {for (int i = 0; i < TOTAL_SQUARE_COUNT; i++) {// 保存畫布canvas.save();float fraction = (float) i / TOTAL_SQUARE_COUNT;// 將畫布以正方形中心進行縮放canvas.scale(fraction, fraction, mHalfWidth, mHalfHeight);canvas.drawRect(mSquareRect, mPaint);// 畫布回滾canvas.restore();}}
一起來看下繪制的效果:
其實最終效果和網(wǎng)上找的還是有點小差別的,由于畫布的縮放,越小的時候畫筆寬度越細(xì),而原圖是所有的都一樣寬度,但似乎畫筆寬度縮放之后效果更佳,哈哈 ... ... ?
三、canvas.rotate( ) - 畫布的旋轉(zhuǎn):
canvas.rotate( )和canvas.scale()可以類比起來看,如果理解了canvas.scale( ),那么canvas.rotate( )將會非常簡單實用;
簡單來講,canvas.rotate( )即是將畫布進行旋轉(zhuǎn),和canvas.scale( )類似的是,它也有兩個可以使用的方法:
[html] view plain copy print ?
/**?? ?*?Preconcat?the?current?matrix?with?the?specified?rotation.?? ?*?? ?*?@param?degrees?The?amount?to?rotate,?in?degrees?? ?*/?? public?native?void?rotate(float?degrees);?? ?? /**?? ?*?Preconcat?the?current?matrix?with?the?specified?rotation.?? ?*?? ?*?@param?degrees?The?amount?to?rotate,?in?degrees?? ?*?@param?px?The?x-coord?for?the?pivot?point?(unchanged?by?the?rotation)?? ?*?@param?py?The?y-coord?for?the?pivot?point?(unchanged?by?the?rotation)?? ?*/?? public?final?void?rotate(float?degrees,?float?px,?float?py)?{?? ????translate(px,?py);?? ????rotate(degrees);?? ????translate(-px,?-py);?? }?? /*** Preconcat the current matrix with the specified rotation.** @param degrees The amount to rotate, in degrees*/public native void rotate(float degrees);/*** Preconcat the current matrix with the specified rotation.** @param degrees The amount to rotate, in degrees* @param px The x-coord for the pivot point (unchanged by the rotation)* @param py The y-coord for the pivot point (unchanged by the rotation)*/public final void rotate(float degrees, float px, float py) {translate(px, py);rotate(degrees);translate(-px, -py);}
兩個方法的區(qū)別也是在于基準(zhǔn)點的選取,默認(rèn)是以原點作為基準(zhǔn)點,另一個則是以傳入的x,y 作為基準(zhǔn)點,是不是和scale 一模一樣,咱們一起來rotate一下:
咱們先轉(zhuǎn)轉(zhuǎn)左上角的矩形,轉(zhuǎn)多少度呢?先來個90度玩玩吧;
[html] view plain copy print ?
@Override?? protected?void?onDraw(Canvas?canvas)?{?? ????super.onDraw(canvas);?? ????canvas.drawColor(Color.BLUE);?? ????canvas.drawRect(new?Rect(0,?0,?400,?400),?mPaint);?? ????mPaint.setColor(Color.YELLOW);?? ????canvas.rotate(90);?? ????canvas.drawRect(new?Rect(0,?0,?400,?400),?mPaint);?? }?? @Overrideprotected void onDraw(Canvas canvas) {super.onDraw(canvas);canvas.drawColor(Color.BLUE);canvas.drawRect(new Rect(0, 0, 400, 400), mPaint);mPaint.setColor(Color.YELLOW);canvas.rotate(90);canvas.drawRect(new Rect(0, 0, 400, 400), mPaint);}
我們的預(yù)期是屏幕上有個旋轉(zhuǎn)了的騷黃色矩形,一起來看看;
擦,黃色的矩形呢?
由于基準(zhǔn)點是原點,我們直接旋轉(zhuǎn)了90 度,所以已經(jīng)將矩形旋轉(zhuǎn)出屏幕,當(dāng)然看不到了,我們將角度調(diào)小一點,改為45 度:
[html] view plain copy print ?
@Override?? protected?void?onDraw(Canvas?canvas)?{?? ????super.onDraw(canvas);?? ????canvas.drawColor(Color.BLUE);?? ????canvas.drawRect(new?Rect(0,?0,?400,?400),?mPaint);?? ????mPaint.setColor(Color.YELLOW);?? ????canvas.rotate(45);?? ????canvas.drawRect(new?Rect(0,?0,?400,?400),?mPaint);?? }?? @Overrideprotected void onDraw(Canvas canvas) {super.onDraw(canvas);canvas.drawColor(Color.BLUE);canvas.drawRect(new Rect(0, 0, 400, 400), mPaint);mPaint.setColor(Color.YELLOW);canvas.rotate(45);canvas.drawRect(new Rect(0, 0, 400, 400), mPaint);}
此時我們可以可以清楚的看到黃色的矩形是紅色矩形繞原點(0,0)旋轉(zhuǎn)45度之后的結(jié)果;
我們再將旋轉(zhuǎn)基準(zhǔn)點改為矩形中心看看:
[html] view plain copy print ?
canvas.rotate(45,200,200);?? canvas.rotate(45,200,200);
可以看到現(xiàn)在黃色矩形是紅色矩形繞著中心旋轉(zhuǎn)后的結(jié)果:
到這里,我們已經(jīng)了解了canvas.rotate(float degrees)和 canvas.rotate(float degrees,float px , float py)的使用,同樣也應(yīng)該清楚后者的實現(xiàn)如下:
[html] view plain copy print ?
translate(px,?py);?? rotate(degrees);?? translate(-px,?-py);?? translate(px, py);
rotate(degrees);
translate(-px, -py);
好了,我們再利用canvas.rotate()完成個鬧鐘表盤的小例子:
鬧鐘表盤其實和刻度尺類似,只是一個是在一條直線上繪制,一個是在一個圓周上繪制,說到底都是確定一個位置繪制刻度線;
既然是圓周,最簡單的方式莫過于在鬧鐘的12點鐘處劃線,通過canvas的旋轉(zhuǎn)繪制到對應(yīng)圓周處,我們一起實現(xiàn)一下:
整個圓周是360 度,每隔 30 度為一個整時間刻度,整刻度與刻度之間有四個短刻度,劃分出5個小段,每個段為6度,有了這些分析,我們則可以采用如下代碼進行繪制:
[html] view plain copy print ?
/**?? ?*?繪制刻度?? ?*??? ?*?@param?canvas?? ?*/?? private?void?drawLines(Canvas?canvas)?{?? ????for?(int?i ?=?0 ;?i?< =?360;?i++)?{?? ????????if?(i?%?30 ?==?0)?{?? ????????????mLineBottom ?=?mLineTop ?+?mLongLineHeight;?? ????????????mLinePaint.setStrokeWidth(mLineWidth);?? ????????}?else?{?? ????????????mLineBottom ?=?mLineTop ?+?mShortLineHeight;?? ????????????mLinePaint.setStrokeWidth(mHalfLineWidth);?? ????????}?? ?? ????????if?(i?%?6 ?==?0)?{?? ????????????canvas.save();?? ????????????canvas.rotate(i,?mHalfWidth,?mHalfHeight);?? ????????????canvas.drawLine(mLineLeft,?mLineTop,?mLineLeft,?mLineBottom,?mLinePaint);?? ????????????canvas.restore();?? ????????}?? ????}?? }?? /*** 繪制刻度* * @param canvas*/private void drawLines(Canvas canvas) {for (int i = 0; i <= 360; i++) {if (i % 30 == 0) {mLineBottom = mLineTop + mLongLineHeight;mLinePaint.setStrokeWidth(mLineWidth);} else {mLineBottom = mLineTop + mShortLineHeight;mLinePaint.setStrokeWidth(mHalfLineWidth);}if (i % 6 == 0) {canvas.save();canvas.rotate(i, mHalfWidth, mHalfHeight);canvas.drawLine(mLineLeft, mLineTop, mLineLeft, mLineBottom, mLinePaint);canvas.restore();}}}
此時效果如下:
整體代碼如下:
[html] view plain copy print ?
/**?? ?*?鬧鐘表盤?? ?*??? ?*?@author?AJian?? ?*/?? public?class?RotateClockView?extends?View?{?? ?? ????private?static?final?int?LONG_LINE_HEIGHT ?=?35 ;?? ????private?static?final?int?SHORT_LINE_HEIGHT ?=?25 ;?? ????private?Paint?mCirclePaint,?mLinePaint;?? ????private?DrawFilter?mDrawFilter;?? ????private?int?mHalfWidth,?mHalfHeight;?? ?? ????//?圓環(huán)線寬度?? ????private?int?mCircleLineWidth,?mHalfCircleLineWidth;?? ????//?直線刻度線寬度?? ????private?int?mLineWidth,?mHalfLineWidth;?? ????//?長線長度?? ????private?int?mLongLineHeight;?? ????//?短線長度?? ????private?int?mShortLineHeight;?? ????//?刻度線的左、上位置?? ????private?int?mLineLeft,?mLineTop;?? ?? ????//?刻度線的下邊位置?? ????private?int?mLineBottom;?? ????//?用于控制刻度線位置?? ????private?int?mFixLineHeight;?? ?? ????public?RotateClockView(Context?context)?{?? ????????super(context);?? ????????mDrawFilter ?=?new ?PaintFlagsDrawFilter(0,?Paint.ANTI_ALIAS_FLAG?? ????????????????|?Paint.FILTER_BITMAP_FLAG);?? ?? ????????mCircleLineWidth ?=?(int)?TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP,?8,?? ????????????????getResources().getDisplayMetrics());?? ????????mHalfCircleLineWidth ?=?mCircleLineWidth ;?? ????????mLineWidth ?=?(int)?TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP,?4,?? ????????????????getResources().getDisplayMetrics());?? ????????mHalfLineWidth ?=?mLineWidth ?/?2;?? ?? ????????mFixLineHeight ?=?(int)?TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP,?4,?? ????????????????getResources().getDisplayMetrics());?? ?? ????????mLongLineHeight ?=?(int)?TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP,?? ????????????????LONG_LINE_HEIGHT,?? ????????????????getResources().getDisplayMetrics());?? ????????mShortLineHeight ?=?(int)?TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP,?? ????????????????SHORT_LINE_HEIGHT,?? ????????????????getResources().getDisplayMetrics());?? ????????initPaint();?? ????}?? ?? ????private?void?initPaint()?{?? ????????mCirclePaint ?=?new ?Paint(Paint.ANTI_ALIAS_FLAG);?? ????????mCirclePaint.setColor(Color.RED);?? ????????//?將畫筆設(shè)置為空心?? ????????mCirclePaint.setStyle(Style.STROKE);?? ????????//?設(shè)置畫筆寬度?? ????????mCirclePaint.setStrokeWidth(mCircleLineWidth);?? ?? ????????mLinePaint ?=?new ?Paint(Paint.ANTI_ALIAS_FLAG);?? ????????mLinePaint.setColor(Color.RED);?? ????????mLinePaint.setStyle(Style.FILL_AND_STROKE);?? ????????//?設(shè)置畫筆寬度?? ????????mLinePaint.setStrokeWidth(mLineWidth);?? ????}?? ?? ????@Override?? ????protected?void?onMeasure(int?widthMeasureSpec,?int?heightMeasureSpec)?{?? ????????super.onMeasure(widthMeasureSpec,?heightMeasureSpec);?? ????}?? ?? ????@Override?? ????protected?void?onDraw(Canvas?canvas)?{?? ????????canvas.setDrawFilter(mDrawFilter);?? ????????super.onDraw(canvas);?? ????????//?繪制表盤?? ????????drawCircle(canvas);?? ????????//?繪制刻度?? ????????drawLines(canvas);?? ????}?? ?? ????/**?? ?????*?繪制刻度?? ?????*??? ?????*?@param?canvas?? ?????*/?? ????private?void?drawLines(Canvas?canvas)?{?? ????????for?(int?i ?=?0 ;?i?< =?360;?i++)?{?? ????????????if?(i?%?30 ?==?0)?{?? ????????????????mLineBottom ?=?mLineTop ?+?mLongLineHeight;?? ????????????????mLinePaint.setStrokeWidth(mLineWidth);?? ????????????}?else?{?? ????????????????mLineBottom ?=?mLineTop ?+?mShortLineHeight;?? ????????????????mLinePaint.setStrokeWidth(mHalfLineWidth);?? ????????????}?? ?? ????????????if?(i?%?6 ?==?0)?{?? ????????????????canvas.save();?? ????????????????canvas.rotate(i,?mHalfWidth,?mHalfHeight);?? ????????????????canvas.drawLine(mLineLeft,?mLineTop,?mLineLeft,?mLineBottom,?mLinePaint);?? ????????????????canvas.restore();?? ????????????}?? ????????}?? ????}?? ?? ????/**?? ?????*?繪制表盤?? ?????*??? ?????*?@param?canvas?? ?????*/?? ????private?void?drawCircle(Canvas?canvas)?{?? ????????canvas.drawCircle(mHalfWidth,?mHalfHeight,?mHalfWidth?-?mHalfCircleLineWidth,?mCirclePaint);?? ????}?? ?? ????@Override?? ????protected?void?onSizeChanged(int?w,?int?h,?int?oldw,?int?oldh)?{?? ????????super.onSizeChanged(w,?h,?oldw,?oldh);?? ????????mHalfWidth ?=?w ?/?2;?? ????????mHalfHeight ?=?h ?/?2;?? ?? ????????mLineLeft ?=?mHalfWidth ?-?mHalfLineWidth;?? ????????mLineTop ?=?mHalfHeight ?-?mHalfWidth?+?mFixLineHeight;?? ????}?? }?? /*** 鬧鐘表盤* * @author AJian*/
public class RotateClockView extends View {private static final int LONG_LINE_HEIGHT = 35;private static final int SHORT_LINE_HEIGHT = 25;private Paint mCirclePaint, mLinePaint;private DrawFilter mDrawFilter;private int mHalfWidth, mHalfHeight;// 圓環(huán)線寬度private int mCircleLineWidth, mHalfCircleLineWidth;// 直線刻度線寬度private int mLineWidth, mHalfLineWidth;// 長線長度private int mLongLineHeight;// 短線長度private int mShortLineHeight;// 刻度線的左、上位置private int mLineLeft, mLineTop;// 刻度線的下邊位置private int mLineBottom;// 用于控制刻度線位置private int mFixLineHeight;public RotateClockView(Context context) {super(context);mDrawFilter = new PaintFlagsDrawFilter(0, Paint.ANTI_ALIAS_FLAG| Paint.FILTER_BITMAP_FLAG);mCircleLineWidth = (int) TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, 8,getResources().getDisplayMetrics());mHalfCircleLineWidth = mCircleLineWidth;mLineWidth = (int) TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, 4,getResources().getDisplayMetrics());mHalfLineWidth = mLineWidth / 2;mFixLineHeight = (int) TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, 4,getResources().getDisplayMetrics());mLongLineHeight = (int) TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP,LONG_LINE_HEIGHT,getResources().getDisplayMetrics());mShortLineHeight = (int) TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP,SHORT_LINE_HEIGHT,getResources().getDisplayMetrics());initPaint();}private void initPaint() {mCirclePaint = new Paint(Paint.ANTI_ALIAS_FLAG);mCirclePaint.setColor(Color.RED);// 將畫筆設(shè)置為空心mCirclePaint.setStyle(Style.STROKE);// 設(shè)置畫筆寬度mCirclePaint.setStrokeWidth(mCircleLineWidth);mLinePaint = new Paint(Paint.ANTI_ALIAS_FLAG);mLinePaint.setColor(Color.RED);mLinePaint.setStyle(Style.FILL_AND_STROKE);// 設(shè)置畫筆寬度mLinePaint.setStrokeWidth(mLineWidth);}@Overrideprotected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {super.onMeasure(widthMeasureSpec, heightMeasureSpec);}@Overrideprotected void onDraw(Canvas canvas) {canvas.setDrawFilter(mDrawFilter);super.onDraw(canvas);// 繪制表盤drawCircle(canvas);// 繪制刻度drawLines(canvas);}/*** 繪制刻度* * @param canvas*/private void drawLines(Canvas canvas) {for (int i = 0; i <= 360; i++) {if (i % 30 == 0) {mLineBottom = mLineTop + mLongLineHeight;mLinePaint.setStrokeWidth(mLineWidth);} else {mLineBottom = mLineTop + mShortLineHeight;mLinePaint.setStrokeWidth(mHalfLineWidth);}if (i % 6 == 0) {canvas.save();canvas.rotate(i, mHalfWidth, mHalfHeight);canvas.drawLine(mLineLeft, mLineTop, mLineLeft, mLineBottom, mLinePaint);canvas.restore();}}}/*** 繪制表盤* * @param canvas*/private void drawCircle(Canvas canvas) {canvas.drawCircle(mHalfWidth, mHalfHeight, mHalfWidth - mHalfCircleLineWidth, mCirclePaint);}@Overrideprotected void onSizeChanged(int w, int h, int oldw, int oldh) {super.onSizeChanged(w, h, oldw, oldh);mHalfWidth = w / 2;mHalfHeight = h / 2;mLineLeft = mHalfWidth - mHalfLineWidth;mLineTop = mHalfHeight - mHalfWidth + mFixLineHeight;}
}
同樣的,有興趣的同學(xué)可以自己補上文字;
四、canvas.skew( ) - 畫布的錯切:?
[html] view plain copy print ?
/**?? ?*?Preconcat?the?current?matrix?with?the?specified?skew.?? ?*?? ?*?@param?sx?The?amount?to?skew?in?X?? ?*?@param?sy?The?amount?to?skew?in?Y?? ?*/?? public?native?void?skew(float?sx,?float?sy);?? /*** Preconcat the current matrix with the specified skew.** @param sx The amount to skew in X* @param sy The amount to skew in Y*/public native void skew(float sx, float sy);
這個方法只要理解了兩個參數(shù)即可:
float sx:將畫布在x方向上傾斜相應(yīng)的角度,sx為傾斜角度的tan值;
float sy:將畫布在y軸方向上傾斜相應(yīng)的角度,sy為傾斜角度的tan值;
注意,這里全是傾斜角度的tan值,比如我們打算在X軸方向上傾斜45度,tan45=1;
先在X 軸上傾斜45 度,我們一起看看:
[html] view plain copy print ?
@Override?? protected?void?onDraw(Canvas?canvas)?{?? ????super.onDraw(canvas);?? ????canvas.drawColor(Color.BLUE);?? ????canvas.drawRect(new?Rect(0,?0,?400,?400),?mPaint);?? ?? ????//?x?方向上傾斜45?度?? ????canvas.skew(1,?0);?? ????mPaint.setColor(0x8800ff00);?? ????canvas.drawRect(new?Rect(0,?0,?400,?400),?mPaint);?? }?? @Overrideprotected void onDraw(Canvas canvas) {super.onDraw(canvas);canvas.drawColor(Color.BLUE);canvas.drawRect(new Rect(0, 0, 400, 400), mPaint);// x 方向上傾斜45 度canvas.skew(1, 0);mPaint.setColor(0x8800ff00);canvas.drawRect(new Rect(0, 0, 400, 400), mPaint);}
效果如下:
再在y軸上傾斜45度看看:
[html] view plain copy print ?
@Override?? protected?void?onDraw(Canvas?canvas)?{?? ????super.onDraw(canvas);?? ????canvas.drawColor(Color.BLUE);?? ????canvas.drawRect(new?Rect(0,?0,?400,?400),?mPaint);?? ?? ????//?y?方向上傾斜45?度?? ????canvas.skew(0,?1);?? ????mPaint.setColor(0x8800ff00);?? ????canvas.drawRect(new?Rect(0,?0,?400,?400),?mPaint);?? }?? @Overrideprotected void onDraw(Canvas canvas) {super.onDraw(canvas);canvas.drawColor(Color.BLUE);canvas.drawRect(new Rect(0, 0, 400, 400), mPaint);// y 方向上傾斜45 度canvas.skew(0, 1);mPaint.setColor(0x8800ff00);canvas.drawRect(new Rect(0, 0, 400, 400), mPaint);}
此時效果如下:
關(guān)于Canvas(畫布)的translate(平移)、scale(縮放) 、rotate(旋轉(zhuǎn)) 、skew(錯切)就說這么多,這些方法都不復(fù)雜,而靈活的使用往往能解決繪制中很多看似復(fù)雜的問題,所以重在理解,并在看到與之相關(guān)的效果時能夠及時恰當(dāng)?shù)倪M行關(guān)聯(lián)。
當(dāng)然對Canvas的操作往往使用Matrix(后面會單獨講)也能達到同樣的效果,想看例子可參考? 一個絢麗的loading動效分析與實現(xiàn)!
源碼下載鏈接
<script>window._bd_share_config = { "common": { "bdSnsKey": {}, "bdText": "", "bdMini": "1", "bdMiniList": false, "bdPic": "", "bdStyle": "0", "bdSize": "16" }, "share": {} }; with (document) 0[(getElementsByTagName('head')[0] || body).appendChild(createElement('script')).src = 'http://bdimg.share.baidu.com/static/api/js/share.js?v=89860593.js?cdnversion=' + ~(-new Date() / 36e5)];</script> rel="stylesheet" href="http://static.blog.csdn.net/css/blog_detail.css" /> <script type="text/javascript" id="bdshare_js" data="type=tools&uid=1536434" src="http://bdimg.share.baidu.com/static/js/bds_s_v2.js?cdnversion=410647"></script><script type="text/javascript">document.getElementById("bdshell_js").src = "http://bdimg.share.baidu.com/static/js/shell_v2.js?cdnversion=" + Math.ceil(new Date()/3600000)</script> 頂
15 踩
2 <script type="text/javascript">function btndigga() { $(".tracking-ad[data-mod='popu_222'] a").click(); } function btnburya() { $(".tracking-ad[data-mod='popu_223'] a").click(); }</script>
上一篇Android 漂浮類動效的分析與實現(xiàn)! 下一篇Path相關(guān)方法講解(一) 我的同類文章 android動效篇(12) http://blog.csdn.net
?Path特效之PathMeasure打造萬能路徑動效2015-07-26閱讀8378 ?Path相關(guān)方法講解(一)2015-06-15閱讀6706 ?Canvas開篇之drawBitmap方法講解2015-04-14閱讀22155 ?Android使用SVG矢量圖打造酷炫動效!2015-03-31閱讀36646 ?Paint、Canvas、Matrix使用講解(一、Paint)2015-03-18閱讀11862 ?Path相關(guān)方法講解(二)2015-07-19閱讀3457 ?Android 漂浮類動效的分析與實現(xiàn)!2015-04-22閱讀6852 ?Android Paint之 setXfermode PorterDuffXfermode 講解2015-04-07閱讀13335 ?一個絢麗的loading動效分析與實現(xiàn)!2015-03-23閱讀30643 ?自定義view實現(xiàn)水波紋效果2015-03-12閱讀14176 更多文章 <script type="text/javascript">$(function () { GetCategoryArticles('2873607', 'tianjian4592','foot','45234419'); });</script> <script language="javascript" type="text/javascript">$(function(){ $.get("/tianjian4592/svc/GetSuggestContent/45234419",function(data){ $("#suggest").html(data); }); });</script> .blog-ass-articl dd {
color: #369;
width: 99%; /*修改行*/
float: left;
overflow: hidden;
font: normal normal 12px/23px "SimSun";
height: 23px;
margin: 0;
padding: 0 0 0 10px;
margin-right: 30px;
background: url(http://static.blog.csdn.net/skin/default/images/blog-dot-red3.gif) no-repeat 0 10px;
} rel="stylesheet" href="http://static.blog.csdn.net/css/replace.css" />
參考知識庫 .NET知識庫 1387關(guān)注|800收錄
Android知識庫 21013關(guān)注|1809收錄
更多資料請參考: 猜你在找 <script src="http://csdnimg.cn/jobreco/job_reco.js" type="text/javascript"></script> <script type="text/javascript">csdn.position.showEdu({ sourceType: "blog", searchType: "detail", searchKey: "45234419", username: "", recordcount: "5", containerId: "adCollege" //容器DIV的id。 });</script>
解析移動應(yīng)用的身份認(rèn)證, 數(shù)據(jù)分析及信息推送 TalkingData研發(fā)副總裁閻志濤:Spark在TalkingData移動大數(shù)據(jù)平臺的實踐 WEB開發(fā):拉鉤網(wǎng)遮罩移動效果 如何打造移動環(huán)境下滿足業(yè)務(wù)場景的高可用架構(gòu) 移動直播技術(shù)專場:百萬彈幕下的直播禮物系統(tǒng) 移動端干貨 移動開發(fā) 這個項目收集移動端開發(fā)所需要的一些資源與小技巧 Android自定義繪制 手機那點事已有高人把常見的不常見的坑都給找出來了我就隨便轉(zhuǎn)一下了 <script type="text/javascript">$(function () { setTimeout(function () { var searchtitletags = 'Canvas之translate、scale、rotate、skew方法講解!' + ',' + $("#tags").html(); searchService({ index: 'blog', query: searchtitletags, from: 5, size: 5, appendTo: '#res', url: 'recommend', his: 2, client: "blog_cf_enhance", tmpl: '
#{ title } ' }); }, 500); });</script> <script src="//pagead2.googlesyndication.com/pagead/js/adsbygoogle.js"></script> width="728" height="90" frameborder="0" marginwidth="0" marginheight="0" vspace="0" hspace="0" allowtransparency="true" scrolling="no" allowfullscreen="true" οnlοad="var i=this.id,s=window.google_iframe_oncopy,H=s&&s.handlers,h=H&&H[i],w=this.contentWindow,d;try{d=w.document}catch(e){}if(h&&d&&(!d.body||!d.body.firstChild)){if(h.call){setTimeout(h,0)}else if(h.match){try{h=s.upd(h,i)}catch(e){}w.location.replace(h)}}" id="aswift_0" name="aswift_0" style="left:0;position:absolute;top:0;"><script>(adsbygoogle=window.adsbygoogle || []).push({});</script> 10樓
又是美好一天 2016-09-07 21:03發(fā)表 [回復(fù)] “scale(float sx , float sy, float px,float py):先將畫布平移px,py,然后scale,scale結(jié)束之后再將畫布平移回原基準(zhǔn)點;我們再在之前的基礎(chǔ)上繪制一個同樣的矩形,x , y 均縮放為 0.5 倍,縮放中心為矩形的中心;”這句話的意思是縮放中心為矩形中心,那為什么canvas.scale(0.5f, 0.5f);畫布在x,y方向上均縮放為 0.5 倍,使用默認(rèn)基準(zhǔn)點(原點 0,0),而不是矩形中心呢? 9樓
code_river 2016-07-07 15:15發(fā)表 [回復(fù)] 感謝樓主分享 8樓
nailsoul 2016-03-29 23:30發(fā)表 [回復(fù)] 贊一個 通過該栗子搞懂了save和restore的意思了 謝謝樓主了 唉名字取的有奇異啊 xxState因該好理解點 7樓
FionaRyan 2016-03-25 17:11發(fā)表 [回復(fù)] # 2016一線互聯(lián)網(wǎng)名企集結(jié)號# #實習(xí)# “簡尋”聯(lián)合阿里、搜狗、百度音樂、小米、蘑菇街、鳳凰網(wǎng)等 20+ 一線互聯(lián)網(wǎng)公司舉辦2016技術(shù)實習(xí)專場活動,?200+技術(shù)實習(xí)崗,通過審核的可獲5-10 次名企面試推薦。 【報名方式】 1.活動報名地址:https://h5.jianxun.io開啟一鍵求職 2.搜索微信公眾號:jianxun-fuwu 【面向群體】 1. 實習(xí)生:2017 年及以后畢業(yè)的本科生/研究生,尋找技術(shù)類的 春季 / 暑期 實習(xí) 2. 應(yīng)屆生:2016 年應(yīng)屆畢業(yè)生 , 技術(shù)類工作 【活動時間】 3月15日 - 5月15日 注:春季/暑期實習(xí)皆可,具體事宜可與企業(yè)單獨商議 【簡尋提供】 1.??直接面試機會 一線企業(yè):阿里B2B、搜狗、蘑菇街、小米、豌豆莢 等 實力大牌:果殼網(wǎng)、人人、百度作業(yè)幫、鳳凰網(wǎng)、么么嗖?等 新銳團隊:長亭科技、酷家樂、云校、野糖、海智網(wǎng)聚 等 2. 活動福利 最優(yōu)秀的三名學(xué)生將獲活動協(xié)辦方—— 包子IT 免費提供得北美頂尖 IT公司(Microsoft、google、facebook、Linkedin、amazon等)工程師進行一對一的全英模擬面試+指導(dǎo),面試優(yōu)異者可直接獲得北美名企的內(nèi)推機會。 其他優(yōu)秀學(xué)生,包子IT 還將提供免費針對北美 CS 方向的模擬試題;頂尖公司和明星創(chuàng)業(yè)公司的多位老師們,將為大家講解 題目+背后線索,認(rèn)真閱讀每一份考卷、每一行代碼,幫助大家提高代碼結(jié)構(gòu)和質(zhì)量。 【活動流程】 1.???報名注冊 → 2.???簡歷審核 → 3.???電話面試 → 4. 企業(yè)推薦 → 5. 企業(yè)復(fù)面 → 6. 發(fā)放offer 6樓
yubaoma 2016-03-16 09:51發(fā)表 [回復(fù)] mark 5樓
xiaomingi07 2016-02-26 15:41發(fā)表 [回復(fù)] 介紹的東西太實用了,而且栗子也容易理解,一定要踩一下! 4樓
mr_gang1992 2016-01-21 16:54發(fā)表 [回復(fù)] 樓主在上面寫文字的時候,遇到一個問題,就是文字跟著畫布旋轉(zhuǎn)了,如何才能保證文字,文字不旋轉(zhuǎn)...望樓主解答啊。。。 Re:
學(xué)問積年而成 2016-01-21 17:37發(fā)表 [回復(fù)] 回復(fù)mr_gang1992:使用 canvas.save(); XXXX; canvas.restore(); 3樓
gongyong2008 2015-06-03 13:16發(fā)表 [回復(fù)] 大神帶我飛啊 2樓
kangGe_studio 2015-05-10 16:34發(fā)表 [回復(fù)] 贊一個 1樓
LFy_Yu 2015-05-08 09:10發(fā)表 [回復(fù)] 給力 您還沒有登錄,請 [登錄]或 [注冊] * 以上用戶言論只代表其個人觀點,不代表CSDN網(wǎng)站的觀點或立場 <script type="text/javascript">var fileName = '45234419'; var commentscount = 11; var islock = false</script><script type="text/javascript" src="http://static.blog.csdn.net/scripts/comment.js"></script> <script type="text/javascript">$(function () { $("#ad_frm_0").height("90px"); setTimeout(function(){ $("#ad_frm_2").height("200px"); },1000); });</script> .tag_list{background: none repeat scroll 0 0 #FFFFFF;border: 1px solid #D7CBC1;color: #000000;font-size: 12px;line-height: 20px;list-style: none outside none;margin: 10px 2% 0 1%;padding: 1px;}.tag_list h5{background: none repeat scroll 0 0 #E0DBD3;color: #47381C;font-size: 12px;height: 24px;line-height: 24px;padding: 0 5px;margin: 0;}.tag_list h5 a{color: #47381C;}.classify{margin: 10px 0;padding: 4px 12px 8px;}.classify a{margin-right: 20px;white-space: nowrap;}
核心技術(shù)類目 全部主題 Hadoop AWS 移動游戲 Java Android iOS Swift 智能硬件 Docker OpenStack VPN Spark ERP IE10 Eclipse CRM JavaScript 數(shù)據(jù)庫 Ubuntu NFC WAP jQuery BI HTML5 Spring Apache .NET API HTML SDK IIS Fedora XML LBS Unity Splashtop UML components Windows Mobile Rails QEMU KDE Cassandra CloudStack FTC coremail OPhone CouchBase 云計算 iOS6 Rackspace Web App SpringSide Maemo Compuware 大數(shù)據(jù) aptech Perl Tornado Ruby Hibernate ThinkPHP HBase Pure Solr Angular Cloud Foundry Redis Scala Django Bootstrap <script language="javascript" type="text/javascript">$(function(){ setTimeout(function(){ $.get("/tianjian4592/svc/GetTagContent",function(data){ $(".tag_list").html(data).show(); }); }); },500);</script> #popup_mask{position: absolute;width: 100%;height: 100%;background: #000;z-index: 9999;left: 0px;top: 0px;opacity: 0.3;filter: alpha(opacity=30);display: none;}<script type="text/javascript">$(function(){ setTimeout(function(){ $(".comment_body:contains('回復(fù)')").each(function(index,item){ var u=$(this).text().split(':')[0].toString().replace("回復(fù)","") var thisComment=$(this); if(u) { $.getJSON("https://passport.csdn.net/get/nick?callback=?", {users: u}, function(a) { if(a!=null&&a.data!=null&&a.data.length>0) { nick=a.data[0].n; if(u!=nick) { thisComment.text(thisComment.text().replace(u,nick)); } } }); } }); },200); setTimeout(function(){ $(".math").each(function(index,value){$(this).find("span").last().css("color","#fff"); }) },5000); setTimeout(function(){ $(".math").each(function(index,value){$(this).find("span").last().css("color","#fff"); }) },10000); setTimeout(function(){ $(".math").each(function(index,value){$(this).find("span").last().css("color","#fff"); }) },15000); setTimeout(function(){ $("a img[src='http://js.tongji.linezing.com/stats.gif']").parent().css({"position":"absolute","left":"50%"}); },300); }); function loginbox(){ var $logpop=$("#pop_win"); $logpop.html(' src="https://passport.csdn.net/account/loginbox?service=http://static.blog.csdn.net/callback.htm" frameborder="0" height="600" width="400" scrolling="no">'); $('#popup_mask').css({ opacity: 0.5, width: $( document ).width() + 'px', height: $( document ).height() + 'px' }); $('#popup_mask').css("display","block"); $logpop.css( { top: ($( window ).height() - $logpop.height())/ 2 + $( window ).scrollTop() + 'px', left:($( window ).width() - $logpop.width())/ 2 } ); setTimeout( function () { $logpop.show(); $logpop.css( { opacity: 1 } ); }, 200 ); $('#popup_mask').unbind("click"); $('#popup_mask').bind("click", function(){ $('#popup_mask').hide(); var $clopop = $("#pop_win"); $("#common_ask_div_sc").css("display","none"); $clopop.css( { opacity: 0 } ); setTimeout( function () { $clopop.hide(); }, 350 ); return false; }); }</script> <script language="javascript" type="text/javascript" src="http://ads.csdn.net/js/async_new.js"></script>
學(xué)問積年而成 訪問:242632次 積分:2709 等級: 積分:2709 排名:第10054名 原創(chuàng):56篇 轉(zhuǎn)載:0篇 譯文:0篇 評論:340條 <script type="text/javascript">$(function () { $("#btnSubmit").click(function () { search(); }); $("#frmSearch").submit(function () { search(); return false; }); function search() { var url = "http://so.csdn.net/so/search/s.do?q=" + encodeURIComponent($("#inputSearch").val()) + "&u=" + username + "&t=blog"; window.location.href = url; } });</script>
android動效篇(13) 性能優(yōu)化(0) 反編譯(0) android常見問題(2) 基礎(chǔ)總結(jié)(20) javascript(5) javaweb(11) JDBC(3) AJAX(1) 心路歷程(0) 2015年07月(2) 2015年06月(1) 2015年05月(1) 2015年04月(4) 2015年03月(6) 2015年02月(1) 2012年09月(3) 2012年08月(2) 2012年07月(20) 2012年06月(13) 2012年05月(3) 展開 Android使用SVG矢量圖打造酷炫動效!(36738) 一個絢麗的loading動效分析與實現(xiàn)!(30684) Canvas開篇之drawBitmap方法講解(22260) 自定義view實現(xiàn)水波紋效果(14259) Android Paint之 setXfermode PorterDuffXfermode 講解(13369) Paint、Canvas、Matrix使用講解(一、Paint)(11889) Canvas之translate、scale、rotate、skew方法講解!(8984) 關(guān)于引入第三方j(luò)ar包引發(fā)的java.lang.NoClassDefFoundError解決(8766) Path特效之PathMeasure打造萬能路徑動效(8404) android動效開篇(8335) 一個絢麗的loading動效分析與實現(xiàn)!(177) 自定義view實現(xiàn)水波紋效果(33) Paint、Canvas、Matrix使用講解(一、Paint)(25) Android Paint之 setXfermode PorterDuffXfermode 講解(21) Android使用SVG矢量圖打造酷炫動效!(20) Canvas開篇之drawBitmap方法講解(15) Canvas之translate、scale、rotate、skew方法講解!(11) Animation & Property Animation 使用(9) android動效開篇(8) Android 漂浮類動效的分析與實現(xiàn)!(7) 一個絢麗的loading動效分析與實現(xiàn)! 碧海銀劍:@fanshouyizhi:大神,你這個demo很棒,不過進度會突然100%,不是平滑過渡的,而且到...
Android Paint之 setXfermode PorterDuffXfermode 講解 george_zyf:頂樓主,開闊眼界了
Paint、Canvas、Matrix使用講解(一、Paint) Lgd_東:相恨見晚
關(guān)于引入第三方j(luò)ar包引發(fā)的java.lang.NoClassDefFoundError解決 聆聽璇律:studio怎么弄啊
一個絢麗的loading動效分析與實現(xiàn)! jiong103:mOrangeRectF.right = mCurrentProgressPosition+mLef...
一個絢麗的loading動效分析與實現(xiàn)! Liming4Android:好像demo中沒有加載到100%的時候那個風(fēng)扇縮小和100%放大的那個代碼吧
一個絢麗的loading動效分析與實現(xiàn)! Hebe_fans:這叫不難。。。我操
自定義view實現(xiàn)水波紋效果 隨手就是一巴掌叫你丫的做程序員:Bitmap too large to be uploaded into a texture (默認(rèn)...
Android Paint之 setXfermode PorterDuffXfermode 講解 隨手就是一巴掌叫你丫的做程序員:學(xué)習(xí)了,樓主辛苦!!!!
Android Paint之 setXfermode PorterDuffXfermode 講解 W偉V:mark
* 程序員10月書訊,評論得書 * Android中Xposed框架篇---修改系統(tǒng)位置信息實現(xiàn)自身隱藏功能 * Chromium插件(Plugin)模塊(Module)加載過程分析 * Android TV開發(fā)總結(jié)--構(gòu)建一個TV app的直播節(jié)目實例 * 架構(gòu)設(shè)計:系統(tǒng)存儲--MySQL簡單主從方案及暴露的問題 id="iframeu2734128_0" src="http://pos.baidu.com/acrm?sz=200x200&rdid=2734128&dc=2&di=u2734128&dri=0&dis=0&dai=2&ps=2908x314&coa=at%3D3%26rsi0%3D200%26rsi1%3D200%26pat%3D6%26tn%3DbaiduCustNativeAD%26rss1%3D%2523FFFFFF%26conBW%3D1%26adp%3D1%26ptt%3D0%26titFF%3D%2525E5%2525BE%2525AE%2525E8%2525BD%2525AF%2525E9%25259B%252585%2525E9%2525BB%252591%26titFS%3D%26rss2%3D%2523000000%26titSU%3D0%26ptbg%3D90%26piw%3D0%26pih%3D0%26ptp%3D0&dcb=BAIDU_SSP_define&dtm=HTML_POST&dvi=0.0&dci=-1&dpt=none&tsr=0&tpr=1478326006940&ti=Canvas%E4%B9%8Btranslate%E3%80%81scale%E3%80%81rotate%E3%80%81skew%E6%96%B9%E6%B3%95%E8%AE%B2%E8%A7%A3%EF%BC%81%20-%20Ajian_studio%20-%20%E5%8D%9A%E5%AE%A2%E9%A2%91&ari=2&dbv=2&drs=3&pcs=1829x1019&pss=1829x19885&cfv=0&cpl=4&chi=3&cce=true&cec=UTF-8&tlm=1478326006&rw=1019<u=http%3A%2F%2Fblog.csdn.net%2Ftianjian4592%2Farticle%2Fdetails%2F45234419&ecd=1&psr=1920x1080&par=1846x1080&pis=-1x-1&ccd=24&cja=false&cmi=6&col=zh-CN&cdo=-1&tcn=1478326007&qn=c31dff3e505510bd&tt=1478326006861.137.138.470" width="200" height="200" align="center,center" vspace="0" hspace="0" marginwidth="0" marginheight="0" scrolling="no" frameborder="0" style="border:0; vertical-align:bottom;margin:0;" allowtransparency="true"> <script type="text/javascript">(window['cproStyleApi'] = window['cproStyleApi'] ||{})['u2734128']={at:'3',rsi0:'200',rsi1:'200',pat:'6',tn:'baiduCustNativeAD',rss1:'#FFFFFF',conBW:'1',adp:'1',ptt:'0',titFF:'%E5%BE%AE%E8%BD%AF%E9%9B%85%E9%BB%91',titFS:'',rss2:'#000000',titSU:'0',ptbg:'90',piw:'0',pih:'0',ptp:'0'};/*服務(wù)器頻道首頁置頂Banner960*90,創(chuàng)建于2014-7-3*/(window.cproArray = window.cproArray || []).push({id:'u2734128'});</script> <script src="http://cpro.baidustatic.com/cpro/ui/c.js" type="text/javascript"></script> <script type="text/javascript" src="http://c.csdnimg.cn/rabbit/cnick/cnick.js"></script><script type="text/javascript" src="http://static.blog.csdn.net/scripts/newblog.min.js"></script><script type="text/javascript" src="http://medal.blog.csdn.net/showblogmedal.ashx?blogid=1298835"></script><script type="text/javascript" src="http://static.blog.csdn.net/scripts/JavaScript1.js"></script> rel="stylesheet" type="text/css" href="//csdnimg.cn/pubfooter/css/pub_footer_2014.css" />
src="about:blank" frameborder="0" scrolling="no" style="z-index:-1;position:absolute;top:0;left:0;width:100%;height:100%;background:transparent"> 您有
0 條新通知 <script id="noticeScript" type="text/javascript" btnid="header_notice_num" wrapid="note1" count="5" subcount="5" src="//csdnimg.cn/rabbit/notev2/js/notify.js?9d86d94"></script> <script type="text/javascript" src="http://passport.csdn.net/content/loginbox/login.js"></script><script type="text/javascript">document.write(" ");</script> <script type="text/javascript" src="http://www.csdn.net/ui/scripts/Csdn/counter.js"></script><script type="text/javascript" charset="UTF-8" src="http://message.csdn.net/msg.popup.js"></script><script type="text/javascript" src="http://ad.csdn.net/scripts/ad-blog.js"></script><script type="text/javascript">$(function () { function __get_code_toolbar(snippet_id) { return $("
" + "
"); } $("[code_snippet_id]").each(function () { __s_id = $(this).attr("code_snippet_id"); if (__s_id != null && __s_id != "" && __s_id != 0 && parseInt(__s_id) > 70020) { __code_tool = __get_code_toolbar(__s_id); $(this).prev().find(".tools").append(__code_tool); } }); $(".bar").show(); });</script> <script id="csdn-toolbar-id" btnid="header_notice_num" wrapid="note1" count="5" subcount="5" type="text/javascript" src="http://c.csdnimg.cn/public/common/toolbar/js/toolbar.js"></script> href="http://c.csdnimg.cn/comm_ask/css/ask_float_block.css" type="text/css" rel="stylesheet" /> <script language="JavaScript" type="text/javascript" src="http://c.csdnimg.cn/comm_ask/js/libs/wmd.js"></script> <script language="JavaScript" type="text/javascript" src="http://c.csdnimg.cn/comm_ask/js/libs/showdown.js"></script> <script language="JavaScript" type="text/javascript" src="http://c.csdnimg.cn/comm_ask/js/libs/prettify.js"></script> <script language="JavaScript" type="text/javascript" src="http://c.csdnimg.cn/comm_ask/js/apps/ask_float_block.js"></script>
<script id="adJs52b5334" src="http://ads.csdn.net/js/opt/52b5334.js?t=0.2122191662760713"></script> <script>document.getElementById("adJs52b5334").src = "http://ads.csdn.net/js/opt/52b5334.js?t=" + Math.random();</script>
rel="stylesheet" href="http://static.blog.csdn.net/css/blog_code.css" /> <script type="text/javascript" src="http://static.blog.csdn.net/scripts/saveToCode.js"></script> <script type="text/javascript" src="//csdnimg.cn/rabbit/tracking-ad/main.js?75eacd8"></script>
rel="stylesheet" type="text/css" media="screen" href="http://ask.csdn.net/assets/ask_float_fonts_css-6b30a53970eb5c3a2a045e3df585b475.css" />
提問 您的問題將會被發(fā)布在“技術(shù)問答”頻道 ×
該問題已存在,請勿重復(fù)提問 插入鏈接 本地上傳 網(wǎng)絡(luò)圖片 src="http://ask.csdn.net/upload.html">
插入圖片 | | | | | | ?
? 0 0 0:0 推薦標(biāo)簽: 我要懸賞 幣 取消 發(fā)布
可能存在類似的問題: 我想提一個新問題
保存代碼片 整理和分享保存的代碼片,請訪問代碼筆記
? 標(biāo)簽 Canvasx android畫布x canvas.translatex canvas.scalex canvas.rotatex 取消 確定
總結(jié)
以上是生活随笔 為你收集整理的Canvas之translate、scale、rotate、skew 的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
如果覺得生活随笔 網(wǎng)站內(nèi)容還不錯,歡迎將生活随笔 推薦給好友。