[英]Rotating a bitmap around a pivot on a canvas
我正在嘗試實現一個表面,其中手的位圖圖像圍繞畫布上的臉部中心旋轉。
任何幫助都會得到滿足!
基本步驟:
例如,從資源中解碼您的位圖,但還有其他方法。 (初始化類時,您可能希望執行此操作,而不是在每個繪制周期中執行此操作。):
Bitmap = mBitmap = BitmapFactory.decodeResource(getResources(), R.drawable.watch_face);
在onDraw
設置Matrix
以進行旋轉。 就像是:
Matrix mMatrix = new Matrix(); mMatrix.setRotate (degreeOfRotation, mBitmap.getWidth()/2, mBitmap.getHeight()/2);
使用接收Matrix的方法繪制位圖: canvas.drawBitmap(mBitmap, mMatrix, mPaint);
還有其他細節。 設置Paint
。 您可能會發現需要使用Matrix的postRotate
方法。 等等。但這應該足以讓你開始谷歌搜索。
在這種情況下(我猜你試圖用谷歌表面api旋轉位圖)你應該記住這篇精彩帖子中描述的規則,並避免使用大型位圖用於表針。 這意味着您必須指定垂直和水平邊距。 我在這里使用了Jave發布的解決方案。
yourCanvas.save(Canvas.MATRIX_SAVE_FLAG); //Save the canvas
yourCanvas.rotate(currentRotation, centerX, centerY);
int marginX = (width - yourBitmap.getWidth()) / 2; //Calculate horizontal margin
yourCanvas.drawBitmap(yourBitmap, marginX, 0, yourPaint);
yourCanvas.restore();
我放棄了垂直裁剪位圖,因為以這種方式旋轉它更容易,但如果你想完全符合規則,應該考慮它。 最好不要在這里計算marginX
。 它可以在onSurfaceChanged
中完成,如上面提到的帖子中所述。
我最近需要解決Android Wear表盤的位圖旋轉問題。 以下onDraw代碼對我有用。 在調用onDraw之前,請確保縮放位圖:
// first draw the background
if (isInAmbientMode()) {
canvas.drawColor(Color.BLACK);
} else {
if (mBackgroundBitmapScaled == null) {
canvas.drawRect(0, 0, canvas.getWidth(), canvas.getHeight(), mBackgroundPaint);
}
else {
canvas.drawBitmap(mBackgroundBitmapScaled, 0, 0, null);
}
}
// now setup to draw the hands..
float centerX = bounds.width() / 2f;
float centerY = bounds.height() / 2f;
float secRot = mCalendar.get(Calendar.SECOND) / 30f * (float) Math.PI;
int minutes = mCalendar.get(Calendar.MINUTE);
float minRot = minutes / 30f * (float) Math.PI;
float hrRot = ((mCalendar.get(Calendar.HOUR) + (minutes / 60f)) / 6f) * (float) Math.PI;
if (isInAmbientMode()) {
mHandPaint.clearShadowLayer();
float minLength = centerX - 40;
float hrLength = centerX - 80;
// hour hand
float hrX = (float) Math.sin(hrRot) * hrLength;
float hrY = (float) -Math.cos(hrRot) * hrLength;
canvas.drawLine(centerX, centerY, centerX + hrX, centerY + hrY, mHandPaint);
// minute hand
float minX = (float) Math.sin(minRot) * minLength;
float minY = (float) -Math.cos(minRot) * minLength;
canvas.drawLine(centerX, centerY, centerX + minX, centerY + minY, mHandPaint);
}
else {
// hour hand
Matrix matrix = new Matrix();
matrix.setRotate (hrRot / (float) Math.PI * 180, mHourHandBitmapScaled.getWidth()/2, mHourHandBitmapScaled.getHeight()/2);
canvas.drawBitmap(mHourHandBitmapScaled, matrix, mHandPaint);
// minute hand
matrix = new Matrix();
matrix.setRotate (minRot / (float) Math.PI * 180, mHourHandBitmapScaled.getWidth()/2, mHourHandBitmapScaled.getHeight()/2);
canvas.drawBitmap(mMinuteHandBitmapScaled, matrix, mHandPaint);
}
if (!mAmbient) {
// second hand
float secLength = centerX - 20;
float secX = (float) Math.sin(secRot) * secLength;
float secY = (float) -Math.cos(secRot) * secLength;
canvas.drawLine(centerX, centerY, centerX + secX, centerY + secY, mHandPaint);
}
並用於縮放:
private void scaleWatchFace(int width, int height) {
Log.v(TAG, "scaleWatchFace");
mBackgroundBitmapScaled = Bitmap.createScaledBitmap(mBackgroundBitmap, width, height, true /* filter */);
float ratio = (float) width / mBackgroundBitmap.getWidth();
mMinuteHandBitmapScaled = Bitmap.createScaledBitmap(mMinuteHandBitmap,
(int) (mMinuteHandBitmap.getWidth() * ratio),
(int) (mMinuteHandBitmap.getHeight() * ratio), true);
mHourHandBitmapScaled = Bitmap.createScaledBitmap(mHourHandBitmap,
(int) (mHourHandBitmap.getWidth() * ratio),
(int) (mHourHandBitmap.getHeight() * ratio), true);
}
請注意,我的背景和手表資源的圖像大小都是480x480。 這消除了轉換到中心的任何需要,並且(可能)更容易使用電池。
我希望這很有用。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.