monkeymushroom / miclockview Goto Github PK
View Code? Open in Web Editor NEW高仿小米时钟
高仿小米时钟
查阅 Rotate3dAnimation的景深效果
@OverRide
protected void applyTransformation(float interpolatedTime, Transformation t) {
super.applyTransformation(interpolatedTime, t);
float fromDegree = startDegree;
float degree = fromDegree + (endDegree - startDegree) * interpolatedTime;
final Matrix matrix = t.getMatrix();
mCamera.save();
if (mReverse) {
mCamera.translate(0, 0, deepZ * interpolatedTime);
} else {
mCamera.translate(0, 0, deepZ * (1 - interpolatedTime));
}
if (direction == DIRECTION.Y) {
mCamera.rotateY(degree);
} else {
mCamera.rotateX(degree);
}
mCamera.getMatrix(matrix);
mCamera.restore();
matrix.preTranslate(-centerX, -centerY);
matrix.postTranslate(centerX, centerY);
}
需要先translate 然后rotate就会出现景深效果了
`
//第一处添加
private int missMove=10;// 小幅度滑动忽略阀值
private float startX;// 落手点X
private float startY;// 落手点Y
@Override
public boolean onTouchEvent(MotionEvent event) {
switch (event.getAction()) {
case MotionEvent.ACTION_DOWN:
//第二处添加
startX=event.getX();
startY=event.getY();
System.out.println("按下啦,出发点是"+event.getX()+" "+event.getY());
float rotateX = -(event.getY() - getHeight() / 2);
float rotateY = (event.getX() - getWidth() / 2);
//求出此时旋转的大小与半径之比
float percentX = rotateX / mRadius;
float percentY = rotateY / mRadius;
if (percentX > 1) {
percentX = 1;
} else if (percentX < -1) {
percentX = -1;
}
if (percentY > 1) {
percentY = 1;
} else if (percentY < -1) {
percentY = -1;
}
mShakeAnimX = getShakeAnim(mCameraRotateX, percentX * mMaxCameraRotate);
mShakeAnimX.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
@Override
public void onAnimationUpdate(ValueAnimator valueAnimator) {
mCameraRotateX = (float) valueAnimator.getAnimatedValue();
}
});
mShakeAnimY = getShakeAnim(mCameraRotateY, percentY * mMaxCameraRotate);
mShakeAnimY.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
@Override
public void onAnimationUpdate(ValueAnimator valueAnimator) {
mCameraRotateY = (float) valueAnimator.getAnimatedValue();
}
});
//第三处注释掉原有的
//getCameraRotate(event);
break;
case MotionEvent.ACTION_MOVE:
//根据手指坐标计算camera应该旋转的大小
getCameraRotate(event);
break;
case MotionEvent.ACTION_UP:
//松开手指,时钟复原并伴随晃动动画
mShakeAnimX = getShakeAnim(mCameraRotateX, 0);
mShakeAnimX.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
@Override
public void onAnimationUpdate(ValueAnimator valueAnimator) {
mCameraRotateX = (float) valueAnimator.getAnimatedValue();
}
});
mShakeAnimY = getShakeAnim(mCameraRotateY, 0);
mShakeAnimY.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
@Override
public void onAnimationUpdate(ValueAnimator valueAnimator) {
mCameraRotateY = (float) valueAnimator.getAnimatedValue();
}
});
break;
}
return true;
}
/**
* 获取camera旋转的大小
* 注意view坐标与camera坐标方向的转换
*/
private void getCameraRotate(MotionEvent event) {
//第四处修改,共四处
float moveAll=(Math.abs(event.getX()-startX)+Math.abs(event.getY()-startY));
if(moveAll>missMove) {
System.out.println("停止动画!滑动量过大" + moveAll);
}else{
System.out.println("移动总和是" + moveAll);
}
if (mShakeAnimX != null && mShakeAnimX.isRunning()&&moveAll>missMove) {
mShakeAnimX.cancel();
mShakeAnimY.cancel();
}
float rotateX = -(event.getY() - getHeight() / 2);
float rotateY = (event.getX() - getWidth() / 2);
//求出此时旋转的大小与半径之比
float percentX = rotateX / mRadius;
float percentY = rotateY / mRadius;
if (percentX > 1) {
percentX = 1;
} else if (percentX < -1) {
percentX = -1;
}
if (percentY > 1) {
percentY = 1;
} else if (percentY < -1) {
percentY = -1;
}
//最终旋转的大小按比例匀称改变
mCameraRotateX = percentX * mMaxCameraRotate;
mCameraRotateY = percentY * mMaxCameraRotate;
}
`
您好,我想问一下,3和9两个小时刻度是如何定位的??
为什么这里
(getWidth() - mPaddingRight - mTextRect.height() / 2 - textSmallWidth / 2, getHeight() / 2 + mTextRect.height() / 2)
的xy是这样的,有点不明白。
`
case MotionEvent.ACTION_DOWN:
//第二处添加
startX=event.getX();
startY=event.getY();
//getCameraRotate(event);
float rotateX = -(event.getY() - getHeight() / 2);
float rotateY = (event.getX() - getWidth() / 2);
//求出此时旋转的大小与半径之比
float percentX = rotateX / mRadius;
float percentY = rotateY / mRadius;
if (percentX > 1) {
percentX = 1;
} else if (percentX < -1) {
percentX = -1;
}
if (percentY > 1) {
percentY = 1;
} else if (percentY < -1) {
percentY = -1;
}
mShakeAnimX = getShakeAnim(mCameraRotateX, percentX * mMaxCameraRotate);
mShakeAnimX.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
@Override
public void onAnimationUpdate(ValueAnimator valueAnimator) {
float tmp=(float) valueAnimator.getAnimatedValue();
if(Math.abs(tmp)> mMaxShakeCameraRotate){// 大概是Camara旋转角的二倍
System.out.println(tmp+"修正为"+ mMaxShakeCameraRotate);
if(tmp>0){
tmp= mMaxShakeCameraRotate;
}else{
tmp=-mMaxShakeCameraRotate;
}
}
mCameraRotateX =tmp;
}
});
mShakeAnimY = getShakeAnim(mCameraRotateY, percentY * mMaxCameraRotate);
mShakeAnimY.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
@Override
public void onAnimationUpdate(ValueAnimator valueAnimator) {
float tmp=(float) valueAnimator.getAnimatedValue();
if(Math.abs(tmp)> mMaxShakeCameraRotate){
System.out.println(tmp+"修正为"+ mMaxShakeCameraRotate);
if(tmp>0){
tmp= mMaxShakeCameraRotate;
}else{
tmp=-mMaxShakeCameraRotate;
}
}
mCameraRotateY =tmp;
}
});
//第三处注释掉原有的
//getCameraRotate(event);
break;
`
首先,控件很棒。但有一点就是若背景色是透明,绘制叠加不出刻度线效果。考虑过采用Xfermode,绘制出来的刻度线有所谓黑色透明。
希望作者能更好的解决这一点。
另可优化draw时分秒针的代码。对相应的Path都增加path.isEmpty()
秒针举例:
/**
* 画秒针,根据不断变化的秒针角度旋转画布
*/
private void drawSecondHand() {
mCanvas.save();
mCanvas.translate(mCanvasTranslateX, mCanvasTranslateY);
mCanvas.rotate(mSecondDegree, getWidth() / 2, getHeight() / 2);
if(mSecondHandPath.isEmpty()){
mSecondHandPath.reset();
float offset = mPaddingTop + mTextRect.height() / 2;
mSecondHandPath.moveTo(getWidth() / 2, offset + 0.26f * mRadius);
mSecondHandPath.lineTo(getWidth() / 2 - 0.05f * mRadius, offset + 0.34f * mRadius);
mSecondHandPath.lineTo(getWidth() / 2 + 0.05f * mRadius, offset + 0.34f * mRadius);
mSecondHandPath.close();
mSecondHandPaint.setColor(mLightColor);
}
mCanvas.drawPath(mSecondHandPath, mSecondHandPaint);
mCanvas.restore();
}
A declarative, efficient, and flexible JavaScript library for building user interfaces.
🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
An Open Source Machine Learning Framework for Everyone
The Web framework for perfectionists with deadlines.
A PHP framework for web artisans
Bring data to life with SVG, Canvas and HTML. 📊📈🎉
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
Some thing interesting about web. New door for the world.
A server is a program made to process requests and deliver data to clients.
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
Some thing interesting about visualization, use data art
Some thing interesting about game, make everyone happy.
We are working to build community through open source technology. NB: members must have two-factor auth.
Open source projects and samples from Microsoft.
Google ❤️ Open Source for everyone.
Alibaba Open Source for everyone
Data-Driven Documents codes.
China tencent open source team.