android 下拉窗帘,Android 窗帘(Curtain)效果二之波浪式动态扭曲效果
上一篇文章已經實現了如何把一張圖片扭曲成波浪效果,那么這一篇文章我們介紹如何動態調整系數,去改變波浪圖片的皺褶成度。我們自一次觀察下圖morning routine的效果:
仔細觀察我們發現,當往右滑動時,頭部的溝壑(也就是正弦曲線)是從0遞增到最大的;如果具體到一條水平像素直線的話,這其實就是一條直線扭曲成正弦曲線的一個過程。直線如何扭曲成正弦曲線、正弦曲線如何恢復成直線其實就是系數WAVE_HEIGHT(波峰波谷距離)從0~MAX_WAVE_HEIGHT、MAX_WAVE_HEIGHT~0的動態變化過程,因此我們只要在前一篇文章正弦曲線的公式代碼加入滑動的滑動百分比progress(1>=progress>=0)就可以了:
float yOffset = WAVE_HEIGHT / 2 * progress + WAVE_HEIGHT / 2 * progress * (float) Math.sin((float) j / WIDTH * 5 * Math.PI + k);
上面已經介紹了動態滑動扭曲時如何計算每條水平直線上每個像素的y軸偏移量,但是根據上圖效果其實每個像素的x坐標也是變化的;折疊菜單的最左邊的像素點x坐標等于菜單向左滑動的距離,折疊菜單的最右邊的像素點x坐標緊緊的擠壓邊緣不移動,所以當滑動時每個像素的x坐標是偏移量是從左往右衰減成0的,由此我們可以推導出滑動時計算的每個像素x坐標的公式:
//bitmapwidth 原圖寬度
//origsX 原圖時像素的X坐標
//progress當前滑動百分比
//xPostion 像素的新x坐標
//這個公式計算出的xPostion 越往右跟origsX 的差距越小,最后一像素差距為0
float xPostion = origsX + (bitmapwidth - origsX ) * progress;
原理我們已經理解的差不多了,那么最終的效果如下圖:
全部代碼如下:
public class CurtainView extends View {
private Bitmap mbitmap;
private static int WIDTH = 30;
private static int HEIGHT = 30;
//最大水平的波形高度
private float WAVE_HEIGHT = 50;
//小格相交的總的點數
private int COUNT = (WIDTH + 1) * (HEIGHT + 1);
private float[] verts = new float[COUNT * 2];
private float[] origs = new float[COUNT * 2];
private float k;
private float progress;
public CurtainView(Context context) {
super(context);
init();
}
public CurtainView(Context context, @Nullable AttributeSet attrs) {
super(context, attrs);
init();
}
public CurtainView(Context context, @Nullable AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr);
init();
}
public void setProgress(float progress){
this.progress = progress;
invalidate();
}
@Override
protected void onDraw(Canvas canvas) {
super.onDraw(canvas);
for (int i = 0; i < HEIGHT + 1; i++) {
for (int j = 0; j < WIDTH + 1; j++) {
//把每一個水平像素通過正弦公式轉換成正弦曲線
//WAVE_HEIGHT表示波峰跟波低的垂直距離,皺褶后會王桑超過水平線,所以往下偏移WAVE_HEIGHT / 2
//5表示波浪的密集度,表示波峰波谷總共有五個,對應上面左圖的1,2,3,4,5
//j就是水平像的X軸坐標
//K決定正弦曲線起始點(x=0)點的Y坐標,k=0就是從波峰波谷的中間開始左->右繪制曲線
float yOffset = WAVE_HEIGHT / 2 * progress + WAVE_HEIGHT / 2 * progress * (float) Math.sin((float) j / WIDTH * 5 * Math.PI + k);
//每個像素扭曲后的x坐標
//origs[(i*(WIDTH+1)+j)*2+0] 原圖x坐標
verts[(i * (WIDTH + 1) + j) * 2 + 0] = origs[(i*(WIDTH+1)+j)*2+0] + (bitmapwidth - origs[(i*(WIDTH+1)+j)*2+0]) * progress;
//每個像素扭曲后的Y坐標
//origs[(i*(WIDTH+1)+j)*2+1] 原圖y坐標
verts[(i * (WIDTH + 1) + j) * 2 + 1] = origs[(i * (WIDTH + 1) + j) * 2 + 1] + yOffset;//
}
}
canvas.drawBitmapMesh(mbitmap, WIDTH, HEIGHT, verts, 0, null, 0, null);
}
int bitmapwidth;
int bitmapheight;
public void init() {
mbitmap = BitmapFactory.decodeResource(getResources(), R.mipmap.timg);
bitmapwidth = mbitmap.getWidth();
bitmapheight = mbitmap.getHeight();
COUNT = (WIDTH + 1) * (HEIGHT + 1);
verts = new float[COUNT * 2];
origs = new float[COUNT * 2];
int index = 0;
for (int i = 0; i < HEIGHT + 1; i++) {
float fy = bitmapheight / (float) HEIGHT * i;
for (int j = 0; j < WIDTH + 1; j++) {
float fx = bitmapwidth / (float) WIDTH * j;
//偶數位記錄x坐標 奇數位記錄Y坐標
origs[index * 2 + 0] = verts[index * 2 + 0] = fx;
origs[index * 2 + 1] = verts[index * 2 + 1] = fy;
index++;
}
}
}
}
Android 窗簾(Curtain)效果三之波浪式扭曲效果優化提升
《新程序員》:云原生和全面數字化實踐50位技術專家共同創作,文字、視頻、音頻交互閱讀總結
以上是生活随笔為你收集整理的android 下拉窗帘,Android 窗帘(Curtain)效果二之波浪式动态扭曲效果的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: android 8 esp8266,ES
- 下一篇: [Android工具]安卓音乐下载软件,